[FreeSurround] Further improvements
Still not working, though. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
f05bf71320
commit
8034054d72
7 changed files with 41 additions and 17 deletions
|
@ -84,6 +84,7 @@ enum {
|
||||||
- (id)initWithProperties:(NSDictionary *)properties;
|
- (id)initWithProperties:(NSDictionary *)properties;
|
||||||
|
|
||||||
- (void)assignSamples:(const void *)data frameCount:(size_t)count;
|
- (void)assignSamples:(const void *)data frameCount:(size_t)count;
|
||||||
|
- (void)assignData:(NSData *)data;
|
||||||
|
|
||||||
- (NSData *)removeSamples:(size_t)frameCount;
|
- (NSData *)removeSamples:(size_t)frameCount;
|
||||||
|
|
||||||
|
|
|
@ -148,13 +148,19 @@ static const uint32_t AudioChannelConfigTable[] = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)assignData:(NSData *)data {
|
||||||
|
[chunkData appendData:data];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSData *)removeSamples:(size_t)frameCount {
|
- (NSData *)removeSamples:(size_t)frameCount {
|
||||||
if(formatAssigned) {
|
if(formatAssigned) {
|
||||||
const size_t bytesPerPacket = format.mBytesPerPacket;
|
@autoreleasepool {
|
||||||
const size_t byteCount = bytesPerPacket * frameCount;
|
const size_t bytesPerPacket = format.mBytesPerPacket;
|
||||||
NSData *ret = [chunkData subdataWithRange:NSMakeRange(0, byteCount)];
|
const size_t byteCount = bytesPerPacket * frameCount;
|
||||||
[chunkData replaceBytesInRange:NSMakeRange(0, byteCount) withBytes:NULL length:0];
|
NSData *ret = [chunkData subdataWithRange:NSMakeRange(0, byteCount)];
|
||||||
return ret;
|
[chunkData replaceBytesInRange:NSMakeRange(0, byteCount) withBytes:NULL length:0];
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return [NSData data];
|
return [NSData data];
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,7 +464,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
|
||||||
AudioChunk *ret = [[AudioChunk alloc] init];
|
AudioChunk *ret = [[AudioChunk alloc] init];
|
||||||
[ret setFormat:[chunk format]];
|
[ret setFormat:[chunk format]];
|
||||||
[ret setChannelConfig:[chunk channelConfig]];
|
[ret setChannelConfig:[chunk channelConfig]];
|
||||||
[ret assignSamples:[removedData bytes] frameCount:maxFrameCount];
|
[ret assignData:removedData];
|
||||||
listDuration -= [ret duration];
|
listDuration -= [ret duration];
|
||||||
inRemover = NO;
|
inRemover = NO;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -126,6 +126,12 @@ struct freesurround_params {
|
||||||
freesurround_decoder *_decoder = (freesurround_decoder *)decoder;
|
freesurround_decoder *_decoder = (freesurround_decoder *)decoder;
|
||||||
|
|
||||||
float tempInput[4096 * 2];
|
float tempInput[4096 * 2];
|
||||||
|
uint32_t zeroCount = 0;
|
||||||
|
|
||||||
|
if(count > 4096) {
|
||||||
|
zeroCount = count - 4096;
|
||||||
|
count = 4096;
|
||||||
|
}
|
||||||
|
|
||||||
if(count < 4096) {
|
if(count < 4096) {
|
||||||
cblas_scopy(count * 2, samplesIn, 1, &tempInput[0], 1);
|
cblas_scopy(count * 2, samplesIn, 1, &tempInput[0], 1);
|
||||||
|
@ -138,6 +144,9 @@ struct freesurround_params {
|
||||||
for(unsigned c = 0, num = channelCount; c < num; c++) {
|
for(unsigned c = 0, num = channelCount; c < num; c++) {
|
||||||
unsigned idx = [AudioChunk channelIndexFromConfig:channelConfig forFlag:_params->chanmap[c]];
|
unsigned idx = [AudioChunk channelIndexFromConfig:channelConfig forFlag:_params->chanmap[c]];
|
||||||
cblas_scopy(count, src + c, num, samplesOut + idx, num);
|
cblas_scopy(count, src + c, num, samplesOut + idx, num);
|
||||||
|
if(zeroCount) {
|
||||||
|
vDSP_vclr(samplesOut + idx + count, num, zeroCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ using std::atomic_long;
|
||||||
FSurroundFilter *fsurround;
|
FSurroundFilter *fsurround;
|
||||||
|
|
||||||
float *samplePtr;
|
float *samplePtr;
|
||||||
|
float tempBuffer[512 * 32];
|
||||||
float inputBuffer[4096 * 32]; // 4096 samples times maximum supported channel count
|
float inputBuffer[4096 * 32]; // 4096 samples times maximum supported channel count
|
||||||
float fsurroundBuffer[4096 * 6];
|
float fsurroundBuffer[4096 * 6];
|
||||||
float hrtfBuffer[4096 * 2];
|
float hrtfBuffer[4096 * 2];
|
||||||
|
|
|
@ -745,7 +745,10 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
int bytesRendered = 0;
|
int bytesRendered = 0;
|
||||||
do {
|
do {
|
||||||
int maxToRender = MIN(4096 - inputRendered, 512);
|
int maxToRender = MIN(4096 - inputRendered, 512);
|
||||||
int rendered = [self renderInput:maxToRender toBuffer:(float *)(((uint8_t *)inputBuffer) + bytesRendered)];
|
int rendered = [self renderInput:maxToRender toBuffer:&tempBuffer[0]];
|
||||||
|
if(rendered > 0) {
|
||||||
|
memcpy((((uint8_t *)inputBuffer) + bytesRendered), &tempBuffer[0], rendered * newFormat.mBytesPerPacket);
|
||||||
|
}
|
||||||
inputRendered += rendered;
|
inputRendered += rendered;
|
||||||
bytesRendered += rendered * newFormat.mBytesPerPacket;
|
bytesRendered += rendered * newFormat.mBytesPerPacket;
|
||||||
if(streamFormatChanged) {
|
if(streamFormatChanged) {
|
||||||
|
@ -887,6 +890,8 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
|
|
||||||
audioFormatDescription = NULL;
|
audioFormatDescription = NULL;
|
||||||
|
|
||||||
|
enableFSurround = YES;
|
||||||
|
|
||||||
running = NO;
|
running = NO;
|
||||||
stopping = NO;
|
stopping = NO;
|
||||||
stopped = NO;
|
stopped = NO;
|
||||||
|
|
|
@ -63,19 +63,19 @@ class decoder_impl {
|
||||||
public:
|
public:
|
||||||
// instantiate the decoder with a given channel setup and processing block size (in samples)
|
// instantiate the decoder with a given channel setup and processing block size (in samples)
|
||||||
decoder_impl(channel_setup setup, unsigned N)
|
decoder_impl(channel_setup setup, unsigned N)
|
||||||
: N(N), log2N(log2n(N)), Nover2((N + 1) / 2),
|
: N(N), log2N(log2n(N)),
|
||||||
wnd(N), inbuf(3 * N), setup(setup), C((unsigned)chn_alloc[setup].size()),
|
wnd(N), inbuf(3 * N), setup(setup), C((unsigned)chn_alloc[setup].size()),
|
||||||
buffer_empty(true), lt(N), rt(N), dst(N), dstf(N),
|
buffer_empty(true), lt(N), rt(N), dst(N), dstf(N),
|
||||||
dftsetupF(vDSP_DFT_zrop_CreateSetupD(0, N, vDSP_DFT_FORWARD)),
|
dftsetupF(vDSP_DFT_zrop_CreateSetupD(0, N, vDSP_DFT_FORWARD)),
|
||||||
dftsetupB(vDSP_DFT_zrop_CreateSetupD(0, N, vDSP_DFT_INVERSE)) {
|
dftsetupB(vDSP_DFT_zrop_CreateSetupD(0, N, vDSP_DFT_INVERSE)) {
|
||||||
_dsp_complexalloc(&lf, Nover2);
|
_dsp_complexalloc(&lf, N/2 + 1);
|
||||||
_dsp_complexalloc(&rf, Nover2);
|
_dsp_complexalloc(&rf, N/2 + 1);
|
||||||
|
|
||||||
// allocate per-channel buffers
|
// allocate per-channel buffers
|
||||||
outbuf.resize((N + N / 2) * C);
|
outbuf.resize((N + N / 2) * C);
|
||||||
signal.resize(C);
|
signal.resize(C);
|
||||||
for(unsigned k = 0; k < C; k++)
|
for(unsigned k = 0; k < C; k++)
|
||||||
_dsp_complexalloc(&signal[k], N);
|
_dsp_complexalloc(&signal[k], N/2 + 1);
|
||||||
|
|
||||||
// init the window function
|
// init the window function
|
||||||
for(unsigned k = 0; k < N; k++)
|
for(unsigned k = 0; k < N; k++)
|
||||||
|
@ -209,8 +209,8 @@ class decoder_impl {
|
||||||
vDSP_vmulD(&rt[0], 1, &wnd[0], 1, &rt[0], 1, N);
|
vDSP_vmulD(&rt[0], 1, &wnd[0], 1, &rt[0], 1, N);
|
||||||
|
|
||||||
// map into spectral domain
|
// map into spectral domain
|
||||||
vDSP_ctozD((DSPDoubleComplex *)(<[0]), 2, &lf, 1, Nover2);
|
vDSP_ctozD((DSPDoubleComplex *)(<[0]), 2, &lf, 1, N / 2);
|
||||||
vDSP_ctozD((DSPDoubleComplex *)(&rt[0]), 2, &rf, 1, Nover2);
|
vDSP_ctozD((DSPDoubleComplex *)(&rt[0]), 2, &rf, 1, N / 2);
|
||||||
|
|
||||||
vDSP_DFT_ExecuteD(dftsetupF, lf.realp, lf.imagp, lf.realp, lf.imagp);
|
vDSP_DFT_ExecuteD(dftsetupF, lf.realp, lf.imagp, lf.realp, lf.imagp);
|
||||||
vDSP_DFT_ExecuteD(dftsetupF, rf.realp, rf.imagp, rf.realp, rf.imagp);
|
vDSP_DFT_ExecuteD(dftsetupF, rf.realp, rf.imagp, rf.realp, rf.imagp);
|
||||||
|
@ -218,6 +218,8 @@ class decoder_impl {
|
||||||
for(unsigned c = 0; c < C; c++) {
|
for(unsigned c = 0; c < C; c++) {
|
||||||
signal[c].realp[0] = 0;
|
signal[c].realp[0] = 0;
|
||||||
signal[c].imagp[0] = 0;
|
signal[c].imagp[0] = 0;
|
||||||
|
signal[c].realp[N/2] = 0;
|
||||||
|
signal[c].imagp[N/2] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute multichannel output signal in the spectral domain
|
// compute multichannel output signal in the spectral domain
|
||||||
|
@ -253,7 +255,7 @@ class decoder_impl {
|
||||||
// map position to channel volumes
|
// map position to channel volumes
|
||||||
for(unsigned c = 0; c < C - 1; c++) {
|
for(unsigned c = 0; c < C - 1; c++) {
|
||||||
// look up channel map at respective position (with bilinear interpolation) and build the signal
|
// look up channel map at respective position (with bilinear interpolation) and build the signal
|
||||||
vector<float *> &a = chn_alloc[setup][c];
|
const vector<float *> &a = chn_alloc[setup][c];
|
||||||
polar(amp_total * ((1 - x) * (1 - y) * a[q][p] + x * (1 - y) * a[q][p + 1] + (1 - x) * y * a[q + 1][p] + x * y * a[q + 1][p + 1]),
|
polar(amp_total * ((1 - x) * (1 - y) * a[q][p] + x * (1 - y) * a[q][p + 1] + (1 - x) * y * a[q + 1][p] + x * y * a[q + 1][p + 1]),
|
||||||
phase_of[1 + (int)sign(chn_xsf[setup][c])], signal[c], f);
|
phase_of[1 + (int)sign(chn_xsf[setup][c])], signal[c], f);
|
||||||
}
|
}
|
||||||
|
@ -275,14 +277,14 @@ class decoder_impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// shift the last 2/3 to the first 2/3 of the output buffer
|
// shift the last 2/3 to the first 2/3 of the output buffer
|
||||||
memcpy(&outbuf[0], &outbuf[C * N / 2], N * C * 4);
|
memmove(&outbuf[0], &outbuf[C * N / 2], N * C * 4);
|
||||||
// and clear the rest
|
// and clear the rest
|
||||||
memset(&outbuf[C * N], 0, C * 4 * N / 2);
|
memset(&outbuf[C * N], 0, C * 4 * N / 2);
|
||||||
// backtransform each channel and overlap-add
|
// backtransform each channel and overlap-add
|
||||||
for(unsigned c = 0; c < C; c++) {
|
for(unsigned c = 0; c < C; c++) {
|
||||||
// back-transform into time domain
|
// back-transform into time domain
|
||||||
vDSP_DFT_ExecuteD(dftsetupB, signal[c].realp, signal[c].imagp, signal[c].realp, signal[c].imagp);
|
vDSP_DFT_ExecuteD(dftsetupB, signal[c].realp, signal[c].imagp, signal[c].realp, signal[c].imagp);
|
||||||
vDSP_ztocD(&signal[c], 1, (DSPDoubleComplex *)(&dst[0]), 2, Nover2);
|
vDSP_ztocD(&signal[c], 1, (DSPDoubleComplex *)(&dst[0]), 2, N / 2);
|
||||||
// add the result to the last 2/3 of the output buffer, windowed (and remultiplex)
|
// add the result to the last 2/3 of the output buffer, windowed (and remultiplex)
|
||||||
vDSP_vmulD(&dst[0], 1, &wnd[0], 1, &dst[0], 1, N);
|
vDSP_vmulD(&dst[0], 1, &wnd[0], 1, &dst[0], 1, N);
|
||||||
vDSP_vdpsp(&dst[0], 1, &dstf[0], 1, N);
|
vDSP_vdpsp(&dst[0], 1, &dstf[0], 1, N);
|
||||||
|
@ -334,7 +336,7 @@ class decoder_impl {
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
unsigned N, C; // number of samples per input/output block, number of output channels
|
unsigned N, C; // number of samples per input/output block, number of output channels
|
||||||
unsigned log2N, Nover2; // derivations of the block size
|
unsigned log2N; // derivations of the block size
|
||||||
channel_setup setup; // the channel setup
|
channel_setup setup; // the channel setup
|
||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
|
|
Loading…
Reference in a new issue