Vital
Loading...
Searching...
No Matches
fir_halfband_decimator.cpp
Go to the documentation of this file.
2#include "poly_utils.h"
3
4namespace vital {
5
13 static const mono_float coefficients[kNumTaps] = {
14 0.000088228877315364f, 0.000487010018128278f, 0.000852264975437944f, -0.001283563593466774f,
15 -0.010130591831925894f, -0.025688727779244691f, -0.036346596505004387f, -0.024088355516718698f,
16 0.012246773417129486f, 0.040021434054637831f, 0.017771298164062477f, -0.046866403416502632f,
17 -0.075597513455990611f, 0.013331126342402619f, 0.202889888191404910f, 0.362615173769444080f,
18 0.362615173769444080f, 0.202889888191404910f, 0.013331126342402619f, -0.075597513455990611f,
19 -0.046866403416502632f, 0.017771298164062477f, 0.040021434054637831f, 0.012246773417129486f,
20 -0.024088355516718698f, -0.036346596505004387f, -0.025688727779244691f, -0.010130591831925894f,
21 -0.001283563593466774f, 0.000852264975437944f, 0.000487010018128278f, 0.000088228877315364f,
22 };
23
24 // Pack every pair of coefficients into taps_
25 for (int i = 0; i < kNumTaps / 2; ++i)
26 taps_[i] = poly_float(coefficients[2 * i], coefficients[2 * i + 1]);
27
29 }
30
38 void FirHalfbandDecimator::saveMemory(int num_samples) {
39 int input_buffer_size = 2 * num_samples;
41
42 // Compute where in the input buffer we should start saving
43 int start_audio_index = input_buffer_size - kNumTaps + 2;
44 for (int i = 0; i < kNumTaps / 2 - 1; ++i) {
45 int audio_index = start_audio_index + 2 * i;
46 // Consolidate two channels/samples at a time for poly_float
47 memory_[i] = utils::consolidateAudio(audio[audio_index], audio[audio_index + 1]);
48 }
49 }
50
58 void FirHalfbandDecimator::process(int num_samples) {
59 const poly_float* audio = input(kAudio)->source->buffer;
60 int output_buffer_size = num_samples;
61
62 // Basic checks to ensure buffer sizes are valid
63 VITAL_ASSERT(output_buffer_size > kNumTaps / 2);
64 VITAL_ASSERT(input(kAudio)->source->buffer_size >= 2 * output_buffer_size);
65
66 poly_float* audio_out = output()->buffer;
67
68 // First, use memory_ from the previous block to fill the early samples
69 for (int memory_start = 0; memory_start < kNumTaps / 2 - 1; ++memory_start) {
70 poly_float sum = 0.0f;
71
72 // Use stored memory first
73 int tap_index = 0;
74 int num_memory = kNumTaps / 2 - memory_start - 1;
75 for (; tap_index < num_memory; ++tap_index) {
76 sum = utils::mulAdd(sum, memory_[tap_index + memory_start], taps_[tap_index]);
77 }
78
79 // Then move on to the current block's audio
80 int audio_index = 0;
81 for (; tap_index < kNumTaps / 2; ++tap_index) {
82 // Consolidate two adjacent samples into a poly_float
83 poly_float consolidated = utils::consolidateAudio(audio[audio_index], audio[audio_index + 1]);
84 sum = utils::mulAdd(sum, consolidated, taps_[tap_index]);
85 audio_index += 2;
86 }
87
88 // Write out a decimated sample (sum both lanes)
89 audio_out[memory_start] = utils::sumSplitAudio(sum);
90 }
91
92 // Process the rest of the block
93 int out_index = kNumTaps / 2 - 1;
94 int audio_start = 0;
95 for (; out_index < output_buffer_size; ++out_index) {
96 poly_float sum = 0.0f;
97 int audio_index = audio_start;
98
99 // Sum over all taps for each output sample
100 for (int tap_index = 0; tap_index < kNumTaps / 2; ++tap_index) {
101 poly_float consolidated = utils::consolidateAudio(audio[audio_index], audio[audio_index + 1]);
102 sum = utils::mulAdd(sum, consolidated, taps_[tap_index]);
103 audio_index += 2;
104 }
105 audio_start += 2;
106
107 audio_out[out_index] = utils::sumSplitAudio(sum);
108 }
109
110 // Save the end of this block to memory for seamless continuity next time
111 saveMemory(num_samples);
112 }
113
120 void FirHalfbandDecimator::reset(poly_mask reset_mask) {
121 for (int i = 0; i < kNumTaps / 2 - 1; ++i)
122 memory_[i] = 0.0f;
123 }
124
125} // namespace vital
FirHalfbandDecimator()
Constructs a FirHalfbandDecimator and initializes taps.
Definition fir_halfband_decimator.cpp:12
@ kAudio
The main audio input.
Definition fir_halfband_decimator.h:27
virtual void process(int num_samples) override
Processes the input audio by decimating it, producing half the number of output samples.
Definition fir_halfband_decimator.cpp:58
static constexpr int kNumTaps
Number of FIR taps in the filter.
Definition fir_halfband_decimator.h:20
void saveMemory(int num_samples)
Saves the last few samples of audio to memory, preparing for the next processing block.
Definition fir_halfband_decimator.cpp:38
Base class for all signal-processing units in Vital.
Definition processor.h:212
force_inline Input * input(unsigned int index=0) const
Retrieves the Input pointer at a given index.
Definition processor.h:587
force_inline Output * output(unsigned int index=0) const
Retrieves the Output pointer at a given index.
Definition processor.h:616
#define VITAL_ASSERT(x)
Definition common.h:11
const poly_mask kFullMask
A mask covering all lanes of a poly_float vector.
Definition synth_constants.h:257
force_inline poly_float consolidateAudio(poly_float one, poly_float two)
Interleaves two stereo poly_floats into a single vector with left channels first, then right channels...
Definition poly_utils.h:491
force_inline poly_float mulAdd(poly_float a, poly_float b, poly_float c)
Performs a fused multiply-add on SIMD data: (a * b) + c.
Definition poly_utils.h:61
force_inline poly_float sumSplitAudio(poly_float sum)
Adds two stereo lanes for each voice, returning a combined mono result in each lane.
Definition poly_utils.h:517
Contains classes and functions used within the Vital synthesizer framework.
float mono_float
Definition common.h:33
const Output * source
The output from which this input reads samples.
Definition processor.h:134
poly_float * buffer
Pointer to the output buffer.
Definition processor.h:110
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
Represents a vector of integer values using SIMD instructions.
Definition poly_values.h:56