diff --git a/Audio/Chain/ConverterNode.h b/Audio/Chain/ConverterNode.h index 397741070..2a23f455b 100644 --- a/Audio/Chain/ConverterNode.h +++ b/Audio/Chain/ConverterNode.h @@ -62,8 +62,12 @@ AudioStreamBasicDescription rememberedInputFormat; RefillNode *refillNode; id __weak originalPreviousNode; + + NSString *outputResampling; } +@property AudioStreamBasicDescription inputFormat; + - (id)initWithController:(id)c previous:(id)p; - (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inputFormat outputFormat:(AudioStreamBasicDescription)outputFormat; diff --git a/Audio/Chain/ConverterNode.m b/Audio/Chain/ConverterNode.m index d288f9906..e5a339826 100644 --- a/Audio/Chain/ConverterNode.m +++ b/Audio/Chain/ConverterNode.m @@ -35,6 +35,8 @@ void PrintStreamDesc (AudioStreamBasicDescription *inDesc) @implementation ConverterNode +@synthesize inputFormat; + - (id)initWithController:(id)c previous:(id)p { self = [super initWithController:c previous:p]; @@ -68,6 +70,8 @@ void PrintStreamDesc (AudioStreamBasicDescription *inDesc) dsd2pcm = NULL; dsd2pcmCount = 0; + + outputResampling = @""; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" 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"]) { // Reset resampler - if (resampler && resampler_data) - [self inputFormatDidChange:inputFormat]; + if (resampler && resampler_data) { + 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))) 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) { // Decimate this for speed - inputFormat.mSampleRate *= 1.0 / 8.0; - dsd2pcmCount = inputFormat.mChannelsPerFrame; + floatFormat.mSampleRate *= 1.0 / 8.0; + dsd2pcmCount = floatFormat.mChannelsPerFrame; dsd2pcm = calloc(dsd2pcmCount, sizeof(void*)); dsd2pcm[0] = dsd2pcm_alloc(); 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; inpSize = 0; @@ -1142,9 +1149,9 @@ static float db_to_scale(float db) convert_s16_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) { @@ -1162,6 +1169,8 @@ static float db_to_scale(float db) else if ([resampling isEqualToString:@"highest"]) quality = RESAMPLER_QUALITY_HIGHEST; + outputResampling = resampling; + if (!retro_resampler_realloc(&resampler_data, &resampler, "sinc", quality, inputFormat.mChannelsPerFrame, sampleRatio)) { return NO; @@ -1211,7 +1220,8 @@ static float db_to_scale(float db) DLog(@"FORMAT CHANGED"); paused = YES; [self cleanUp]; - if (outputFormatChanged && ![buffer isEmpty]) + if (outputFormatChanged && ![buffer isEmpty] && + memcmp(&outputFormat, &previousOutputFormat, sizeof(outputFormat)) != 0) { // Transfer previously buffered data, remember input format rememberedInputFormat = format; diff --git a/Audio/Chain/InputNode.m b/Audio/Chain/InputNode.m index 8568dc501..f63437bb4 100644 --- a/Audio/Chain/InputNode.m +++ b/Audio/Chain/InputNode.m @@ -102,7 +102,10 @@ DLog(@"Input format changed"); // Converter doesn't need resetting for this, as output format hasn't changed 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"]) { //Inform something of metadata change