Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: upsampling PCM (Read 6666 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

upsampling PCM

I am looking for an open source library or algorithm to upsampling pcm file from 8k to 16k(or 32k is better).
Since system limitation, integer (fixed point) is better than floating-point. And, speed is more important than quality.
I had try resample(http://www-ccrma.stanford.edu/~jos/), but it seem a little bit complex.

Additionally, how to convert 8 bitspersample data to 16 bitspersample?

upsampling PCM

Reply #1
I am looking for an open source library or algorithm to upsampling pcm file from 8k to 16k(or 32k is better).
Since system limitation, integer (fixed point) is better than floating-point. And, speed is more important than quality.

libsamplerate is a starting point. It does need floating point though. If it's all about performance, then coding a simple zeroeth order hold or linear interpolation SRC program with fixed point would be trivial. I can describe the algorithms required if you need them.

Additionally, how to convert 8 bitspersample data to 16 bitspersample?
The fastest way would be simple sign extension. It's likely that your hardware (it sounds like you are targetting an embedded system) will have an instruction to provide sign extension from 8 to 16 (ARMv5, x86 and others have such instructions). If you are writing in C, then a good compiler should generate these instructions from an explicit or implicit cast.

upsampling PCM

Reply #2
Additionally, how to convert 8 bitspersample data to 16 bitspersample?


8bit pcm (can) be unsigned so i would do something as

Code: [Select]
  upsampled = ((signed short int)(sample)-128) << 8



edit: 8-bit pcm isn't always unsigned 

upsampling PCM

Reply #3
libsamplerate is a starting point. It does need floating point though. If it's all about performance, then coding a simple zeroeth order hold or linear interpolation SRC program with fixed point would be trivial. I can describe the algorithms required if you need them.


Yes, I need. Thank you

upsampling PCM

Reply #4
Ok, the zeroth order hold algorithm is very simple. In your target pulse train (Y[n]) you set Y[n] to the value of X[n] which is most recent. For upsampling from 8k to 16k, your new sample train will look like Y = X[0] X[0] X[1] X[1] X[2] X[2] and so on. Upsampling from 8 to 32k, your result train will look like this: Y = X[0] X[0] X[0] X[0] X[1] X[1] X[1] X[1] and so on. This algorithm is very poor from a quality perspective, but can be implemented almost for free on low-powered embedded systems (you just pass the DAC the same value for a few consecutive bits).

A slightly (but only slightly) better (from a quality perspective) and not much slower algorithm would be a linear interpolation. For example - Y = X[0] (0.5*X[0]+0.5*X[1]) X[1] (0.5*X[1]+0.5*X[2]). As I am sure you can see, you can implement this with an average of one add and two shifts every second sample - or half and add and one shift a sample. Unless your hardware is very, very slow then this won't prove taxing at all.

The quality of these algorithms is very poor. Their only advantage is high efficiency and ease of implementation. If you have any CPU power to spare, I would encourage you to use a better algorithm. Such algorithms have been discussed here in the past, or you can look at a good textbook.

upsampling PCM

Reply #5
If you go for speed and are not satisfied with the quality of linear interpolation for 8->16 kHz you could also try this:

... X[3] f(3) X[4] f(4) X[5] f(5) ...

where f(index) =
+ a * (X[index-0]+X[index+1])
+ b * (X[index-1]+X[index+2])
+ c * (X[index-2]+X[index+3])
+ ...

linear interpolation for 2X oversampling is a special case of this with a=1/2, b=c=0
(corresponds to half-band LPF with 2 zeros at -1)

The next best thing would be to use
a = 9/16
b = -1/16, c=0
(corresponds to half-band LPF with 4 zeros at -1 plus two other zeros)

If still not good enough try
a = 150/256
b = -25/256
c = 3/256
(corresponds to half-band LPF with 6 zeros at -1 plus four other zeros)

For 4X oversampling you could repeat this step. If you do, make the first stage at least as good as the second because the quality of the first stage is more important than the 2nd for oversampling. For example: Use the three-coefficient interpolation for the first stage (1X->2X) and the two-coefficient interpolation for the 2nd stage (2X->4X). That should be a good quality/speed trade-off.

An implementation may look like this:
itpl = (150*(X+X[i+1]) - 25*(X[i-1]+X[i+2]) + 3*(X[i-2]+X[i+3]) + 128) >> 8;


 

upsampling PCM

Reply #7
It doesn't really matter, does it?

(x+128)>>8  maps -128..127 to 0 and is exactly the same as round(x/256.0)
(x+127)>>8  maps -127..128 to 0 which is more like round((x-1)/256.0)