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

Side by Side Diff: third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html

Issue 2895963003: Apply layout-test-tidy to LayoutTests/webaudio (Closed)
Patch Set: Created 3 years, 7 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
OLDNEW
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2
3 <!-- 2 <!--
4 Tests that AudioBufferSourceNode supports loop-points with .loopStart and .loopE nd. 3 Tests that AudioBufferSourceNode supports loop-points with .loopStart and .loopE nd.
5 --> 4 -->
5 <html>
6 <head>
7 <title>
8 audiobuffersource-loop-points.html
9 </title>
10 <script src="../../resources/testharness.js"></script>
11 <script src="../../resources/testharnessreport.js"></script>
12 <script src="../resources/audit-util.js"></script>
13 <script src="../resources/audit.js"></script>
14 </head>
15 <body>
16 <script id="layout-test-code">
17 let audit = Audit.createTaskRunner();
6 18
7 <html> 19 let sampleRate = 44100.0;
8 <head> 20 let numberOfNotes = 60; // play over a 5 octave range
9 <script src="../../resources/testharness.js"></script> 21 let noteDuration = 0.025;
10 <script src="../../resources/testharnessreport.js"></script> 22 let noteSpacing =
11 <script src="../resources/audit-util.js"></script> 23 noteDuration + 0.005; // leave 5ms of silence between each "note"
12 <script src="../resources/audit.js"></script> 24 let lengthInSeconds = numberOfNotes * noteSpacing;
13 25
14 </head> 26 let context = 0;
15 <body> 27 let expectedAudio;
16 28
17 <script> 29 function createTestBuffer(frequency, sampleRate) {
18 let audit = Audit.createTaskRunner(); 30 // Create a buffer containing two periods at this frequency.
31 // The 1st half is a pure sine wave period scaled by a linear ramp from
32 // 0 -> 1. The 2nd half of the buffer corresponds exactly to one pure
33 // sine wave period.
34 let onePeriodDuration = 1 / frequency;
35 let sampleFrameLength = 2 * onePeriodDuration * sampleRate;
19 36
20 let sampleRate = 44100.0; 37 let audioBuffer =
21 let numberOfNotes = 60; // play over a 5 octave range 38 context.createBuffer(1, sampleFrameLength, sampleRate);
22 let noteDuration = 0.025;
23 let noteSpacing =
24 noteDuration + 0.005; // leave 5ms of silence between each "note"
25 let lengthInSeconds = numberOfNotes * noteSpacing;
26 39
27 let context = 0; 40 let n = audioBuffer.length;
28 let expectedAudio; 41 let channelData = audioBuffer.getChannelData(0);
29 42
30 function createTestBuffer(frequency, sampleRate) { 43 for (let i = 0; i < n; ++i) {
31 // Create a buffer containing two periods at this frequency. 44 let sample = Math.sin(frequency * 2.0 * Math.PI * i / sampleRate);
32 // The 1st half is a pure sine wave period scaled by a linear ramp from 0 ->
33 // 1. The 2nd half of the buffer corresponds exactly to one pure sine wave
34 // period.
35 let onePeriodDuration = 1 / frequency;
36 let sampleFrameLength = 2 * onePeriodDuration * sampleRate;
37 45
38 let audioBuffer = context.createBuffer(1, sampleFrameLength, sampleRate); 46 // Linear ramp from 0 -> 1 for the first period.
47 // Stay at 1 for the 2nd period.
48 let scale = i < n / 2 ? i / (n / 2) : 1;
49 sample *= scale;
39 50
40 let n = audioBuffer.length; 51 channelData[i] = sample;
41 let channelData = audioBuffer.getChannelData(0); 52 }
42 53
43 for (let i = 0; i < n; ++i) { 54 return audioBuffer;
44 let sample = Math.sin(frequency * 2.0 * Math.PI * i / sampleRate);
45
46 // Linear ramp from 0 -> 1 for the first period.
47 // Stay at 1 for the 2nd period.
48 let scale = i < n / 2 ? i / (n / 2) : 1;
49 sample *= scale;
50
51 channelData[i] = sample;
52 }
53
54 return audioBuffer;
55 }
56
57 function playNote(buffer, time, duration, playbackRate) {
58 let source = context.createBufferSource();
59 source.buffer = buffer;
60 source.playbackRate.value = playbackRate;
61
62 let gainNode = context.createGain();
63 source.connect(gainNode);
64 gainNode.connect(context.destination);
65
66 // Loop the 2nd half of the buffer.
67 // We should be able to hear any problems as glitches if the looping
68 // incorrectly indexes to anywhere outside of the desired loop-points, since
69 // only the 2nd half is a perfect sine-wave cycle, while the 1st half of the
70 // buffer contains a linear ramp of a sine-wave cycle.
71 source.loop = true;
72 source.loopStart = 0.5 * buffer.duration;
73 source.loopEnd = buffer.duration;
74
75 // Play for the given duration.
76 source.start(time);
77 source.stop(time + duration);
78
79 // Apply a quick linear fade-out to avoid a click at the end of the note.
80 gainNode.gain.value = 1;
81 gainNode.gain.setValueAtTime(1, time + duration - 0.005);
82 gainNode.gain.linearRampToValueAtTime(0, time + duration);
83 }
84
85 audit.define(
86 {label: 'initialize', description: 'Set up context and expected results'},
87 (task, should) => {
88 // Create offline audio context.
89 should(
90 () => {context = new OfflineAudioContext(
91 2, sampleRate * lengthInSeconds, sampleRate)},
92 'Creating context for testing')
93 .notThrow();
94
95 should(
96 Audit.loadFileFromUrl('audiobuffersource-loop-points-expected.wav')
97 .then(arrayBuffer => {
98 context.decodeAudioData(arrayBuffer).then(audioBuffer => {
99 expectedAudio = audioBuffer;
100 });
101 }),
102 'Fetching expected audio')
103 .beResolved()
104 .then(() => task.done());
105 });
106
107 audit.define(
108 {
109 label: 'test',
110 description: 'Test loop points and compare with expected results'
111 },
112 (task, should) => {
113 // Create the test buffer.
114 // We'll loop this with the loop-points set for the 2nd half of this
115 // buffer.
116 let buffer = createTestBuffer(440.0, sampleRate);
117
118 // Play all the notes as a chromatic scale.
119 for (let i = 0; i < numberOfNotes; ++i) {
120 let time = i * noteSpacing;
121 // start three octaves down
122 let semitone = i - numberOfNotes / 2;
123
124 // Convert from semitone to rate.
125 let playbackRate = Math.pow(2, semitone / 12);
126
127 playNote(buffer, time, noteDuration, playbackRate);
128 } 55 }
129 56
130 context.startRendering() 57 function playNote(buffer, time, duration, playbackRate) {
131 .then(renderedAudio => { 58 let source = context.createBufferSource();
132 // Compute a threshold based on the maximum error, |maxUlp|, in ULP. 59 source.buffer = buffer;
133 // This is experimentally determined. Assuming that the reference 60 source.playbackRate.value = playbackRate;
134 // file is a 16-bit wav file, the max values in the wave file
135 // are +/- 32768.
136 let maxUlp = 0.9999;
137 let threshold = maxUlp / 32768;
138 61
139 for (let k = 0; k < renderedAudio.numberOfChannels; ++k) { 62 let gainNode = context.createGain();
140 should( 63 source.connect(gainNode);
141 renderedAudio.getChannelData(k), 64 gainNode.connect(context.destination);
142 'Rendered audio for channel ' + k) 65
143 .beCloseToArray( 66 // Loop the 2nd half of the buffer.
144 expectedAudio.getChannelData(k), 67 // We should be able to hear any problems as glitches if the looping
145 {absoluteThreshold: threshold}); 68 // incorrectly indexes to anywhere outside of the desired loop-points,
69 // since only the 2nd half is a perfect sine-wave cycle, while the 1st
70 // half of the buffer contains a linear ramp of a sine-wave cycle.
71 source.loop = true;
72 source.loopStart = 0.5 * buffer.duration;
73 source.loopEnd = buffer.duration;
74
75 // Play for the given duration.
76 source.start(time);
77 source.stop(time + duration);
78
79 // Apply a quick linear fade-out to avoid a click at the end of the
80 // note.
81 gainNode.gain.value = 1;
82 gainNode.gain.setValueAtTime(1, time + duration - 0.005);
83 gainNode.gain.linearRampToValueAtTime(0, time + duration);
84 }
85
86 audit.define(
87 {
88 label: 'initialize',
89 description: 'Set up context and expected results'
90 },
91 (task, should) => {
92 // Create offline audio context.
93 should(
94 () => {context = new OfflineAudioContext(
95 2, sampleRate * lengthInSeconds, sampleRate)},
96 'Creating context for testing')
97 .notThrow();
98
99 should(
100 Audit
101 .loadFileFromUrl(
102 'audiobuffersource-loop-points-expected.wav')
103 .then(arrayBuffer => {
104 context.decodeAudioData(arrayBuffer).then(audioBuffer => {
105 expectedAudio = audioBuffer;
106 });
107 }),
108 'Fetching expected audio')
109 .beResolved()
110 .then(() => task.done());
111 });
112
113 audit.define(
114 {
115 label: 'test',
116 description: 'Test loop points and compare with expected results'
117 },
118 (task, should) => {
119 // Create the test buffer.
120 // We'll loop this with the loop-points set for the 2nd half of this
121 // buffer.
122 let buffer = createTestBuffer(440.0, sampleRate);
123
124 // Play all the notes as a chromatic scale.
125 for (let i = 0; i < numberOfNotes; ++i) {
126 let time = i * noteSpacing;
127 // start three octaves down
128 let semitone = i - numberOfNotes / 2;
129
130 // Convert from semitone to rate.
131 let playbackRate = Math.pow(2, semitone / 12);
132
133 playNote(buffer, time, noteDuration, playbackRate);
146 } 134 }
147 })
148 .then(() => task.done());
149 });
150 135
151 audit.run(); 136 context.startRendering()
137 .then(renderedAudio => {
138 // Compute a threshold based on the maximum error, |maxUlp|,
139 // in ULP. This is experimentally determined. Assuming that
140 // the reference file is a 16-bit wav file, the max values in
141 // the wave file are +/- 32768.
142 let maxUlp = 0.9999;
143 let threshold = maxUlp / 32768;
152 144
153 </script> 145 for (let k = 0; k < renderedAudio.numberOfChannels; ++k) {
146 should(
147 renderedAudio.getChannelData(k),
148 'Rendered audio for channel ' + k)
149 .beCloseToArray(
150 expectedAudio.getChannelData(k),
151 {absoluteThreshold: threshold});
152 }
153 })
154 .then(() => task.done());
155 });
154 156
155 </body> 157 audit.run();
158 </script>
159 </body>
156 </html> 160 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698