[Output] [Downmixer] Optimize a bit

Rewrite some of the output and a lot of the downmixer to use Accelerate
framework instead of dumb for loops.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2022-06-06 08:16:27 -07:00
parent 0ba766023e
commit 18af8a06df
2 changed files with 68 additions and 73 deletions

View file

@ -12,6 +12,8 @@
#import "AudioChunk.h" #import "AudioChunk.h"
#import <Accelerate/Accelerate.h>
static void downmix_to_stereo(const float *inBuffer, int channels, uint32_t config, float *outBuffer, size_t count) { static void downmix_to_stereo(const float *inBuffer, int channels, uint32_t config, float *outBuffer, size_t count) {
float FrontRatios[2] = { 0.0F, 0.0F }; float FrontRatios[2] = { 0.0F, 0.0F };
float FrontCenterRatio = 0.0F; float FrontCenterRatio = 0.0F;
@ -71,73 +73,77 @@ static void downmix_to_stereo(const float *inBuffer, int channels, uint32_t conf
channelIndexes[i] = [AudioChunk findChannelIndex:[AudioChunk extractChannelFlag:i fromConfig:config]]; channelIndexes[i] = [AudioChunk findChannelIndex:[AudioChunk extractChannelFlag:i fromConfig:config]];
} }
for(size_t i = 0; i < count; ++i) { vDSP_vclr(outBuffer, 1, count * 2);
float left = 0.0F, right = 0.0F;
for(uint32_t j = 0; j < channels; ++j) {
float inSample = inBuffer[i * channels + j];
switch(channelIndexes[j]) {
case 0:
left += inSample * FrontRatios[0];
right += inSample * FrontRatios[1];
break;
case 1: float tempBuffer[count * 2];
left += inSample * FrontRatios[1];
right += inSample * FrontRatios[0];
break;
case 2: for(uint32_t i = 0; i < channels; ++i) {
left += inSample * FrontCenterRatio; float leftRatio = 0.0F;
right += inSample * FrontCenterRatio; float rightRatio = 0.0F;
break; switch(channelIndexes[i]) {
case 0:
leftRatio = FrontRatios[0];
rightRatio = FrontRatios[1];
break;
case 3: case 1:
left += inSample * LFERatio; leftRatio = FrontRatios[1];
right += inSample * LFERatio; rightRatio = FrontRatios[0];
break; break;
case 4: case 2:
left += inSample * BackRatios[0]; leftRatio = FrontCenterRatio;
right += inSample * BackRatios[1]; rightRatio = FrontCenterRatio;
break; break;
case 5: case 3:
left += inSample * BackRatios[1]; leftRatio = LFERatio;
right += inSample * BackRatios[0]; rightRatio = LFERatio;
break; break;
case 6: case 4:
case 7: leftRatio = BackRatios[0];
break; rightRatio = BackRatios[1];
break;
case 8: case 5:
left += inSample * BackCenterRatio; leftRatio = BackRatios[1];
right += inSample * BackCenterRatio; rightRatio = BackRatios[0];
break; break;
case 9: case 6:
left += inSample * SideRatios[0]; case 7:
right += inSample * SideRatios[1]; break;
break;
case 10: case 8:
left += inSample * SideRatios[1]; leftRatio = BackCenterRatio;
right += inSample * SideRatios[0]; rightRatio = BackCenterRatio;
break; break;
case 11: case 9:
case 12: leftRatio = SideRatios[0];
case 13: rightRatio = SideRatios[1];
case 14: break;
case 15:
case 16: case 10:
case 17: leftRatio = SideRatios[1];
default: rightRatio = SideRatios[0];
break; break;
}
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
default:
break;
} }
outBuffer[i * 2 + 0] = left; vDSP_vsmul(inBuffer + i, channels, &leftRatio, tempBuffer, 1, count);
outBuffer[i * 2 + 1] = right; vDSP_vsmul(inBuffer + i, channels, &rightRatio, tempBuffer + count, 1, count);
vDSP_vadd(outBuffer, 2, tempBuffer, 1, outBuffer, 2, count);
vDSP_vadd(outBuffer + 1, 2, tempBuffer + count, 1, outBuffer + 1, 2, count);
} }
} }
@ -147,13 +153,8 @@ static void downmix_to_mono(const float *inBuffer, int channels, uint32_t config
inBuffer = tempBuffer; inBuffer = tempBuffer;
channels = 2; channels = 2;
config = AudioConfigStereo; config = AudioConfigStereo;
for(size_t i = 0; i < count; ++i) { cblas_scopy((int)count, inBuffer, 2, outBuffer, 1);
float sample = 0; vDSP_vadd(outBuffer, 1, inBuffer + 1, 2, outBuffer, 1, count);
for(int j = 0; j < channels; ++j) {
sample += inBuffer[i * channels + j];
}
outBuffer[i] = sample;
}
} }
static void upmix(const float *inBuffer, int inchannels, uint32_t inconfig, float *outBuffer, int outchannels, uint32_t outconfig, size_t count) { static void upmix(const float *inBuffer, int inchannels, uint32_t inconfig, float *outBuffer, int outchannels, uint32_t outconfig, size_t count) {

View file

@ -15,6 +15,8 @@
#import "Logging.h" #import "Logging.h"
#import <Accelerate/Accelerate.h>
extern void scale_by_volume(float *buffer, size_t count, float volume); extern void scale_by_volume(float *buffer, size_t count, float volume);
static NSString *CogPlaybackDidBeginNotficiation = @"CogPlaybackDidBeginNotficiation"; static NSString *CogPlaybackDidBeginNotficiation = @"CogPlaybackDidBeginNotficiation";
@ -27,11 +29,7 @@ static void fillBuffers(AudioBufferList *ioData, float *inbuffer, size_t count,
const size_t maxCount = (ioData->mBuffers[i].mDataByteSize / sizeof(float)) - offset; const size_t maxCount = (ioData->mBuffers[i].mDataByteSize / sizeof(float)) - offset;
float *output = ((float *)ioData->mBuffers[i].mData) + offset; float *output = ((float *)ioData->mBuffers[i].mData) + offset;
const float *input = inbuffer + i; const float *input = inbuffer + i;
for(size_t j = 0, k = (count > maxCount) ? maxCount : count; j < k; ++j) { cblas_scopy((int)((count > maxCount) ? maxCount : count), input, (int)channels, output, 1);
*output = *input;
output++;
input += channels;
}
ioData->mBuffers[i].mNumberChannels = 1; ioData->mBuffers[i].mNumberChannels = 1;
} }
} }
@ -724,11 +722,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
float *outBuffer = ((float *)inputData->mBuffers[0].mData) + i; float *outBuffer = ((float *)inputData->mBuffers[0].mData) + i;
const float *inBuffer = ((float *)ioData->mBuffers[i].mData); const float *inBuffer = ((float *)ioData->mBuffers[i].mData);
const int frameCount = ioData->mBuffers[i].mDataByteSize / sizeof(float); const int frameCount = ioData->mBuffers[i].mDataByteSize / sizeof(float);
for(int j = 0; j < frameCount; ++j) { cblas_scopy(frameCount, inBuffer, 1, outBuffer, channels);
*outBuffer = *inBuffer;
inBuffer++;
outBuffer += channels;
}
} }
#ifdef OUTPUT_LOG #ifdef OUTPUT_LOG