Question

I'm trying to write ALAC files from data held in memory. If I write the file as AIFF the file is 43.5MB. If I write the file as ALAC it comes out as 73.9MB. The two files play perfectly, but obviously the ALAC should be smaller than the AIFF. (Incidently when I convert the AIFF to ALAC using iTunes the resulting file is 28MB, which is roughly what I'd expect for a losslessly compressed format)

Finder's file info

The obvious difference is the lack of Bits per sample for the ALAC.

Have I missed some compression setting, or something to set that would make the ALAC files smaller?

The data is stored in memory as non-interleaved floats, and this is the code that handles the format settings.

_outputFormat.mSampleRate = 44100
_outputFormat.mFormatID = <either kAudioFormatLinearPCM or kAudioFormatAppleLossless>;
_outputFormat.mChannelsPerFrame = 2;

if (_outputFormat.mFormatID == kAudioFormatLinearPCM) {
    _outputFormat.mBitsPerChannel = 16;
    _outputFormat.mBytesPerPacket = _outputFormat.mChannelsPerFrame * (_outputFormat.mBitsPerChannel / 8);
    _outputFormat.mFramesPerPacket = 1;
    _outputFormat.mBytesPerFrame = _outputFormat.mBytesPerPacket;
    _outputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;

    if (_isBigEndian) {
        _outputFormat.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
    }
} else {
    size = sizeof(_outputFormat);
    err = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &_outputFormat);
    if (check_status_is_error(err, "AudioFileGetProperty")) {
        self = nil;
        return nil;
    }
}

CFURLRef urlRef = (__bridge CFURLRef)_url;

err = ExtAudioFileCreateWithURL(urlRef,
                                <either kAudioFileAIFFType or kAudioFileM4AType>,
                                &(_outputFormat),
                                NULL, kAudioFileFlags_EraseFile, &(_outputFile));
if (check_status_is_error(err, "ExtAudioFileCreateWithURL")) {
    self = nil;
    return nil;
}

AudioStreamBasicDescription clientFormat;

clientFormat.mFormatID = kAudioFormatLinearPCM;
clientFormat.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical;
clientFormat.mSampleRate = _outputFormat.mSampleRate;
clientFormat.mChannelsPerFrame = _outputFormat.mChannelsPerFrame;
clientFormat.mFramesPerPacket = 1;
clientFormat.mBytesPerFrame = 4;
clientFormat.mBytesPerPacket = 4;
clientFormat.mBitsPerChannel = 8 * sizeof(AudioUnitSampleType);

size = sizeof(clientFormat);
err = ExtAudioFileSetProperty(_outputFile, 
                              kExtAudioFileProperty_ClientDataFormat,
                              size, &clientFormat);
Was it helpful?

Solution

The solution is to set the mFormatFlags of the AudioStreamBasicDescription structure to include kAppleLosslessFormatFlag_16BitSourceData whenever saving ALAC files

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top