iconEuler Examples

Increasing the Sample Rate

I found a blog in the web at which uses Euler to analyze sound,
implementing a very simple code to scale up the rate of a sound
sample.

For a demonstration, I generate a sound with harmonics using a sample
rate of 8820Hz.
>r=8820; ...
>t=soundsec(2,rate=r); ...
>s=sin(t*440)+sin(2t*440)/2+sin(3t*440)/3;
The time ticks t[i] can be generated with soundsec, and the sound with
the matrix language. The sound can be analized very easily using FFT
in Euler.
>analyzesound(s,rate=r); insimg;

Sample Rates of Sound

We can clearly see and hear the frequencies.
>playwave(s,rate=r);
We want to increase the sample rate of 8820Hz to 22050Hz. Obviously,
this requires some interpolation.

First, we use a very simple scheme. Effectively, we repeat the sound
items as many times as is necessary.
>i=round(linspace(1,cols(t),cols(t)*2.75-1),0);
This index vector contains the indices to take the from the original
sample.
>i[1:10], i[-10:-1]
[ 1  1  2  2  2  3  3  4  4  4 ]
[ 17637  17637  17637  17638  17638  17639  17639  17639  17640  17640 ]
>s1=s[i]; r1=r*2.75;
The original sound is smooth.
>plot2d(s[1:100]); insimg;

Sample Rates of Sound

The interpolated sound contains lots of steps.
>plot2d(s1[1:275]); insimg;

Sample Rates of Sound

The analysis looks good, however.
>analyzesound(s1,rate=r1); insimg;

Sample Rates of Sound

But there are many higher frequencies, which are artifacts generated
by the steps.
>analyzesound(s1,rate=r1,fmax=5000); insimg;

Sample Rates of Sound

And in fact, you can hear those artifacts. The sound sounds terrible.
>playwave(s1,rate=r1);
The blog at the address above uses a different, more complicated
scheme.
>function scaleup (s) ...
n=1;
idx=0;
res=zeros(1,cols(s)*2.5);
for i=1 to cols(res)
  idx=idx+93;
  if idx>256 then idx=idx-256; n=n+1; endif;
  res[i]=s[n];
end;
return res
endfunction
>s2=scaleup(s);
The result has even more high frequencies.
>analyzesound(s2,rate=r1,fmax=5000); insimg;

Sample Rates of Sound

And it sounds even worse.
>playwave(s2,rate=r1);
Of course, we need to interpolate the data much better.

In the following, I use a linear interpolation between adjacent data
points. E.g., I set

Sample Rates of Sound

where delta is the time scale of the original sound.

In Euler, this can be done in the following way. First, we need the
indices we would like to take, evenly spaced along the indices of our
sound.
>i=linspace(1,cols(t),cols(t)*2.75-1); i[1:20]
[ 1  1.36362324517  1.72724649034  2.09086973551  2.45449298068
2.81811622585  3.18173947103  3.5453627162  3.90898596137
4.27260920654  4.63623245171  4.99985569688  5.36347894205
5.72710218722  6.09072543239  6.45434867756  6.81797192274
7.18159516791  7.54521841308  7.90884165825 ]
Then we compute integer indices and the weights.
>i1=floor(i); f1=1-(i-i1);
>i2=ceil(i); f2=1-(i2-i);
Finally, we can assemble the new sound.
>s3=f1*s[i1]+f2*s[i2];
It looks very clean now.
>analyzesound(s3,rate=r1,fmax=5000); insimg;

Sample Rates of Sound

And it sound very clean.
>playwave(s3,rate=r1);

Examples Homepage