 Chromium Code Reviews
 Chromium Code Reviews Issue 2732523003:
  Make ConvolverNode conform to spec  (Closed)
    
  
    Issue 2732523003:
  Make ConvolverNode conform to spec  (Closed) 
  | 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 30 matching lines...) Expand all Loading... | |
| 41 // a good value. But, the Reverb object is multi-threaded, so we want this as | 41 // a good value. But, the Reverb object is multi-threaded, so we want this as | 
| 42 // high as possible without losing too much accuracy. Very large FFTs will have | 42 // high as possible without losing too much accuracy. Very large FFTs will have | 
| 43 // worse phase errors. Given these constraints 32768 is a good compromise. | 43 // worse phase errors. Given these constraints 32768 is a good compromise. | 
| 44 const size_t MaxFFTSize = 32768; | 44 const size_t MaxFFTSize = 32768; | 
| 45 | 45 | 
| 46 namespace blink { | 46 namespace blink { | 
| 47 | 47 | 
| 48 ConvolverHandler::ConvolverHandler(AudioNode& node, float sampleRate) | 48 ConvolverHandler::ConvolverHandler(AudioNode& node, float sampleRate) | 
| 49 : AudioHandler(NodeTypeConvolver, node, sampleRate), m_normalize(true) { | 49 : AudioHandler(NodeTypeConvolver, node, sampleRate), m_normalize(true) { | 
| 50 addInput(); | 50 addInput(); | 
| 51 addOutput(2); | 51 addOutput(1); | 
| 
hongchan
2017/03/28 16:44:35
Why 1? The default channel value is 1 and then can
 
Raymond Toy
2017/03/28 17:34:49
We start the convolver with 1 output channel.  m_c
 
hongchan
2017/03/28 19:01:43
Acknowledged.
 | |
| 52 | 52 | 
| 53 // Node-specific default mixing rules. | 53 // Node-specific default mixing rules. | 
| 54 m_channelCount = 2; | 54 m_channelCount = 2; | 
| 55 setInternalChannelCountMode(ClampedMax); | 55 setInternalChannelCountMode(ClampedMax); | 
| 56 setInternalChannelInterpretation(AudioBus::Speakers); | 56 setInternalChannelInterpretation(AudioBus::Speakers); | 
| 57 | 57 | 
| 58 initialize(); | 58 initialize(); | 
| 59 } | 59 } | 
| 60 | 60 | 
| 61 PassRefPtr<ConvolverHandler> ConvolverHandler::create(AudioNode& node, | 61 PassRefPtr<ConvolverHandler> ConvolverHandler::create(AudioNode& node, | 
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 // reference to it is kept for later use in that class. | 129 // reference to it is kept for later use in that class. | 
| 130 RefPtr<AudioBus> bufferBus = | 130 RefPtr<AudioBus> bufferBus = | 
| 131 AudioBus::create(numberOfChannels, bufferLength, false); | 131 AudioBus::create(numberOfChannels, bufferLength, false); | 
| 132 for (unsigned i = 0; i < numberOfChannels; ++i) | 132 for (unsigned i = 0; i < numberOfChannels; ++i) | 
| 133 bufferBus->setChannelMemory(i, buffer->getChannelData(i)->data(), | 133 bufferBus->setChannelMemory(i, buffer->getChannelData(i)->data(), | 
| 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( | 
| 140 bufferBus.get(), AudioUtilities::kRenderQuantumFrames, MaxFFTSize, 2, | 140 new Reverb(bufferBus.get(), AudioUtilities::kRenderQuantumFrames, | 
| 141 context() && context()->hasRealtimeConstraint(), m_normalize)); | 141 MaxFFTSize, numberOfChannels, | 
| 142 context() && context()->hasRealtimeConstraint(), m_normalize)); | |
| 142 | 143 | 
| 143 { | 144 { | 
| 144 // Synchronize with process(). | 145 // Synchronize with process(). | 
| 145 MutexLocker locker(m_processLock); | 146 MutexLocker locker(m_processLock); | 
| 146 m_reverb = std::move(reverb); | 147 m_reverb = std::move(reverb); | 
| 147 m_buffer = buffer; | 148 m_buffer = buffer; | 
| 148 } | 149 } | 
| 149 } | 150 } | 
| 150 | 151 | 
| 151 AudioBuffer* ConvolverHandler::buffer() { | 152 AudioBuffer* ConvolverHandler::buffer() { | 
| (...skipping 18 matching lines...) Expand all Loading... | |
| 170 if (tryLocker.locked()) | 171 if (tryLocker.locked()) | 
| 171 return m_reverb | 172 return m_reverb | 
| 172 ? m_reverb->latencyFrames() / | 173 ? m_reverb->latencyFrames() / | 
| 173 static_cast<double>(context()->sampleRate()) | 174 static_cast<double>(context()->sampleRate()) | 
| 174 : 0; | 175 : 0; | 
| 175 // Since we don't want to block the Audio Device thread, we return a large | 176 // Since we don't want to block the Audio Device thread, we return a large | 
| 176 // value instead of trying to acquire the lock. | 177 // value instead of trying to acquire the lock. | 
| 177 return std::numeric_limits<double>::infinity(); | 178 return std::numeric_limits<double>::infinity(); | 
| 178 } | 179 } | 
| 179 | 180 | 
| 181 void ConvolverHandler::setChannelCount(unsigned long channelCount, | |
| 182 ExceptionState& exceptionState) { | |
| 183 DCHECK(isMainThread()); | |
| 184 BaseAudioContext::AutoLocker locker(context()); | |
| 185 | |
| 186 // channelCount must be 2. | |
| 187 if (channelCount != 2) { | |
| 
hongchan
2017/03/28 16:44:35
If this cannot be changed, why did we start from 1
 
Raymond Toy
2017/03/28 17:34:49
m_channelCount is initialized to 2.
 
hongchan
2017/03/28 19:01:43
Acknowledged.
 | |
| 188 exceptionState.throwDOMException( | |
| 189 NotSupportedError, | |
| 190 "ConvolverNode: channelCount cannot be changed from 2"); | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 void ConvolverHandler::setChannelCountMode(const String& mode, | |
| 195 ExceptionState& exceptionState) { | |
| 196 DCHECK(isMainThread()); | |
| 197 BaseAudioContext::AutoLocker locker(context()); | |
| 198 | |
| 199 // channcelCountMode must be 'clamped-max'. | |
| 200 if (mode != "clamped-max") { | |
| 201 exceptionState.throwDOMException( | |
| 202 NotSupportedError, | |
| 203 "ConvolverNode: channelCountMode cannot be changed from 'clamped-max'"); | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 void ConvolverHandler::checkNumberOfChannelsForInput(AudioNodeInput* input) { | |
| 208 DCHECK(context()->isAudioThread()); | |
| 209 #if DCHECK_IS_ON() | |
| 210 DCHECK(context()->isGraphOwner()); | |
| 211 #endif | |
| 212 | |
| 213 DCHECK(input); | |
| 214 DCHECK_EQ(input, &this->input(0)); | |
| 215 if (input != &this->input(0)) | |
| 216 return; | |
| 217 | |
| 218 if (m_buffer) { | |
| 219 unsigned numberOfChannels = input->numberOfChannels(); | |
| 220 unsigned numReverbChannels = m_buffer->numberOfChannels(); | |
| 
hongchan
2017/03/28 16:44:35
numReverbChannels => numberOfReverbChannels
 
Raymond Toy
2017/03/28 17:34:49
I was following the style in other parts of this f
 | |
| 221 unsigned numOutputsDesired = | |
| 
hongchan
2017/03/28 16:44:35
Ditto. I think it's better to spell out as much as
 | |
| 222 std::min(2u, std::max(numberOfChannels, numReverbChannels)); | |
| 223 | |
| 224 if (isInitialized() && numOutputsDesired != output(0).numberOfChannels()) { | |
| 225 // We're already initialized but the channel count has changed. | |
| 226 uninitialize(); | |
| 227 } | |
| 228 | |
| 229 if (!isInitialized()) { | |
| 230 // This will propagate the channel count to any nodes connected further | |
| 231 // downstream in the graph. | |
| 232 output(0).setNumberOfChannels(numOutputsDesired); | |
| 233 initialize(); | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 // Update the input's internal bus if needed. | |
| 238 AudioHandler::checkNumberOfChannelsForInput(input); | |
| 239 } | |
| 180 // ---------------------------------------------------------------- | 240 // ---------------------------------------------------------------- | 
| 181 | 241 | 
| 182 ConvolverNode::ConvolverNode(BaseAudioContext& context) : AudioNode(context) { | 242 ConvolverNode::ConvolverNode(BaseAudioContext& context) : AudioNode(context) { | 
| 183 setHandler(ConvolverHandler::create(*this, context.sampleRate())); | 243 setHandler(ConvolverHandler::create(*this, context.sampleRate())); | 
| 184 } | 244 } | 
| 185 | 245 | 
| 186 ConvolverNode* ConvolverNode::create(BaseAudioContext& context, | 246 ConvolverNode* ConvolverNode::create(BaseAudioContext& context, | 
| 187 ExceptionState& exceptionState) { | 247 ExceptionState& exceptionState) { | 
| 188 DCHECK(isMainThread()); | 248 DCHECK(isMainThread()); | 
| 189 | 249 | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 | 288 | 
| 229 bool ConvolverNode::normalize() const { | 289 bool ConvolverNode::normalize() const { | 
| 230 return convolverHandler().normalize(); | 290 return convolverHandler().normalize(); | 
| 231 } | 291 } | 
| 232 | 292 | 
| 233 void ConvolverNode::setNormalize(bool normalize) { | 293 void ConvolverNode::setNormalize(bool normalize) { | 
| 234 convolverHandler().setNormalize(normalize); | 294 convolverHandler().setNormalize(normalize); | 
| 235 } | 295 } | 
| 236 | 296 | 
| 237 } // namespace blink | 297 } // namespace blink | 
| OLD | NEW |