[pulseaudio-discuss] An raop2 support

Hajime Fujita crisp.fujita at nifty.com
Wed Sep 18 21:09:16 PDT 2013


Hi Tanu,

Thank you so much for your advice.

Tanu Kaskinen wrote:
> On Sun, 2013-09-15 at 00:24 -0500, Hajime Fujita wrote:
>> For those who are interested in raop2 experiments,
>>
>> As Matthias pointed out [1], current volume calculation is incorrect.
>> https://bugs.freedesktop.org/show_bug.cgi?id=42804#c43
>>
>> I have uploaded a patch which calculates volume in more reasonable way.
>> https://github.com/hfujita/pulseaudio-raop2/commit/69f3ce883dfb93eb7b24f98b9664e14071672475
>>
>> First I have to confess that this is the first time for me to deal with
>> the unit 'dB', so maybe I'm doing totally stupid. I'd be very happy if I
>> could have any suggestions from who is more experienced in this field.
>>
>> I started looking at pa_raop_client_set_volume() in
>> src/modules/raop/raop_client.c. It was using pa_sw_volume_to_dB to
>> calculate dB from a linear scale.
> 
> Correction: pa_volume_t doesn't use a linear scale, it uses a cubic
> scale (see pa_sw_volume_from_linear() and pa_sw_volume_to_linear()).

I see. I should have noticed some comments about cubic scale.
http://cgit.freedesktop.org/pulseaudio/pulseaudio/tree/src/pulse/volume.c#n251

> 
>> Then I learned from code reading that pa_sw_volume_to_dB essentially
>> calculates the following:
>>   20 * log10((v/MAXVOLUME)^3) = 60 * log10(v/MAXVOLUME)
>> This does not fit into the volume scale which RAOP is expecting, where
>> -30.0 db is a kind of minimum [2].
>>
>> [2]: http://git.zx2c4.com/Airtunes2/about/#id29
>>
>> Also I looked at packet dumps from iPad and guessed how it calculated dB
>> from a linear scale. It looked like iPad was using the following formula.
>>   db = 10 * log10(volume/MAXVOLUME/30)
>> So for the time being I decided to follow this way.
> 
> The way to convert pa_volume_t to dB is to use pa_sw_volume_to_dB().
> Doing anything else means that the result is not dB, it's something
> different.
> 
> The way to handle this is to ensure that the volume that is given to
> pa_raop_client_set_volume() is never outside the supported range. In
> module-raop-sink.c there's sink_set_volume_cb(), which calls
> pa_raop_client_set_volume(). In sink_set_volume_cb() there's this line:
> 
>     pa_cvolume_set(&hw, s->sample_spec.channels, v);
> 
> Before that line you should check what dB value v corresponds to, and if
> it's outside the supported range, then you should modify v to fall into
> the supported range. Any modification that you make to v will be
> compensated with software volume, so the modifications shouldn't affect
> the resulting volume at all, assuming that the RAOP device actually
> attenuates the signal by the dB amount that you send to it.
> 

According to your advice, I inserted an adjustment to v before
pa_cvolume_set. Here's the patch.
https://github.com/hfujita/pulseaudio-raop2/commit/c6337c0fef7710ee20b42ed3fb87ec12910ce35a

Adjustment goes like this (pa_raop_client_adjust_volume()):
  adj(v) = v * (1 - minv/maxv) + minv;
where pa_sw_volume_to_dB(minv) = -30.0,
and pa_sw_volume_to_dB(maxv) = 0.0

The idea is that when the original v is 0, adj(0) = minv. And when the
original v is maxv, adj(maxv) = maxv;

Does this make sense?

As you noted, this also affects the software volume, and in my
environment, the actual volume (volume heard from the speaker) may be
way too small.
Should I pass the volume before adjustment to pa_cvolume_set()?


Thanks,
Hajime



More information about the pulseaudio-discuss mailing list