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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 bufferLength); | 134 bufferLength); |
135 | 135 |
136 bufferBus->setSampleRate(buffer->sampleRate()); | 136 bufferBus->setSampleRate(buffer->sampleRate()); |
137 | 137 |
138 // Create the reverb with the given impulse response. | 138 // Create the reverb with the given impulse response. |
139 std::unique_ptr<Reverb> reverb = WTF::wrapUnique(new Reverb( | 139 std::unique_ptr<Reverb> reverb = WTF::wrapUnique(new Reverb( |
140 bufferBus.get(), AudioUtilities::kRenderQuantumFrames, MaxFFTSize, | 140 bufferBus.get(), AudioUtilities::kRenderQuantumFrames, MaxFFTSize, |
141 context() && context()->hasRealtimeConstraint(), m_normalize)); | 141 context() && context()->hasRealtimeConstraint(), m_normalize)); |
142 | 142 |
143 { | 143 { |
| 144 // The context must be locked since changing the buffer can |
| 145 // re-configure the number of channels that are output. |
| 146 BaseAudioContext::AutoLocker contextLocker(context()); |
| 147 |
144 // Synchronize with process(). | 148 // Synchronize with process(). |
145 MutexLocker locker(m_processLock); | 149 MutexLocker locker(m_processLock); |
146 m_reverb = std::move(reverb); | 150 m_reverb = std::move(reverb); |
147 m_buffer = buffer; | 151 m_buffer = buffer; |
| 152 if (buffer) { |
| 153 // This will propagate the channel count to any nodes connected further |
| 154 // downstream in the graph. |
| 155 output(0).setNumberOfChannels(computeNumberOfOutputChannels( |
| 156 input(0).numberOfChannels(), m_buffer->numberOfChannels())); |
| 157 } |
148 } | 158 } |
149 } | 159 } |
150 | 160 |
151 AudioBuffer* ConvolverHandler::buffer() { | 161 AudioBuffer* ConvolverHandler::buffer() { |
152 DCHECK(isMainThread()); | 162 DCHECK(isMainThread()); |
153 return m_buffer.get(); | 163 return m_buffer.get(); |
154 } | 164 } |
155 | 165 |
156 double ConvolverHandler::tailTime() const { | 166 double ConvolverHandler::tailTime() const { |
157 MutexTryLocker tryLocker(m_processLock); | 167 MutexTryLocker tryLocker(m_processLock); |
(...skipping 12 matching lines...) Expand all Loading... |
170 if (tryLocker.locked()) | 180 if (tryLocker.locked()) |
171 return m_reverb | 181 return m_reverb |
172 ? m_reverb->latencyFrames() / | 182 ? m_reverb->latencyFrames() / |
173 static_cast<double>(context()->sampleRate()) | 183 static_cast<double>(context()->sampleRate()) |
174 : 0; | 184 : 0; |
175 // Since we don't want to block the Audio Device thread, we return a large | 185 // Since we don't want to block the Audio Device thread, we return a large |
176 // value instead of trying to acquire the lock. | 186 // value instead of trying to acquire the lock. |
177 return std::numeric_limits<double>::infinity(); | 187 return std::numeric_limits<double>::infinity(); |
178 } | 188 } |
179 | 189 |
| 190 unsigned ConvolverHandler::computeNumberOfOutputChannels( |
| 191 unsigned inputChannels, |
| 192 unsigned responseChannels) const { |
| 193 // The number of output channels for a Convolver must be one or two. |
| 194 // And can only be one if there's a mono source and a mono response |
| 195 // buffer. |
| 196 return clampTo(std::max(inputChannels, responseChannels), 1, 2); |
| 197 } |
| 198 |
180 void ConvolverHandler::setChannelCount(unsigned long channelCount, | 199 void ConvolverHandler::setChannelCount(unsigned long channelCount, |
181 ExceptionState& exceptionState) { | 200 ExceptionState& exceptionState) { |
182 DCHECK(isMainThread()); | 201 DCHECK(isMainThread()); |
183 BaseAudioContext::AutoLocker locker(context()); | 202 BaseAudioContext::AutoLocker locker(context()); |
184 | 203 |
185 // channelCount must be 2. | 204 // channelCount must be 2. |
186 if (channelCount != 2) { | 205 if (channelCount != 2) { |
187 exceptionState.throwDOMException( | 206 exceptionState.throwDOMException( |
188 NotSupportedError, | 207 NotSupportedError, |
189 "ConvolverNode: channelCount cannot be changed from 2"); | 208 "ConvolverNode: channelCount cannot be changed from 2"); |
(...skipping 18 matching lines...) Expand all Loading... |
208 #if DCHECK_IS_ON() | 227 #if DCHECK_IS_ON() |
209 DCHECK(context()->isGraphOwner()); | 228 DCHECK(context()->isGraphOwner()); |
210 #endif | 229 #endif |
211 | 230 |
212 DCHECK(input); | 231 DCHECK(input); |
213 DCHECK_EQ(input, &this->input(0)); | 232 DCHECK_EQ(input, &this->input(0)); |
214 if (input != &this->input(0)) | 233 if (input != &this->input(0)) |
215 return; | 234 return; |
216 | 235 |
217 if (m_buffer) { | 236 if (m_buffer) { |
218 unsigned numberOfChannels = input->numberOfChannels(); | 237 unsigned numberOfOutputChannels = computeNumberOfOutputChannels( |
219 unsigned numberOfReverbeChannels = m_buffer->numberOfChannels(); | 238 input->numberOfChannels(), m_buffer->numberOfChannels()); |
220 unsigned numberOfOutputChannels = | |
221 std::min(2u, std::max(numberOfChannels, numberOfReverbeChannels)); | |
222 | 239 |
223 if (isInitialized() && | 240 if (isInitialized() && |
224 numberOfOutputChannels != output(0).numberOfChannels()) { | 241 numberOfOutputChannels != output(0).numberOfChannels()) { |
225 // We're already initialized but the channel count has changed. | 242 // We're already initialized but the channel count has changed. |
226 uninitialize(); | 243 uninitialize(); |
227 } | 244 } |
228 | 245 |
229 if (!isInitialized()) { | 246 if (!isInitialized()) { |
230 // This will propagate the channel count to any nodes connected further | 247 // This will propagate the channel count to any nodes connected further |
231 // downstream in the graph. | 248 // downstream in the graph. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 | 305 |
289 bool ConvolverNode::normalize() const { | 306 bool ConvolverNode::normalize() const { |
290 return convolverHandler().normalize(); | 307 return convolverHandler().normalize(); |
291 } | 308 } |
292 | 309 |
293 void ConvolverNode::setNormalize(bool normalize) { | 310 void ConvolverNode::setNormalize(bool normalize) { |
294 convolverHandler().setNormalize(normalize); | 311 convolverHandler().setNormalize(normalize); |
295 } | 312 } |
296 | 313 |
297 } // namespace blink | 314 } // namespace blink |
OLD | NEW |