I m using ExtAudioFileWriteAsync to write an audio file while using device recording, but once I get recording finished I try to read it with ExtAudioFileRead function and samples I get are not same samples I m writing... Anyone know why this could happen?
For writing:
self.audioManager.inputBlock = ^(float *data, UInt32 numFrames, UInt32 numChannels) {
for (int i = 0; i < numFrames*numChannels; i++) {
printf("write*%f\n", data[i]);
}
UInt32 numIncomingBytes = numFrames*numChannels*sizeof(float);
UInt32 *outputBuffer =(UInt32*)malloc(numIncomingBytes);
memcpy(outputBuffer, recordedData, numIncomingBytes);
AudioBufferList outgoingAudio;
outgoingAudio.mNumberBuffers = 1;
outgoingAudio.mBuffers[0].mNumberChannels = numChannels;
outgoingAudio.mBuffers[0].mDataByteSize = numIncomingBytes;
outgoingAudio.mBuffers[0].mData = self.outputBuffer;
if( 0 == pthread_mutex_trylock( &outputAudioFileLock ) )
{
ExtAudioFileWriteAsync(outputFile, numFrames, &outgoingAudio);
}
pthread_mutex_unlock( &outputAudioFileLock );
};
[self.audioManager play];
For reading:
UInt32 *outputBuffer = (UInt32 *)malloc(numFrames*numChannels*sizeof(float));
AudioBufferList convertedData;
convertedData.mNumberBuffers = 1;
convertedData.mBuffers[0].mNumberChannels = numChannels;
convertedData.mBuffers[0].mDataByteSize = numFrames*numChannels*sizeof(float);
convertedData.mBuffers[0].mData = outputBuffer;
NSMutableArray *samplesArray = [[NSMutableArray alloc]init];
while (numFrames > 0) {
ExtAudioFileRead(inputFile, &numFrames, &convertedData);
if (numFrames > 0) {
AudioBuffer audioBuffer = convertedData.mBuffers[0];
float *samples = (float *)audioBuffer.mData;
for (int i = 0; i < frameCount*numChannels; i++) {
printf("read*%f\n", samples[i]);
}
}
}
By the way I'm using Novocaine project in order to get device audio. I can reproduce saved audio with Novocaine code or with any other player.
When writing ExtAudioFileRef output :
ExtAudioFileCreateWithURL(audioFileRef, kAudioFileM4AType, &outputFileDesc, NULL, kAudioFileFlags_EraseFile, &outputFile);
Where outputFileDesc is
AudioStreamBasicDescription outputFileDesc = {44100.0, kAudioFormatMPEG4AAC, 0, 0, 1024, 0, thisNumChannels, 0, 0}; outputFileDesc.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
When reading ExtAudioFileRef inputFile:
ExtAudioFileOpenURL(audioFileRef, &inputFile):
And in both cases (writing and reading) it is applied same format:
AudioStreamBasicDescription outputFormat;
_outputFormat.mSampleRate = self.samplingRate;
_outputFormat.mFormatID = kAudioFormatLinearPCM;
_outputFormat.mFormatFlags = kAudioFormatFlagIsFloat;
_outputFormat.mBytesPerPacket = 4*self.numChannels;
_outputFormat.mFramesPerPacket = 1;
_outputFormat.mBytesPerFrame = 4*self.numChannels;
_outputFormat.mChannelsPerFrame = self.numChannels;
_outputFormat.mBitsPerChannel = 32;
ExtAudioFileSetProperty(outputFile, kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &_outputFormat);
ExtAudioFileSetProperty(inputFile, kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &_outputFormat);
And by the way, even if read samples are not equal to written samples, mean value of both signals are quite similar. But I do not fully understand why are not totally equal!
Any idea what I'm doing wrong?
It sounds like there is an implicit format conversion from one or both of the ExtaudioFileRefs and you are seeing different samples as a result of the conversion. You have three formats: audio_in_format, file_format, and audio_out_format. If audio_in_format is different than file_format, The writing ExtAudioFileRef will create an audio converter for you to convert the input audio to file_format before writing to disk. And the reading ExtAudioFileRef will also create a converter if file_format is different than audio_out_format.
Opinion: It's confusing that you named your writing ExtAudioFileRef "outputFile", and your reading ExtAudioFileRef "inputFile". I would use something like audioWriter and audioReader.