0
votes

I am using ffmpeg to acquire audio from .mov files. Looking over my settings, I am not sample rate converting the audio buffers I am generating so that is unlikely to account for the issues I am having. Regardless of the sample rate I set on my Built-in Output, my audio files that are at 44.1 kHz playback at the correct rate. If I playback a 48kHz file, the file plays back slower (at 91% of the normal rate) which indicates that the true rate is 44.1kHz. I can change my built-in output to 44.1, 48, or 96 kHz and the same phenomenon exists. I change my default output rate using the Audio Midi Setup app. I then verify my sample rate using AudioUnitGetProperty on my ouputAudioUnit. This matches the sample rate in the Audio Midi Setup.

Thoughts? I am including my audio graph code

CheckError(NewAUGraph(&fp.graph), "Couldn't create a new AUGraph");

//varispeednode has an input callback
//the vairspeed node feeds an output node which is running 
//at the frequency of the system default output

AUNode outputNode;
AudioComponentDescription outputcd = [self defaultOutputComponent];
CheckError(AUGraphAddNode(fp.graph, &outputcd, &outputNode),
           "AUGraphAddNode[kAudioUnitSubType_DefaultOutput] failed");

AUNode varispeedNode;
AudioComponentDescription varispeedcd = [self variSpeedComponent];
CheckError(AUGraphAddNode(fp.graph, &varispeedcd, &varispeedNode),
           "AUGraphAddNode[kAudioUnitSubType_Varispeed] failed");

CheckError(AUGraphOpen(fp.graph),
           "Couldn't Open AudioGraph");

CheckError(AUGraphNodeInfo(fp.graph, outputNode, NULL, &fp.outputAudioUnit),
           "Couldn't Retrieve output node");

CheckError(AUGraphNodeInfo(fp.graph, varispeedNode, NULL, &fp.variSpeedAudioUnit),
           "Couldn't Retrieve Varispeed Audio Unit");

AURenderCallbackStruct input;
input.inputProc = CBufferProviderCallback;
input.inputProcRefCon = &playerStruct;
CheckError(AudioUnitSetProperty(fp.variSpeedAudioUnit,
                                kAudioUnitProperty_SetRenderCallback, 
                                kAudioUnitScope_Input,
                                0,
                                &input, 
                                sizeof(input)),
           "AudioUnitSetProperty failed");


CheckError(AUGraphConnectNodeInput(fp.graph, varispeedNode, 0, outputNode, 0),
           "Couldn't Connect varispeed to output");

CheckError(AUGraphInitialize(fp.graph),
           "Couldn't Initialize AUGraph");

// check output sample rate

Float64 outputSampleRate = 48000.0;
UInt32 sizeOfFloat64 = sizeof(Float64);

outputSampleRate = 0.0;
CheckError(AudioUnitGetProperty(fp.outputAudioUnit,
                               kAudioUnitProperty_SampleRate,
                               kAudioUnitScope_Global,
                               0,
                               &outputSampleRate,
                               &sizeOfFloat64), 
          "Couldn't get output sampleRate");
1

1 Answers

1
votes

I solved the issue. When building the audio graph, you need to specify the input sample rate of the varispeed audio unit before you connect it to an output node inside of the augraph. See the example code at https://developer.apple.com/library/content/samplecode/CAPlayThrough/Listings/ReadMe_txt.html

CheckError(NewAUGraph(&fp.graph), "BuildGraphError");

AUNode outputNode;
AudioComponentDescription outputcd = [self defaultOutputComponent];
CheckError(AUGraphAddNode(fp.graph, &outputcd, &outputNode),
       "AUGraphAddNode[kAudioUnitSubType_DefaultOutput] failed");

AUNode varispeedNode;
AudioComponentDescription varispeedcd = [self variSpeedComponent];
CheckError(AUGraphAddNode(fp.graph, &varispeedcd, &varispeedNode),
       "AUGraphAddNode[kAudioUnitSubType_Varispeed] failed");

CheckError(AUGraphOpen(fp.graph),
       "Couldn't Open AudioGraph");

CheckError(AUGraphNodeInfo(fp.graph, outputNode, NULL, &fp.outputAudioUnit),
       "Couldn't Retrieve File Audio Unit");

CheckError(AUGraphNodeInfo(fp.graph, varispeedNode, NULL, &fp.variSpeedAudioUnit),
       "Couldn't Retrieve Varispeed Audio Unit");

AURenderCallbackStruct input;
  input.inputProc = CBufferProviderCallback;
input.inputProcRefCon = &playerStruct;
CheckError(AudioUnitSetProperty(fp.variSpeedAudioUnit,
                kAudioUnitProperty_SetRenderCallback, 
                kAudioUnitScope_Input,
                0,
                &input, 
                sizeof(input)),
       "AudioUnitSetProperty failed");

  //you have to set the varispeed rate before you connect it
  //see CAPlayThrough

AudioStreamBasicDescription asbd = {0};
UInt32 size;
Boolean outWritable;

//Gets the size of the Stream Format Property and if it is writable
OSStatus result = AudioUnitGetPropertyInfo(fp.variSpeedAudioUnit,
                                           kAudioUnitProperty_StreamFormat,
                                           kAudioUnitScope_Output,
                                           0,
                                           &size,
                                           &outWritable);

//Get the current stream format of the output
result = AudioUnitGetProperty (fp.variSpeedAudioUnit,
                               kAudioUnitProperty_StreamFormat,
                               kAudioUnitScope_Output,
                               0,
                               &asbd,
                               &size);

asbd.mSampleRate = targetSampleRate;

//Set the stream format of the output to match the input
result = AudioUnitSetProperty (fp.variSpeedAudioUnit,
                               kAudioUnitProperty_StreamFormat,
                               kAudioUnitScope_Input,
                               0,
                               &asbd,
                               size);

printf("AudioUnitSetProperty result %d %d\n", result, noErr);



CheckError(AUGraphConnectNodeInput(fp.graph, varispeedNode, 0, outputNode, 0),
       "Couldn't Connect varispeed to output");

CheckError(AUGraphInitialize(fp.graph),
       "Couldn't Initialize AUGraph");

Float64 outputSampleRate = 48000.0;
  UInt32 sizeOfFloat64 = sizeof(Float64);

  outputSampleRate = 0.0;
  CheckError(AudioUnitGetProperty(fp.outputAudioUnit,
                                  kAudioUnitProperty_SampleRate,
                                  kAudioUnitScope_Global,
                                  0,
                                  &outputSampleRate,
                                  &sizeOfFloat64), 
             "Couldn't get output sampleRate");

NSLog(@"Output Sample Rate of the ->%f", outputSampleRate);