OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 const double MaxRate = 1024; | 51 const double MaxRate = 1024; |
52 | 52 |
53 PassRefPtr<AudioBufferSourceNode> AudioBufferSourceNode::create(AudioContext* co
ntext, float sampleRate) | 53 PassRefPtr<AudioBufferSourceNode> AudioBufferSourceNode::create(AudioContext* co
ntext, float sampleRate) |
54 { | 54 { |
55 return adoptRef(new AudioBufferSourceNode(context, sampleRate)); | 55 return adoptRef(new AudioBufferSourceNode(context, sampleRate)); |
56 } | 56 } |
57 | 57 |
58 AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context, float sample
Rate) | 58 AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context, float sample
Rate) |
59 : AudioScheduledSourceNode(context, sampleRate) | 59 : AudioScheduledSourceNode(context, sampleRate) |
60 , m_buffer(nullptr) | 60 , m_buffer(nullptr) |
| 61 , m_nullableBuffer(nullptr) |
61 , m_isLooping(false) | 62 , m_isLooping(false) |
62 , m_loopStart(0) | 63 , m_loopStart(0) |
63 , m_loopEnd(0) | 64 , m_loopEnd(0) |
64 , m_virtualReadIndex(0) | 65 , m_virtualReadIndex(0) |
65 , m_isGrain(false) | 66 , m_isGrain(false) |
66 , m_grainOffset(0.0) | 67 , m_grainOffset(0.0) |
67 , m_grainDuration(DefaultGrainDuration) | 68 , m_grainDuration(DefaultGrainDuration) |
68 , m_lastGain(1.0) | 69 , m_lastGain(1.0) |
69 , m_pannerNode(0) | 70 , m_pannerNode(0) |
70 { | 71 { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 if (!loop()) { | 150 if (!loop()) { |
150 // If we're not looping, then stop playing when we get to the end. | 151 // If we're not looping, then stop playing when we get to the end. |
151 | 152 |
152 if (framesToProcess > 0) { | 153 if (framesToProcess > 0) { |
153 // We're not looping and we've reached the end of the sample data, b
ut we still need to provide more output, | 154 // We're not looping and we've reached the end of the sample data, b
ut we still need to provide more output, |
154 // so generate silence for the remaining. | 155 // so generate silence for the remaining. |
155 for (unsigned i = 0; i < numberOfChannels(); ++i) | 156 for (unsigned i = 0; i < numberOfChannels(); ++i) |
156 memset(m_destinationChannels[i] + index, 0, sizeof(float) * fram
esToProcess); | 157 memset(m_destinationChannels[i] + index, 0, sizeof(float) * fram
esToProcess); |
157 } | 158 } |
158 | 159 |
159 finish(); | 160 // If buffer was set to null, it sould keep to render slience to ready r
endering with proper buffer with setBuffer(). |
| 161 if (m_buffer != m_nullableBuffer) |
| 162 finish(); |
| 163 |
160 return true; | 164 return true; |
161 } | 165 } |
162 return false; | 166 return false; |
163 } | 167 } |
164 | 168 |
165 bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destination
FrameOffset, size_t numberOfFrames) | 169 bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destination
FrameOffset, size_t numberOfFrames) |
166 { | 170 { |
167 ASSERT(context()->isAudioThread()); | 171 ASSERT(context()->isAudioThread()); |
168 | 172 |
169 // Basic sanity checking | 173 // Basic sanity checking |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 | 331 |
328 m_virtualReadIndex = virtualReadIndex; | 332 m_virtualReadIndex = virtualReadIndex; |
329 | 333 |
330 return true; | 334 return true; |
331 } | 335 } |
332 | 336 |
333 | 337 |
334 void AudioBufferSourceNode::setBuffer(AudioBuffer* buffer, ExceptionState& excep
tionState) | 338 void AudioBufferSourceNode::setBuffer(AudioBuffer* buffer, ExceptionState& excep
tionState) |
335 { | 339 { |
336 ASSERT(isMainThread()); | 340 ASSERT(isMainThread()); |
337 // FIXME: It does not look like we should throw if the buffer is null as | 341 |
338 // the attribute is nullable in the specification. | 342 // If a buffer is null, it is one channel of silence according to specificat
ion. |
339 if (!buffer) { | 343 if (!buffer) { |
340 exceptionState.throwTypeError("buffer cannot be null"); | 344 // Set mono channel, default frame = 512 and destination's sampleRate. |
341 return; | 345 if (!m_nullableBuffer) |
| 346 m_nullableBuffer = context()->createBuffer(1, 512, context()->sample
Rate(), exceptionState); |
| 347 |
| 348 if (!m_nullableBuffer) { |
| 349 exceptionState.throwTypeError("failed creation of nullable buffer"); |
| 350 return; |
| 351 } |
| 352 |
| 353 buffer = m_nullableBuffer.get(); |
342 } | 354 } |
343 | 355 |
344 // The context must be locked since changing the buffer can re-configure the
number of channels that are output. | 356 // The context must be locked since changing the buffer can re-configure the
number of channels that are output. |
345 AudioContext::AutoLocker contextLocker(context()); | 357 AudioContext::AutoLocker contextLocker(context()); |
346 | 358 |
347 // This synchronizes with process(). | 359 // This synchronizes with process(). |
348 MutexLocker processLocker(m_processLock); | 360 MutexLocker processLocker(m_processLock); |
349 | 361 |
350 if (buffer) { | 362 if (buffer) { |
351 // Do any necesssary re-configuration to the buffer's number of channels
. | 363 // Do any necesssary re-configuration to the buffer's number of channels
. |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 void AudioBufferSourceNode::finish() | 515 void AudioBufferSourceNode::finish() |
504 { | 516 { |
505 clearPannerNode(); | 517 clearPannerNode(); |
506 ASSERT(!m_pannerNode); | 518 ASSERT(!m_pannerNode); |
507 AudioScheduledSourceNode::finish(); | 519 AudioScheduledSourceNode::finish(); |
508 } | 520 } |
509 | 521 |
510 } // namespace WebCore | 522 } // namespace WebCore |
511 | 523 |
512 #endif // ENABLE(WEB_AUDIO) | 524 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |