Skip to content

Commit

Permalink
Don't clip FFT output values to minDecibels.
Browse files Browse the repository at this point in the history
If the (linear) FFT value is zero, the dB value was set to
analyser.minDecibels.  The spec doesn't require this and it makes more
sense to return the expected -Infinity instead.

BUG=588853
TEST=realtimeanalyser-zero.html

Review URL: https://codereview.chromium.org/1729783002

Cr-Commit-Position: refs/heads/master@{#378081}
  • Loading branch information
rtoy authored and Commit bot committed Feb 27, 2016
1 parent 455d762 commit ef6f6ae
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Test AnalyserNode getFloatFrequencyData With Zero-Valued Input

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


PASS getFloatFrequencyData() with zero-valued input contains only the constant -Infinity.
PASS successfullyParsed is true

TEST COMPLETE

63 changes: 63 additions & 0 deletions third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-zero.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<!doctype html>
<html>
<head>
<script src="../resources/js-test.js"></script>
<script src="resources/compatibility.js"></script>
<script src="resources/audio-testing.js"></script>
<title>Test getFloatFrequencyData With Zero Inputs</title>
</head>

<body>
<script>
description("Test AnalyserNode getFloatFrequencyData With Zero-Valued Input");
window.jsTestIsAsync = true;

var sampleRate = 48000;

// Render enough data to run the test.
var renderFrames = 2*1024;
var renderDuration = renderFrames / sampleRate;

var audit = Audit.createTaskRunner();


// Test that getFloatFrequencyData returns -Infinity when the input is all-zeroes.
audit.defineTask("zero input", function (done) {
var context = new OfflineAudioContext(1, renderFrames, sampleRate);

// Constant source of 0's.
var source = context.createBufferSource();
source.buffer = createConstantBuffer(context, 1, 0);
source.loop = true;

// Create analyser and use some non-default minDecibels value.
var analyser = context.createAnalyser();
analyser.minDecibels = -123;

source.connect(analyser);
analyser.connect(context.destination);

source.start();

// Suspend after some number of frames and grab the float frequency data.
context.suspend(1024 / sampleRate).then(function () {
var f = new Float32Array(analyser.frequencyBinCount);
analyser.getFloatFrequencyData(f);

Should("getFloatFrequencyData() with zero-valued input", f)
.beConstantValueOf(-Infinity);
}).then(context.resume.bind(context));

context.startRendering().then(done);
});

audit.defineTask("finish", function (done) {
finishJSTest();
done();
});

audit.runTasks();

</script>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ void RealtimeAnalyser::doFFTAnalysis()
void RealtimeAnalyser::convertFloatToDb(DOMFloat32Array* destinationArray)
{
// Convert from linear magnitude to floating-point decibels.
const double minDecibels = m_minDecibels;
unsigned sourceLength = magnitudeBuffer().size();
size_t len = std::min(sourceLength, destinationArray->length());
if (len > 0) {
Expand All @@ -197,7 +196,7 @@ void RealtimeAnalyser::convertFloatToDb(DOMFloat32Array* destinationArray)

for (unsigned i = 0; i < len; ++i) {
float linearValue = source[i];
double dbMag = !linearValue ? minDecibels : AudioUtilities::linearToDecibels(linearValue);
double dbMag = AudioUtilities::linearToDecibels(linearValue);
destination[i] = float(dbMag);
}
}
Expand Down Expand Up @@ -234,7 +233,7 @@ void RealtimeAnalyser::convertToByteData(DOMUint8Array* destinationArray)

for (unsigned i = 0; i < len; ++i) {
float linearValue = source[i];
double dbMag = !linearValue ? minDecibels : AudioUtilities::linearToDecibels(linearValue);
double dbMag = AudioUtilities::linearToDecibels(linearValue);

// The range m_minDecibels to m_maxDecibels will be scaled to byte values from 0 to UCHAR_MAX.
double scaledValue = UCHAR_MAX * (dbMag - minDecibels) * rangeScaleFactor;
Expand Down
6 changes: 1 addition & 5 deletions third_party/WebKit/Source/platform/audio/AudioUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,7 @@ float decibelsToLinear(float decibels)

float linearToDecibels(float linear)
{
// It's not possible to calculate decibels for a zero linear value since it would be -Inf.
// -1000.0 dB represents a very tiny linear value in case we ever reach this case.
ASSERT(linear);
if (!linear)
return -1000;
ASSERT(linear >= 0);

return 20 * log10f(linear);
}
Expand Down

0 comments on commit ef6f6ae

Please sign in to comment.