def cosine_flat(n: int, diameter: int, falloff: int) -> np.ndarray: cosine = windows.hann(falloff * 2) # assert cosine.dtype == FLOAT left, right = cosine[:falloff], cosine[falloff:] window = np.concatenate([left, np.ones(diameter, dtype=FLOAT), right]) padded = midpad(window, n) # assert padded.dtype == FLOAT return padded
def __init__(self, *args, **kwargs): PostTrigger.__init__(self, *args, **kwargs) self._buffer_nsamp = self._tsamp # Precompute data window... TODO Hann, or extract fancy dynamic-width from CorrelationTrigger? self._data_window = windows.hann(self._buffer_nsamp) assert self._data_window.dtype == FLOAT # Precompute edge correlation buffer self._windowed_step = calc_step(self._tsamp, self.cfg.strength, 1 / 3) # Precompute normalized _cost_norm function N = self._buffer_nsamp corr_len = 2 * N - 1 self._cost_norm = (np.arange(corr_len, dtype=FLOAT) - N)**2
def _calc_data_taper(self) -> np.ndarray: """ Input data window. Zeroes out all data older than 1 frame old. See https://github.com/jimbo1qaz/corrscope/wiki/Correlation-Trigger """ N = self._buffer_nsamp halfN = N // 2 # - Create a cosine taper of `width` <= 1 frame # - Right-pad(value=1, len=1 frame) # - Place in left half of N-sample buffer. # To avoid cutting off data, use a narrow transition zone (invariant to stride). # _real_samp_frame (unit=subsample) == stride * frame. transition_nsamp = round(self._real_samp_frame * self.cfg.lag_prevention) tsamp_frame = self._tsamp_frame # Left half of a Hann cosine taper # Width (type=subsample) = min(stride*frame * lag_prevention, 1 frame) width = min(transition_nsamp, tsamp_frame) taper = windows.hann(width * 2)[:width] # Right-pad=1 taper to 1 frame long [t-1f, t] if width < tsamp_frame: taper = np.pad(taper, (0, tsamp_frame - width), "constant", constant_values=1) assert len(taper) == tsamp_frame # Left-pad=0 taper to left `halfN` of data_taper [t-halfN, t] taper = leftpad(taper, halfN) # Generate left half-taper to prevent correlating with 1-frame-old data. # Right-pad=1 taper to [t-halfN, t-halfN+N] # TODO why not extract a right-pad function? data_taper = np.ones(N, dtype=FLOAT) data_taper[:halfN] = np.minimum(data_taper[:halfN], taper) return data_taper
def _calc_lag_prevention(self) -> np.ndarray: """ Returns input-data window, which zeroes out all data older than 1-ish frame old. See https://github.com/jimbo1qaz/corrscope/wiki/Correlation-Trigger """ N = self._buffer_nsamp halfN = N // 2 # - Create a cosine taper of `width` <= 1 frame # - Right-pad(value=1, len=1 frame) # - Place in left half of N-sample buffer. # To avoid cutting off data, use a narrow transition zone (invariant to stride). lag_prevention = self.cfg.lag_prevention tsamp_frame = self._tsamp_frame transition_nsamp = round(tsamp_frame * lag_prevention.transition_frames) # Left half of a Hann cosine taper # Width (type=subsample) = min(frame * lag_prevention, 1 frame) assert transition_nsamp <= tsamp_frame width = transition_nsamp taper = windows.hann(width * 2)[:width] # Right-pad=1 taper to lag_prevention.max_frames long [t-#*f, t] taper = rightpad(taper, iround(tsamp_frame * lag_prevention.max_frames)) # Left-pad=0 taper to left `halfN` of data_taper [t-halfN, t] taper = leftpad(taper, halfN) # Generate left half-taper to prevent correlating with 1-frame-old data. # Right-pad=1 taper to [t-halfN, t-halfN+N] # TODO switch to rightpad()? Does it return FLOAT or not? data_taper = np.ones(N, dtype=FLOAT) data_taper[:halfN] = np.minimum(data_taper[:halfN], taper) return data_taper