[pulseaudio-discuss] Processing audio data in module-alsa-sink

Lennart Poettering lennart at poettering.net
Mon Sep 8 13:42:19 PDT 2008

On Mon, 08.09.08 12:27, Baek Chang (breakchange at gmail.com) wrote:

> I am trying to modify the module-alsa-sink module to process the audio
> data.
> Within: static int mmap_write(struct userdata *u) {}

Please note that mmap_write() is used only if mmap()-style audio
output is available, otherwise we fall back to use unix_write().
> I am calling a routine that just sets the audio data to 0 so I know that I
> can actually affect the data.  I am doing this like so:
>        /* Check these are multiples of 8 bit */
>         pa_assert((areas[0].first & 7) == 0);
>         pa_assert((areas[0].step & 7)== 0);
>         /* We assume a single interleaved memory buffer */
>         pa_assert((areas[0].first >> 3) == 0);
>         pa_assert((areas[0].step >> 3) == u->frame_size);
>         p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
>         zeroData((uint8_t*) p, frames * u->frame_size);
>         chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames *
> u->frame_size, 1);
>         chunk.length = pa_memblock_get_length(chunk.memblock);
>         chunk.index = 0;
>         pa_sink_render_into_full(u->sink, &chunk);

This is the function call that is actually rendering the audio data
and is writing it to the memory the chunk refers to.

So basically, your zeroData() call is zeroing audio data first which
then subsequently gets overwritten by the actually audio data. That's
why your zeroing has no effect.

> here is my function for zeroData():
> static void biquadProcess(uint8_t *p, int length)
> {
>     int j;
>     for(j = 0; j < length; j++)
>         *p++ = 0;
> }

so, is it biquadProcess or zeroData?

(also, on POSIX memory sizes should be of type size_t, not int, otherwise
things might break for you on 64bit hosts)

> This does not seem to affect the audio at all.  I don't know what I am doing
> wrong.  Also is there a way to access the data through chunk.memblock?
> chunk is of type pa_memchunk.

A memchunk just describes a part of a memblock. It is just a small
structure that has a reference to the memblock, an index into the
memblock and a size. Pretty simple.

The memblock actually carries real information and is a much more
complex structure. If you want to get a pointer to the data stored in
it, call pa_memblock_acquire(). When you are done accessing it, you
MUST explicitly give up the access to it via
pa_memblock_release() later. Every call to _acquire MUST be followed be
exactly one call of _release(). You can call _acquire many times in a
row on the same memblock or on different ones. But afterwards you need
to call _release() the same number of times.

The pointer returned by pa_memblock_acquire() is only valid until the
matching pa_memblock_release(). You are expected to call _release()
only when you really need the data and only for very short periods of

The logic behind _acquire() and _release() is that our memory can move
in the address: i.e. when a mmap() is lost due to hardware unplug or
because a client disconnects. When we move the memory we need to be
sure that noone is accessing it while we do it, so we need to count
who is accessing it.


Lennart Poettering                        Red Hat, Inc.
lennart [at] poettering [dot] net         ICQ# 11060553
http://0pointer.net/lennart/           GnuPG 0x1A015CC4

More information about the pulseaudio-discuss mailing list