DSPRelated.com
Forums

Sample rate conversion help

Started by KWhat4 August 1, 2007
I am very new to dsp in general and I am attempting to convert 16khz
PCM stream (byte array) to 8khz stream (byte array) in Java.  I have
figured out that I can copy over every other frame from the 16khz
stream to the 8khz one but I get what I think is called dithering?  My
question are the following:

How do I clean up the audio so it sounds close to normal?

Is there a better way todo this insted of copying some ratio of
frames?

Should I really be using PCM or is some other format more effective/
easier/faster?

Are there some example snipits to do this sort of thing?  (Java / C /
Sudo)


Thanks in advance.

KWhat4 wrote:

> I am very new to dsp in general and I am attempting to convert 16khz > PCM stream (byte array) to 8khz stream (byte array) in Java.
I assume your audio is 16 bit PCM. You need to operate on it as such.
> I have > figured out that I can copy over every other frame from the 16khz > stream to the 8khz one
That s effectively zero-order hold resampling. It will not sound good.
> but I get what I think is called dithering?
No, its called aliasing. Dithering is something else. http://en.wikipedia.org/wiki/Aliasing http://en.wikipedia.org/wiki/Dithering
> My > question are the following: > > How do I clean up the audio so it sounds close to normal?
Once you audio has aliasing noise it is not really possible to clean it up again (the eggs cannot be unscrambled). What you need to do is go back to the clean signal and resample it correctly.
> Is there a better way todo this insted of copying some ratio of > frames?
Yes, for your particular case, you need to apply a low pass filter that blocks frequencies higher than 4 kHz and then dropping every second sample will sound just fine. The more general case is much more complicate.
> Are there some example snipits to do this sort of thing? (Java / C / > Sudo)
I am the author of a high quality audio resampler realeased under the terms of the GNU General Public Licence: http://www.mega-nerd.com/SRC/ Commercial use licenses are also available at reasonable rates. HTH, Erik -- ----------------------------------------------------------------- Erik de Castro Lopo ----------------------------------------------------------------- BSD: A psychoactive drug, popular in the 80s, probably developed at UC Berkeley or thereabouts. Similar in many ways to the prescription-only medication called "System V", but infinitely more useful. (Or, at least, more fun.) The full chemical name is "Berkeley Standard Distribution".
On Aug 1, 11:31 am, KWhat4 <heispsycho...@gmail.com> wrote:
> I am very new to dsp in general and I am attempting to convert 16khz > PCM stream (byte array) to 8khz stream (byte array) in Java. I have > figured out that I can copy over every other frame from the 16khz > stream to the 8khz one but I get what I think is called dithering?
Aliasing. Your original 16k sample/sec stream probably contained frequency content from 20 Hz or so to nearly 8 kHz. If so and you didn't do any filtering, then your 8k sample/sec stream will contain not only 0 to 4 kHz sound, but also 4 to 8 kHz sounds folded down in frequency right on top of and mixed up with the 0 to 4 kHz sound. So before you decimate (reduce the sample rate by throwing away samples) you need to low pass filter so that there is very little content at or above half the new sample rate (or you can filter as you decimate in one step).
> My question are the following: > > How do I clean up the audio so it sounds close to normal?
You need to filter before decimating. Your "dithered" sound already has noise mixed in that can't be removed (without reference to the original signal).
> Is there a better way todo this insted of copying some ratio of > frames?
Copying a ratio of frames will work if each channel of the signal has been appropriately low pass filtered beforehand or is during the copy. You have to filter each channel separately, so you may have to decompose and recompose the frames before/after filtering. If you don't care about optimization, then the filtering can be done in only a few dozen lines of code. Here's some untested, quick and dirty code (in Basic !) which might filter one channel, and even interpolate if needed: ---cut here--- rem - QDSS Windowed Sinc ReSampling subroutine in Basic rem rem : x = new sample point location (relative to old indexes) rem (e.g. every other integer for 0.5x decimation) rem : indat = original data array rem : alim = size of data array rem : fmax = low pass filter cutoff frequency rem : fs = sample rate rem : wnwdth = width of windowed sinc used as the low pass filter rem - resamp() returns a filtered new sample point sub resamp(x, indat, alim, fmax, fs, wnwdth) r_g = 2 * fmax / fs : rem Calc gain correction factor r_y = 0 for r_i = -wnwdth/2 to (wnwdth/2)-1 : rem For 1 window width r_j = int(x + r_i) : rem Calc input sample index : rem calculate von Hann Window. Scale and calculate Sinc r_w = 0.5 - 0.5 * cos(2*pi*(0.5 + (r_j - x)/wnwdth)) r_a = 2*pi*(r_j - x)*fmax/fs r_snc = 1 : if (r_a <> 0) then r_snc = sin(r_a)/r_a if (r_j >= 0) and (r_j < alim) then r_y = r_y + r_g * r_w * r_snc * indat(r_j) endif next r_i resamp = r_y : rem Return new filtered sample end sub rem * Note that fmax should be less than half of fs, and less rem than half of new_fs (the reciprocal of the x step size). rem * Filter quality increases with a larger window width. rem The wider the window, the closer fmax can approach half rem of fs or new_fs. rem * Note that several operations inside the FOR loop can be rem precalculated. rem * There are more optimal windows than the von Hann window. rem * Note that if the x step size is rational the same Window rem and Sinc values will be recalculated repeatedly; therefore rem these values can either be cached, or precalculated and rem stored in a table; or interpolated from a smaller rem precalculated table; or computed with a low-order rem polynomial fit to each lobe between zero crossings rem of the windowed sinc. (Performance optimization is rem left as an exercise for the student). rem Ron Nicholson's QDSS ReSampler cookbook recipe rem QDSS = Quick, Dirty, Simple and Short rem Copyright 2007 Ronald H. Nicholson Jr. rem Version 0.1 - 2007-Aug-01 rem No warranties implied. Error checking, optimization, and rem quality assessment of the "results" is left as an exercise rem for the student. rem (consider this code Open Source under a BSD style license) rem IMHO. YMMV. http://www.nicholson.com/rhn/dsp.html