|
1 <!DOCTYPE HTML> |
|
2 <html> |
|
3 <head> |
|
4 <title>Test tail time lifetime of DelayNode after input finishes and new input added</title> |
|
5 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
|
6 <script type="text/javascript" src="webaudio.js"></script> |
|
7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> |
|
8 </head> |
|
9 <body> |
|
10 <pre id="test"> |
|
11 <script class="testbody" type="text/javascript"> |
|
12 |
|
13 SimpleTest.waitForExplicitFinish(); |
|
14 |
|
15 // The buffer source will start on a block boundary, so keeping the signal |
|
16 // within one block ensures that it will not cross AudioProcessingEvent buffer |
|
17 // boundaries. |
|
18 const signalLength = 128; |
|
19 const bufferSize = 1024; |
|
20 // Delay should be long enough to allow CC to run |
|
21 var delayBufferCount = 50; |
|
22 var delayBufferOffset; |
|
23 const delayLength = delayBufferCount * bufferSize; |
|
24 |
|
25 var phase = "initial"; |
|
26 var sourceCount = 0; |
|
27 var delayCount = 0; |
|
28 var oscillator; |
|
29 var delay; |
|
30 var source; |
|
31 |
|
32 function applySignal(buffer, offset) { |
|
33 for (var i = 0; i < signalLength; ++i) { |
|
34 buffer.getChannelData(0)[offset + i] = Math.cos(Math.PI * i / signalLength); |
|
35 } |
|
36 } |
|
37 |
|
38 function bufferIsSilent(buffer, out) { |
|
39 for (var i = 0; i < buffer.length; ++i) { |
|
40 if (buffer.getChannelData(0)[i] != 0) { |
|
41 if (out) { |
|
42 out.soundOffset = i; |
|
43 } |
|
44 return false; |
|
45 } |
|
46 } |
|
47 return true; |
|
48 } |
|
49 |
|
50 function onDelayOutput(e) { |
|
51 switch(phase) { |
|
52 |
|
53 case "initial": |
|
54 // Wait for oscillator sound to exit delay |
|
55 if (bufferIsSilent(e.inputBuffer)) |
|
56 break; |
|
57 |
|
58 phase = "played oscillator"; |
|
59 break; |
|
60 |
|
61 case "played oscillator": |
|
62 // First tail time has expired. Start second source and remove references |
|
63 // to the delay and connected second source. |
|
64 oscillator.disconnect(); |
|
65 source.connect(delay); |
|
66 source.start(); |
|
67 source = null; |
|
68 delay = null; |
|
69 phase = "started second source"; |
|
70 break; |
|
71 |
|
72 case "second tail time": |
|
73 if (delayCount == delayBufferCount) { |
|
74 var ctx = e.target.context; |
|
75 var expected = ctx.createBuffer(1, bufferSize, ctx.sampleRate); |
|
76 applySignal(expected, delayBufferOffset); |
|
77 compareBuffers(e.inputBuffer, expected); |
|
78 e.target.onaudioprocess = null; |
|
79 SimpleTest.finish(); |
|
80 } |
|
81 } |
|
82 |
|
83 delayCount++; |
|
84 } |
|
85 |
|
86 function onSourceOutput(e) { |
|
87 switch(phase) { |
|
88 case "started second source": |
|
89 var out = {}; |
|
90 if (!bufferIsSilent(e.inputBuffer, out)) { |
|
91 delayBufferCount += sourceCount; |
|
92 delayBufferOffset = out.soundOffset; |
|
93 phase = "played second source"; |
|
94 } |
|
95 break; |
|
96 case "played second source": |
|
97 SpecialPowers.forceGC(); |
|
98 SpecialPowers.forceCC(); |
|
99 phase = "second tail time"; |
|
100 e.target.onaudioprocess = null; |
|
101 } |
|
102 |
|
103 sourceCount++; |
|
104 } |
|
105 |
|
106 function startTest() { |
|
107 var ctx = new AudioContext(); |
|
108 var delayDuration = delayLength / ctx.sampleRate; |
|
109 delay = ctx.createDelay(delayDuration); |
|
110 delay.delayTime.value = delayDuration; |
|
111 var processor1 = ctx.createScriptProcessor(bufferSize, 1, 0); |
|
112 delay.connect(processor1); |
|
113 processor1.onaudioprocess = onDelayOutput; |
|
114 processor1.connect(ctx.destination); // work around bug 916387 |
|
115 |
|
116 // Signal to trigger initial tail time reference |
|
117 oscillator = ctx.createOscillator(); |
|
118 oscillator.start(0); |
|
119 oscillator.stop(100/ctx.sampleRate); |
|
120 oscillator.connect(delay); |
|
121 |
|
122 // Short signal, not started yet, with a ScriptProcessor to detect when it |
|
123 // starts. It should finish before garbage collection. |
|
124 var buffer = ctx.createBuffer(1, signalLength, ctx.sampleRate); |
|
125 applySignal(buffer, 0); |
|
126 source = ctx.createBufferSource(); |
|
127 source.buffer = buffer; |
|
128 var processor2 = ctx.createScriptProcessor(bufferSize, 1, 0); |
|
129 source.connect(processor2); |
|
130 processor2.onaudioprocess = onSourceOutput; |
|
131 processor2.connect(ctx.destination); // guard against bug 916387 |
|
132 }; |
|
133 |
|
134 startTest(); |
|
135 </script> |
|
136 </pre> |
|
137 </body> |
|
138 </html> |