Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(633)

Side by Side Diff: third_party/WebKit/LayoutTests/webaudio/Oscillator/start-sampling.html

Issue 2186813003: Sub-sample accurate start of OscillatorNode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Wrap lines nicely Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 <!doctype html>
2 <html>
3 <head>
4 <title>Test Sampling of Oscillator Start Times</title>
5 <script src="../../resources/testharness.js"></script>
6 <script src="../../resources/testharnessreport.js"></script>
7 <script src="../resources/audit-util.js"></script>
8 <script src="../resources/audit.js"></script>
9 </head>
10
11 <body>
12 <script>
13 // Experimentation indicates that this sample rate with a 440 Hz
14 // oscillator makes for a large difference in the difference signal if the
15 // oscillator start isn't sampled correctly.
16 var defaultSampleRate = 24000;
hongchan 2017/01/05 23:48:05 This is a new test, so we should use 'let'.
Raymond Toy 2017/01/10 00:09:48 Done.
17 var renderDuration = 1;
18 var renderFrames = renderDuration * defaultSampleRate;
19
20 var audit = Audit.createTaskRunner();
21
22 audit.define("basic test small", function (task, should) {
23 task.describe("Start oscillator slightly past a sample frame")
24 testStartSampling(should, 1.25, {
25 error: 1.0842e-4,
26 snrThreshold: 84.055
27 })
28 .then(task.done.bind(task));
29 });
30
31 audit.define("basic test big", function (task, should) {
32 task.describe("Start oscillator slightly before a sample frame")
33 testStartSampling(should, 1.75, {
34 error: 1.0838e-4,
35 snrThreshold: 84.056
36 })
37 .then(task.done.bind(task));
38 });
39
40 audit.define("diff big offset", function (task, should) {
41 task.describe("Test sampling with start offset greater than 1/2 sampling frame");
hongchan 2017/01/05 23:48:05 Can we wrap this line?
Raymond Toy 2017/01/10 00:09:48 Done.
42 // With a sample rate of 24000 Hz, and an oscillator frequency of 440 Hz
43 // (the default), a quarter wave delay is 13.636363... frames. This
44 // tests the case where the starting time is more than 1/2 frame from
45 // the preceding sampling frame. This tests one path of the internal
46 // implementation.
47 testStartWithGain(should, defaultSampleRate, {
48 error: 4.1724e-7,
49 snrThreshold: 137.536
50 })
51 .then(task.done.bind(task));
52 });
53
54 audit.define("diff small offset", function (task, should) {
55 task.describe("Test sampling with start offset less than 1/2 sampling fr ame");
hongchan 2017/01/05 23:48:05 ditto.
Raymond Toy 2017/01/10 00:09:48 Done.
56 // With a sample rate of 48000 Hz, and an oscillator frequency of 440 Hz
57 // (the default), a quarter wave delay is 27.2727... frames. This tests
58 // the case where the starting time is less than 1/2 frame from the
59 // preceding sampling frame. This tests one path of the internal
60 // implementation.
61 testStartWithGain(should, 48000, {
62 error: 4.1724e-7,
63 snrThreshold: 137.536
64 })
65 .then(task.done.bind(task));
66 });
67
68 function testStartSampling(should, startFrame, thresholds) {
69 // Start the oscillator in the middle of a sample frame and compare
70 // against the theoretical result.
71 var context = new OfflineAudioContext(1, renderFrames, defaultSampleRate );
hongchan 2017/01/05 23:48:05 ditto.
Raymond Toy 2017/01/10 00:09:48 Done.
72 var osc = context.createOscillator();
73 osc.connect(context.destination);
74 osc.start(startFrame / context.sampleRate);
75
76 return context.startRendering().then(function (result) {
77 var actual = result.getChannelData(0);
78 var expected = new Array(actual.length);
79 expected.fill(0);
80
81 // The expected curve is
82 //
83 // sin(2*pi*f*(t-t0))
84 //
85 // where f is the oscillator frequency and t0 is the start time.
86 var actualStart = Math.ceil(startFrame);
87 var omega = 2 * Math.PI * osc.frequency.value / context.sampleRate;
88 for (var k = actualStart; k < actual.length; ++k) {
89 expected[k] = Math.sin(omega * (k - startFrame));
90 }
91
92 should(actual, "Oscillator.start(" + startFrame + " frames)")
93 .beCloseToArray(expected, {
94 absoluteThreshold: thresholds.error
95 });
96 var snr = 10 * Math.log10(computeSNR(actual, expected));
97 should(snr, "SNR")
98 .beGreaterThanOrEqualTo(thresholds.snrThreshold);
99 })
100 }
101
102 function testStartWithGain(should, sampleRate, thresholds) {
103 // Test consists of starting a cosine wave with a quarter wavelength
104 // delay and comparing that with a sine wave that has the initial
105 // quarter wavelength zeroed out. These should be equal.
106
107 var context = new OfflineAudioContext(3, renderFrames, sampleRate);
108 var osc = context.createOscillator();
109
110 var merger = context.createChannelMerger(3);
111 merger.connect(context.destination);
112
113 // Start the cosine oscillator at this time. This means the wave starts
114 // at frame 13.636363....
115 var quarterWaveTime = (1 / 4) / osc.frequency.value;
116
117 // Sine wave oscillator with gain term to zero out the initial quarter
118 // wave length of the output.
119 var osc = context.createOscillator();
120 var g = context.createGain();
121 g.gain.setValueAtTime(0, 0);
122 g.gain.setValueAtTime(1, quarterWaveTime);
123 osc.connect(g);
124 g.connect(merger, 0, 2);
125 g.connect(merger, 0, 0);
126
127 // Cosine wave oscillator with starting after a quarter wave length.
128 var osc2 = context.createOscillator();
129 // Creates a cosine wave.
130 var wave = context.createPeriodicWave(
131 Float32Array.from([0, 1]),
132 Float32Array.from([0, 0]));
133 osc2.setPeriodicWave(wave);
134
135 osc2.connect(merger, 0, 1);
136
137 // A gain inverter so subtract the two waveforms.
138 var inverter = context.createGain();
139 inverter.gain.value = -1;
140 osc2.connect(inverter);
141 inverter.connect(merger, 0, 0);
142
143 osc.start();
144 osc2.start(quarterWaveTime);
145
146 return context.startRendering().then(function (result) {
147 // Channel 0 = diff
148 // Channel 1 = osc with start
149 // Channel 2 = osc with gain
150
151 // Channel 0 should be very close to 0.
152 // Channel 1 should match channel 2 very closely.
153 var diff = result.getChannelData(0);
154 var oscStart = result.getChannelData(1);
155 var oscGain = result.getChannelData(2);
156 var snr = 10 * Math.log10(computeSNR(oscStart, oscGain));
157
158 should(oscStart, "Delayed cosine oscillator at sample rate " + sampleR ate)
159 .beCloseToArray(oscGain, {
160 absoluteThreshold: thresholds.error
161 });
162 should(snr, "SNR")
163 .beGreaterThanOrEqualTo(thresholds.snrThreshold);
164 });
165 }
166
167 audit.run();
168 </script>
169 </body>
170 </html>
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698