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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 if (tryLocker.locked() && tryListenerLocker.locked()) { | 121 if (tryLocker.locked() && tryListenerLocker.locked()) { |
122 if (!context()->hasRealtimeConstraint() && | 122 if (!context()->hasRealtimeConstraint() && |
123 m_panningModel == Panner::PanningModelHRTF) { | 123 m_panningModel == Panner::PanningModelHRTF) { |
124 // For an OfflineAudioContext, we need to make sure the HRTFDatabase | 124 // For an OfflineAudioContext, we need to make sure the HRTFDatabase |
125 // is loaded before proceeding. For realtime contexts, we don't | 125 // is loaded before proceeding. For realtime contexts, we don't |
126 // have to wait. The HRTF panner handles that case itself. | 126 // have to wait. The HRTF panner handles that case itself. |
127 listener()->waitForHRTFDatabaseLoaderThreadCompletion(); | 127 listener()->waitForHRTFDatabaseLoaderThreadCompletion(); |
128 } | 128 } |
129 | 129 |
130 if (hasSampleAccurateValues() || listener()->hasSampleAccurateValues()) { | 130 if (hasSampleAccurateValues() || listener()->hasSampleAccurateValues()) { |
131 // It's tempting to skip sample-accurate processing if isAzimuthElevationD
irty() and | 131 // It's tempting to skip sample-accurate processing if |
132 // isDistanceConeGain() both return false. But in general we can't becaus
e something | 132 // isAzimuthElevationDirty() and isDistanceConeGain() both return false. |
133 // may scheduled to start in the middle of the rendering quantum. On the
other hand, | 133 // But in general we can't because something may scheduled to start in the |
134 // the audible effect may be small enough that we can afford to do this op
timization. | 134 // middle of the rendering quantum. On the other hand, the audible effect |
| 135 // may be small enough that we can afford to do this optimization. |
135 processSampleAccurateValues(destination, source, framesToProcess); | 136 processSampleAccurateValues(destination, source, framesToProcess); |
136 } else { | 137 } else { |
137 // Apply the panning effect. | 138 // Apply the panning effect. |
138 double azimuth; | 139 double azimuth; |
139 double elevation; | 140 double elevation; |
140 | 141 |
141 // Update dirty state in case something has moved; this can happen if the
AudioParam for | 142 // Update dirty state in case something has moved; this can happen if the |
142 // the position or orientation component is set directly. | 143 // AudioParam for the position or orientation component is set directly. |
143 updateDirtyState(); | 144 updateDirtyState(); |
144 | 145 |
145 azimuthElevation(&azimuth, &elevation); | 146 azimuthElevation(&azimuth, &elevation); |
146 | 147 |
147 m_panner->pan(azimuth, elevation, source, destination, framesToProcess, | 148 m_panner->pan(azimuth, elevation, source, destination, framesToProcess, |
148 internalChannelInterpretation()); | 149 internalChannelInterpretation()); |
149 | 150 |
150 // Get the distance and cone gain. | 151 // Get the distance and cone gain. |
151 float totalGain = distanceConeGain(); | 152 float totalGain = distanceConeGain(); |
152 | 153 |
153 m_lastGain = totalGain; | 154 m_lastGain = totalGain; |
154 | 155 |
155 // Apply gain in-place with de-zippering. | 156 // Apply gain in-place with de-zippering. |
156 destination->copyWithGainFrom(*destination, &m_lastGain, totalGain); | 157 destination->copyWithGainFrom(*destination, &m_lastGain, totalGain); |
157 } | 158 } |
158 } else { | 159 } else { |
159 // Too bad - The tryLock() failed. | 160 // Too bad - The tryLock() failed. We must be in the middle of changing the |
160 // We must be in the middle of changing the properties of the panner or the
listener. | 161 // properties of the panner or the listener. |
161 destination->zero(); | 162 destination->zero(); |
162 } | 163 } |
163 } | 164 } |
164 | 165 |
165 void PannerHandler::processSampleAccurateValues(AudioBus* destination, | 166 void PannerHandler::processSampleAccurateValues(AudioBus* destination, |
166 const AudioBus* source, | 167 const AudioBus* source, |
167 size_t framesToProcess) { | 168 size_t framesToProcess) { |
168 RELEASE_ASSERT(framesToProcess <= ProcessingSizeInFrames); | 169 RELEASE_ASSERT(framesToProcess <= ProcessingSizeInFrames); |
169 | 170 |
170 // Get the sample accurate values from all of the AudioParams, including the v
alues from the | 171 // Get the sample accurate values from all of the AudioParams, including the |
171 // AudioListener. | 172 // values from the AudioListener. |
172 float pannerX[ProcessingSizeInFrames]; | 173 float pannerX[ProcessingSizeInFrames]; |
173 float pannerY[ProcessingSizeInFrames]; | 174 float pannerY[ProcessingSizeInFrames]; |
174 float pannerZ[ProcessingSizeInFrames]; | 175 float pannerZ[ProcessingSizeInFrames]; |
175 | 176 |
176 float orientationX[ProcessingSizeInFrames]; | 177 float orientationX[ProcessingSizeInFrames]; |
177 float orientationY[ProcessingSizeInFrames]; | 178 float orientationY[ProcessingSizeInFrames]; |
178 float orientationZ[ProcessingSizeInFrames]; | 179 float orientationZ[ProcessingSizeInFrames]; |
179 | 180 |
180 m_positionX->calculateSampleAccurateValues(pannerX, framesToProcess); | 181 m_positionX->calculateSampleAccurateValues(pannerX, framesToProcess); |
181 m_positionY->calculateSampleAccurateValues(pannerY, framesToProcess); | 182 m_positionY->calculateSampleAccurateValues(pannerY, framesToProcess); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 } | 229 } |
229 | 230 |
230 void PannerHandler::initialize() { | 231 void PannerHandler::initialize() { |
231 if (isInitialized()) | 232 if (isInitialized()) |
232 return; | 233 return; |
233 | 234 |
234 m_panner = Panner::create(m_panningModel, sampleRate(), | 235 m_panner = Panner::create(m_panningModel, sampleRate(), |
235 listener()->hrtfDatabaseLoader()); | 236 listener()->hrtfDatabaseLoader()); |
236 listener()->addPanner(*this); | 237 listener()->addPanner(*this); |
237 | 238 |
238 // Set the cached values to the current values to start things off. The panne
r is already | 239 // Set the cached values to the current values to start things off. The |
239 // marked as dirty, so this won't matter. | 240 // panner is already marked as dirty, so this won't matter. |
240 m_lastPosition = position(); | 241 m_lastPosition = position(); |
241 m_lastOrientation = orientation(); | 242 m_lastOrientation = orientation(); |
242 | 243 |
243 AudioHandler::initialize(); | 244 AudioHandler::initialize(); |
244 } | 245 } |
245 | 246 |
246 void PannerHandler::uninitialize() { | 247 void PannerHandler::uninitialize() { |
247 if (!isInitialized()) | 248 if (!isInitialized()) |
248 return; | 249 return; |
249 | 250 |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 DCHECK(isMainThread()); | 564 DCHECK(isMainThread()); |
564 BaseAudioContext::AutoLocker locker(context()); | 565 BaseAudioContext::AutoLocker locker(context()); |
565 | 566 |
566 ChannelCountMode oldMode = internalChannelCountMode(); | 567 ChannelCountMode oldMode = internalChannelCountMode(); |
567 | 568 |
568 if (mode == "clamped-max") { | 569 if (mode == "clamped-max") { |
569 m_newChannelCountMode = ClampedMax; | 570 m_newChannelCountMode = ClampedMax; |
570 } else if (mode == "explicit") { | 571 } else if (mode == "explicit") { |
571 m_newChannelCountMode = Explicit; | 572 m_newChannelCountMode = Explicit; |
572 } else if (mode == "max") { | 573 } else if (mode == "max") { |
573 // This is not supported for a PannerNode, which can only handle 1 or 2 chan
nels. | 574 // This is not supported for a PannerNode, which can only handle 1 or 2 |
| 575 // channels. |
574 exceptionState.throwDOMException(NotSupportedError, | 576 exceptionState.throwDOMException(NotSupportedError, |
575 "Panner: 'max' is not allowed"); | 577 "Panner: 'max' is not allowed"); |
576 m_newChannelCountMode = oldMode; | 578 m_newChannelCountMode = oldMode; |
577 } else { | 579 } else { |
578 // Do nothing for other invalid values. | 580 // Do nothing for other invalid values. |
579 m_newChannelCountMode = oldMode; | 581 m_newChannelCountMode = oldMode; |
580 } | 582 } |
581 | 583 |
582 if (m_newChannelCountMode != oldMode) | 584 if (m_newChannelCountMode != oldMode) |
583 context()->deferredTaskHandler().addChangedChannelCountMode(this); | 585 context()->deferredTaskHandler().addChangedChannelCountMode(this); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 visitor->trace(m_positionZ); | 774 visitor->trace(m_positionZ); |
773 | 775 |
774 visitor->trace(m_orientationX); | 776 visitor->trace(m_orientationX); |
775 visitor->trace(m_orientationY); | 777 visitor->trace(m_orientationY); |
776 visitor->trace(m_orientationZ); | 778 visitor->trace(m_orientationZ); |
777 | 779 |
778 AudioNode::trace(visitor); | 780 AudioNode::trace(visitor); |
779 } | 781 } |
780 | 782 |
781 } // namespace blink | 783 } // namespace blink |
OLD | NEW |