[pulseaudio-discuss] PulseAudio and AC3 passthrough

Tanu Kaskinen tanuk at iki.fi
Mon Jun 14 11:08:04 PDT 2010

On Wed, 2010-06-09 at 14:56 -0500, pl bossart wrote:
> It's been more than a year that this topic shows as 'being on the
> roadmap', but for now the reality is that people bypass PulseAudio to
> hear multichannel sound. I thought solving this would be a nice summer
> skunkworks project while everyone is busy increasing their chances of
> skin cancer.

Sounds good. I too would prefer hassle-free AC3 playback over skin

> Here's the deal: formatting an AC3 file into the required IEC format
> takes about 30 lines of code, this can be done in the application that
> connects to PulseAudio.

Do you plan to do it (the formatting) inside or outside libpulse?

> Then the problem is to pass raw data
> internally without applying any volume controls and with mixing
> disabled. There's no issue with timing or variable bitrate since the
> formatting adds headers and zero-padding to reach the non-compressed
> PCM bitrate, i.e. all the bytes-to-ms conversions still apply.
> I started looking into this but the volume control code is spread out
> between sink-input, sink, alsa, and it's hard to figure out how to go
> about this. Likewise, preventing mixing isn't self-explanatory. If
> anyone has pointers on these points or is willing to contribute, let
> me know.

Here's some thoughts of how I'd approach the task:

Sink inputs would get a new flag: PA_SINK_INPUT_NONPCM. The flag would
mean that no automatic conversion may be done before passing the stream
data to the sink, and also that the sink must know what it's doing (=
understand the non-PCM semantics) if it wants to modify the stream data
in any way. For example, module-combine doesn't understand any other
data types than PCM, so module-combine couldn't accept AC3 streams. If
there was "module-combine-ac3" that would decode the stream, or use
magic to resample the raw AC3 data, then that would be fine.

Sinks would get a new function: pa_sink_accept_input(pa_sink *s,
pa_sink_input *si). The function would check whether the sink input is
suitable for that sink. It would be called inside
pa_sink_input_may_move_to() and inside pa_sink_input_put(), or if making
_put() a failable function is not acceptable, then whenever anyone wants
to call _put(), he must first call _accept_input().

Sink implementers could provide a callback that would be called inside
pa_sink_accept_input(). By default inputs with the _NONPCM flag would be
rejected, but the ALSA sink and module-combine-ac3 would accept also
_NONPCM inputs if the sample format happened to be PA_SAMPLE_AC3 (for
ALSA sinks, of course only if the sink's sample format would also be

So, I'd introduce a new sample format: PA_SAMPLE_AC3.

Preventing mixing would be achieved by the fact that either sinks only
accept one AC3 stream at a time, or they don't use pa_sink_render(), but
do the mixing themselves if they somehow can handle that. I think
pa_sink_render() should be safe for the ALSA sink to use as long as
there's only one input and the sample rates match[1]. (I assume AC3
streams always have six channels. If that's not the case, then there are
more complications.)

Avoiding applying sw volume could be done by introducing another sink
input flag: PA_SINK_INPUT_NO_VOLUME and making sure that such sink
inputs are initialized with PA_VOLUME_NORM. pa_sink_input_set_volume()
would contain an assertion making sure that it's not called for inputs
with that flag. That would mean that all the places that call
pa_sink_input_set_volume() would need to be adapted. The detail that
even while conceptually the sink input wouldn't have volume,
initializing the volume to PA_VOLUME_NORM would probably save us from
touching pa_sink_render() code.

Similar flag would be needed for sinks too, and similar modifications to
the places that call pa_sink_set_volume().

I think that covers the most important pieces. The lack of volume would
need to be communicated to clients somehow (with sink and stream flags
probably). But old clients wouldn't understand that anyway - when a
client tries to set the volume of a sink or stream without volume, then
just make the operation fail, or make the operation a no-op.

[1] Is it a problem that a sink can't reconfigure its sample rate at
runtime? According to Wikipedia, an AC3 stream's sample rate can be
either 32 kHz, 44.1 kHz or 48 kHz. It would seem to me that the sink
should reinitialize its sample rate whenever a new AC3 stream is
connected to it, otherwise the user can play only those files that have
the right sample rate.

Tanu Kaskinen

More information about the pulseaudio-discuss mailing list