DSPRelated.com
Forums

Polyphase filter outputs

Started by nikolatesla20 July 14, 2009
Hi,

I am almost a complete newbie when it comes to DSP. I've been studying
various internet articles a lot over the last week but I still have some
questions that I don't understand.

What I'm trying to accomplish is to resample an audio signal to change
it's pitch. I don't care if the length changes, I just want to get pitch
changes. Since some pitch changes may be somewhat small (notes) I need to
upsample (interpolate) and then filter, and then decimate.

I have some java code that works pretty well to do this, along with that I
have a simple FIR filter algorithm in Java, using coefficients that I
worked out using ScopeFIR. 

So, for example, I have a sound file sampled at 22050hz. If I upsample my
sound file by 2 (to reduce it down by one octave), I know I have to apply a
low pass filter to get rid of frequencies that are higher than the new
Nyquist/2. So I had to actually design the filter to run at 44100hz. 

However, I need a way to have a filter that can be used for lots of
different upsample/downsample rates, and of course in some cases the
upsample rate may be high (so I can get  the correct ratio of up  to down),
so the filter ends up having to operate at a very high frequency, on lots
of samples.

Since I'm using zero stuffing, I read that you can save time by using a
polyphase filter. So I've been trying to see how to get that implemented in
my java code.

So right now my questions are the following:

1. I supposedly read that if you use a polyphase filter, you can use the
coefficients that work at the input sample rate, to keep the filter
simpler. Is that true? Would I be able to use the same coef's over all
upsample rates then?

2. In the polyphase filter, you have several "outputs". Do you then add
all these outputs together to get the current sample then? None of the docs
I found actually say that you add them together when you are done doing all
the outputs.


Thanks for your help!

-niko

Here are my basic question


nikolatesla20 wrote:

> 1. I supposedly read that if you use a polyphase filter, you can > use the coefficients that work at the input sample rate, to keep > the filter simpler. Is that true? Would I be able to use the > same coef's over all upsample rates then?
No. Polyphase filtering is a way to arrange the computation to operate at the low rate, but does not bear on the design of coefficients which always targets the high rate. To generate FIR filters on the fly given an arbitrary rate change factor, look into windowed-sinc design. It is suboptimal but quite straightforward to do.
> 2. In the polyphase filter, you have several "outputs". Do you > then add all these outputs together to get the current sample > then? None of the docs I found actually say that you add them > together when you are done doing all the outputs.
When interpolating, you multiplex (interlace) the phase output sequences to build the high-rate sequence. When decimating, a polyphase FIR filter is pointless but you would indeed add the phase outputs in the case of IIR filtering. Martin -- Quidquid latine scriptum est, altum videtur.
nikolatesla20 wrote:
> Hi, > > I am almost a complete newbie when it comes to DSP. I've been studying > various internet articles a lot over the last week but I still have some > questions that I don't understand.
Wow! a whole week and you aren't yet an expert. Are you surprised? :-)
> What I'm trying to accomplish is to resample an audio signal to change > it's pitch. I don't care if the length changes, I just want to get pitch > changes. Since some pitch changes may be somewhat small (notes) I need to > upsample (interpolate) and then filter, and then decimate.
If you don't care about the timing, can you use the original samples at a new rate, just as you would change the speed of a record or tape? Most hardware won't let you adjust the rate in small steps, so you need to do these resampling manipulations, but that's the only reason. More versatile hardware is the simplest if available.
> I have some java code that works pretty well to do this, along with that I > have a simple FIR filter algorithm in Java, using coefficients that I > worked out using ScopeFIR. > > So, for example, I have a sound file sampled at 22050hz. If I upsample my > sound file by 2 (to reduce it down by one octave), I know I have to apply a > low pass filter to get rid of frequencies that are higher than the new > Nyquist/2. So I had to actually design the filter to run at 44100hz.
What is commonly called upsampling by 2 doubles the sample rate without affecting the signal.
> However, I need a way to have a filter that can be used for lots of > different upsample/downsample rates, and of course in some cases the > upsample rate may be high (so I can get the correct ratio of up to down), > so the filter ends up having to operate at a very high frequency, on lots > of samples.
Have you read http://www.dspdimension.com/admin/time-pitch-overview/? There is pitch-shifting code for download on that site.
> Since I'm using zero stuffing, I read that you can save time by using a > polyphase filter. So I've been trying to see how to get that implemented in > my java code. > > So right now my questions are the following: > > 1. I supposedly read that if you use a polyphase filter, you can use the > coefficients that work at the input sample rate, to keep the filter > simpler. Is that true? Would I be able to use the same coef's over all > upsample rates then? > > 2. In the polyphase filter, you have several "outputs". Do you then add > all these outputs together to get the current sample then? None of the docs > I found actually say that you add them together when you are done doing all > the outputs. > > > Thanks for your help! > > -niko > > Here are my basic question > >
-- Engineering is the art of making what you want from things you can get. �����������������������������������������������������������������������
On 14 Jul, 13:58, "nikolatesla20" <nikolatesl...@yahoo.com> wrote:

> What I'm trying to accomplish is to resample an audio signal to change > it's pitch. I don't care if the length changes, I just want to get pitch > changes.
If one reads the stated objective literally, the simplest way to achieve this would be to play the sampled file while specifying a different sampling frequency. If you start from a signal sampled at 10 kHz and play the raw data back at 5 kHz, the effect is that the pitch lowers by 1 octave. And the duration of the signal doubles. I doubt this is what you want, so it seems you might want to specify your objective in somewhat more detail. Rune

>On 14 Jul, 13:58, "nikolatesla20" <nikolatesl...@yahoo.com> wrote: > >> What I'm trying to accomplish is to resample an audio signal to change >> it's pitch. I don't care if the length changes, I just want to get
pitch
>> changes. > >If one reads the stated objective literally, the simplest >way to achieve this would be to play the sampled file while >specifying a different sampling frequency. > >If you start from a signal sampled at 10 kHz and play >the raw data back at 5 kHz, the effect is that the >pitch lowers by 1 octave. And the duration of the >signal doubles. > >I doubt this is what you want, so it seems you might >want to specify your objective in somewhat more detail. > >Rune >
Hi guys, Thanks for the responses. I'll look into that pitch shifting link you gave. What I'm doing is I've built a simple sample driven drum machine for mobile phones (android) and I just want some pitch adjustment for the samples, it doesn't have to be musically correct (as in per-note), but just has to allow room to adjust the sample pitch up/down to your liking. My audio buffer stream plays at 22050hz, so I need to resample the samples to change their pitch. This morning I came up with a solution that seems to work for what I want. What I'm doing now is just always upsampling by 5, then I filter, and then I use a varying downsample rate to get the ratio I want. So Down/Up 2/5 = .4 3/5 = .6 4/5 = .8 5/5 = 1 (no change) 6/5 = 1.2 7/5 = 1.4 8/5 = 1.6 9/5 = 1.8 My filter is set to cut -80db at 10000hz running at 110250 sample rate. (22050 times 5). Since I dont change the upsample rate I can use the same filter. I've tested it now on lots of samples and it seems to work OK and it allows you to change the pitch up/down by almost an octave. -niko
nikolatesla20 wrote:

> This morning I came up with a solution that seems to work for > what I want. What I'm doing now is just always upsampling by 5, > then I filter, and then I use a varying downsample rate to get > the ratio I want.
> My filter is set to cut -80db at 10000hz running at 110250 > sample rate. (22050 times 5). Since I dont change the upsample > rate I can use the same filter.
To avoid any aliasing when the replay rate is faster than the recording rate (pitching up) the filter edge needs to sit below the original Nyquist frequency by the same ratio. Otherwise some treble components will fold back. However, in a music application the aliasing may even be desirable to keep -- it depends on whether you like the sonic character it lends. Martin -- Quidquid latine scriptum est, altum videtur.
>nikolatesla20 wrote: > >> This morning I came up with a solution that seems to work for >> what I want. What I'm doing now is just always upsampling by 5, >> then I filter, and then I use a varying downsample rate to get >> the ratio I want. > >> My filter is set to cut -80db at 10000hz running at 110250 >> sample rate. (22050 times 5). Since I dont change the upsample >> rate I can use the same filter. > >To avoid any aliasing when the replay rate is faster than the >recording rate (pitching up) the filter edge needs to sit below the >original Nyquist frequency by the same ratio. Otherwise some treble >components will fold back. However, in a music application the >aliasing may even be desirable to keep -- it depends on whether you >like the sonic character it lends. > > >Martin > >-- >Quidquid latine scriptum est, altum videtur. >
Hi Martin, You're right, I think I do see some aliasing in the higher notes if I do an FFT spectrum to examine them. It looks like it won't start hitting me until I get to the 7/5 ratio or so. 6/5 would still be (110250 /6) which is 18375, and div that by 2 you get 9187, I think my filter is close enough to roll off the aliasing in that case. So 7/5 and up I will get aliasing, but from my tests I don't know if it's that audible (in any case it probably is such high frequency you may not be able to hear it well). -niko
>nikolatesla20 wrote: > >> 1. I supposedly read that if you use a polyphase filter, you can >> use the coefficients that work at the input sample rate, to keep >> the filter simpler. Is that true? Would I be able to use the >> same coef's over all upsample rates then? > >No. Polyphase filtering is a way to arrange the computation to >operate at the low rate, but does not bear on the design of >coefficients which always targets the high rate. > >To generate FIR filters on the fly given an arbitrary rate change >factor, look into windowed-sinc design. It is suboptimal but quite >straightforward to do. > >> 2. In the polyphase filter, you have several "outputs". Do you >> then add all these outputs together to get the current sample >> then? None of the docs I found actually say that you add them >> together when you are done doing all the outputs. > >When interpolating, you multiplex (interlace) the phase output >sequences to build the high-rate sequence. When decimating, a >polyphase FIR filter is pointless but you would indeed add the phase >outputs in the case of IIR filtering. > > >Martin > >-- >Quidquid latine scriptum est, altum videtur. >
Hi Martin, Could you answer one more question. By "multiplex" the outputs, do you mean that basically the outputs become the values that replace the zero filling in the new buffer? Thanks! -niko
nikolatesla20 wrote:

>>When interpolating, you multiplex (interlace) the phase output >>sequences to build the high-rate sequence. When decimating, a >>polyphase FIR filter is pointless but you would indeed add the >>phase outputs in the case of IIR filtering.
> Could you answer one more question. By "multiplex" the outputs, > do you mean that basically the outputs become the values that > replace the zero filling in the new buffer?
Yes, if I interpret your formulation right. Each input value is turned into a block of successive result values that is just the list of phase outputs. Martin -- Quidquid latine scriptum est, altum videtur.
>nikolatesla20 wrote: > >>>When interpolating, you multiplex (interlace) the phase output >>>sequences to build the high-rate sequence. When decimating, a >>>polyphase FIR filter is pointless but you would indeed add the >>>phase outputs in the case of IIR filtering. > >> Could you answer one more question. By "multiplex" the outputs, >> do you mean that basically the outputs become the values that >> replace the zero filling in the new buffer? > >Yes, if I interpret your formulation right. Each input value is >turned into a block of successive result values that is just the list >of phase outputs. > > >Martin > >-- >Quidquid latine scriptum est, altum videtur. >
Thanks for your answer Martin. ACK! I do have to say though that the polyphase is extremely confusing. I haven't found anything on the internet that explains them well. For example, I found the articles at dspguru where he shows an "example" polyphase that has 16 taps and interpolation ration of 3. Then he shows a table of how the values are calculated. But the table is confusing! They way he shows it seems like the data is being "shifted" into the delay line..which I could understand, but then he shows each equation for each "poly" channel.. Basically I trying to do this in code. I can just copy my entire buffer and step through it for now to avoid looping buffers until I get it working. My interpolation ratio is 5. But do I step ONE sample at a time or 5 samples at a time? And if I step 1 sample at a time, then I'm assuming I will have 5 polyphase filters, so then do I add the result of all of them and put that in as the new calculated sample, or do the 5 outputs create the new values for position 1-5? Ugh. I just need a nice clear step by step explanation, not more equations...I get how the math makes it faster, but I want to understand how do I implement the darn thing! -niko