convolve_filter<T>::convolve_filter(const univector<T>& data, size_t block_size) : fft(2 * next_poweroftwo(block_size)), size(data.size()), block_size(next_poweroftwo(block_size)), temp(fft.temp_size), segments((data.size() + next_poweroftwo(block_size) - 1) / next_poweroftwo(block_size)), ir_segments((data.size() + next_poweroftwo(block_size) - 1) / next_poweroftwo(block_size)), input_position(0), position(0) { set_data(data); }
size_t process(univector<T, Tag>& output, univector_ref<const T> input) { const itype required_input_size = input_size_for_output(output.size()); const itype input_size = input.size(); for (size_t i = 0; i < output.size(); i++) { const itype intermediate_index = output_position_to_intermediate(static_cast<itype>(i) + output_position); const itype intermediate_start = intermediate_index - taps + 1; const std::lldiv_t input_pos = floor_div(intermediate_start + interpolation_factor - 1, interpolation_factor); const itype input_start = input_pos.quot; // first input sample const itype tap_start = interpolation_factor - 1 - input_pos.rem; const univector_ref<T> tap_ptr = filter.slice(static_cast<size_t>(tap_start * depth)); if (input_start >= input_position + input_size) { output[i] = T(0); } else if (input_start >= input_position) { output[i] = dotproduct(input.slice(input_start - input_position, depth), tap_ptr); } else { const itype prev_count = input_position - input_start; output[i] = dotproduct(delay.slice(size_t(depth - prev_count)), tap_ptr) + dotproduct(input.slice(0, size_t(depth - prev_count)), tap_ptr.slice(size_t(prev_count), size_t(depth - prev_count))); } } if (required_input_size >= depth) { delay.slice(0, delay.size()) = padded(input.slice(size_t(required_input_size - depth))); } else { delay.truncate(size_t(depth - required_input_size)) = delay.slice(size_t(required_input_size)); delay.slice(size_t(depth - required_input_size)) = padded(input); } input_position += required_input_size; output_position += output.size(); return required_input_size; }
void convolve_filter<T>::set_data(const univector<T>& data) { univector<T> input(fft.size); const T ifftsize = reciprocal(T(fft.size)); for (size_t i = 0; i < ir_segments.size(); i++) { segments[i].resize(block_size); ir_segments[i].resize(block_size, 0); input = padded(data.slice(i * block_size, block_size)); fft.execute(ir_segments[i], input, temp, dft_pack_format::Perm); process(ir_segments[i], ir_segments[i] * ifftsize); } saved_input.resize(block_size, 0); scratch.resize(block_size * 2); premul.resize(block_size, 0); cscratch.resize(block_size); overlap.resize(block_size, 0); }
short_fir_state(const univector<const T, N>& taps) : taps(widen<tapcount>(read<N>(taps.data()), T(0))), delayline(0) { }
inline std::string repr(const univector<T, Tag>& v) { return repr(v.data(), v.size()); }