| 138 | } |
| 139 | |
| 140 | AudioEffectState OverlapSaveConvolutionEffect::apply(const OverlapSaveConvolutionEffectParams& params, |
| 141 | const AudioBuffer& in, |
| 142 | AudioBuffer& out) |
| 143 | { |
| 144 | assert(in.numSamples() == out.numSamples()); |
| 145 | assert(in.numChannels() == 1); |
| 146 | assert(out.numChannels() == mNumChannels); |
| 147 | |
| 148 | PROFILE_FUNCTION(); |
| 149 | |
| 150 | auto crossfade = apply(params, in); |
| 151 | |
| 152 | for (auto i = 0; i < params.numChannels; ++i) |
| 153 | { |
| 154 | mFFT.applyInverse(mFFTWet[i], mWet[i]); |
| 155 | } |
| 156 | |
| 157 | if (crossfade) |
| 158 | { |
| 159 | for (auto i = 0; i < params.numChannels; ++i) |
| 160 | { |
| 161 | mFFT.applyInverse(mPrevFFTWet[i], mPrevWet[i]); |
| 162 | |
| 163 | for (auto j = 0; j < mFrameSize; ++j) |
| 164 | { |
| 165 | auto weight = static_cast<float>(j) / static_cast<float>(mFrameSize); |
| 166 | mWet[i][j + mFrameSize] = (1.0f - weight) * mPrevWet[i][j + mFrameSize] + weight * mWet[i][j + mFrameSize]; |
| 167 | } |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | out.makeSilent(); |
| 172 | |
| 173 | for (auto i = 0; i < params.numChannels; ++i) |
| 174 | { |
| 175 | memcpy(out[i], &mWet[i][mFrameSize], mFrameSize * sizeof(float)); |
| 176 | } |
| 177 | |
| 178 | return (mNumTailBlocksRemaining > 0) ? AudioEffectState::TailRemaining : AudioEffectState::TailComplete; |
| 179 | } |
| 180 | |
| 181 | AudioEffectState OverlapSaveConvolutionEffect::apply(const OverlapSaveConvolutionEffectParams& params, |
| 182 | const AudioBuffer& in, |
nothing calls this directly
no test coverage detected