[pulseaudio-discuss] native digital equalizer for pulseaudio submission

Tanu Kaskinen tanuk at iki.fi
Fri Jul 17 00:50:21 PDT 2009


to, 2009-07-16 kello 23:08 -0700, Jason Newton kirjoitti:
> ...Is what I'd like to say.  I've attached it in it's current form.
> It's based of the LADSPA sink though it would seem that following a
> working state, it will move to a filtering api in someone elses work.
> 
> Equalization frequencies and coefficients are specified in two arrays
> and hardcoded in (the coefficients are linear,not in dB). at the moment.
> 
> But I'm having a bit of a problem.  I need a fixed amount of data before
> I can process a block and pulseaudio doesn't usually like to give me
> that block without dropouts and other problems as the cost.  The trouble
> routine is module-equalizer-sink.c:270 sink_input_pop_cb.  The amount of
> data requested each processing iteration is chosen indirectly by the
> window_size parameter (hardcoded in pa__init).  The actual amount of
> data is R, this is calculated right below.  This value works for my
> laptop w/ mplayer and ao=pulse for some reason but not my desktop.  I
> found it completely by accident and have no idea how to find others.
> Suggestions are very welcomed as I'm out of ideas.

(Line numbers in the following refer to the patch file.)

I don't think I have enough time before next week to look into this in
more detail and actually try things before giving advice, but here are
some hints. At 272 you create a new memblock. I think you should get
that block from the filtered audio buffer with pa_memblockq_peek. _peek
returns a memchunk, set its length to min(nbytes, chunk->length). Return
that chunk.

Remove the if check at 267, and instead check before that whether the
buffer memblockq is empty. If it is, then you need to fill the buffer.
You mentioned in IRC that creating memblocks large enough for the
algorithm causes problems with shm. My understanding of pa_memblock_new
is that it can create blocks of any size, so I don't quite know what
problems you ran into. But too big blocks are allocated with pa_xnew,
which isn't desirable in a realtime context like this. I think
allocating some blocks beforehand at module initialization time would be
appropriate here. For this, use pa_memblock_new_user. Provide a free
callback that puts the block back to the reserve from which you take new
memblocks when filtering.

When requesting for data for filtering, take a memblock from the reserve
(or if none are available, allocate new memory and create a new memblock
with pa_memblock_new_user). Then call pa_sink_render_into repeatedly
until the jumbo-sized memblock is fully populated. Then run the filter
on the memblock and push the memblock to the buffer memblockq. The next
step is then what I wrote in my first paragraph.

I think this approach may cause underruns, because pa_sink_render_into
is called relatively seldom, but with big requirements. There may not be
enough data available from the clients. You may need to tune this
algorithm so that every time sink_input_pop_cb is called, you already
fill the next memblock for the filter in advance as much as you can.
This way the requests for new data come to the clients in a smoother
manner.

HTH.

-- 
Tanu Kaskinen




More information about the pulseaudio-discuss mailing list