kopia lustrzana https://github.com/corrscope/corrscope
Fix CorrelationTrigger
rodzic
cd33fcee6e
commit
0e575d9792
|
|
@ -43,10 +43,10 @@ def main(wave_dir: str, master_wave: Optional[str], fps: int):
|
|||
master_wave=master_wave,
|
||||
fps=fps,
|
||||
trigger=CorrelationTrigger.Config(
|
||||
trigger_strength=0.1,
|
||||
trigger_strength=10,
|
||||
|
||||
responsiveness=0.1,
|
||||
falloff_width=0.5,
|
||||
responsiveness=1,
|
||||
falloff_width=2,
|
||||
),
|
||||
render=RendererConfig( # todo
|
||||
1280, 720,
|
||||
|
|
@ -107,6 +107,7 @@ class Ovgen:
|
|||
for wave in self.waves:
|
||||
sample = round(wave.smp_s * time_seconds)
|
||||
trigger_sample = wave.trigger.get_trigger(sample)
|
||||
print(f'- {trigger_sample}')
|
||||
center_smps.append(trigger_sample)
|
||||
|
||||
print(frame)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from typing import NamedTuple, List, Dict, Any, TYPE_CHECKING
|
|||
from dataclasses import dataclass
|
||||
|
||||
import numpy as np
|
||||
from matplotlib import pyplot as plt
|
||||
from scipy import signal
|
||||
|
||||
from ovgenpy.renderer import MatplotlibRenderer, RendererConfig
|
||||
|
|
@ -32,13 +33,29 @@ class TriggerConfig:
|
|||
raise NotImplementedError
|
||||
|
||||
|
||||
SHOW_TRIGGER = True
|
||||
SHOW_TRIGGER = False
|
||||
SHOW_TRIGGER2 = False
|
||||
|
||||
|
||||
def lerp(x: np.ndarray, y: np.ndarray, a: float):
|
||||
return x * (1 - a) + y * a
|
||||
|
||||
|
||||
class Dummy:
|
||||
def __getattr__(self, item):
|
||||
return self
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self
|
||||
|
||||
|
||||
def plots(nplot):
|
||||
for i in range(nplot):
|
||||
if SHOW_TRIGGER2:
|
||||
yield plt.subplot(nplot, 1, i+1)
|
||||
else:
|
||||
yield Dummy()
|
||||
|
||||
class CorrelationTrigger(Trigger):
|
||||
MIN_AMPLITUDE = 0.01
|
||||
|
||||
|
|
@ -86,19 +103,47 @@ class CorrelationTrigger(Trigger):
|
|||
data = self._wave.get_around(offset, self._buffer_nsamp)
|
||||
N = len(data)
|
||||
|
||||
ps = plots(4)
|
||||
next(ps).plot(data)
|
||||
|
||||
# Add "step function" to correlation buffer
|
||||
prev_buffer = self._buffer.copy()
|
||||
prev_buffer[N//2:] += trigger_strength
|
||||
halfN = N // 2
|
||||
|
||||
wave_period = get_period(data)
|
||||
window = signal.gaussian(N, std = halfN // 3)
|
||||
|
||||
step = np.empty(N)
|
||||
step[:halfN] = -trigger_strength / 2
|
||||
step[halfN:] = trigger_strength / 2
|
||||
step *= window
|
||||
|
||||
prev_buffer = self._buffer + step
|
||||
next(ps).plot(prev_buffer)
|
||||
|
||||
# Find optimal offset (within ±N//4)
|
||||
delta = N-1
|
||||
radius = N//4
|
||||
|
||||
# Calculate correlation
|
||||
corr = signal.correlate(prev_buffer, data)
|
||||
"""
|
||||
If offset < optimal, we need to `offset += positive`.
|
||||
- The peak will appear near the right of `data`.
|
||||
|
||||
Either we must slide prev_buffer to the right:
|
||||
- correlate(data, prev_buffer)
|
||||
- trigger = offset + peak_offset
|
||||
|
||||
Or we must slide data to the left (by sliding offset to the right):
|
||||
- correlate(prev_buffer, data)
|
||||
- trigger = offset - peak_offset
|
||||
"""
|
||||
corr = signal.correlate(data, prev_buffer)
|
||||
assert len(corr) == 2*N - 1
|
||||
next(ps).plot(corr)
|
||||
|
||||
corr = corr[delta-radius : delta+radius+1]
|
||||
delta = radius
|
||||
next(ps).plot(corr)
|
||||
|
||||
# argmax(corr) == delta + peak_offset == (data >> peak_offset)
|
||||
# peak_offset == argmax(corr) - delta
|
||||
|
|
@ -108,7 +153,8 @@ class CorrelationTrigger(Trigger):
|
|||
# Update correlation buffer (distinct from visible area)
|
||||
aligned = self._wave.get_around(trigger, self._buffer_nsamp)
|
||||
self._update_buffer(aligned)
|
||||
|
||||
if SHOW_TRIGGER2:
|
||||
plt.show()
|
||||
return trigger
|
||||
|
||||
def _update_buffer(self, data: np.ndarray) -> None:
|
||||
|
|
|
|||
Plik binarny nie jest wyświetlany.
|
|
@ -18,21 +18,33 @@ cfg = CorrelationTrigger.Config(
|
|||
|
||||
|
||||
def test_trigger():
|
||||
wave = Wave(None, 'tests/sine440.wav')
|
||||
# wave = Wave(None, 'tests/sine440.wav')
|
||||
wave = Wave(None, 'tests/impulse24000.wav')
|
||||
|
||||
iters = 5
|
||||
plot = False
|
||||
x = 24000 - 500
|
||||
trigger = cfg(wave, 4000)
|
||||
|
||||
BIG = 0.95
|
||||
SMALL = 0.05
|
||||
fig, axes = plt.subplots(5, gridspec_kw=dict(
|
||||
top=BIG, right=BIG,
|
||||
bottom=SMALL, left=SMALL,
|
||||
)) # type: Figure, Axes
|
||||
fig.tight_layout()
|
||||
if plot:
|
||||
BIG = 0.95
|
||||
SMALL = 0.05
|
||||
fig, axes = plt.subplots(iters, gridspec_kw=dict(
|
||||
top=BIG, right=BIG,
|
||||
bottom=SMALL, left=SMALL,
|
||||
)) # type: Figure, Axes
|
||||
fig.tight_layout()
|
||||
else:
|
||||
axes = range(iters)
|
||||
|
||||
for i, ax in enumerate(axes):
|
||||
if i:
|
||||
print(trigger.get_trigger(4000))
|
||||
ax.plot(trigger._buffer, label=str(i))
|
||||
ax.grid()
|
||||
offset2 = trigger.get_trigger(x)
|
||||
print(offset2)
|
||||
assert offset2 == 24000
|
||||
if plot:
|
||||
ax.plot(trigger._buffer, label=str(i))
|
||||
ax.grid()
|
||||
|
||||
plt.show()
|
||||
if plot:
|
||||
plt.show()
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue