On Wed, 2013-09-18 at 23:09 -0500, Hajime Fujita wrote: > 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? The idea was to simply adjust v to -30 dB if the original v is less than that. There's no need to do any complicated calculations. > 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. What do you mean by way too small? The maximum volume will be the same as before, but the minimum volume will be quieter than before. With the original code you complained that you need to keep the volume at rather low levels, so extending the scale towards low volumes should help with this. -- Tanu