2

I am currently able to record and playback in reverse (thanks to a couple examples), but I would like to give the user the ability to select a previously recorded .AAC file from a table view and reverse it. I have tried changing the input file url to the url of the user's file, but I either get static or an audio file with 0.0 duration. Is this type of reversal possible with AAC files? If so, how do I correct my settings to accept it?

recordedAudioUrl = [NSURL URLWithString:[savedURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog( @"url is %@", [recordedAudioUrl absoluteString]);

flippedAudioUrl = [NSURL URLWithString:[reverseURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog( @"url is %@", [flippedAudioUrl absoluteString]);

AudioFileID outputAudioFile;

AudioStreamBasicDescription myPCMFormat;
myPCMFormat.mSampleRate = 16000.00;
myPCMFormat.mFormatID = kAudioFormatLinearPCM ;
myPCMFormat.mFormatFlags =  kAudioFormatFlagsCanonical;
myPCMFormat.mChannelsPerFrame = 1;
myPCMFormat.mFramesPerPacket = 1;
myPCMFormat.mBitsPerChannel = 16;
myPCMFormat.mBytesPerPacket = 2;
myPCMFormat.mBytesPerFrame = 2;

AudioFileCreateWithURL((__bridge CFURLRef)flippedAudioUrl,
                       kAudioFileCAFType,
                       &myPCMFormat,
                       kAudioFileFlags_EraseFile,
                       &outputAudioFile);

AudioFileID inputAudioFile;
OSStatus theErr = noErr;
UInt64 fileDataSize = 0;

AudioStreamBasicDescription theFileFormat;
UInt32 thePropertySize = sizeof(theFileFormat);

theErr = AudioFileOpenURL((__bridge CFURLRef)recordedAudioUrl, kAudioFileReadPermission, 0, &inputAudioFile);

thePropertySize = sizeof(fileDataSize);
theErr = AudioFileGetProperty(inputAudioFile, kAudioFilePropertyAudioDataByteCount, &thePropertySize, &fileDataSize);

UInt32 dataSize = fileDataSize;
void* theData = malloc(dataSize);

//Read data into buffer
SInt64 readPoint  = dataSize;
UInt32 writePoint = 0;
while( readPoint > 0 )
{
    UInt32 bytesToRead = 2;
    AudioFileReadBytes( inputAudioFile, false, readPoint, &bytesToRead, theData );
    AudioFileWriteBytes( outputAudioFile, false, writePoint, &bytesToRead, theData );

    writePoint += 2;
    readPoint -= 2;
}

free(theData);
AudioFileClose(inputAudioFile);
AudioFileClose(outputAudioFile);

}

2 Answers2

2

Your code is reading raw AAC data backwards (AudioFileReadBytes doesn't even respect packet boundaries, unlike AudioFileReadPacketData), and then writing it forwards as LPCM. No wonder you're hearing static. To reverse an AAC file you will have to decode it to LPCM first. I suggest you switch your reading code from AudioFile to either ExtendedAudioFile or AVAudioFile.

Your read-backwards-and-write-forwards approach should still work with the above change.

The APIs mentioned can decode AAC (among other things) to LPCM, e.g. decoding with AVAudioFile and decoding with ExtAudioFile

NB the examples aren't reading AAC, but that doesn't matter as the APIs hide the details from you so your code doesn't need to care what the source format is.

Community
  • 1
  • 1
Rhythmic Fistman
  • 34,352
  • 5
  • 87
  • 159
0

What you need to do is:

  1. decode your whole input file to PCM
  2. reverse decoded PCM samples
  3. encode reversed PCM samples to AAC and save

This will give you reversed.aac.

Danijel
  • 8,198
  • 18
  • 69
  • 133
  • Thank you very much for your reply. Could you provide a bit of sample code to get me on the right track? I am very new to Objective-C and having trouble finding decoding tutorials. – Derek Southard Jan 19 '16 at 20:31