I'd like to reverse an existing audio file (e.g. WAV, CAF, ...) on iOS. Any suggestions on how to achieve this? Open-source libraries?
4 Answers
I have worked on a sample app, which records what user says and plays them backwards. I have used CoreAudio to achieve this. Link to app code.
As each sample is 16-bits in size(2 bytes)(mono channel). You can load each sample at a time by copying it into a different buffer by starting at the end of the recording and reading backwards. When you get to the start of the data you have reversed the data and playing will be reversed.
// set up output file
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)self.flippedAudioUrl,
kAudioFileCAFType,
&myPCMFormat,
kAudioFileFlags_EraseFile,
&outputAudioFile);
// set up input file
AudioFileID inputAudioFile;
OSStatus theErr = noErr;
UInt64 fileDataSize = 0;
AudioStreamBasicDescription theFileFormat;
UInt32 thePropertySize = sizeof(theFileFormat);
theErr = AudioFileOpenURL((__bridge CFURLRef)self.recordedAudioUrl, kAudioFileReadPermission, 0, &inputAudioFile);
thePropertySize = sizeof(fileDataSize);
theErr = AudioFileGetProperty(inputAudioFile, kAudioFilePropertyAudioDataByteCount, &thePropertySize, &fileDataSize);
UInt32 dataSize = fileDataSize;
void* theData = malloc(dataSize);
//Read data into buffer
UInt32 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);

- 916
- 6
- 16
-
Is there any way to do this with a .m4a file instead of a .caf file? – Chan Jing Hong Dec 24 '16 at 06:23
Kiran's answer in Swift 2.2:
let forwardAudioURL: NSURL = ... // wherever your original audio is
let reversedAudioURL: NSURL = ... // wherever you want the reversed file to go
// Load forward audio into originalAudioFile
var originalAudioFile: AudioFileID = nil
let possibleError1 = AudioFileOpenURL(forwardAudioURL,
AudioFilePermissions.ReadPermission,
0,
&originalAudioFile)
// Load the size in bytes of the original audio into originalAudioSize variable
var originalAudioSize: Int64 = 0
var propertySize: UInt32 = 8
let possibleError2 = AudioFileGetProperty(originalAudioFile,
kAudioFilePropertyAudioDataByteCount,
&propertySize,
&originalAudioSize)
if possibleError1 != 0 || possibleError2 != 0 {
// Handle errors if you want
}
// Set up file that the reversed audio will be loaded into
var reversedAudioFile: AudioFileID = nil
var format = AudioStreamBasicDescription()
format.mSampleRate = 16000
format.mFormatID = kAudioFormatLinearPCM
format.mChannelsPerFrame = 1
format.mFramesPerPacket = 1
format.mBitsPerChannel = 16
format.mBytesPerPacket = 2
format.mBytesPerFrame = 2
AudioFileCreateWithURL(reversedAudioURL,
kAudioFileCAFType,
&format,
AudioFileFlags.EraseFile,
&reversedAudioFile)
// Read data into the reversedAudioFile
var readPoint: Int64 = originalAudioSize
var writePoint: Int64 = 0
var buffer: Int16 = 0
while readPoint > 0 {
var bytesToRead: UInt32 = 2;
AudioFileReadBytes(originalAudioFile,
false,
readPoint,
&bytesToRead,
&buffer)
AudioFileWriteBytes(reversedAudioFile,
false,
writePoint,
&bytesToRead,
&buffer)
writePoint += 2
readPoint -= 2
}
AudioFileClose(originalAudioFile)
AudioFileClose(reversedAudioFile)

- 46
- 4
-
I have tried this code but playing speed become slow like, 1:45 min audio file becomes 4:15 min. any solution for that? @mckennac4 – Vivek Goswami Dec 26 '17 at 15:12
-
** Note: this code doesn't work with any other formats. it has to be .wav audio file ! – Maryam Fekri Jul 08 '18 at 23:17
-
the speed for my case is faster than the original file. what value exactly changes the speed ? @mckennac4 – Maryam Fekri Jul 08 '18 at 23:42
A WAV file just contains raw PCM samples. If you play them in the reverse order, you will get the reverse sound. See this question for details. (and also this search)
-
-
1A PCM sample is one digital sample of an analog waveform (and sound is ultimately just a waveform... If you play the waveform backwards, you get the reversed sound) See the graphic in http://en.wikipedia.org/wiki/Pulse-code_modulation. Each discrete level is one sample. The WAV file is just an array of those samples (plus a bit of metadata). Reverse the array, feed it to your WAV player and you are done. – AShelly Jul 06 '11 at 21:26
Using libsndfile, I was able to read in the recorded audio sample. The following code snippet then shows how to open the input file, and write the output in reversed order. You should note though that all data is read in memory!
SF_INFO info_read;
info_read.format = 0;
SNDFILE* sndfilein = sf_open("my_input_file.caf", SFM_READ, &info_read);
SF_INFO info_write;
info_write.format = info.format;
info_write.channels = info.channels;
info_write.frames = info.frames;
info_write.samplerate = info.samplerate;
info_write.sections = info.sections;
info_write.seekable = info.seekable;
SNDFILE* sndfileout = sf_open("my_output_file.caf", SFM_RDWR, &info_write);
int* buf = new int[8000 * 30];
int framesRead = sf_readf_int(sndfilein, buf, info.frames);
for (int i = 0; i < info.frames; i++)
sf_writef_int(sndfileout, &buf[info.frames - i], 1);
delete[] buf;
sf_close(sndfilein);
sf_close(sndfileout);

- 579
- 6
- 13