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

Side by Side Diff: Source/modules/webaudio/OscillatorNode.cpp

Issue 18182009: WaveTable name has changed to PeriodicWave (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: fix global constructors test Created 7 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « Source/modules/webaudio/OscillatorNode.h ('k') | Source/modules/webaudio/OscillatorNode.idl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012, Google Inc. All rights reserved. 2 * Copyright (C) 2012, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 15 matching lines...) Expand all
26 26
27 #if ENABLE(WEB_AUDIO) 27 #if ENABLE(WEB_AUDIO)
28 28
29 #include "modules/webaudio/OscillatorNode.h" 29 #include "modules/webaudio/OscillatorNode.h"
30 30
31 #include "core/dom/ExceptionCode.h" 31 #include "core/dom/ExceptionCode.h"
32 #include "core/platform/audio/AudioUtilities.h" 32 #include "core/platform/audio/AudioUtilities.h"
33 #include "core/platform/audio/VectorMath.h" 33 #include "core/platform/audio/VectorMath.h"
34 #include "modules/webaudio/AudioContext.h" 34 #include "modules/webaudio/AudioContext.h"
35 #include "modules/webaudio/AudioNodeOutput.h" 35 #include "modules/webaudio/AudioNodeOutput.h"
36 #include "modules/webaudio/WaveTable.h" 36 #include "modules/webaudio/PeriodicWave.h"
37 #include <algorithm> 37 #include <algorithm>
38 #include "wtf/MathExtras.h" 38 #include "wtf/MathExtras.h"
39 39
40 using namespace std; 40 using namespace std;
41 41
42 namespace WebCore { 42 namespace WebCore {
43 43
44 using namespace VectorMath; 44 using namespace VectorMath;
45 45
46 WaveTable* OscillatorNode::s_waveTableSine = 0; 46 PeriodicWave* OscillatorNode::s_periodicWaveSine = 0;
47 WaveTable* OscillatorNode::s_waveTableSquare = 0; 47 PeriodicWave* OscillatorNode::s_periodicWaveSquare = 0;
48 WaveTable* OscillatorNode::s_waveTableSawtooth = 0; 48 PeriodicWave* OscillatorNode::s_periodicWaveSawtooth = 0;
49 WaveTable* OscillatorNode::s_waveTableTriangle = 0; 49 PeriodicWave* OscillatorNode::s_periodicWaveTriangle = 0;
50 50
51 PassRefPtr<OscillatorNode> OscillatorNode::create(AudioContext* context, float s ampleRate) 51 PassRefPtr<OscillatorNode> OscillatorNode::create(AudioContext* context, float s ampleRate)
52 { 52 {
53 return adoptRef(new OscillatorNode(context, sampleRate)); 53 return adoptRef(new OscillatorNode(context, sampleRate));
54 } 54 }
55 55
56 OscillatorNode::OscillatorNode(AudioContext* context, float sampleRate) 56 OscillatorNode::OscillatorNode(AudioContext* context, float sampleRate)
57 : AudioScheduledSourceNode(context, sampleRate) 57 : AudioScheduledSourceNode(context, sampleRate)
58 , m_type(SINE) 58 , m_type(SINE)
59 , m_firstRender(true) 59 , m_firstRender(true)
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 else if (type == "sawtooth") 111 else if (type == "sawtooth")
112 setType(SAWTOOTH); 112 setType(SAWTOOTH);
113 else if (type == "triangle") 113 else if (type == "triangle")
114 setType(TRIANGLE); 114 setType(TRIANGLE);
115 else 115 else
116 ASSERT_NOT_REACHED(); 116 ASSERT_NOT_REACHED();
117 } 117 }
118 118
119 bool OscillatorNode::setType(unsigned type) 119 bool OscillatorNode::setType(unsigned type)
120 { 120 {
121 WaveTable* waveTable = 0; 121 PeriodicWave* periodicWave = 0;
122 float sampleRate = this->sampleRate(); 122 float sampleRate = this->sampleRate();
123 123
124 switch (type) { 124 switch (type) {
125 case SINE: 125 case SINE:
126 if (!s_waveTableSine) 126 if (!s_periodicWaveSine)
127 s_waveTableSine = WaveTable::createSine(sampleRate).leakRef(); 127 s_periodicWaveSine = PeriodicWave::createSine(sampleRate).leakRef();
128 waveTable = s_waveTableSine; 128 periodicWave = s_periodicWaveSine;
129 break; 129 break;
130 case SQUARE: 130 case SQUARE:
131 if (!s_waveTableSquare) 131 if (!s_periodicWaveSquare)
132 s_waveTableSquare = WaveTable::createSquare(sampleRate).leakRef(); 132 s_periodicWaveSquare = PeriodicWave::createSquare(sampleRate).leakRe f();
133 waveTable = s_waveTableSquare; 133 periodicWave = s_periodicWaveSquare;
134 break; 134 break;
135 case SAWTOOTH: 135 case SAWTOOTH:
136 if (!s_waveTableSawtooth) 136 if (!s_periodicWaveSawtooth)
137 s_waveTableSawtooth = WaveTable::createSawtooth(sampleRate).leakRef( ); 137 s_periodicWaveSawtooth = PeriodicWave::createSawtooth(sampleRate).le akRef();
138 waveTable = s_waveTableSawtooth; 138 periodicWave = s_periodicWaveSawtooth;
139 break; 139 break;
140 case TRIANGLE: 140 case TRIANGLE:
141 if (!s_waveTableTriangle) 141 if (!s_periodicWaveTriangle)
142 s_waveTableTriangle = WaveTable::createTriangle(sampleRate).leakRef( ); 142 s_periodicWaveTriangle = PeriodicWave::createTriangle(sampleRate).le akRef();
143 waveTable = s_waveTableTriangle; 143 periodicWave = s_periodicWaveTriangle;
144 break; 144 break;
145 case CUSTOM: 145 case CUSTOM:
146 default: 146 default:
147 // Return error for invalid types, including CUSTOM since setWaveTable() method must be 147 // Return error for invalid types, including CUSTOM since setPeriodicWav e() method must be
148 // called explicitly. 148 // called explicitly.
149 return false; 149 return false;
150 } 150 }
151 151
152 setWaveTable(waveTable); 152 setPeriodicWave(periodicWave);
153 m_type = type; 153 m_type = type;
154 return true; 154 return true;
155 } 155 }
156 156
157 bool OscillatorNode::calculateSampleAccuratePhaseIncrements(size_t framesToProce ss) 157 bool OscillatorNode::calculateSampleAccuratePhaseIncrements(size_t framesToProce ss)
158 { 158 {
159 bool isGood = framesToProcess <= m_phaseIncrements.size() && framesToProcess <= m_detuneValues.size(); 159 bool isGood = framesToProcess <= m_phaseIncrements.size() && framesToProcess <= m_detuneValues.size();
160 ASSERT(isGood); 160 ASSERT(isGood);
161 if (!isGood) 161 if (!isGood)
162 return false; 162 return false;
163 163
164 if (m_firstRender) { 164 if (m_firstRender) {
165 m_firstRender = false; 165 m_firstRender = false;
166 m_frequency->resetSmoothedValue(); 166 m_frequency->resetSmoothedValue();
167 m_detune->resetSmoothedValue(); 167 m_detune->resetSmoothedValue();
168 } 168 }
169 169
170 bool hasSampleAccurateValues = false; 170 bool hasSampleAccurateValues = false;
171 bool hasFrequencyChanges = false; 171 bool hasFrequencyChanges = false;
172 float* phaseIncrements = m_phaseIncrements.data(); 172 float* phaseIncrements = m_phaseIncrements.data();
173 173
174 float finalScale = m_waveTable->rateScale(); 174 float finalScale = m_periodicWave->rateScale();
175 175
176 if (m_frequency->hasSampleAccurateValues()) { 176 if (m_frequency->hasSampleAccurateValues()) {
177 hasSampleAccurateValues = true; 177 hasSampleAccurateValues = true;
178 hasFrequencyChanges = true; 178 hasFrequencyChanges = true;
179 179
180 // Get the sample-accurate frequency values and convert to phase increme nts. 180 // Get the sample-accurate frequency values and convert to phase increme nts.
181 // They will be converted to phase increments below. 181 // They will be converted to phase increments below.
182 m_frequency->calculateSampleAccurateValues(phaseIncrements, framesToProc ess); 182 m_frequency->calculateSampleAccurateValues(phaseIncrements, framesToProc ess);
183 } else { 183 } else {
184 // Handle ordinary parameter smoothing/de-zippering if there are no sche duled changes. 184 // Handle ordinary parameter smoothing/de-zippering if there are no sche duled changes.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 return; 234 return;
235 235
236 // The audio thread can't block on this lock, so we call tryLock() instead. 236 // The audio thread can't block on this lock, so we call tryLock() instead.
237 MutexTryLocker tryLocker(m_processLock); 237 MutexTryLocker tryLocker(m_processLock);
238 if (!tryLocker.locked()) { 238 if (!tryLocker.locked()) {
239 // Too bad - the tryLock() failed. We must be in the middle of changing wave-tables. 239 // Too bad - the tryLock() failed. We must be in the middle of changing wave-tables.
240 outputBus->zero(); 240 outputBus->zero();
241 return; 241 return;
242 } 242 }
243 243
244 // We must access m_waveTable only inside the lock. 244 // We must access m_periodicWave only inside the lock.
245 if (!m_waveTable.get()) { 245 if (!m_periodicWave.get()) {
246 outputBus->zero(); 246 outputBus->zero();
247 return; 247 return;
248 } 248 }
249 249
250 size_t quantumFrameOffset; 250 size_t quantumFrameOffset;
251 size_t nonSilentFramesToProcess; 251 size_t nonSilentFramesToProcess;
252 252
253 updateSchedulingInfo(framesToProcess, outputBus, quantumFrameOffset, nonSile ntFramesToProcess); 253 updateSchedulingInfo(framesToProcess, outputBus, quantumFrameOffset, nonSile ntFramesToProcess);
254 254
255 if (!nonSilentFramesToProcess) { 255 if (!nonSilentFramesToProcess) {
256 outputBus->zero(); 256 outputBus->zero();
257 return; 257 return;
258 } 258 }
259 259
260 unsigned waveTableSize = m_waveTable->waveTableSize(); 260 unsigned periodicWaveSize = m_periodicWave->periodicWaveSize();
261 double invWaveTableSize = 1.0 / waveTableSize; 261 double invPeriodicWaveSize = 1.0 / periodicWaveSize;
262 262
263 float* destP = outputBus->channel(0)->mutableData(); 263 float* destP = outputBus->channel(0)->mutableData();
264 264
265 ASSERT(quantumFrameOffset <= framesToProcess); 265 ASSERT(quantumFrameOffset <= framesToProcess);
266 266
267 // We keep virtualReadIndex double-precision since we're accumulating values . 267 // We keep virtualReadIndex double-precision since we're accumulating values .
268 double virtualReadIndex = m_virtualReadIndex; 268 double virtualReadIndex = m_virtualReadIndex;
269 269
270 float rateScale = m_waveTable->rateScale(); 270 float rateScale = m_periodicWave->rateScale();
271 float invRateScale = 1 / rateScale; 271 float invRateScale = 1 / rateScale;
272 bool hasSampleAccurateValues = calculateSampleAccuratePhaseIncrements(frames ToProcess); 272 bool hasSampleAccurateValues = calculateSampleAccuratePhaseIncrements(frames ToProcess);
273 273
274 float frequency = 0; 274 float frequency = 0;
275 float* higherWaveData = 0; 275 float* higherWaveData = 0;
276 float* lowerWaveData = 0; 276 float* lowerWaveData = 0;
277 float tableInterpolationFactor; 277 float tableInterpolationFactor;
278 278
279 if (!hasSampleAccurateValues) { 279 if (!hasSampleAccurateValues) {
280 frequency = m_frequency->smoothedValue(); 280 frequency = m_frequency->smoothedValue();
281 float detune = m_detune->smoothedValue(); 281 float detune = m_detune->smoothedValue();
282 float detuneScale = powf(2, detune / 1200); 282 float detuneScale = powf(2, detune / 1200);
283 frequency *= detuneScale; 283 frequency *= detuneScale;
284 m_waveTable->waveDataForFundamentalFrequency(frequency, lowerWaveData, h igherWaveData, tableInterpolationFactor); 284 m_periodicWave->waveDataForFundamentalFrequency(frequency, lowerWaveData , higherWaveData, tableInterpolationFactor);
285 } 285 }
286 286
287 float incr = frequency * rateScale; 287 float incr = frequency * rateScale;
288 float* phaseIncrements = m_phaseIncrements.data(); 288 float* phaseIncrements = m_phaseIncrements.data();
289 289
290 unsigned readIndexMask = waveTableSize - 1; 290 unsigned readIndexMask = periodicWaveSize - 1;
291 291
292 // Start rendering at the correct offset. 292 // Start rendering at the correct offset.
293 destP += quantumFrameOffset; 293 destP += quantumFrameOffset;
294 int n = nonSilentFramesToProcess; 294 int n = nonSilentFramesToProcess;
295 295
296 while (n--) { 296 while (n--) {
297 unsigned readIndex = static_cast<unsigned>(virtualReadIndex); 297 unsigned readIndex = static_cast<unsigned>(virtualReadIndex);
298 unsigned readIndex2 = readIndex + 1; 298 unsigned readIndex2 = readIndex + 1;
299 299
300 // Contain within valid range. 300 // Contain within valid range.
301 readIndex = readIndex & readIndexMask; 301 readIndex = readIndex & readIndexMask;
302 readIndex2 = readIndex2 & readIndexMask; 302 readIndex2 = readIndex2 & readIndexMask;
303 303
304 if (hasSampleAccurateValues) { 304 if (hasSampleAccurateValues) {
305 incr = *phaseIncrements++; 305 incr = *phaseIncrements++;
306 306
307 frequency = invRateScale * incr; 307 frequency = invRateScale * incr;
308 m_waveTable->waveDataForFundamentalFrequency(frequency, lowerWaveDat a, higherWaveData, tableInterpolationFactor); 308 m_periodicWave->waveDataForFundamentalFrequency(frequency, lowerWave Data, higherWaveData, tableInterpolationFactor);
309 } 309 }
310 310
311 float sample1Lower = lowerWaveData[readIndex]; 311 float sample1Lower = lowerWaveData[readIndex];
312 float sample2Lower = lowerWaveData[readIndex2]; 312 float sample2Lower = lowerWaveData[readIndex2];
313 float sample1Higher = higherWaveData[readIndex]; 313 float sample1Higher = higherWaveData[readIndex];
314 float sample2Higher = higherWaveData[readIndex2]; 314 float sample2Higher = higherWaveData[readIndex2];
315 315
316 // Linearly interpolate within each table (lower and higher). 316 // Linearly interpolate within each table (lower and higher).
317 float interpolationFactor = static_cast<float>(virtualReadIndex) - readI ndex; 317 float interpolationFactor = static_cast<float>(virtualReadIndex) - readI ndex;
318 float sampleHigher = (1 - interpolationFactor) * sample1Higher + interpo lationFactor * sample2Higher; 318 float sampleHigher = (1 - interpolationFactor) * sample1Higher + interpo lationFactor * sample2Higher;
319 float sampleLower = (1 - interpolationFactor) * sample1Lower + interpola tionFactor * sample2Lower; 319 float sampleLower = (1 - interpolationFactor) * sample1Lower + interpola tionFactor * sample2Lower;
320 320
321 // Then interpolate between the two tables. 321 // Then interpolate between the two tables.
322 float sample = (1 - tableInterpolationFactor) * sampleHigher + tableInte rpolationFactor * sampleLower; 322 float sample = (1 - tableInterpolationFactor) * sampleHigher + tableInte rpolationFactor * sampleLower;
323 323
324 *destP++ = sample; 324 *destP++ = sample;
325 325
326 // Increment virtual read index and wrap virtualReadIndex into the range 0 -> waveTableSize. 326 // Increment virtual read index and wrap virtualReadIndex into the range 0 -> periodicWaveSize.
327 virtualReadIndex += incr; 327 virtualReadIndex += incr;
328 virtualReadIndex -= floor(virtualReadIndex * invWaveTableSize) * waveTab leSize; 328 virtualReadIndex -= floor(virtualReadIndex * invPeriodicWaveSize) * peri odicWaveSize;
329 } 329 }
330 330
331 m_virtualReadIndex = virtualReadIndex; 331 m_virtualReadIndex = virtualReadIndex;
332 332
333 outputBus->clearSilentFlag(); 333 outputBus->clearSilentFlag();
334 } 334 }
335 335
336 void OscillatorNode::reset() 336 void OscillatorNode::reset()
337 { 337 {
338 m_virtualReadIndex = 0; 338 m_virtualReadIndex = 0;
339 } 339 }
340 340
341 void OscillatorNode::setWaveTable(WaveTable* waveTable) 341 void OscillatorNode::setPeriodicWave(PeriodicWave* periodicWave)
342 { 342 {
343 ASSERT(isMainThread()); 343 ASSERT(isMainThread());
344 344
345 // This synchronizes with process(). 345 // This synchronizes with process().
346 MutexLocker processLocker(m_processLock); 346 MutexLocker processLocker(m_processLock);
347 m_waveTable = waveTable; 347 m_periodicWave = periodicWave;
348 m_type = CUSTOM; 348 m_type = CUSTOM;
349 } 349 }
350 350
351 bool OscillatorNode::propagatesSilence() const 351 bool OscillatorNode::propagatesSilence() const
352 { 352 {
353 return !isPlayingOrScheduled() || hasFinished() || !m_waveTable.get(); 353 return !isPlayingOrScheduled() || hasFinished() || !m_periodicWave.get();
354 } 354 }
355 355
356 } // namespace WebCore 356 } // namespace WebCore
357 357
358 #endif // ENABLE(WEB_AUDIO) 358 #endif // ENABLE(WEB_AUDIO)
OLDNEW
« no previous file with comments | « Source/modules/webaudio/OscillatorNode.h ('k') | Source/modules/webaudio/OscillatorNode.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698