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 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
109 // impulseResponse. | 109 // impulseResponse. |
110 // FIXME: What about roundoff? Perhaps consider making a temporary scaled copy | 110 // FIXME: What about roundoff? Perhaps consider making a temporary scaled copy |
111 // instead of scaling and unscaling in place. | 111 // instead of scaling and unscaling in place. |
112 if (normalize && scale) | 112 if (normalize && scale) |
113 impulseResponse->scale(1 / scale); | 113 impulseResponse->scale(1 / scale); |
114 } | 114 } |
115 | 115 |
116 void Reverb::initialize(AudioBus* impulseResponseBuffer, | 116 void Reverb::initialize(AudioBus* impulseResponseBuffer, |
117 size_t renderSliceSize, | 117 size_t renderSliceSize, |
118 size_t maxFFTSize, | 118 size_t maxFFTSize, |
119 size_t numberOfChannels, | 119 size_t numberOfResponseChannels, |
120 bool useBackgroundThreads) { | 120 bool useBackgroundThreads) { |
121 m_impulseResponseLength = impulseResponseBuffer->length(); | 121 m_impulseResponseLength = impulseResponseBuffer->length(); |
122 m_numberOfResponseChannels = numberOfResponseChannels; | |
122 | 123 |
123 // The reverb can handle a mono impulse response and still do stereo | 124 // The reverb can handle a mono impulse response and still do stereo |
124 // processing | 125 // processing. |
125 size_t numResponseChannels = impulseResponseBuffer->numberOfChannels(); | 126 size_t numResponseChannels = impulseResponseBuffer->numberOfChannels(); |
hongchan
2017/03/28 19:01:44
How this |numResponseChannels| is different from |
Raymond Toy
2017/03/28 20:18:02
Good point. I don't think there is anymore and num
| |
126 m_convolvers.reserveCapacity(numberOfChannels); | 127 size_t numConvolvers = std::max(numResponseChannels, static_cast<size_t>(2)); |
hongchan
2017/03/28 19:01:44
If |numResponseChannel| is unsigned we don't need
| |
128 m_convolvers.reserveCapacity(numConvolvers); | |
hongchan
2017/03/28 19:01:44
Then we can do .reserveCapacity(static_cast<size_t
Raymond Toy
2017/03/28 20:18:02
This is ok. Just means we also need more casting i
| |
127 | 129 |
128 int convolverRenderPhase = 0; | 130 int convolverRenderPhase = 0; |
129 for (size_t i = 0; i < numResponseChannels; ++i) { | 131 for (size_t i = 0; i < numConvolvers; ++i) { |
130 AudioChannel* channel = impulseResponseBuffer->channel(i); | 132 AudioChannel* channel = |
133 impulseResponseBuffer->channel(std::min(i, numResponseChannels - 1)); | |
131 | 134 |
132 std::unique_ptr<ReverbConvolver> convolver = WTF::wrapUnique( | 135 std::unique_ptr<ReverbConvolver> convolver = WTF::wrapUnique( |
133 new ReverbConvolver(channel, renderSliceSize, maxFFTSize, | 136 new ReverbConvolver(channel, renderSliceSize, maxFFTSize, |
134 convolverRenderPhase, useBackgroundThreads)); | 137 convolverRenderPhase, useBackgroundThreads)); |
135 m_convolvers.push_back(std::move(convolver)); | 138 m_convolvers.push_back(std::move(convolver)); |
136 | 139 |
137 convolverRenderPhase += renderSliceSize; | 140 convolverRenderPhase += renderSliceSize; |
138 } | 141 } |
139 | 142 |
140 // For "True" stereo processing we allocate a temporary buffer to avoid | 143 // For "True" stereo processing we allocate a temporary buffer to avoid |
(...skipping 25 matching lines...) Expand all Loading... | |
166 destinationBus->zero(); | 169 destinationBus->zero(); |
167 return; | 170 return; |
168 } | 171 } |
169 | 172 |
170 AudioChannel* destinationChannelL = destinationBus->channel(0); | 173 AudioChannel* destinationChannelL = destinationBus->channel(0); |
171 const AudioChannel* sourceChannelL = sourceBus->channel(0); | 174 const AudioChannel* sourceChannelL = sourceBus->channel(0); |
172 | 175 |
173 // Handle input -> output matrixing... | 176 // Handle input -> output matrixing... |
174 size_t numInputChannels = sourceBus->numberOfChannels(); | 177 size_t numInputChannels = sourceBus->numberOfChannels(); |
175 size_t numOutputChannels = destinationBus->numberOfChannels(); | 178 size_t numOutputChannels = destinationBus->numberOfChannels(); |
176 size_t numReverbChannels = m_convolvers.size(); | 179 size_t numberOfResponseChannels = m_numberOfResponseChannels; |
177 | 180 |
178 if (numInputChannels == 2 && numReverbChannels == 2 && | 181 DCHECK_LE(numInputChannels, 2ul); |
182 DCHECK_LE(numOutputChannels, 2ul); | |
183 DCHECK(numberOfResponseChannels == 1 || numberOfResponseChannels == 2 || | |
184 numberOfResponseChannels == 4); | |
185 | |
186 // These are the possible combinations of number inputs, response | |
187 // channels and outputs channels that need to be supported: | |
188 // | |
189 // numInputChannels: 1 or 2 | |
190 // numberOfResponseChannels: 1, 2, or 4 | |
191 // numOutputChannels: 1 or 2 | |
192 // | |
193 // Not all possible combinations are valid. numOutputChannels is | |
194 // one only if both numInputChannels and numberOfResponseChannels are 1. | |
195 // Otherwise numOutputChannels MUST be 2. | |
196 // | |
197 // The valid combinations are | |
198 // | |
199 // Case in -> resp -> out | |
200 // 1 1 -> 1 -> 1 | |
201 // 2 1 -> 2 -> 2 | |
202 // 3 1 -> 4 -> 2 | |
203 // 4 2 -> 1 -> 2 | |
204 // 5 2 -> 2 -> 2 | |
205 // 6 2 -> 4 -> 2 | |
206 | |
207 if (numInputChannels == 2 && | |
208 (numberOfResponseChannels == 1 || numberOfResponseChannels == 2) && | |
179 numOutputChannels == 2) { | 209 numOutputChannels == 2) { |
180 // 2 -> 2 -> 2 | 210 // Case 4 and 5: 2 -> 2 -> 2 or 2 -> 1 -> 2. |
211 // | |
212 // These can be handled in the same way because in the latter | |
213 // case, two connvolvers are still created with the second being a | |
214 // copy of the first. | |
181 const AudioChannel* sourceChannelR = sourceBus->channel(1); | 215 const AudioChannel* sourceChannelR = sourceBus->channel(1); |
182 AudioChannel* destinationChannelR = destinationBus->channel(1); | 216 AudioChannel* destinationChannelR = destinationBus->channel(1); |
183 m_convolvers[0]->process(sourceChannelL, destinationChannelL, | 217 m_convolvers[0]->process(sourceChannelL, destinationChannelL, |
184 framesToProcess); | 218 framesToProcess); |
185 m_convolvers[1]->process(sourceChannelR, destinationChannelR, | 219 m_convolvers[1]->process(sourceChannelR, destinationChannelR, |
186 framesToProcess); | 220 framesToProcess); |
187 } else if (numInputChannels == 1 && numOutputChannels == 2 && | 221 } else if (numInputChannels == 1 && numOutputChannels == 2 && |
188 numReverbChannels == 2) { | 222 numberOfResponseChannels == 2) { |
189 // 1 -> 2 -> 2 | 223 // Case 2: 1 -> 2 -> 2 |
190 for (int i = 0; i < 2; ++i) { | 224 for (int i = 0; i < 2; ++i) { |
191 AudioChannel* destinationChannel = destinationBus->channel(i); | 225 AudioChannel* destinationChannel = destinationBus->channel(i); |
192 m_convolvers[i]->process(sourceChannelL, destinationChannel, | 226 m_convolvers[i]->process(sourceChannelL, destinationChannel, |
193 framesToProcess); | 227 framesToProcess); |
194 } | 228 } |
195 } else if (numInputChannels == 1 && numReverbChannels == 1 && | 229 } else if (numInputChannels == 1 && numberOfResponseChannels == 1) { |
196 numOutputChannels == 2) { | 230 // Case 1: 1 -> 1 -> 1 |
197 // 1 -> 1 -> 2 | 231 DCHECK_EQ(numOutputChannels, 1ul); |
198 m_convolvers[0]->process(sourceChannelL, destinationChannelL, | 232 m_convolvers[0]->process(sourceChannelL, destinationChannelL, |
199 framesToProcess); | 233 framesToProcess); |
200 | 234 } else if (numInputChannels == 2 && numberOfResponseChannels == 4 && |
201 // simply copy L -> R | |
202 AudioChannel* destinationChannelR = destinationBus->channel(1); | |
203 bool isCopySafe = destinationChannelL->data() && | |
204 destinationChannelR->data() && | |
205 destinationChannelL->length() >= framesToProcess && | |
206 destinationChannelR->length() >= framesToProcess; | |
207 ASSERT(isCopySafe); | |
208 if (!isCopySafe) | |
209 return; | |
210 memcpy(destinationChannelR->mutableData(), destinationChannelL->data(), | |
211 sizeof(float) * framesToProcess); | |
212 } else if (numInputChannels == 1 && numReverbChannels == 1 && | |
213 numOutputChannels == 1) { | |
214 // 1 -> 1 -> 1 | |
215 m_convolvers[0]->process(sourceChannelL, destinationChannelL, | |
216 framesToProcess); | |
217 } else if (numInputChannels == 2 && numReverbChannels == 4 && | |
218 numOutputChannels == 2) { | 235 numOutputChannels == 2) { |
219 // 2 -> 4 -> 2 ("True" stereo) | 236 // Case 6: 2 -> 4 -> 2 ("True" stereo) |
220 const AudioChannel* sourceChannelR = sourceBus->channel(1); | 237 const AudioChannel* sourceChannelR = sourceBus->channel(1); |
221 AudioChannel* destinationChannelR = destinationBus->channel(1); | 238 AudioChannel* destinationChannelR = destinationBus->channel(1); |
222 | 239 |
223 AudioChannel* tempChannelL = m_tempBuffer->channel(0); | 240 AudioChannel* tempChannelL = m_tempBuffer->channel(0); |
224 AudioChannel* tempChannelR = m_tempBuffer->channel(1); | 241 AudioChannel* tempChannelR = m_tempBuffer->channel(1); |
225 | 242 |
226 // Process left virtual source | 243 // Process left virtual source |
227 m_convolvers[0]->process(sourceChannelL, destinationChannelL, | 244 m_convolvers[0]->process(sourceChannelL, destinationChannelL, |
228 framesToProcess); | 245 framesToProcess); |
229 m_convolvers[1]->process(sourceChannelL, destinationChannelR, | 246 m_convolvers[1]->process(sourceChannelL, destinationChannelR, |
230 framesToProcess); | 247 framesToProcess); |
231 | 248 |
232 // Process right virtual source | 249 // Process right virtual source |
233 m_convolvers[2]->process(sourceChannelR, tempChannelL, framesToProcess); | 250 m_convolvers[2]->process(sourceChannelR, tempChannelL, framesToProcess); |
234 m_convolvers[3]->process(sourceChannelR, tempChannelR, framesToProcess); | 251 m_convolvers[3]->process(sourceChannelR, tempChannelR, framesToProcess); |
235 | 252 |
236 destinationBus->sumFrom(*m_tempBuffer); | 253 destinationBus->sumFrom(*m_tempBuffer); |
237 } else if (numInputChannels == 1 && numReverbChannels == 4 && | 254 } else if (numInputChannels == 1 && numberOfResponseChannels == 4 && |
238 numOutputChannels == 2) { | 255 numOutputChannels == 2) { |
239 // 1 -> 4 -> 2 (Processing mono with "True" stereo impulse response) | 256 // Case 3: 1 -> 4 -> 2 (Processing mono with "True" stereo impulse |
240 // This is an inefficient use of a four-channel impulse response, but we | 257 // response) This is an inefficient use of a four-channel impulse |
241 // should handle the case. | 258 // response, but we should handle the case. |
242 AudioChannel* destinationChannelR = destinationBus->channel(1); | 259 AudioChannel* destinationChannelR = destinationBus->channel(1); |
243 | 260 |
244 AudioChannel* tempChannelL = m_tempBuffer->channel(0); | 261 AudioChannel* tempChannelL = m_tempBuffer->channel(0); |
245 AudioChannel* tempChannelR = m_tempBuffer->channel(1); | 262 AudioChannel* tempChannelR = m_tempBuffer->channel(1); |
246 | 263 |
247 // Process left virtual source | 264 // Process left virtual source |
248 m_convolvers[0]->process(sourceChannelL, destinationChannelL, | 265 m_convolvers[0]->process(sourceChannelL, destinationChannelL, |
249 framesToProcess); | 266 framesToProcess); |
250 m_convolvers[1]->process(sourceChannelL, destinationChannelR, | 267 m_convolvers[1]->process(sourceChannelL, destinationChannelR, |
251 framesToProcess); | 268 framesToProcess); |
252 | 269 |
253 // Process right virtual source | 270 // Process right virtual source |
254 m_convolvers[2]->process(sourceChannelL, tempChannelL, framesToProcess); | 271 m_convolvers[2]->process(sourceChannelL, tempChannelL, framesToProcess); |
255 m_convolvers[3]->process(sourceChannelL, tempChannelR, framesToProcess); | 272 m_convolvers[3]->process(sourceChannelL, tempChannelR, framesToProcess); |
256 | 273 |
257 destinationBus->sumFrom(*m_tempBuffer); | 274 destinationBus->sumFrom(*m_tempBuffer); |
258 } else { | 275 } else { |
259 // Handle gracefully any unexpected / unsupported matrixing | 276 NOTREACHED(); |
260 // FIXME: add code for 5.1 support... | |
261 destinationBus->zero(); | 277 destinationBus->zero(); |
262 } | 278 } |
263 } | 279 } |
264 | 280 |
265 void Reverb::reset() { | 281 void Reverb::reset() { |
266 for (size_t i = 0; i < m_convolvers.size(); ++i) | 282 for (size_t i = 0; i < m_convolvers.size(); ++i) |
267 m_convolvers[i]->reset(); | 283 m_convolvers[i]->reset(); |
268 } | 284 } |
269 | 285 |
270 size_t Reverb::latencyFrames() const { | 286 size_t Reverb::latencyFrames() const { |
271 return !m_convolvers.isEmpty() ? m_convolvers.front()->latencyFrames() : 0; | 287 return !m_convolvers.isEmpty() ? m_convolvers.front()->latencyFrames() : 0; |
272 } | 288 } |
273 | 289 |
274 } // namespace blink | 290 } // namespace blink |
OLD | NEW |