[FreeSurround] Further improvements

Still not working, though.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
main
Christopher Snowhill 2022-07-11 14:37:10 -07:00
parent 60429490b3
commit 8b418004eb
7 changed files with 41 additions and 17 deletions

View File

@ -84,6 +84,7 @@ enum {
- (id)initWithProperties:(NSDictionary *)properties;
- (void)assignSamples:(const void *)data frameCount:(size_t)count;
- (void)assignData:(NSData *)data;
- (NSData *)removeSamples:(size_t)frameCount;

View File

@ -148,13 +148,19 @@ static const uint32_t AudioChannelConfigTable[] = {
}
}
- (void)assignData:(NSData *)data {
[chunkData appendData:data];
}
- (NSData *)removeSamples:(size_t)frameCount {
if(formatAssigned) {
const size_t bytesPerPacket = format.mBytesPerPacket;
const size_t byteCount = bytesPerPacket * frameCount;
NSData *ret = [chunkData subdataWithRange:NSMakeRange(0, byteCount)];
[chunkData replaceBytesInRange:NSMakeRange(0, byteCount) withBytes:NULL length:0];
return ret;
@autoreleasepool {
const size_t bytesPerPacket = format.mBytesPerPacket;
const size_t byteCount = bytesPerPacket * frameCount;
NSData *ret = [chunkData subdataWithRange:NSMakeRange(0, byteCount)];
[chunkData replaceBytesInRange:NSMakeRange(0, byteCount) withBytes:NULL length:0];
return ret;
}
}
return [NSData data];
}

View File

@ -464,7 +464,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
AudioChunk *ret = [[AudioChunk alloc] init];
[ret setFormat:[chunk format]];
[ret setChannelConfig:[chunk channelConfig]];
[ret assignSamples:[removedData bytes] frameCount:maxFrameCount];
[ret assignData:removedData];
listDuration -= [ret duration];
inRemover = NO;
return ret;

View File

@ -126,6 +126,12 @@ struct freesurround_params {
freesurround_decoder *_decoder = (freesurround_decoder *)decoder;
float tempInput[4096 * 2];
uint32_t zeroCount = 0;
if(count > 4096) {
zeroCount = count - 4096;
count = 4096;
}
if(count < 4096) {
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++) {
unsigned idx = [AudioChunk channelIndexFromConfig:channelConfig forFlag:_params->chanmap[c]];
cblas_scopy(count, src + c, num, samplesOut + idx, num);
if(zeroCount) {
vDSP_vclr(samplesOut + idx + count, num, zeroCount);
}
}
}

View File

@ -114,6 +114,7 @@ using std::atomic_long;
FSurroundFilter *fsurround;
float *samplePtr;
float tempBuffer[512 * 32];
float inputBuffer[4096 * 32]; // 4096 samples times maximum supported channel count
float fsurroundBuffer[4096 * 6];
float hrtfBuffer[4096 * 2];

View File

@ -745,7 +745,10 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
int bytesRendered = 0;
do {
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;
bytesRendered += rendered * newFormat.mBytesPerPacket;
if(streamFormatChanged) {
@ -886,6 +889,8 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
commandStop = NO;
audioFormatDescription = NULL;
enableFSurround = YES;
running = NO;
stopping = NO;

View File

@ -63,19 +63,19 @@ class decoder_impl {
public:
// instantiate the decoder with a given channel setup and processing block size (in samples)
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()),
buffer_empty(true), lt(N), rt(N), dst(N), dstf(N),
dftsetupF(vDSP_DFT_zrop_CreateSetupD(0, N, vDSP_DFT_FORWARD)),
dftsetupB(vDSP_DFT_zrop_CreateSetupD(0, N, vDSP_DFT_INVERSE)) {
_dsp_complexalloc(&lf, Nover2);
_dsp_complexalloc(&rf, Nover2);
_dsp_complexalloc(&lf, N/2 + 1);
_dsp_complexalloc(&rf, N/2 + 1);
// allocate per-channel buffers
outbuf.resize((N + N / 2) * C);
signal.resize(C);
for(unsigned k = 0; k < C; k++)
_dsp_complexalloc(&signal[k], N);
_dsp_complexalloc(&signal[k], N/2 + 1);
// init the window function
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);
// map into spectral domain
vDSP_ctozD((DSPDoubleComplex *)(&lt[0]), 2, &lf, 1, Nover2);
vDSP_ctozD((DSPDoubleComplex *)(&rt[0]), 2, &rf, 1, Nover2);
vDSP_ctozD((DSPDoubleComplex *)(&lt[0]), 2, &lf, 1, N / 2);
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, rf.realp, rf.imagp, rf.realp, rf.imagp);
@ -218,6 +218,8 @@ class decoder_impl {
for(unsigned c = 0; c < C; c++) {
signal[c].realp[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
@ -253,7 +255,7 @@ class decoder_impl {
// map position to channel volumes
for(unsigned c = 0; c < C - 1; c++) {
// 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]),
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
memcpy(&outbuf[0], &outbuf[C * N / 2], N * C * 4);
memmove(&outbuf[0], &outbuf[C * N / 2], N * C * 4);
// and clear the rest
memset(&outbuf[C * N], 0, C * 4 * N / 2);
// backtransform each channel and overlap-add
for(unsigned c = 0; c < C; c++) {
// back-transform into time domain
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)
vDSP_vmulD(&dst[0], 1, &wnd[0], 1, &dst[0], 1, N);
vDSP_vdpsp(&dst[0], 1, &dstf[0], 1, N);
@ -334,7 +336,7 @@ class decoder_impl {
// constants
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
// parameters