Hopefully fix memory usage during playback
Shuffle around @autoreleasepool blocks, and also add one to the audio processing code in the playback callback, so audio memory is released during playback instead of accumulating. Fixes #379 Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
bc330e75f6
commit
1c95771ed0
2 changed files with 62 additions and 62 deletions
|
@ -93,28 +93,24 @@ void scale_by_volume(float *buffer, size_t count, float volume) {
|
||||||
// when the end of stream is reached. Convert function instead processes what it can,
|
// when the end of stream is reached. Convert function instead processes what it can,
|
||||||
// and returns 0 samples when it has nothing more to process at the end of stream.
|
// and returns 0 samples when it has nothing more to process at the end of stream.
|
||||||
while([self shouldContinue] == YES) {
|
while([self shouldContinue] == YES) {
|
||||||
AudioChunk *chunk = nil;
|
|
||||||
while(paused) {
|
while(paused) {
|
||||||
usleep(500);
|
usleep(500);
|
||||||
}
|
}
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
AudioChunk *chunk = nil;
|
||||||
chunk = [self convert];
|
chunk = [self convert];
|
||||||
}
|
if(!chunk) {
|
||||||
if(!chunk) {
|
if([self endOfStream] == YES) {
|
||||||
if([self endOfStream] == YES) {
|
break;
|
||||||
break;
|
}
|
||||||
}
|
if(paused || !streamFormatChanged) {
|
||||||
if(paused || !streamFormatChanged) {
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
|
||||||
@autoreleasepool {
|
|
||||||
[self writeChunk:chunk];
|
[self writeChunk:chunk];
|
||||||
chunk = nil;
|
chunk = nil;
|
||||||
}
|
}
|
||||||
}
|
if(streamFormatChanged) {
|
||||||
if(streamFormatChanged) {
|
|
||||||
@autoreleasepool {
|
|
||||||
[self cleanUp];
|
[self cleanUp];
|
||||||
[self setupWithInputFormat:newInputFormat withInputConfig:newInputChannelConfig outputFormat:self->outputFormat isLossless:rememberedLossless];
|
[self setupWithInputFormat:newInputFormat withInputConfig:newInputChannelConfig outputFormat:self->outputFormat isLossless:rememberedLossless];
|
||||||
}
|
}
|
||||||
|
|
|
@ -422,36 +422,38 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
secondsLatency = 1.0;
|
secondsLatency = 1.0;
|
||||||
|
|
||||||
while(!stopping) {
|
while(!stopping) {
|
||||||
if(outputdevicechanged) {
|
@autoreleasepool {
|
||||||
[self updateDeviceFormat];
|
if(outputdevicechanged) {
|
||||||
outputdevicechanged = NO;
|
[self updateDeviceFormat];
|
||||||
}
|
outputdevicechanged = NO;
|
||||||
|
|
||||||
if([outputController shouldReset]) {
|
|
||||||
[outputController setShouldReset:NO];
|
|
||||||
[outputLock lock];
|
|
||||||
secondsLatency = 0.0;
|
|
||||||
visPushed = 0.0;
|
|
||||||
started = NO;
|
|
||||||
restarted = NO;
|
|
||||||
if(rsvis) {
|
|
||||||
rsstate_delete(rsvis);
|
|
||||||
rsvis = NULL;
|
|
||||||
}
|
}
|
||||||
lastClippedSampleRate = 0.0;
|
|
||||||
lastVisRate = 0.0;
|
|
||||||
[outputLock unlock];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(stopping)
|
if([outputController shouldReset]) {
|
||||||
break;
|
[outputController setShouldReset:NO];
|
||||||
|
[outputLock lock];
|
||||||
|
secondsLatency = 0.0;
|
||||||
|
visPushed = 0.0;
|
||||||
|
started = NO;
|
||||||
|
restarted = NO;
|
||||||
|
if(rsvis) {
|
||||||
|
rsstate_delete(rsvis);
|
||||||
|
rsvis = NULL;
|
||||||
|
}
|
||||||
|
lastClippedSampleRate = 0.0;
|
||||||
|
lastVisRate = 0.0;
|
||||||
|
[outputLock unlock];
|
||||||
|
}
|
||||||
|
|
||||||
if(!started && !paused) {
|
if(stopping)
|
||||||
[self resume];
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if([outputController shouldContinue] == NO) {
|
if(!started && !paused) {
|
||||||
break;
|
[self resume];
|
||||||
|
}
|
||||||
|
|
||||||
|
if([outputController shouldContinue] == NO) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep(5000);
|
usleep(5000);
|
||||||
|
@ -1037,29 +1039,31 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
|
|
||||||
OutputCoreAudio *_self = (__bridge OutputCoreAudio *)refCon;
|
OutputCoreAudio *_self = (__bridge OutputCoreAudio *)refCon;
|
||||||
int renderedSamples = 0;
|
int renderedSamples = 0;
|
||||||
|
|
||||||
while(renderedSamples < frameCount) {
|
|
||||||
int inputRemain = _self->inputRemain;
|
|
||||||
while(!inputRemain) {
|
|
||||||
inputRemain = [_self renderAndConvert];
|
|
||||||
if(_self->stopping)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(inputRemain) {
|
|
||||||
int inputTodo = MIN(inputRemain, frameCount - renderedSamples);
|
|
||||||
cblas_scopy(inputTodo * channels, _self->samplePtr, 1, ((float *)inputData->mBuffers[0].mData) + renderedSamples * channels, 1);
|
|
||||||
_self->samplePtr += inputTodo * channels;
|
|
||||||
inputRemain -= inputTodo;
|
|
||||||
renderedSamples += inputTodo;
|
|
||||||
}
|
|
||||||
_self->inputRemain = inputRemain;
|
|
||||||
}
|
|
||||||
|
|
||||||
inputData->mBuffers[0].mDataByteSize = renderedSamples * format->mBytesPerPacket;
|
@autoreleasepool {
|
||||||
inputData->mBuffers[0].mNumberChannels = channels;
|
while(renderedSamples < frameCount) {
|
||||||
|
int inputRemain = _self->inputRemain;
|
||||||
double secondsRendered = (double)renderedSamples / format->mSampleRate;
|
while(!inputRemain) {
|
||||||
[_self updateLatency:secondsRendered];
|
inputRemain = [_self renderAndConvert];
|
||||||
|
if(_self->stopping)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(inputRemain) {
|
||||||
|
int inputTodo = MIN(inputRemain, frameCount - renderedSamples);
|
||||||
|
cblas_scopy(inputTodo * channels, _self->samplePtr, 1, ((float *)inputData->mBuffers[0].mData) + renderedSamples * channels, 1);
|
||||||
|
_self->samplePtr += inputTodo * channels;
|
||||||
|
inputRemain -= inputTodo;
|
||||||
|
renderedSamples += inputTodo;
|
||||||
|
}
|
||||||
|
_self->inputRemain = inputRemain;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputData->mBuffers[0].mDataByteSize = renderedSamples * format->mBytesPerPacket;
|
||||||
|
inputData->mBuffers[0].mNumberChannels = channels;
|
||||||
|
|
||||||
|
double secondsRendered = (double)renderedSamples / format->mSampleRate;
|
||||||
|
[_self updateLatency:secondsRendered];
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
[BadSampleCleaner cleanSamples:(float *)inputData->mBuffers[0].mData
|
[BadSampleCleaner cleanSamples:(float *)inputData->mBuffers[0].mData
|
||||||
|
|
Loading…
Reference in a new issue