Search code examples
objective-ccore-audioavassetwriter

How can I write to an AVAssetWriter my custom float / shorts array?


So i used AVAssetReader got the CMSampleBufferRefand then i got the samples values from CMBlockBufferRef data.

I then changed this samples with a custom filter.

Now i have an array of Shorts which i want to write back to a file, using AVAssetWriter.

My question here is how do I create back a CMSampleBufferRef and a CMBlockBufferRef to send to the AVAssetWriter?


Solution

  • Have a look at this apple developer page.

    EDIT: Based on your comments, to create a samplebuffer directly from a shorts array, you should use Core Media Framework components, i.e. CMSampleBufferCreate

    1. Convert sample data in shorts array to AudioBufferList
    2. Convert the AudioBufferList to a CMSampleBuffer.

    For example:

    OSStatus status = noErr;
    CMItemCount framesToProcess = 8192;
    unsigned long sizeInBytes = framesToProcess * sizeof(SInt16);
    
    // Init ABL from sample array
    AudioBufferList *myAudioBufferList; // contains converted
    myAudioBufferList = static_cast<AudioBufferList *>(calloc(1, offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer))));
    myAudioBufferList->mNumberBuffers = 1;
    myAudioBufferList->mBuffers[0].mNumberChannels = 1;
    myAudioBufferList->mBuffers[0].mData = JoãoSamplesArrayPointer;
    myAudioBufferList->mBuffers[0].mDataByteSize = (UInt32)sizeInBytes;
    
    // sampleBuffer in (from the assetreader) you already have this
    CMSampleBufferRef sampleBufferIn = [self.assetReaderAudioOutput copyNextSampleBuffer];
    
    CMAudioFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sampleBufferIn);
    const AudioStreamBasicDescription *assetReaderOutputASBD = CMAudioFormatDescriptionGetStreamBasicDescription(format);
    
    // setup output samplebuffer
    CMSampleBufferRef sampleBufferOut = NULL;
    CMSampleTimingInfo timing = { CMTimeMake(1, sampleRate), kCMTimeZero, kCMTimeInvalid };
    
    // create description
    status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, assetReaderOutputASBD, 0, NULL, 0, NULL, NULL, &format);
    
    // create buffer
    CMSampleBufferCreate( kCFAllocatorDefault, NULL, false, NULL, NULL, format, framesToProcess, 1, &timing, 0, NULL, &sampleBufferOut);
    
    // put data into buffer from ABL (audio buffer list)
    status = CMSampleBufferSetDataBufferFromAudioBufferList( sampleBufferOut, kCFAllocatorDefault,  kCFAllocatorDefault, 0, myAudioBufferList );
    
    // write to assetwriter audioinput
    BOOL success = [self.assetWriterAudioInput appendSampleBuffer:sampleBufferOut];
    CFRelease(sampleBufferOut);