mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 17:35:08 +02:00
Merge pull request #8182 from kencooke/master
floating-point versions of the audio resampler and reverb
This commit is contained in:
commit
87cdb4144d
4 changed files with 237 additions and 33 deletions
|
@ -13,13 +13,13 @@
|
|||
#include "AudioReverb.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4351) // new behavior: elements of array will be default initialized
|
||||
|
||||
#include <intrin.h>
|
||||
inline static int MULHI(int a, int b) {
|
||||
long long c = __emul(a, b);
|
||||
return ((int*)&c)[1];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define MULHI(a,b) (int)(((long long)(a) * (b)) >> 32)
|
||||
|
@ -1725,7 +1725,7 @@ void ReverbImpl::reset() {
|
|||
// Public API
|
||||
//
|
||||
|
||||
static const int REVERB_BLOCK = 1024;
|
||||
static const int REVERB_BLOCK = 256;
|
||||
|
||||
AudioReverb::AudioReverb(float sampleRate) {
|
||||
|
||||
|
@ -1804,7 +1804,7 @@ void AudioReverb::render(float** inputs, float** outputs, int numFrames) {
|
|||
#include <emmintrin.h>
|
||||
|
||||
// convert int16_t to float, deinterleave stereo
|
||||
void AudioReverb::convertInputFromInt16(const int16_t* input, float** outputs, int numFrames) {
|
||||
void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFrames) {
|
||||
__m128 scale = _mm_set1_ps(1/32768.0f);
|
||||
|
||||
int i = 0;
|
||||
|
@ -1855,8 +1855,8 @@ static inline __m128 dither4() {
|
|||
return _mm_mul_ps(d0, _mm_set1_ps(1/65536.0f));
|
||||
}
|
||||
|
||||
// convert float to int16_t, interleave stereo
|
||||
void AudioReverb::convertOutputToInt16(float** inputs, int16_t* output, int numFrames) {
|
||||
// convert float to int16_t with dither, interleave stereo
|
||||
void AudioReverb::convertOutput(float** inputs, int16_t* output, int numFrames) {
|
||||
__m128 scale = _mm_set1_ps(32768.0f);
|
||||
|
||||
int i = 0;
|
||||
|
@ -1898,10 +1898,48 @@ void AudioReverb::convertOutputToInt16(float** inputs, int16_t* output, int numF
|
|||
}
|
||||
}
|
||||
|
||||
// deinterleave stereo
|
||||
void AudioReverb::convertInput(const float* input, float** outputs, int numFrames) {
|
||||
|
||||
int i = 0;
|
||||
for (; i < numFrames - 3; i += 4) {
|
||||
__m128 f0 = _mm_loadu_ps(&input[2*i + 0]);
|
||||
__m128 f1 = _mm_loadu_ps(&input[2*i + 4]);
|
||||
|
||||
// deinterleave
|
||||
_mm_storeu_ps(&outputs[0][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(2,0,2,0)));
|
||||
_mm_storeu_ps(&outputs[1][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(3,1,3,1)));
|
||||
}
|
||||
for (; i < numFrames; i++) {
|
||||
// deinterleave
|
||||
outputs[0][i] = input[2*i + 0];
|
||||
outputs[1][i] = input[2*i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// interleave stereo
|
||||
void AudioReverb::convertOutput(float** inputs, float* output, int numFrames) {
|
||||
|
||||
int i = 0;
|
||||
for(; i < numFrames - 3; i += 4) {
|
||||
__m128 f0 = _mm_loadu_ps(&inputs[0][i]);
|
||||
__m128 f1 = _mm_loadu_ps(&inputs[1][i]);
|
||||
|
||||
// interleave
|
||||
_mm_storeu_ps(&output[2*i + 0],_mm_unpacklo_ps(f0,f1));
|
||||
_mm_storeu_ps(&output[2*i + 4],_mm_unpackhi_ps(f0,f1));
|
||||
}
|
||||
for(; i < numFrames; i++) {
|
||||
// interleave
|
||||
output[2*i + 0] = inputs[0][i];
|
||||
output[2*i + 1] = inputs[1][i];
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// convert int16_t to float, deinterleave stereo
|
||||
void AudioReverb::convertInputFromInt16(const int16_t* input, float** outputs, int numFrames) {
|
||||
void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFrames) {
|
||||
const float scale = 1/32768.0f;
|
||||
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
|
@ -1919,8 +1957,8 @@ static inline float dither() {
|
|||
return (int32_t)(r0 - r1) * (1/65536.0f);
|
||||
}
|
||||
|
||||
// convert float to int16_t, interleave stereo
|
||||
void AudioReverb::convertOutputToInt16(float** inputs, int16_t* output, int numFrames) {
|
||||
// convert float to int16_t with dither, interleave stereo
|
||||
void AudioReverb::convertOutput(float** inputs, int16_t* output, int numFrames) {
|
||||
const float scale = 32768.0f;
|
||||
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
|
@ -1944,6 +1982,26 @@ void AudioReverb::convertOutputToInt16(float** inputs, int16_t* output, int numF
|
|||
}
|
||||
}
|
||||
|
||||
// deinterleave stereo
|
||||
void AudioReverb::convertInput(const float* input, float** outputs, int numFrames) {
|
||||
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
// deinterleave
|
||||
outputs[0][i] = input[2*i + 0];
|
||||
outputs[1][i] = input[2*i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// interleave stereo
|
||||
void AudioReverb::convertOutput(float** inputs, float* output, int numFrames) {
|
||||
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
// interleave
|
||||
output[2*i + 0] = inputs[0][i];
|
||||
output[2*i + 1] = inputs[1][i];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
|
@ -1955,11 +2013,32 @@ void AudioReverb::render(const int16_t* input, int16_t* output, int numFrames) {
|
|||
|
||||
int n = MIN(numFrames, REVERB_BLOCK);
|
||||
|
||||
convertInputFromInt16(input, _inout, n);
|
||||
convertInput(input, _inout, n);
|
||||
|
||||
_impl->process(_inout, _inout, n);
|
||||
|
||||
convertOutputToInt16(_inout, output, n);
|
||||
convertOutput(_inout, output, n);
|
||||
|
||||
input += 2 * n;
|
||||
output += 2 * n;
|
||||
numFrames -= n;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// This version handles input/output as interleaved float
|
||||
//
|
||||
void AudioReverb::render(const float* input, float* output, int numFrames) {
|
||||
|
||||
while (numFrames) {
|
||||
|
||||
int n = MIN(numFrames, REVERB_BLOCK);
|
||||
|
||||
convertInput(input, _inout, n);
|
||||
|
||||
_impl->process(_inout, _inout, n);
|
||||
|
||||
convertOutput(_inout, output, n);
|
||||
|
||||
input += 2 * n;
|
||||
output += 2 * n;
|
||||
|
|
|
@ -64,13 +64,20 @@ public:
|
|||
// interleaved int16_t input/output
|
||||
void render(const int16_t* input, int16_t* output, int numFrames);
|
||||
|
||||
// interleaved float input/output
|
||||
void render(const float* input, float* output, int numFrames);
|
||||
|
||||
private:
|
||||
ReverbImpl *_impl;
|
||||
ReverbParameters _params;
|
||||
|
||||
float* _inout[2];
|
||||
void convertInputFromInt16(const int16_t* input, float** outputs, int numFrames);
|
||||
void convertOutputToInt16(float** inputs, int16_t* output, int numFrames);
|
||||
|
||||
void convertInput(const int16_t* input, float** outputs, int numFrames);
|
||||
void convertOutput(float** inputs, int16_t* output, int numFrames);
|
||||
|
||||
void convertInput(const float* input, float** outputs, int numFrames);
|
||||
void convertOutput(float** inputs, float* output, int numFrames);
|
||||
};
|
||||
|
||||
#endif // hifi_AudioReverb_h
|
||||
|
|
|
@ -389,7 +389,7 @@ int AudioSRC::multirateFilter2(const float* input0, const float* input1, float*
|
|||
}
|
||||
|
||||
// convert int16_t to float, deinterleave stereo
|
||||
void AudioSRC::convertInputFromInt16(const int16_t* input, float** outputs, int numFrames) {
|
||||
void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) {
|
||||
__m128 scale = _mm_set1_ps(1/32768.0f);
|
||||
|
||||
if (_numChannels == 1) {
|
||||
|
@ -467,8 +467,8 @@ static inline __m128 dither4() {
|
|||
return _mm_mul_ps(d0, _mm_set1_ps(1/65536.0f));
|
||||
}
|
||||
|
||||
// convert float to int16_t, interleave stereo
|
||||
void AudioSRC::convertOutputToInt16(float** inputs, int16_t* output, int numFrames) {
|
||||
// convert float to int16_t with dither, interleave stereo
|
||||
void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) {
|
||||
__m128 scale = _mm_set1_ps(32768.0f);
|
||||
|
||||
if (_numChannels == 1) {
|
||||
|
@ -539,6 +539,58 @@ void AudioSRC::convertOutputToInt16(float** inputs, int16_t* output, int numFram
|
|||
}
|
||||
}
|
||||
|
||||
// deinterleave stereo
|
||||
void AudioSRC::convertInput(const float* input, float** outputs, int numFrames) {
|
||||
|
||||
if (_numChannels == 1) {
|
||||
|
||||
memcpy(outputs[0], input, numFrames * sizeof(float));
|
||||
|
||||
} else if (_numChannels == 2) {
|
||||
|
||||
int i = 0;
|
||||
for (; i < numFrames - 3; i += 4) {
|
||||
__m128 f0 = _mm_loadu_ps(&input[2*i + 0]);
|
||||
__m128 f1 = _mm_loadu_ps(&input[2*i + 4]);
|
||||
|
||||
// deinterleave
|
||||
_mm_storeu_ps(&outputs[0][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(2,0,2,0)));
|
||||
_mm_storeu_ps(&outputs[1][i], _mm_shuffle_ps(f0, f1, _MM_SHUFFLE(3,1,3,1)));
|
||||
}
|
||||
for (; i < numFrames; i++) {
|
||||
// deinterleave
|
||||
outputs[0][i] = input[2*i + 0];
|
||||
outputs[1][i] = input[2*i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// interleave stereo
|
||||
void AudioSRC::convertOutput(float** inputs, float* output, int numFrames) {
|
||||
|
||||
if (_numChannels == 1) {
|
||||
|
||||
memcpy(output, inputs[0], numFrames * sizeof(float));
|
||||
|
||||
} else if (_numChannels == 2) {
|
||||
|
||||
int i = 0;
|
||||
for (; i < numFrames - 3; i += 4) {
|
||||
__m128 f0 = _mm_loadu_ps(&inputs[0][i]);
|
||||
__m128 f1 = _mm_loadu_ps(&inputs[1][i]);
|
||||
|
||||
// interleave
|
||||
_mm_storeu_ps(&output[2*i + 0], _mm_unpacklo_ps(f0, f1));
|
||||
_mm_storeu_ps(&output[2*i + 4], _mm_unpackhi_ps(f0, f1));
|
||||
}
|
||||
for (; i < numFrames; i++) {
|
||||
// interleave
|
||||
output[2*i + 0] = inputs[0][i];
|
||||
output[2*i + 1] = inputs[1][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int AudioSRC::multirateFilter1(const float* input0, float* output0, int inputFrames) {
|
||||
|
@ -674,7 +726,7 @@ int AudioSRC::multirateFilter2(const float* input0, const float* input1, float*
|
|||
}
|
||||
|
||||
// convert int16_t to float, deinterleave stereo
|
||||
void AudioSRC::convertInputFromInt16(const int16_t* input, float** outputs, int numFrames) {
|
||||
void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) {
|
||||
const float scale = 1/32768.0f;
|
||||
|
||||
if (_numChannels == 1) {
|
||||
|
@ -698,8 +750,8 @@ static inline float dither() {
|
|||
return (int32_t)(r0 - r1) * (1/65536.0f);
|
||||
}
|
||||
|
||||
// convert float to int16_t, interleave stereo
|
||||
void AudioSRC::convertOutputToInt16(float** inputs, int16_t* output, int numFrames) {
|
||||
// convert float to int16_t with dither, interleave stereo
|
||||
void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) {
|
||||
const float scale = 32768.0f;
|
||||
|
||||
if (_numChannels == 1) {
|
||||
|
@ -738,9 +790,41 @@ void AudioSRC::convertOutputToInt16(float** inputs, int16_t* output, int numFram
|
|||
}
|
||||
}
|
||||
|
||||
// deinterleave stereo
|
||||
void AudioSRC::convertInput(const float* input, float** outputs, int numFrames) {
|
||||
|
||||
if (_numChannels == 1) {
|
||||
|
||||
memcpy(outputs[0], input, numFrames * sizeof(float));
|
||||
|
||||
} else if (_numChannels == 2) {
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
// deinterleave
|
||||
outputs[0][i] = input[2*i + 0];
|
||||
outputs[1][i] = input[2*i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// interleave stereo
|
||||
void AudioSRC::convertOutput(float** inputs, float* output, int numFrames) {
|
||||
|
||||
if (_numChannels == 1) {
|
||||
|
||||
memcpy(output, inputs[0], numFrames * sizeof(float));
|
||||
|
||||
} else if (_numChannels == 2) {
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
// interleave
|
||||
output[2*i + 0] = inputs[0][i];
|
||||
output[2*i + 1] = inputs[1][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int AudioSRC::processFloat(float** inputs, float** outputs, int inputFrames) {
|
||||
int AudioSRC::render(float** inputs, float** outputs, int inputFrames) {
|
||||
int outputFrames = 0;
|
||||
|
||||
int nh = std::min(_numHistory, inputFrames); // number of frames from history buffer
|
||||
|
@ -749,19 +833,19 @@ int AudioSRC::processFloat(float** inputs, float** outputs, int inputFrames) {
|
|||
if (_numChannels == 1) {
|
||||
|
||||
// refill history buffers
|
||||
memcpy(_history[0] + _numHistory, _inputs[0], nh * sizeof(float));
|
||||
memcpy(_history[0] + _numHistory, inputs[0], nh * sizeof(float));
|
||||
|
||||
// process history buffer
|
||||
outputFrames += multirateFilter1(_history[0], _outputs[0], nh);
|
||||
outputFrames += multirateFilter1(_history[0], outputs[0], nh);
|
||||
|
||||
// process remaining input
|
||||
if (ni) {
|
||||
outputFrames += multirateFilter1(_inputs[0], _outputs[0] + outputFrames, ni);
|
||||
outputFrames += multirateFilter1(inputs[0], outputs[0] + outputFrames, ni);
|
||||
}
|
||||
|
||||
// shift history buffers
|
||||
if (ni) {
|
||||
memcpy(_history[0], _inputs[0] + ni, _numHistory * sizeof(float));
|
||||
memcpy(_history[0], inputs[0] + ni, _numHistory * sizeof(float));
|
||||
} else {
|
||||
memmove(_history[0], _history[0] + nh, _numHistory * sizeof(float));
|
||||
}
|
||||
|
@ -769,15 +853,15 @@ int AudioSRC::processFloat(float** inputs, float** outputs, int inputFrames) {
|
|||
} else if (_numChannels == 2) {
|
||||
|
||||
// refill history buffers
|
||||
memcpy(_history[0] + _numHistory, _inputs[0], nh * sizeof(float));
|
||||
memcpy(_history[1] + _numHistory, _inputs[1], nh * sizeof(float));
|
||||
memcpy(_history[0] + _numHistory, inputs[0], nh * sizeof(float));
|
||||
memcpy(_history[1] + _numHistory, inputs[1], nh * sizeof(float));
|
||||
|
||||
// process history buffer
|
||||
outputFrames += multirateFilter2(_history[0], _history[1], _outputs[0], _outputs[1], nh);
|
||||
outputFrames += multirateFilter2(_history[0], _history[1], outputs[0], outputs[1], nh);
|
||||
|
||||
// process remaining input
|
||||
if (ni) {
|
||||
outputFrames += multirateFilter2(_inputs[0], _inputs[1], _outputs[0] + outputFrames, _outputs[1] + outputFrames, ni);
|
||||
outputFrames += multirateFilter2(inputs[0], inputs[1], outputs[0] + outputFrames, outputs[1] + outputFrames, ni);
|
||||
}
|
||||
|
||||
// shift history buffers
|
||||
|
@ -869,12 +953,38 @@ int AudioSRC::render(const int16_t* input, int16_t* output, int inputFrames) {
|
|||
|
||||
int ni = std::min(inputFrames, _inputBlock);
|
||||
|
||||
convertInputFromInt16(input, _inputs, ni);
|
||||
convertInput(input, _inputs, ni);
|
||||
|
||||
int no = processFloat(_inputs, _outputs, ni);
|
||||
int no = render(_inputs, _outputs, ni);
|
||||
assert(no <= SRC_BLOCK);
|
||||
|
||||
convertOutputToInt16(_outputs, output, no);
|
||||
convertOutput(_outputs, output, no);
|
||||
|
||||
input += _numChannels * ni;
|
||||
output += _numChannels * no;
|
||||
inputFrames -= ni;
|
||||
outputFrames += no;
|
||||
}
|
||||
|
||||
return outputFrames;
|
||||
}
|
||||
|
||||
//
|
||||
// This version handles input/output as interleaved float
|
||||
//
|
||||
int AudioSRC::render(const float* input, float* output, int inputFrames) {
|
||||
int outputFrames = 0;
|
||||
|
||||
while (inputFrames) {
|
||||
|
||||
int ni = std::min(inputFrames, _inputBlock);
|
||||
|
||||
convertInput(input, _inputs, ni);
|
||||
|
||||
int no = render(_inputs, _outputs, ni);
|
||||
assert(no <= SRC_BLOCK);
|
||||
|
||||
convertOutput(_outputs, output, no);
|
||||
|
||||
input += _numChannels * ni;
|
||||
output += _numChannels * no;
|
||||
|
|
|
@ -34,8 +34,15 @@ public:
|
|||
AudioSRC(int inputSampleRate, int outputSampleRate, int numChannels);
|
||||
~AudioSRC();
|
||||
|
||||
// deinterleaved float input/output (native format)
|
||||
int render(float** inputs, float** outputs, int inputFrames);
|
||||
|
||||
// interleaved int16_t input/output
|
||||
int render(const int16_t* input, int16_t* output, int inputFrames);
|
||||
|
||||
// interleaved float input/output
|
||||
int render(const float* input, float* output, int inputFrames);
|
||||
|
||||
int getMinOutput(int inputFrames);
|
||||
int getMaxOutput(int inputFrames);
|
||||
int getMinInput(int outputFrames);
|
||||
|
@ -75,10 +82,11 @@ private:
|
|||
int multirateFilter1_AVX2(const float* input0, float* output0, int inputFrames);
|
||||
int multirateFilter2_AVX2(const float* input0, const float* input1, float* output0, float* output1, int inputFrames);
|
||||
|
||||
void convertInputFromInt16(const int16_t* input, float** outputs, int numFrames);
|
||||
void convertOutputToInt16(float** inputs, int16_t* output, int numFrames);
|
||||
void convertInput(const int16_t* input, float** outputs, int numFrames);
|
||||
void convertOutput(float** inputs, int16_t* output, int numFrames);
|
||||
|
||||
int processFloat(float** inputs, float** outputs, int inputFrames);
|
||||
void convertInput(const float* input, float** outputs, int numFrames);
|
||||
void convertOutput(float** inputs, float* output, int numFrames);
|
||||
};
|
||||
|
||||
#endif // AudioSRC_h
|
||||
|
|
Loading…
Reference in a new issue