ColinP wrote: ↑Wed Jan 11, 2023 7:28 pm
Hi Chris,
Very nice of you to post this but I'm struggling to understand the working of the main process() method.
Code: Select all
public double process( double value, R_IOversampledProcessor processor )
{
double[] os = new double[m_osFactor];
os[0] = value; // first value is valid, others are zero-stuffed
//////// OVERSAMPLING
for( int i = 0; i < m_osFactor; ++i )
{
os[i] = m_upSampler.process( os[i] );
os[i] = processor.process( m_osFactor * os[i] );
os[i] = m_downSampler.process( os[i] );
}
//////// OVERSAMPLING
return os[0];
}
I'm a little worn out (coping with flooding) so might be missing something blindingly obvious but I don't understand how information flows in the loop. How is os[ 0 ] at the end of the method affected by anything going on in the zero-stuffed parts of the array?
os is an array that keeps track of all oversampled values. initially it is filled with 0s (from initializing). the first index is set to the input
value from the parameter list.
so the array now consists of the actual input and lots of 0 for the zero stuffing. each array element, the actual value and the stuffing 0s, are then put into the upsampler to produce the actual sampling values to feed into the processing function. the array
os keeps track of these values.
after processing the whole array needs to be put through the downsampler one by one. the first array element now holds the actual value. we can discard all other values that resulted from the zero stuffing. these are only needed for the up- and down-sampling filters.
so for 2x oversampling it would look like this
Code: Select all
os[0] = value
os[1] = 0
os[0] = m_upSampler.process( os[0] );
os[0] = processor.process( m_osFactor * os[0] );
os[0] = m_downSampler.process( os[0] );
os[1] = m_upSampler.process( os[1] );
os[1] = processor.process( m_osFactor * os[1] );
os[1] = m_downSampler.process( os[1] );
value = os[0];
so at first os[0] holds the actual value and os[1] is 0. after the upsampling both os[0] and os[1] hold valid samples at the new samplerate that are a result from the interpolation and filtering from the upsampler. these values can now be processed. the downsampler takes these two values and converts them to a single value at the base samplerate. os[1] can now be discarded and os[0] holds the result of the downsampling process.
The zero stuffing is needed for the upsampling and downsampling filters. filters have 'memory'. you are basically tricking the filter into thinking it runs at a higher sample rate. and to accommodate for that you need to feed it more values to get back to the actual frequency. e.g. 20kHz at 48kHz sampling rate are now 40kHz at 96kHz sampling rate. by putting twice the values through you get back to 20kHz. adding 0s reflects the whole spectrum at nyquist. the filter is then removing that part alongside any frequency that would have reflected anyways.
hope this helps!
