Cog Audio: Keep track of last resampler quality used so we don't reinitialize when not necessary, and also keep track of DSD decimated sample rate separately, so the input format remains unmodified

This commit is contained in:
Christopher Snowhill 2022-01-14 11:18:50 -08:00
parent 2e164d3fc8
commit af6677cf34
3 changed files with 33 additions and 16 deletions

View file

@ -62,8 +62,12 @@
AudioStreamBasicDescription rememberedInputFormat; AudioStreamBasicDescription rememberedInputFormat;
RefillNode *refillNode; RefillNode *refillNode;
id __weak originalPreviousNode; id __weak originalPreviousNode;
NSString *outputResampling;
} }
@property AudioStreamBasicDescription inputFormat;
- (id)initWithController:(id)c previous:(id)p; - (id)initWithController:(id)c previous:(id)p;
- (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inputFormat outputFormat:(AudioStreamBasicDescription)outputFormat; - (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inputFormat outputFormat:(AudioStreamBasicDescription)outputFormat;

View file

@ -35,6 +35,8 @@ void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
@implementation ConverterNode @implementation ConverterNode
@synthesize inputFormat;
- (id)initWithController:(id)c previous:(id)p - (id)initWithController:(id)c previous:(id)p
{ {
self = [super initWithController:c previous:p]; self = [super initWithController:c previous:p];
@ -69,6 +71,8 @@ void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
dsd2pcm = NULL; dsd2pcm = NULL;
dsd2pcmCount = 0; dsd2pcmCount = 0;
outputResampling = @"";
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:nil]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:nil];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputResampling" options:0 context:nil]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputResampling" options:0 context:nil];
} }
@ -1038,8 +1042,11 @@ tryagain:
} }
else if ([keyPath isEqual:@"values.outputResampling"]) { else if ([keyPath isEqual:@"values.outputResampling"]) {
// Reset resampler // Reset resampler
if (resampler && resampler_data) if (resampler && resampler_data) {
[self inputFormatDidChange:inputFormat]; NSString *value = [[NSUserDefaults standardUserDefaults] stringForKey:@"outputResampling"];
if (![value isEqualToString:outputResampling])
[self inputFormatDidChange:inputFormat];
}
} }
} }
@ -1104,10 +1111,18 @@ static float db_to_scale(float db)
|| (isFloat && !(inputFormat.mBitsPerChannel == 32 || inputFormat.mBitsPerChannel == 64))) || (isFloat && !(inputFormat.mBitsPerChannel == 32 || inputFormat.mBitsPerChannel == 64)))
return NO; return NO;
// These are really placeholders, as we're doing everything internally now
floatFormat = inputFormat;
floatFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
floatFormat.mBitsPerChannel = 32;
floatFormat.mBytesPerFrame = (32/8)*floatFormat.mChannelsPerFrame;
floatFormat.mBytesPerPacket = floatFormat.mBytesPerFrame * floatFormat.mFramesPerPacket;
if (inputFormat.mBitsPerChannel == 1) { if (inputFormat.mBitsPerChannel == 1) {
// Decimate this for speed // Decimate this for speed
inputFormat.mSampleRate *= 1.0 / 8.0; floatFormat.mSampleRate *= 1.0 / 8.0;
dsd2pcmCount = inputFormat.mChannelsPerFrame; dsd2pcmCount = floatFormat.mChannelsPerFrame;
dsd2pcm = calloc(dsd2pcmCount, sizeof(void*)); dsd2pcm = calloc(dsd2pcmCount, sizeof(void*));
dsd2pcm[0] = dsd2pcm_alloc(); dsd2pcm[0] = dsd2pcm_alloc();
dsd2pcmLatency = dsd2pcm_latency(dsd2pcm[0]); dsd2pcmLatency = dsd2pcm_latency(dsd2pcm[0]);
@ -1117,14 +1132,6 @@ static float db_to_scale(float db)
} }
} }
// These are really placeholders, as we're doing everything internally now
floatFormat = inputFormat;
floatFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
floatFormat.mBitsPerChannel = 32;
floatFormat.mBytesPerFrame = (32/8)*floatFormat.mChannelsPerFrame;
floatFormat.mBytesPerPacket = floatFormat.mBytesPerFrame * floatFormat.mFramesPerPacket;
inpOffset = 0; inpOffset = 0;
inpSize = 0; inpSize = 0;
@ -1142,9 +1149,9 @@ static float db_to_scale(float db)
convert_s16_to_float_init_simd(); convert_s16_to_float_init_simd();
convert_s32_to_float_init_simd(); convert_s32_to_float_init_simd();
skipResampler = outputFormat.mSampleRate == inputFormat.mSampleRate; skipResampler = outputFormat.mSampleRate == floatFormat.mSampleRate;
sampleRatio = (double)outputFormat.mSampleRate / (double)inputFormat.mSampleRate; sampleRatio = (double)outputFormat.mSampleRate / (double)floatFormat.mSampleRate;
if (!skipResampler) if (!skipResampler)
{ {
@ -1162,6 +1169,8 @@ static float db_to_scale(float db)
else if ([resampling isEqualToString:@"highest"]) else if ([resampling isEqualToString:@"highest"])
quality = RESAMPLER_QUALITY_HIGHEST; quality = RESAMPLER_QUALITY_HIGHEST;
outputResampling = resampling;
if (!retro_resampler_realloc(&resampler_data, &resampler, "sinc", quality, inputFormat.mChannelsPerFrame, sampleRatio)) if (!retro_resampler_realloc(&resampler_data, &resampler, "sinc", quality, inputFormat.mChannelsPerFrame, sampleRatio))
{ {
return NO; return NO;
@ -1211,7 +1220,8 @@ static float db_to_scale(float db)
DLog(@"FORMAT CHANGED"); DLog(@"FORMAT CHANGED");
paused = YES; paused = YES;
[self cleanUp]; [self cleanUp];
if (outputFormatChanged && ![buffer isEmpty]) if (outputFormatChanged && ![buffer isEmpty] &&
memcmp(&outputFormat, &previousOutputFormat, sizeof(outputFormat)) != 0)
{ {
// Transfer previously buffered data, remember input format // Transfer previously buffered data, remember input format
rememberedInputFormat = format; rememberedInputFormat = format;

View file

@ -102,7 +102,10 @@
DLog(@"Input format changed"); DLog(@"Input format changed");
// Converter doesn't need resetting for this, as output format hasn't changed // Converter doesn't need resetting for this, as output format hasn't changed
ConverterNode *converter = [[[controller controller] bufferChain] converter]; ConverterNode *converter = [[[controller controller] bufferChain] converter];
[converter inputFormatDidChange:[[[controller controller] bufferChain] inputFormat]]; AudioStreamBasicDescription newInputFormat = [[[controller controller] bufferChain] inputFormat];
AudioStreamBasicDescription oldInputFormat = [converter inputFormat];
if (memcmp(&oldInputFormat, &newInputFormat, sizeof(oldInputFormat)) != 0)
[converter inputFormatDidChange:newInputFormat];
} }
else if ([keyPath isEqual:@"metadata"]) { else if ([keyPath isEqual:@"metadata"]) {
//Inform something of metadata change //Inform something of metadata change