2

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?

M Penades
  • 1,572
  • 13
  • 24
  • Are you getting good audio? Show how you instantiate the ExtAudioFileRefs. – dave234 Sep 21 '15 at 13:41
  • Yes, audio is reproduced correctly. I'm using Novocaine project to get voice easier, i.e: self.audioManager.inputBlock = ^(float *data, UInt32 numFrames, UInt32 numChannels) { "writing audio data"}; [self.audioManager play]; – M Penades Sep 21 '15 at 14:25

1 Answers1

1

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.

dave234
  • 4,793
  • 1
  • 14
  • 29
  • Hi, thanks for your response! I edit question to include ExtAudioFileRef outputFile and inputFile code. It is from Novocaine project so I guess it is ok. After what I see, it is applied same format when writing and reading files. Drawing writing and reading waveforms I can see that they are quite similar (but not equal). ¿Why samples are not exactly the same? – M Penades Sep 22 '15 at 08:22
  • 1
    Look at the mFormatFlags field. When you are recording, the audio is being converted from LPCM to MP4 format before being written to disk. Then when being read, it is converted from MP4 to LPCM before filling your buffers. That conversion is what makes the samples different, MP4 is a "lossy" compression meaning information is lost when doing the initial conversion. – dave234 Sep 22 '15 at 11:50
  • Yep you are right! I must be compression loss what makes samples slightly different. I tried to change it in another format to check with not compression unsuccessfully. Could you please post an example? – M Penades Sep 25 '15 at 07:52
  • About how create a AudioFile without compression loss, just to check wether what is recorded and saved on it is retrieved when reading. I m quite new in AudioFile formats, and after your answer you seemed to know more than me. – M Penades Sep 25 '15 at 09:09
  • You just use the same (lpcm) format for input,file, and output, and no conversions will happen. – dave234 Sep 25 '15 at 14:56