Skip to content

Instantly share code, notes, and snippets.

@sbooth
Created March 24, 2010 13:01
Show Gist options
  • Save sbooth/342257 to your computer and use it in GitHub Desktop.
Save sbooth/342257 to your computer and use it in GitHub Desktop.
Convert to ALAC
#include <CoreFoundation/CoreFoundation.h>
#include <AudioToolbox/AudioToolbox.h>
#include "CAStreamBasicDescription.h"
#define BUFFER_SIZE_FRAMES 512
static AudioBufferList *
allocateBufferList(UInt32 channelsPerFrame, UInt32 bytesPerFrame, bool interleaved, UInt32 capacityFrames)
{
AudioBufferList *bufferList = NULL;
UInt32 numBuffers = interleaved ? 1 : channelsPerFrame;
UInt32 channelsPerBuffer = interleaved ? channelsPerFrame : 1;
bufferList = static_cast<AudioBufferList *>(calloc(1, offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * numBuffers)));
bufferList->mNumberBuffers = numBuffers;
for(UInt32 bufferIndex = 0; bufferIndex < bufferList->mNumberBuffers; ++bufferIndex) {
bufferList->mBuffers[bufferIndex].mData = static_cast<void *>(calloc(capacityFrames, bytesPerFrame));
bufferList->mBuffers[bufferIndex].mDataByteSize = capacityFrames * bytesPerFrame;
bufferList->mBuffers[bufferIndex].mNumberChannels = channelsPerBuffer;
}
return bufferList;
}
static void
deallocateBufferList(AudioBufferList *bufferList)
{
for(UInt32 bufferIndex = 0; bufferIndex < bufferList->mNumberBuffers; ++bufferIndex)
free(bufferList->mBuffers[bufferIndex].mData), bufferList->mBuffers[bufferIndex].mData = NULL;
free(bufferList), bufferList = NULL;
}
int main(int argc, const char * argv [])
{
if(argc < 2) {
printf("Usage: %s input_file.wav output_file.m4a\n", argv[0]);
return EXIT_FAILURE;
}
// Open the input file
ExtAudioFileRef inputFile = NULL;
CFURLRef inputURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)argv[1], strlen(argv[1]), FALSE);
OSStatus result = ExtAudioFileOpenURL(inputURL, &inputFile);
CFRelease(inputURL), inputURL = NULL;
if(noErr != result) {
printf("Unable to open input file: %i\n", result);
return EXIT_FAILURE;
}
// Query file format
CAStreamBasicDescription inputFormat;
UInt32 dataSize = sizeof(inputFormat);
result = ExtAudioFileGetProperty(inputFile, kExtAudioFileProperty_FileDataFormat, &dataSize, &inputFormat);
if(noErr != result) {
printf("ExtAudioFileGetProperty (kExtAudioFileProperty_FileDataFormat) failed: %i\n", result);
result = ExtAudioFileDispose(inputFile);
if(noErr != result)
printf("ExtAudioFileDispose failed: %i\n", result);
return EXIT_FAILURE;
}
// Get the total frames
SInt64 totalFrames = -1;
dataSize = sizeof(totalFrames);
result = ExtAudioFileGetProperty(inputFile,
kExtAudioFileProperty_FileLengthFrames,
&dataSize,
&totalFrames);
if(noErr != result)
printf("ExtAudioFileGetProperty (kExtAudioFileProperty_FileLengthFrames) failed: %i\n", result);
puts("====================");
printf("Input file %s:\n", argv[1]);
inputFormat.Print();
printf("%lld frames\n",totalFrames);
puts("====================");
// Create the output file
CFURLRef outputURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)argv[2], strlen(argv[2]), FALSE);
CAStreamBasicDescription outputFormat;
outputFormat.mFormatID = kAudioFormatAppleLossless;
outputFormat.mFormatFlags = kAppleLosslessFormatFlag_16BitSourceData;
outputFormat.mSampleRate = inputFormat.mSampleRate;
outputFormat.mChannelsPerFrame = inputFormat.mChannelsPerFrame;
ExtAudioFileRef outputFile = NULL;
result = ExtAudioFileCreateWithURL(outputURL, kAudioFileM4AType, &outputFormat, NULL, 0, &outputFile);
CFRelease(outputURL), outputURL = NULL;
if(noErr != result) {
printf("ExtAudioFileCreateWithURL failed: %i\n", result);
result = ExtAudioFileDispose(inputFile);
if(noErr != result)
printf("ExtAudioFileDispose failed: %i\n", result);
return EXIT_FAILURE;
}
// Set the client data format
result = ExtAudioFileSetProperty(outputFile, kExtAudioFileProperty_ClientDataFormat, sizeof(inputFormat), &inputFormat);
if(noErr != result) {
printf("ExtAudioFileSetProperty (kExtAudioFileProperty_ClientDataFormat) failed: %i\n", result);
result = ExtAudioFileDispose(inputFile);
if(noErr != result)
printf("ExtAudioFileDispose failed: %i\n", result);
result = ExtAudioFileDispose(outputFile);
if(noErr != result)
printf("ExtAudioFileDispose failed: %i\n", result);
return EXIT_FAILURE;
}
AudioBufferList *abl = allocateBufferList(inputFormat.mChannelsPerFrame, inputFormat.mBytesPerFrame, !(kAudioFormatFlagIsNonInterleaved & inputFormat.mFormatFlags), BUFFER_SIZE_FRAMES);
for(;;) {
UInt32 frameCount = BUFFER_SIZE_FRAMES;
result = ExtAudioFileRead(inputFile, &frameCount, abl);
if(noErr != result) {
printf("ExtAudioFileRead failed: %i\n", result);
break;
}
if(0 == frameCount)
break;
result = ExtAudioFileWrite(outputFile, frameCount, abl);
if(noErr != result) {
printf("ExtAudioFileWrite failed: %i\n", result);
break;
}
}
ExtAudioFileDispose(inputFile), inputFile = NULL;
ExtAudioFileDispose(outputFile), outputFile = NULL;
deallocateBufferList(abl);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment