Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / webaudio / OscillatorNode.cpp
1 /*
2  * Copyright (C) 2012, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #if ENABLE(WEB_AUDIO)
28
29 #include "modules/webaudio/OscillatorNode.h"
30
31 #include "platform/audio/AudioUtilities.h"
32 #include "platform/audio/VectorMath.h"
33 #include "modules/webaudio/AudioContext.h"
34 #include "modules/webaudio/AudioNodeOutput.h"
35 #include "modules/webaudio/PeriodicWave.h"
36 #include "wtf/MathExtras.h"
37 #include "wtf/StdLibExtras.h"
38 #include <algorithm>
39
40 namespace blink {
41
42 using namespace VectorMath;
43
44 OscillatorNode* OscillatorNode::create(AudioContext* context, float sampleRate)
45 {
46     return new OscillatorNode(context, sampleRate);
47 }
48
49 OscillatorNode::OscillatorNode(AudioContext* context, float sampleRate)
50     : AudioScheduledSourceNode(context, sampleRate)
51     , m_type(SINE)
52     , m_firstRender(true)
53     , m_virtualReadIndex(0)
54     , m_phaseIncrements(AudioNode::ProcessingSizeInFrames)
55     , m_detuneValues(AudioNode::ProcessingSizeInFrames)
56 {
57     setNodeType(NodeTypeOscillator);
58
59     // Use musical pitch standard A440 as a default.
60     m_frequency = AudioParam::create(context, 440);
61     // Default to no detuning.
62     m_detune = AudioParam::create(context, 0);
63
64     // Sets up default wavetable.
65     setType(m_type);
66
67     // An oscillator is always mono.
68     addOutput(AudioNodeOutput::create(this, 1));
69
70     initialize();
71 }
72
73 OscillatorNode::~OscillatorNode()
74 {
75     ASSERT(!isInitialized());
76 }
77
78 void OscillatorNode::dispose()
79 {
80     uninitialize();
81     AudioScheduledSourceNode::dispose();
82 }
83
84 String OscillatorNode::type() const
85 {
86     switch (m_type) {
87     case SINE:
88         return "sine";
89     case SQUARE:
90         return "square";
91     case SAWTOOTH:
92         return "sawtooth";
93     case TRIANGLE:
94         return "triangle";
95     case CUSTOM:
96         return "custom";
97     default:
98         ASSERT_NOT_REACHED();
99         return "custom";
100     }
101 }
102
103 void OscillatorNode::setType(const String& type)
104 {
105     if (type == "sine")
106         setType(SINE);
107     else if (type == "square")
108         setType(SQUARE);
109     else if (type == "sawtooth")
110         setType(SAWTOOTH);
111     else if (type == "triangle")
112         setType(TRIANGLE);
113 }
114
115 bool OscillatorNode::setType(unsigned type)
116 {
117     PeriodicWave* periodicWave = 0;
118     float sampleRate = this->sampleRate();
119
120     switch (type) {
121     case SINE: {
122         DEFINE_STATIC_LOCAL(Persistent<PeriodicWave>, periodicWaveSine, (PeriodicWave::createSine(sampleRate)));
123         periodicWave = periodicWaveSine;
124         break;
125     }
126     case SQUARE: {
127         DEFINE_STATIC_LOCAL(Persistent<PeriodicWave>, periodicWaveSquare, (PeriodicWave::createSquare(sampleRate)));
128         periodicWave = periodicWaveSquare;
129         break;
130     }
131     case SAWTOOTH: {
132         DEFINE_STATIC_LOCAL(Persistent<PeriodicWave>, periodicWaveSawtooth, (PeriodicWave::createSawtooth(sampleRate)));
133         periodicWave = periodicWaveSawtooth;
134         break;
135     }
136     case TRIANGLE: {
137         DEFINE_STATIC_LOCAL(Persistent<PeriodicWave>, periodicWaveTriangle, (PeriodicWave::createTriangle(sampleRate)));
138         periodicWave = periodicWaveTriangle;
139         break;
140     }
141     case CUSTOM:
142     default:
143         // Return error for invalid types, including CUSTOM since setPeriodicWave() method must be
144         // called explicitly.
145         return false;
146     }
147
148     setPeriodicWave(periodicWave);
149     m_type = type;
150     return true;
151 }
152
153 bool OscillatorNode::calculateSampleAccuratePhaseIncrements(size_t framesToProcess)
154 {
155     bool isGood = framesToProcess <= m_phaseIncrements.size() && framesToProcess <= m_detuneValues.size();
156     ASSERT(isGood);
157     if (!isGood)
158         return false;
159
160     if (m_firstRender) {
161         m_firstRender = false;
162         m_frequency->resetSmoothedValue();
163         m_detune->resetSmoothedValue();
164     }
165
166     bool hasSampleAccurateValues = false;
167     bool hasFrequencyChanges = false;
168     float* phaseIncrements = m_phaseIncrements.data();
169
170     float finalScale = m_periodicWave->rateScale();
171
172     if (m_frequency->hasSampleAccurateValues()) {
173         hasSampleAccurateValues = true;
174         hasFrequencyChanges = true;
175
176         // Get the sample-accurate frequency values and convert to phase increments.
177         // They will be converted to phase increments below.
178         m_frequency->calculateSampleAccurateValues(phaseIncrements, framesToProcess);
179     } else {
180         // Handle ordinary parameter smoothing/de-zippering if there are no scheduled changes.
181         m_frequency->smooth();
182         float frequency = m_frequency->smoothedValue();
183         finalScale *= frequency;
184     }
185
186     if (m_detune->hasSampleAccurateValues()) {
187         hasSampleAccurateValues = true;
188
189         // Get the sample-accurate detune values.
190         float* detuneValues = hasFrequencyChanges ? m_detuneValues.data() : phaseIncrements;
191         m_detune->calculateSampleAccurateValues(detuneValues, framesToProcess);
192
193         // Convert from cents to rate scalar.
194         float k = 1.0 / 1200;
195         vsmul(detuneValues, 1, &k, detuneValues, 1, framesToProcess);
196         for (unsigned i = 0; i < framesToProcess; ++i)
197             detuneValues[i] = powf(2, detuneValues[i]); // FIXME: converting to expf() will be faster.
198
199         if (hasFrequencyChanges) {
200             // Multiply frequencies by detune scalings.
201             vmul(detuneValues, 1, phaseIncrements, 1, phaseIncrements, 1, framesToProcess);
202         }
203     } else {
204         // Handle ordinary parameter smoothing/de-zippering if there are no scheduled changes.
205         m_detune->smooth();
206         float detune = m_detune->smoothedValue();
207         float detuneScale = powf(2, detune / 1200);
208         finalScale *= detuneScale;
209     }
210
211     if (hasSampleAccurateValues) {
212         // Convert from frequency to wavetable increment.
213         vsmul(phaseIncrements, 1, &finalScale, phaseIncrements, 1, framesToProcess);
214     }
215
216     return hasSampleAccurateValues;
217 }
218
219 void OscillatorNode::process(size_t framesToProcess)
220 {
221     AudioBus* outputBus = output(0)->bus();
222
223     if (!isInitialized() || !outputBus->numberOfChannels()) {
224         outputBus->zero();
225         return;
226     }
227
228     ASSERT(framesToProcess <= m_phaseIncrements.size());
229     if (framesToProcess > m_phaseIncrements.size())
230         return;
231
232     // The audio thread can't block on this lock, so we call tryLock() instead.
233     MutexTryLocker tryLocker(m_processLock);
234     if (!tryLocker.locked()) {
235         // Too bad - the tryLock() failed. We must be in the middle of changing wave-tables.
236         outputBus->zero();
237         return;
238     }
239
240     // We must access m_periodicWave only inside the lock.
241     if (!m_periodicWave.get()) {
242         outputBus->zero();
243         return;
244     }
245
246     size_t quantumFrameOffset;
247     size_t nonSilentFramesToProcess;
248
249     updateSchedulingInfo(framesToProcess, outputBus, quantumFrameOffset, nonSilentFramesToProcess);
250
251     if (!nonSilentFramesToProcess) {
252         outputBus->zero();
253         return;
254     }
255
256     unsigned periodicWaveSize = m_periodicWave->periodicWaveSize();
257     double invPeriodicWaveSize = 1.0 / periodicWaveSize;
258
259     float* destP = outputBus->channel(0)->mutableData();
260
261     ASSERT(quantumFrameOffset <= framesToProcess);
262
263     // We keep virtualReadIndex double-precision since we're accumulating values.
264     double virtualReadIndex = m_virtualReadIndex;
265
266     float rateScale = m_periodicWave->rateScale();
267     float invRateScale = 1 / rateScale;
268     bool hasSampleAccurateValues = calculateSampleAccuratePhaseIncrements(framesToProcess);
269
270     float frequency = 0;
271     float* higherWaveData = 0;
272     float* lowerWaveData = 0;
273     float tableInterpolationFactor = 0;
274
275     if (!hasSampleAccurateValues) {
276         frequency = m_frequency->smoothedValue();
277         float detune = m_detune->smoothedValue();
278         float detuneScale = powf(2, detune / 1200);
279         frequency *= detuneScale;
280         m_periodicWave->waveDataForFundamentalFrequency(frequency, lowerWaveData, higherWaveData, tableInterpolationFactor);
281     }
282
283     float incr = frequency * rateScale;
284     float* phaseIncrements = m_phaseIncrements.data();
285
286     unsigned readIndexMask = periodicWaveSize - 1;
287
288     // Start rendering at the correct offset.
289     destP += quantumFrameOffset;
290     int n = nonSilentFramesToProcess;
291
292     while (n--) {
293         unsigned readIndex = static_cast<unsigned>(virtualReadIndex);
294         unsigned readIndex2 = readIndex + 1;
295
296         // Contain within valid range.
297         readIndex = readIndex & readIndexMask;
298         readIndex2 = readIndex2 & readIndexMask;
299
300         if (hasSampleAccurateValues) {
301             incr = *phaseIncrements++;
302
303             frequency = invRateScale * incr;
304             m_periodicWave->waveDataForFundamentalFrequency(frequency, lowerWaveData, higherWaveData, tableInterpolationFactor);
305         }
306
307         float sample1Lower = lowerWaveData[readIndex];
308         float sample2Lower = lowerWaveData[readIndex2];
309         float sample1Higher = higherWaveData[readIndex];
310         float sample2Higher = higherWaveData[readIndex2];
311
312         // Linearly interpolate within each table (lower and higher).
313         float interpolationFactor = static_cast<float>(virtualReadIndex) - readIndex;
314         float sampleHigher = (1 - interpolationFactor) * sample1Higher + interpolationFactor * sample2Higher;
315         float sampleLower = (1 - interpolationFactor) * sample1Lower + interpolationFactor * sample2Lower;
316
317         // Then interpolate between the two tables.
318         float sample = (1 - tableInterpolationFactor) * sampleHigher + tableInterpolationFactor * sampleLower;
319
320         *destP++ = sample;
321
322         // Increment virtual read index and wrap virtualReadIndex into the range 0 -> periodicWaveSize.
323         virtualReadIndex += incr;
324         virtualReadIndex -= floor(virtualReadIndex * invPeriodicWaveSize) * periodicWaveSize;
325     }
326
327     m_virtualReadIndex = virtualReadIndex;
328
329     outputBus->clearSilentFlag();
330 }
331
332 void OscillatorNode::setPeriodicWave(PeriodicWave* periodicWave)
333 {
334     ASSERT(isMainThread());
335
336     // This synchronizes with process().
337     MutexLocker processLocker(m_processLock);
338     m_periodicWave = periodicWave;
339     m_type = CUSTOM;
340 }
341
342 bool OscillatorNode::propagatesSilence() const
343 {
344     return !isPlayingOrScheduled() || hasFinished() || !m_periodicWave.get();
345 }
346
347 void OscillatorNode::trace(Visitor* visitor)
348 {
349     visitor->trace(m_frequency);
350     visitor->trace(m_detune);
351     visitor->trace(m_periodicWave);
352     AudioScheduledSourceNode::trace(visitor);
353 }
354
355 } // namespace blink
356
357 #endif // ENABLE(WEB_AUDIO)