1

Some information: I am using a rpi2b with a cirrus logic audio card and have worked out the kernel changes to get the sound card going, I can output without problems, I can record from line in without problems (I am using pyAudio).

Now I only want to filter the signal and have found a lot of functions in the scipy library...

First thing to mention I can only use 2 channels (stereo) input the soundcard seems to doesnt allow 1 channel and I dont have a source to stream mono (iPhone, simple USB player everyone has only stereo)....

The filter line (specifications) is just an example I think it will be an other filter if it works :D

So before the code begins a little to explain. When using stereo input the samples appear to be interleaved so you get on the one channel a sample on the other... I thought this thread was helpful: Convert multi-channel PyAudio into NumPy array

Thats why I also tried to decode my stream into an array, filter and then code it again into a stream for output. If I neglect the interleaving fact I get weird noises thats why I think I should take care of it :)

Now comes the part where I fail: lFilter doesnt want to work! If I just use my unprocessed input_data it says the axis is out of range (I tried -1,0,1,2) dont know :/ and when using my reshaped etc. data I get:

return sigtools._linear_filter(b, a, x, axis, zi)
ValueError: object of too small depth for desired array

Can someone please explain why this is happening? :D Never used signals thats why I am unexperienced but I cant understand why the unprocessed data has axis problems and even though it wouldnt bother because I need the reshaped data like in the linked thread...

WIDTH = 2
CHANNELS = 2
RATE = 44100
p = pyaudio.PyAudio()
[b,a] = signal.iirfilter(2,[50,200],rs=60,btype='band',analog=True,ftype='cheby2')
full_data = np.array([])


def callback(in_data, frame_count, time_info, status):
    global b,a,full_data
    full_data = decode (in_data, 2)
    audio_data = signal.lfilter(b,a, full_data)
    print (audio_data)
    stream_data = encode(audio_data)
    return (stream_data, pyaudio.paContinue)

I skipped the stream open part and the decode and encode since the last ones are right now exactly the same as in the thread and the first one works thats why I just posted these parts. If needed I can also provide the others.

Any help is highly appreciated!

  • Sanj3k

This is an example of what the data looks like, at first its a 1d np array and after the reshape etc ist 2d because of the stereo....

What does lFilter need? Since I have axis errors and with 2d its to small....

screenshot from the terminal

Edit: Btw here is the documentation from scipy library for the lfilter function and it says:

x : array_like
An N-dimensional input array.

http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lfilter.html

Community
  • 1
  • 1
sanj3k
  • 11
  • 6
  • You never know correct `time` if you have more than one `clock` ! – dsgdfg Sep 04 '16 at 18:11
  • it says "ValueError: object of too small depth for desired array", not "axis is out of range". – endolith Sep 04 '16 at 18:18
  • @endolith it says axis is out of range if I just use the in_data as a parameter. But I found now the reason why I get the error ValueError! Look at this: [link](http://i.imgur.com/a2kMY3w.png) My zi is 1d and the reshaped data is 2d! There are only 2 if paths with this valueerror. 1. path if b and a dims arent 1 and the 2. path what i described! So! How do we deal with 2d stereo and 1d zi? – sanj3k Sep 04 '16 at 19:11
  • @dsgdfg Could you explain it only a little further? Import time lib will be enough? As said I am relatively unexperienced and this kind of project is the first for me :) – sanj3k Sep 04 '16 at 19:14
  • Your initial conditions should be 2D also. If they aren't, you get `object of too small depth for desired array`. It might be easier to understand if you separate the two channels first and filter each separately. The initial conditions for global `zi` should just be `zeros((4, 2))`. – endolith Sep 04 '16 at 20:54
  • @endolith This is my progress so far: [valueerror](http://i.imgur.com/gFyUwke.png) and the code: [callback right now](http://i.imgur.com/C0qBa7A.png) Right now I just want to filter ch1 and at least now I could try out the decode and encode part and this works! I also printed the dim of ch and zi dont know how I get the error.... Please help xD – sanj3k Sep 05 '16 at 10:16
  • Hmm, maybe it needs to be 1D arrays in that case? `zeros(max(len(a), len(b)) - 1)` and `ch1 = full_data[:, 0]`? – endolith Sep 05 '16 at 14:40
  • @endolith I get the same zi error even when its 1d... Seems like I have a perfomance problem! When playing back an unfiltered stream (without de- and encoding) there is a few percent cpu usage. Playing back with the de- and encode and leaving it unfiltered brings a usage of more than 50% and when adding lfilter (without zi since I dont get it to work ^^) brings it above 70% and then I get input values with only zeros and no output... – sanj3k Sep 06 '16 at 14:09
  • @sanj3k What format is the data from your sound card? – endolith Sep 06 '16 at 14:23
  • @endolith we did it! So the mistake was in the stream open format! Funny fact (!) right now we dont use zi and we dont have problems at all.Now we have the correct values (paFloat32) and we did it to make it mono :D to get better perfomance. I also got a rpi3b for more cpu power. We will stick to mono first because we need a high order of the filter since our magnitude response looks terrible :D 20db difference but it seems like the build of the speaker is not good enough an other guy havent closen the back at all (where the cables are) also the speaker is not glued properly everywhere etc. – sanj3k Sep 06 '16 at 21:16
  • @endolith Okay new situation! :) On the rpi3b it seems to dont work but with the pi2b it works. We measured the magnitude response with an audio analyzer at my university. Right now the only problem is we get after propably 5 seconds "alsa: underrun occured". I tried to google this error with raspberry pi and couldnt find anything helpful. Do you know how this error is produced and how to get rid of it? – sanj3k Sep 12 '16 at 13:18
  • @sanj3k Can you ask a new question about it? – endolith Sep 12 '16 at 17:50

1 Answers1

0

For one thing, you need to keep the final conditions from one chunk and feed it as initial conditions to the next chunk. Otherwise the filter assumes rest at the start of each chunk, which will result in glitches at each chunk.

global zi
audio_data, zi = signal.lfilter(b, a, full_data, zi=zi)`

So this call will update zi and then on the next cycle it will use it as the input to lfilter, which will update it, etc. As the docs say:

zi : array_like, optional
    Initial conditions for the filter delays.  It is a vector
    (or array of vectors for an N-dimensional input) of length
    ``max(len(a), len(b)) - 1``.  If `zi` is None or is not given then
    initial rest is assumed.

...

zf : array, optional
    If `zi` is None, this is not returned, otherwise, `zf` holds the
    final filter delay values.

To initialize zi in the first place, just create a zeros array of shape (max(len(a), len(b)) - 1, number_of_channels).

endolith
  • 25,479
  • 34
  • 128
  • 192