Correct audio volume output decibels using HTML5 /

2019-05-11 13:22发布

问题:

We have observed that using javascript-based audio from a browser, the output level is not correctly linearly proportional to the input signal level on many systems. For example, if you 'play' two sin waves with amplitude varying by 20dB, the resultant difference from different devices/settings may be markedly different from 20dB, e.g. as far off as 10dB or less. We need to put out simple audio signals (e.g. sin waves) at calibrated decibel levels relative to each other, for example put out one sin wave at one volume, then put out another sin wave that is 20dB quieter than the first one, and have them actually come out that way. We would like to do this from a browser using HTML5/javascript.
We have tried to do this in several ways, e.g. using pre-created, calibrated .mp3 files, using the Web Audio API directly to generate an oscillator with calibrated dB levels. We have gotten (to us) very surprising and basically incorrect results. When we have measured the resulting sounds coming out of the device using a calibrated microphone, all kinds of weird things have been observed, indicating that audio is not just 'played' in a linear way, but complex pre-processing is being done on it before it actually gets output. This seems to depend on all kinds of variables currently outside of our control. It does not work the way that a 'normal' audio amplifier works, ie that a 20dB louder input produces a 20dB louder output, whatever the absolute level is set to. We have found that using the same javascript code produces very different results depending on all kinds of variables including the hardware (e.g. browsing on Mac vs. iPhone), the volume settings chosen (even the relative values not different by 20dB for 20dB difference in input when volume is at 1/2), if headphones are used, etc.

In further testing, it appears that the primary problem is related to the use of external speakers. When using headphones, the results look much better.

The basic problem is that if you create two different signals with known differences in volume, eg 20dB, and put them both out in any of several ways, the measured difference will often not be 20dB, and is in some cases as bad as 10dB.

Is there some way to programmatically do this?

Is there a way to override whatever pre-processing or audio volume compression seems to be adjusting the volume (causing output that is not correctly proportional to input)?

We need a way to do this that will work across platforms (desktop, iOS, Android, different browsers, different headphones/speakers), hence the use of HTML5.

If it isn't possible to do this using HTML5, how can we do it using native iOS/Android code? This appears to be more of a hardware than a software problem, but perhaps there are ways to override it.

Thanks

回答1:

We have answered this issue through significant further research. After detailed testing, the following has become clear: 1) On all systems tested the sound amplitude output has been nearly perfectly 1:1 linearly related to input when headphones are used, regardless of other settings. This was true over multiple browsers, multiple devices, iOS, Android, OSX, multiple powered and unpowered ear-bud and over-the-ear headphones. 2) In many systems/settings/volume levels the sound amplitude output is not 1:1 linearly related to input when the external speaker is used. Instead, the sound is often linear with a slope of less than 1, often significantly less (e.g. 1/2). In addition to this slope, many systems also saturate at higher volume levels. This appears to be because compensation mechanisms are being used with external speakers.

Therefore, the correct answer is: Audio output amplitude generated with HTML5/javascript audio is nearly 1:1 linear vs. input so long as headphones are used. It is not nearly 1:1 linear vs. input when external speakers are used on many devices in common use.