| 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 } else { | 62 } else { |
| 63 ASSERT(!stageOffset); | 63 ASSERT(!stageOffset); |
| 64 ASSERT(stageLength <= fftSize / 2); | 64 ASSERT(stageLength <= fftSize / 2); |
| 65 | 65 |
| 66 m_directKernel = wrapUnique(new AudioFloatArray(fftSize / 2)); | 66 m_directKernel = wrapUnique(new AudioFloatArray(fftSize / 2)); |
| 67 m_directKernel->copyToRange(impulseResponse, 0, stageLength); | 67 m_directKernel->copyToRange(impulseResponse, 0, stageLength); |
| 68 m_directConvolver = wrapUnique(new DirectConvolver(renderSliceSize)); | 68 m_directConvolver = wrapUnique(new DirectConvolver(renderSliceSize)); |
| 69 } | 69 } |
| 70 m_temporaryBuffer.allocate(renderSliceSize); | 70 m_temporaryBuffer.allocate(renderSliceSize); |
| 71 | 71 |
| 72 // The convolution stage at offset stageOffset needs to have a corresponding d
elay to cancel out the offset. | 72 // The convolution stage at offset stageOffset needs to have a corresponding |
| 73 // delay to cancel out the offset. |
| 73 size_t totalDelay = stageOffset + reverbTotalLatency; | 74 size_t totalDelay = stageOffset + reverbTotalLatency; |
| 74 | 75 |
| 75 // But, the FFT convolution itself incurs fftSize / 2 latency, so subtract thi
s out... | 76 // But, the FFT convolution itself incurs fftSize / 2 latency, so subtract |
| 77 // this out... |
| 76 size_t halfSize = fftSize / 2; | 78 size_t halfSize = fftSize / 2; |
| 77 if (!m_directMode) { | 79 if (!m_directMode) { |
| 78 ASSERT(totalDelay >= halfSize); | 80 ASSERT(totalDelay >= halfSize); |
| 79 if (totalDelay >= halfSize) | 81 if (totalDelay >= halfSize) |
| 80 totalDelay -= halfSize; | 82 totalDelay -= halfSize; |
| 81 } | 83 } |
| 82 | 84 |
| 83 // We divide up the total delay, into pre and post delay sections so that we c
an schedule at exactly the moment when the FFT will happen. | 85 // We divide up the total delay, into pre and post delay sections so that we |
| 84 // This is coordinated with the other stages, so they don't all do their FFTs
at the same time... | 86 // can schedule at exactly the moment when the FFT will happen. This is |
| 87 // coordinated with the other stages, so they don't all do their FFTs at the |
| 88 // same time... |
| 85 int maxPreDelayLength = std::min(halfSize, totalDelay); | 89 int maxPreDelayLength = std::min(halfSize, totalDelay); |
| 86 m_preDelayLength = totalDelay > 0 ? renderPhase % maxPreDelayLength : 0; | 90 m_preDelayLength = totalDelay > 0 ? renderPhase % maxPreDelayLength : 0; |
| 87 if (m_preDelayLength > totalDelay) | 91 if (m_preDelayLength > totalDelay) |
| 88 m_preDelayLength = 0; | 92 m_preDelayLength = 0; |
| 89 | 93 |
| 90 m_postDelayLength = totalDelay - m_preDelayLength; | 94 m_postDelayLength = totalDelay - m_preDelayLength; |
| 91 m_preReadWriteIndex = 0; | 95 m_preReadWriteIndex = 0; |
| 92 m_framesProcessed = 0; // total frames processed so far | 96 m_framesProcessed = 0; // total frames processed so far |
| 93 | 97 |
| 94 size_t delayBufferSize = | 98 size_t delayBufferSize = |
| (...skipping 17 matching lines...) Expand all Loading... |
| 112 if (!source) | 116 if (!source) |
| 113 return; | 117 return; |
| 114 | 118 |
| 115 // Deal with pre-delay stream : note special handling of zero delay. | 119 // Deal with pre-delay stream : note special handling of zero delay. |
| 116 | 120 |
| 117 const float* preDelayedSource; | 121 const float* preDelayedSource; |
| 118 float* preDelayedDestination; | 122 float* preDelayedDestination; |
| 119 float* temporaryBuffer; | 123 float* temporaryBuffer; |
| 120 bool isTemporaryBufferSafe = false; | 124 bool isTemporaryBufferSafe = false; |
| 121 if (m_preDelayLength > 0) { | 125 if (m_preDelayLength > 0) { |
| 122 // Handles both the read case (call to process() ) and the write case (memcp
y() ) | 126 // Handles both the read case (call to process() ) and the write case |
| 127 // (memcpy() ) |
| 123 bool isPreDelaySafe = | 128 bool isPreDelaySafe = |
| 124 m_preReadWriteIndex + framesToProcess <= m_preDelayBuffer.size(); | 129 m_preReadWriteIndex + framesToProcess <= m_preDelayBuffer.size(); |
| 125 ASSERT(isPreDelaySafe); | 130 ASSERT(isPreDelaySafe); |
| 126 if (!isPreDelaySafe) | 131 if (!isPreDelaySafe) |
| 127 return; | 132 return; |
| 128 | 133 |
| 129 isTemporaryBufferSafe = framesToProcess <= m_temporaryBuffer.size(); | 134 isTemporaryBufferSafe = framesToProcess <= m_temporaryBuffer.size(); |
| 130 | 135 |
| 131 preDelayedDestination = m_preDelayBuffer.data() + m_preReadWriteIndex; | 136 preDelayedDestination = m_preDelayBuffer.data() + m_preReadWriteIndex; |
| 132 preDelayedSource = preDelayedDestination; | 137 preDelayedSource = preDelayedDestination; |
| 133 temporaryBuffer = m_temporaryBuffer.data(); | 138 temporaryBuffer = m_temporaryBuffer.data(); |
| 134 } else { | 139 } else { |
| 135 // Zero delay | 140 // Zero delay |
| 136 preDelayedDestination = 0; | 141 preDelayedDestination = 0; |
| 137 preDelayedSource = source; | 142 preDelayedSource = source; |
| 138 temporaryBuffer = m_preDelayBuffer.data(); | 143 temporaryBuffer = m_preDelayBuffer.data(); |
| 139 | 144 |
| 140 isTemporaryBufferSafe = framesToProcess <= m_preDelayBuffer.size(); | 145 isTemporaryBufferSafe = framesToProcess <= m_preDelayBuffer.size(); |
| 141 } | 146 } |
| 142 | 147 |
| 143 ASSERT(isTemporaryBufferSafe); | 148 ASSERT(isTemporaryBufferSafe); |
| 144 if (!isTemporaryBufferSafe) | 149 if (!isTemporaryBufferSafe) |
| 145 return; | 150 return; |
| 146 | 151 |
| 147 if (m_framesProcessed < m_preDelayLength) { | 152 if (m_framesProcessed < m_preDelayLength) { |
| 148 // For the first m_preDelayLength frames don't process the convolver, instea
d simply buffer in the pre-delay. | 153 // For the first m_preDelayLength frames don't process the convolver, |
| 149 // But while buffering the pre-delay, we still need to update our index. | 154 // instead simply buffer in the pre-delay. But while buffering the |
| 155 // pre-delay, we still need to update our index. |
| 150 m_accumulationBuffer->updateReadIndex(&m_accumulationReadIndex, | 156 m_accumulationBuffer->updateReadIndex(&m_accumulationReadIndex, |
| 151 framesToProcess); | 157 framesToProcess); |
| 152 } else { | 158 } else { |
| 153 // Now, run the convolution (into the delay buffer). | 159 // Now, run the convolution (into the delay buffer). |
| 154 // An expensive FFT will happen every fftSize / 2 frames. | 160 // An expensive FFT will happen every fftSize / 2 frames. |
| 155 // We process in-place here... | 161 // We process in-place here... |
| 156 if (!m_directMode) | 162 if (!m_directMode) |
| 157 m_fftConvolver->process(m_fftKernel.get(), preDelayedSource, | 163 m_fftConvolver->process(m_fftKernel.get(), preDelayedSource, |
| 158 temporaryBuffer, framesToProcess); | 164 temporaryBuffer, framesToProcess); |
| 159 else | 165 else |
| (...skipping 24 matching lines...) Expand all Loading... |
| 184 m_fftConvolver->reset(); | 190 m_fftConvolver->reset(); |
| 185 else | 191 else |
| 186 m_directConvolver->reset(); | 192 m_directConvolver->reset(); |
| 187 m_preDelayBuffer.zero(); | 193 m_preDelayBuffer.zero(); |
| 188 m_accumulationReadIndex = 0; | 194 m_accumulationReadIndex = 0; |
| 189 m_inputReadIndex = 0; | 195 m_inputReadIndex = 0; |
| 190 m_framesProcessed = 0; | 196 m_framesProcessed = 0; |
| 191 } | 197 } |
| 192 | 198 |
| 193 } // namespace blink | 199 } // namespace blink |
| OLD | NEW |