How to play audio backwards?

流过昼夜 提交于 2019-12-05 18:22:17

Typically, when an ASBD is being used, the fields describe the complete layout of the sample data in the buffers that are represented by this description - where typically those buffers are represented by an AudioBuffer that is contained in an AudioBufferList.

However, when an ASBD has the kAudioFormatFlagIsNonInterleaved flag, the AudioBufferList has a different structure and semantic. In this case, the ASBD fields will describe the format of ONE of the AudioBuffers that are contained in the list, AND each AudioBuffer in the list is determined to have a single (mono) channel of audio data. Then, the ASBD's mChannelsPerFrame will indicate the total number of AudioBuffers that are contained within the AudioBufferList - where each buffer contains one channel. This is used primarily with the AudioUnit (and AudioConverter) representation of this list - and won't be found in the AudioHardware usage of this structure.

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

Hope this helps.

You do not have to allocate a separate buffer to store the reversed data, this can take a fair bit of CPU, depending on the length of sound. To play a sound backwards, just make the sampleNumber counter start at totalFramesInFile - 1.

You can modify MixerHost like this, to achieve the desired effect.

Replace soundStructArray[audioFile].sampleNumber = 0; with soundStructArray[audioFile].sampleNumber = totalFramesInFile - 1;

Make sampleNumber SInt32 instead of UInt32.

Replace the loop which you write the samples out with this.

for (UInt32 frameNumber = 0; frameNumber < inNumberFrames; ++frameNumber) {
    outSamplesChannelLeft[frameNumber]                 = dataInLeft[sampleNumber];
    if (isStereo) outSamplesChannelRight[frameNumber]  = dataInRight[sampleNumber];

    if (--sampleNumber < 0) sampleNumber = frameTotalForSound - 1;
}

This effectively makes it play backwards. Mmmm. It's been a while since I've heard the MixerHost music. I must admit I find it to be quite pleasing.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!