Can AVAssetWriter be used to write a WAVE_FORMAT_PCM Wave file?

I'm reimplementing some very old code that converts an AIFF file to Wave file via Carbon Quicktime APIs.


I need my implementation to run as far back as OS X 10.9, so it seems like using AVFoundation's AVAssetReader/AVAssetWriter is the way to go.

However, I need my output to be a

WAVE_FORMAT_PCM
file, but AVFoundation is outputting a
WAVE_FORMAT_EXTENSIBLE
file with a SubFormat of
KSDATAFORMAT_SUBTYPE_PCM
.


Here is a simplified version of my code:


AVAsset* asset = [AVAsset assetWithURL:url];
AVAssetReader* reader = [AVAssetReader assetReaderWithAsset:asset error:&err];

AVAssetTrack* track = [[asset tracksWithMediaType:AVMediaTypeAudio]
                                    objectAtIndex:0];


NSDictionary *compressionSettings = @{
       AVFormatIDKey: [NSNumber numberWithUnsignedInt:kAudioFormatLinearPCM],
       AVSampleRateKey: [NSNumber numberWithUnsignedInteger:44100],
       AVLinearPCMBitDepthKey: [NSNumber numberWithUnsignedInt:16],
       AVLinearPCMIsNonInterleavedKey: @NO,
       AVLinearPCMIsFloatKey: @NO,
       AVLinearPCMIsBigEndianKey: @NO,
       AVNumberOfChannelsKey: [NSNumber numberWithUnsignedInteger:2]
       };

AVAssetReaderOutput* readerOutput =
    [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track
                                                   outputSettings:compressionSettings];
[reader addOutput:readerOutput];

AVAsset* outAsset = [AVAsset assetWithURL:outURL];
AVAssetWriter* writer = [AVAssetWriter assetWriterWithURL:outURL
                                                 fileType:AVFileTypeWAVE
                                                    error:&err];

AVAssetWriterInput* writerInput =
    [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
                                       outputSettings:compressionSettings];

[writer addInput:writerInput];

[writer startWriting];
[writer startSessionAtSourceTime:kCMTimeZero];
[reader startReading];
CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];
while( sample != NULL )
{
  while (TRUE) {
    if ([writerInput isReadyForMoreMediaData]) {
      [writerInput appendSampleBuffer:sample];
      break;
    }
  }
  CFRelease( sample );
  sample = [readerOutput copyNextSampleBuffer];
}
[writer finishWritingWithCompletionHandler:^(){
  NSLog(@"Done!");
}];


I've looked through the headers where

AVFileTypeWAVE
and
kAudioFormatLinearPCM
are defined, and cannot find any settings that look like they would result in a WAVE_FORMAT_PCM file.


Using

WAVE_FORMAT_EXTENSIBLE
is necessary if the underlying format of the file cannot be described with
WAVE_FORMAT_PCM
, but I do not believe this to be the case for the audio files I am dealing with: I've written code to edit the Wave header, leaving the
data
section of the file untouched, and the resulting file can be processed by my app as desired (and displays and plays back normally in other applications).


If the worst comes to the worst, I can just use this Wave-header editing code in my release, but I'd prefer a cleaner solution if one exists.


Is it possible to get

AVFoundation
to write a file in the format I need, or is there some other API I can use to perform this task?

Replies

It appears that AVAssetWriter uses the extensible format of a WAVE file in order to pad the PCM data to start at a 4k boundary (instead of just after the common 44 byte header). Last time I looked, the format of the added padding section was 'FLLR' followed by the length of the filler bytes.

Yes, that's what I'm seeing, too. Thanks for the reply!