简体   繁体   中英

How to reverse an audio file?

I'd like to reverse an existing audio file (eg WAV, CAF, ...) on iOS. Any suggestions on how to achieve this? Open-source libraries?

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);

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)

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 )

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM