Created
March 24, 2010 13:01
-
-
Save sbooth/342257 to your computer and use it in GitHub Desktop.
Convert to ALAC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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