Audio resampling

Status
Not open for further replies.

WMXZ

Well-known member
I face the following problem
I wanted to do some audio processing on teensy with sampling frequencies higher than 44.1 kHz.
OK, this is easy, but I wanted to use the usb-audio to listen to the acquired sound in real time.
First thought: modify usb-audio for other than 44.1 kHz, but this would interfere with teensyduino upgrades.
Second thought: convert on-teensy audio to 44.1 kHz and use standard usb-audio.

This is what I now follow
For this I need a resampling scheme that is somewhat efficient.
All my frequencies are above 44.1kHz so I need a decimation/interpolation scheme.

So I played with matlab and come up with
Code:
% original signal
fo=1000;
fs1=375000;
i1=(0:fs1)';
t1=i1/fs1;
s1=sin(2*pi*fo*t1);

% output sampling rate
fs2=44100;
i2=(1:45)';
t2=i2/fs2;

% 'ideal' downsampling
s2=interp1(t1,s1,t2);

% sample-based resampling
% scale both sampling frequencies to smallest integer (to be done once)
jfs1=fs1; jfs2=fs2;
while((mod(jfs1,1)==0) && (mod(jfs2,1)==0)), jfs1 = jfs1/10; jfs2=jfs2/10; end  
jfs1=jfs1*10; 
jfs2=jfs2*10; 

% interpolation using integer arithmetic 
i3=1+floor((i2*jfs1+jfs2)/jfs2);
isc=mod(jfs1,jfs2);
s3=s1(i3-1)+mod(i2*isc,jfs2).*(s1(i3)-s1(i3-1))/jfs2;

%
figure(1)
plot(t1,s1,'.-', t2,s2,'*-',t2,s3,'ro-')
xlim([0 0.001])
where the interpolation is obtained by using in integer division and modulo operations and compared to Matlab's interp1 function
The result is shown in this figure
resample.jpg

I'm confident that this method can easily be implemented in 'C'.
If this is well know method, OK, I reinvented the wheel (which is part of the fun)
 
Last edited:
Hi

The ARM DSP library has a very good linear interpolation function that is pretty efficient, see here
https://www.keil.com/pack/doc/CMSIS/DSP/html/group__LinearInterpolate.html
Or
https://www.keil.com/pack/doc/CMSIS/DSP/html/group__LinearInterpExample.html
However, linear interpolation introduces some audible artefacts.

For higher quality and for resampling by a ratio or factor, the upsampling/decimation+ FIR method should give a much better quality at the expense of an higher computationnal cost.
See:
https://www.keil.com/pack/doc/CMSIS/DSP/html/group__FIR__decimate.html

And

https://www.keil.com/pack/doc/CMSIS/DSP/html/group__FIR__Interpolate.html

You will also find several interpolation types and examples used in my distortion modelling codes:

https://github.com/jcugnoni/TeensyDist/blob/master/Library/TeensyDistLib/

For examples, look at the TD_waveshaper.cpp & .h for integer interpolation and resampling as well as TD_multistagedist.cpp & .h for floating point
 
For higher quality and for resampling by a ratio or factor, the upsampling/decimation+ FIR method should give a much better quality at the expense of an higher computationnal cost.

I have no problem replacing Newton interpolation by FIR interpolation. The computational cost is only higher.

Note: this approach is to provide a easy method to monitor Audio processing that occur at higher sampling frequencies (192 kHz 375 kHz).
required 22 kHz anti-aliasing is done and ultrasonic sound may be base-band shifted, etc. etc. in other parts of a functioning program.

To address the critic on 1rst order Newton, I added a second-order to interpolation scheme.

To be more practical I wrote a script that generates a sinewave with 375 kHz sampling frequency and transfers it to PC using 44.1 kHz USB Audio.

general idea:
Audio stream is controlled by PIT (class AudioTrigger)
test class generates 375 kHz signal, which is placed on a circular buffer.
an Audio Interface fetches data (here 375 kHz sampled sine wave) from audio buffer and transfers them into Audio scheme to be passed via USB to PC

Obviously, the non-Audio-Lib processing could be done in floating point (on T3.5/3.6) but the exercise was integer only arithmetic (at least for the AudioInterface class)


the sketch directory of a complete test program is in
View attachment Audio2USB.zip

the resulting PSD is
SinePSD.jpg

Some issues:
Assumed that I send only one channel (left) and have second channel (right) free. But PC gives same signal on both channels. Need to investigate
there are small modulations visible in the spectrogram, maybe due to non-correct signal generation. Need to understand origin of these modulations (or phase jumps).

Edit: corrected some indexing
View attachment Audio2USB2.zip
generated cleaner PSD
SinePSD2.jpg
 
Last edited:
Hello,
I just found this post today while playing with sox under Linux (Raspberry Pi)
I tried realtime upsampling (with Squeezelite) with Raspberry Pi (two cores dedicated to the upsampling) but it faills to do it in realtime, CPU 100%

I wonder if it is possible to upsample on the fly 44K1Hz I2S audio to 188K4Hz I2S or even 356K8Hz I2S with Teensy 3.5 ?

Are there any usable "bloc" to test different upsampling scheme (like with sox minimal phase, etc) ?

Example:
Would it be possible to use this library (https://github.com/avaneev/r8brain-free-src) to perform on the fly I2S upsampling ?

Thank you for your answers,
Jean
 
Last edited:
Status
Not open for further replies.
Back
Top