I am trying to resample a signal (sound sample) from one sampling rate, to a higher sampling rate. Unfortunately it needs some kind of filter, as some 'aliasing' appears to occur, and I'm not familiar with filters. Here is what I came up with:
int i, j, a, b, z;
a = 44100;
b = 8363;
// upsample by a
for(i = z = 0; i < samplen; i++)
for(j = 0; j < a; j++)
cbuf[z++] = sampdata[i];
// some filter goes here???
// downsample by b
for(j = i = 0; i < z; i += b)
buf[j++] = cbuf[i];
The new sample is very similar to the original, but it has some kind of noise. Can you please te开发者_如何学Goll me what filter I need to add, and preferably some code related to that filter?
Original sound: http://www.mediafire.com/?9gnga1in52d6t4x Resampled sound: http://www.mediafire.com/?x34h7ggk8n9k8z1
Don't use linear interpolation unless both sample rates (source and destination) are well above the highest frequency in your data. It's a very poor low-pass filter.
What you want is an interpolating low pass filter with a stop-band starting below half the lower of the two sample rates you are dealing with. Common methods of implementing this are upsampling/downsampling using IIR filters, and using poly-phase FIR filters. A windowed Sinc interpolator also works well for this if you don't need real-time performance, and don't want to upsample/downsample. Here's a Windowed Sinc interpolating low-pass filter in Basic, that should be trivial to convert into C.
If you want to use IIR filtering, here's the canonical Cookbook for biquad IIR filters.
If you want the best explanation of audio resampling theory, here's Stanford CCRMA's Resampling page.
Have you considered using a specialised library for this, such as libsamplerate?
It is quite portable and it is developed by people who know how to do things like this correctly. Even if you do not use it directly, you might find the algorithms it implements quite interesting.
A few comments, although I'm only guessing at your actual intent:
- You are up-sampling at a rate 44100 times the original sample rate. For example, if your input was at 10kHz your intermediate
cbuf[]
would be at 441MHz which is a tad high for most audio analysis. Assuming you wantcbuf[]
to be at 44100Hz then you only need to create44100/OrigSampleRate
of samples incbuf[]
per sample insampdata[]
. - You are incrementing
z
twice in the up-sampling loop. This results in all odd elements ofcbuf[]
to have their original values. I believe this ultimately results in the finalbuf[]
having invalid odd elements which may be the source of your noise. There is also a potential buffer overflow in cbuf if you didn't create it with at least twice the required number of elements. - As mentioned by Steve a linear interpolation is generally the simplest that creates a good result when up-sampling. More complicated up-sampling can be done if desired (polynomials, splines, etc...). Similarly, when down-sampling you may wish to average samples instead of just truncating.
Best resampling code I ever come across: http://shibatch.sourceforge.net/
Take the source, and try to learn something from it. It is in nasty condition, but results of that resampler are far above everything else.
Use FFMpeg and avcodec directly. Here's a good example showing how to do this:
http://tdistler.com/projects/audio-resampling-with-ffmpeg
Before you resample to a lower sample rate you MUST low pass filter the original less than 1/2 times the sample rate or you will introduce alizing artifacts. The spectrum will fold back upon itself for frequencies more than 1/2 the sample rate. So if you want to resample to 11025 from 44100 you must filter the 44100 lowpassa at 1/2 of 11025 or 5500 Hz since faithfulness of reproduction decreases with lower bandwidths its best to do this with max amplitude like -10Db of amplitude. For 16 bits signed the value is like 10^(-10/20)*2^(16-1) or 10362 +/- for max amplitude. The exact algorithms might be found online since there should be no intellectual rights for these old and basic ideas. After doing all calculations with no rounding double precision floating point then you round the results to their proper integer values and interpolate on the time scale exactly where the one set intercepts the other. It requires quite an imagination and memory and previous experience which then puts you in the realm of the mathematician physics programmer. :-O :-)
Linear interpolation works quite well here. The issues is with the author's code, it's not linear interpolation - it's just taking the nearest value without any interpolation at all.
Here is an example of linear interpolation with source sample rate = 5 and destination sample rate = 6
src val: 5 10 5 0 5 (this is our audio data, 5 samples)
src idx: 0 1 2 3 4 (source positions for 5 samples)
dst idx: 0 1 2 3 4 5 (destination positions for 6 samples)
dst val: ? ? ? ? ? ?
At first let's calculate scale factor:
scaleCF = srcSampleRate / dstSampleRate = 0.83333334
Let's look at dst[2] For dst index 2 we need to take part from src[1] and part from src[2] Let's find nearest source indices and their contribution coeffitients:
idxD = (double)idx * cf; = 0.833333334 * 2 = 1.6666668
a = (int)idxD = (int)(1.6666668) = 1
b = a + 1 = 2
bCF = idxD - a = 1.6666668 - 1 = 0.6666668
aCF = 1.0 - bCF = 1.0 - 0.6666668 = 0.3333332
res = (float)(aCF * Data[a] + bCF * Data[b])
= 0.3333332 * 10 + 0.6666668 * 5 = 6.6666666
So our destination value at position 2 will be 6.6666666 Algorithm can be used for downsampling / upsampling. Probably not the most efficient solution and not the most accurate, still easy to implement and works pretty good.
精彩评论