2
0

main.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. /*
  2. Copyright © 2011 Apple Inc. All rights reserved.
  3. IMPORTANT: This Apple software is supplied to you by Apple Inc. (“Apple”) in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software.
  4. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple’s copyrights in this original Apple software (the “Apple Software”), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated.
  5. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
  6. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  7. */
  8. /*
  9. * main.cpp
  10. *
  11. * Converts pcm data contained in a .wav or .caf file into Apple Lossless (ALAC) put into a .caf file
  12. * or converts ALAC data from a .caf file into pcm data and put into a .wav or .caf file
  13. *
  14. */
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. // these are headers for the ALAC encoder and decoder
  19. #include "ALACEncoder.h"
  20. #include "ALACDecoder.h"
  21. #include "ALACBitUtilities.h"
  22. // these are utility headers for this sample code
  23. #include "CAFFileALAC.h"
  24. #include "EndianPortable.h"
  25. #define kMaxBERSize 5
  26. #define kCAFFdataChunkEditsSize 4
  27. #define kWAVERIFFChunkSize 12
  28. #define kWAVEfmtChunkSize 24
  29. #define kWAVEdataChunkHeaderSize 8
  30. #define VERBOSE 0
  31. // Helper functions
  32. int32_t GetInputFormat(FILE * inputFile, AudioFormatDescription * theInputFormat, uint32_t * theFileType);
  33. int32_t SetOutputFormat(AudioFormatDescription theInputFormat, AudioFormatDescription * theOutputFormat);
  34. int32_t FindDataStart(FILE * inputFile, uint32_t inputFileType, int32_t * dataPos, int32_t * dataSize);
  35. int32_t EncodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize);
  36. int32_t DecodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize, uint32_t outputFileType);
  37. void GetOutputFileType(char * outputFileName, uint32_t * outputFileType);
  38. ALACChannelLayoutTag GetALACChannelLayoutTag(uint32_t inChannelsPerFrame);
  39. // Some crude WAVE writing tools
  40. void WriteWAVERIFFChunk(FILE * outputFile);
  41. void WriteWAVEfmtChunk(FILE * outputFile, AudioFormatDescription theOutputFormat);
  42. void WriteWAVEdataChunk(FILE * outputFile);
  43. void WriteWAVEChunkSize(FILE * outputFile, uint32_t numDataBytes);
  44. // Adapted from CoreAudioTypes.h
  45. enum
  46. {
  47. kTestFormatFlag_16BitSourceData = 1,
  48. kTestFormatFlag_20BitSourceData = 2,
  49. kTestFormatFlag_24BitSourceData = 3,
  50. kTestFormatFlag_32BitSourceData = 4
  51. };
  52. int32_t main (int32_t argc, char * argv[])
  53. {
  54. char * inputFileName = argv[1];
  55. char * outputFileName = argv[2];
  56. FILE * inputFile = NULL;
  57. FILE * outputFile = NULL;
  58. bool malformed = argc < 2;
  59. // Parse the commandline and open the necessary files
  60. for (int32_t i = 1; i < argc; ++i)
  61. {
  62. if (strcmp (argv[i], "-h") == 0)
  63. {
  64. malformed = true;
  65. }
  66. else
  67. {
  68. if (argv[i][0] == '-')
  69. {
  70. printf ("unknown option: %s\n", argv[i]);
  71. malformed = true;
  72. }
  73. else
  74. {
  75. if (inputFile == NULL) inputFile = fopen (inputFileName, "rb"); // the b is necessary for Windows -- ignored by Unix
  76. if(inputFile == NULL)
  77. {
  78. fprintf(stderr," Cannot open file \"%s\"\n", inputFileName);
  79. exit (1);
  80. }
  81. if (outputFile == NULL) outputFile = fopen (outputFileName, "w+b"); // the b is necessary for Windows -- ignored by Unix
  82. if(outputFile == NULL)
  83. {
  84. fprintf(stderr," Cannot open file \"%s\"\n", outputFileName);
  85. exit (1);
  86. }
  87. }
  88. }
  89. if (malformed)
  90. {
  91. break;
  92. }
  93. }
  94. if (!malformed)
  95. {
  96. printf("Input file: %s\n", inputFileName);
  97. printf("Output file: %s\n", outputFileName);
  98. // So at this point we have the input and output files open. Need to determine what we're dealing with
  99. int32_t theError = 0;
  100. AudioFormatDescription inputFormat;
  101. AudioFormatDescription outputFormat;
  102. int32_t inputDataPos = 0, inputDataSize = 0;
  103. uint32_t inputFileType = 0; // 'caff' or 'WAVE'
  104. uint32_t outputFileType = 0; // 'caff' or 'WAVE'
  105. theError = GetInputFormat(inputFile, &inputFormat, &inputFileType);
  106. if (theError)
  107. {
  108. fprintf(stderr," Cannot determine what format file \"%s\" is\n", inputFileName);
  109. exit (1);
  110. }
  111. if (inputFileType != 'WAVE' && inputFileType != 'caff')
  112. {
  113. fprintf(stderr," File \"%s\" is of an unsupported type\n", outputFileName);
  114. exit (1);
  115. }
  116. if (inputFormat.mFormatID != kALACFormatAppleLossless && inputFormat.mFormatID != kALACFormatLinearPCM)
  117. {
  118. fprintf(stderr," File \"%s\'s\" data format is of an unsupported type\n", outputFileName);
  119. exit (1);
  120. }
  121. SetOutputFormat(inputFormat, &outputFormat);
  122. if (theError)
  123. {
  124. fprintf(stderr," Cannot determine what format file \"%s\" is\n", outputFileName);
  125. exit (1);
  126. }
  127. FindDataStart(inputFile, inputFileType, &inputDataPos, &inputDataSize);
  128. fseek(inputFile, inputDataPos, SEEK_SET);
  129. // We know where we are and we know what we're doing
  130. if (outputFormat.mFormatID == kALACFormatAppleLossless)
  131. {
  132. // encoding
  133. EncodeALAC(inputFile, outputFile, inputFormat, outputFormat, inputDataSize);
  134. }
  135. else
  136. {
  137. // decoding
  138. GetOutputFileType(outputFileName, &outputFileType);
  139. if (outputFileType == 'WAVE' && outputFormat.mChannelsPerFrame > 2)
  140. {
  141. // we don't support WAVE because we don't want to reinterleave on output
  142. fprintf(stderr," Cannot decode more than two channels to WAVE\n");
  143. exit (1);
  144. }
  145. DecodeALAC(inputFile, outputFile, inputFormat, outputFormat, inputDataSize, outputFileType);
  146. }
  147. }
  148. if (malformed) {
  149. printf ("Usage:\n");
  150. printf ("Encode:\n");
  151. printf (" alacconvert <input wav or caf file> <output caf file>\n");
  152. printf ("Decode:\n");
  153. printf (" alacconvert <input caf file> <output wav or caf file>\n");
  154. printf ("\n");
  155. return 1;
  156. }
  157. if (inputFile) fclose(inputFile);
  158. if (outputFile) fclose(outputFile);
  159. return 0;
  160. }
  161. int32_t GetInputFormat(FILE * inputFile, AudioFormatDescription * theInputFormat, uint32_t * theFileType)
  162. {
  163. // assumes the file is open
  164. uint8_t theReadBuffer[20];
  165. bool done = false;
  166. uint32_t chunkType = 0;
  167. fread(theReadBuffer, 1, 4, inputFile);
  168. if (theReadBuffer[0] == 'c' && theReadBuffer[1] == 'a' && theReadBuffer[2] == 'f' & theReadBuffer[3] == 'f')
  169. {
  170. // It's a caff file!
  171. *theFileType = 'caff';
  172. // We support pcm data for encode and alac data for decode
  173. done = GetCAFFdescFormat(inputFile, theInputFormat);
  174. }
  175. else if (theReadBuffer[0] == 'R' && theReadBuffer[1] == 'I' && theReadBuffer[2] == 'F' & theReadBuffer[3] == 'F')
  176. {
  177. fread(theReadBuffer, 1, 8, inputFile);
  178. if (theReadBuffer[4] == 'W' && theReadBuffer[5] == 'A' && theReadBuffer[6] == 'V' & theReadBuffer[7] == 'E')
  179. {
  180. // It's a WAVE file!
  181. *theFileType = 'WAVE';
  182. // We only support pcm data
  183. while (!done)
  184. {
  185. uint32_t theChunkSize = 0, theSampleRate = 0;
  186. fread(theReadBuffer, 1, 4, inputFile);
  187. chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
  188. switch (chunkType)
  189. {
  190. case 'fmt ':
  191. fread(theReadBuffer, 1, 20, inputFile);
  192. // Remember campers we're in little endian land
  193. if (theReadBuffer[4] != 1 || theReadBuffer[5] != 0)
  194. {
  195. // we only support PCM
  196. *theFileType = 0; // clear it
  197. return -1;
  198. }
  199. theInputFormat->mFormatID = kALACFormatLinearPCM;
  200. theInputFormat->mChannelsPerFrame = theReadBuffer[6];
  201. theSampleRate = ((int32_t)(theReadBuffer[11]) << 24) + ((int32_t)(theReadBuffer[10]) << 16) + ((int32_t)(theReadBuffer[9]) << 8) + theReadBuffer[8];
  202. theInputFormat->mSampleRate = theSampleRate;
  203. theInputFormat->mBitsPerChannel = theReadBuffer[18];
  204. theInputFormat->mFormatFlags = kALACFormatFlagIsSignedInteger | kALACFormatFlagIsPacked; // always little endian
  205. theInputFormat->mBytesPerPacket = theInputFormat->mBytesPerFrame = (theInputFormat->mBitsPerChannel >> 3) * theInputFormat->mChannelsPerFrame;
  206. theInputFormat->mFramesPerPacket = 1;
  207. theInputFormat->mReserved = 0;
  208. done = true;
  209. break;
  210. default:
  211. // read the size and skip
  212. fread(theReadBuffer, 1, 4, inputFile);
  213. theChunkSize = ((int32_t)(theReadBuffer[3]) << 24) + ((int32_t)(theReadBuffer[2]) << 16) + ((int32_t)(theReadBuffer[1]) << 8) + theReadBuffer[0];
  214. fseek(inputFile, theChunkSize, SEEK_CUR);
  215. break;
  216. }
  217. }
  218. }
  219. else
  220. {
  221. *theFileType = 0; // clear it
  222. return -1;
  223. }
  224. }
  225. else
  226. {
  227. *theFileType = 0; // clear it
  228. return -1;
  229. }
  230. if (!done) return -1;
  231. return 0;
  232. }
  233. int32_t SetOutputFormat(AudioFormatDescription theInputFormat, AudioFormatDescription * theOutputFormat)
  234. {
  235. if (theInputFormat.mFormatID == kALACFormatLinearPCM)
  236. {
  237. // encoding
  238. theOutputFormat->mFormatID = kALACFormatAppleLossless;
  239. theOutputFormat->mSampleRate = theInputFormat.mSampleRate;
  240. switch(theInputFormat.mBitsPerChannel)
  241. {
  242. case 16:
  243. theOutputFormat->mFormatFlags = kTestFormatFlag_16BitSourceData;
  244. break;
  245. case 20:
  246. theOutputFormat->mFormatFlags = kTestFormatFlag_20BitSourceData;
  247. break;
  248. case 24:
  249. theOutputFormat->mFormatFlags = kTestFormatFlag_24BitSourceData;
  250. break;
  251. case 32:
  252. theOutputFormat->mFormatFlags = kTestFormatFlag_32BitSourceData;
  253. break;
  254. default:
  255. return -1;
  256. break;
  257. }
  258. theOutputFormat->mFramesPerPacket = kALACDefaultFramesPerPacket;
  259. theOutputFormat->mChannelsPerFrame = theInputFormat.mChannelsPerFrame;
  260. // mBytesPerPacket == 0 because we are VBR
  261. // mBytesPerFrame and mBitsPerChannel == 0 because there are no discernable bits assigned to a particular sample
  262. // mReserved is always 0
  263. theOutputFormat->mBytesPerPacket = theOutputFormat->mBytesPerFrame = theOutputFormat->mBitsPerChannel = theOutputFormat->mReserved = 0;
  264. }
  265. else
  266. {
  267. // decoding
  268. theOutputFormat->mFormatID = kALACFormatLinearPCM;
  269. theOutputFormat->mSampleRate = theInputFormat.mSampleRate;
  270. switch(theInputFormat.mFormatFlags)
  271. {
  272. case kTestFormatFlag_16BitSourceData:
  273. theOutputFormat->mBitsPerChannel = 16;
  274. break;
  275. case kTestFormatFlag_20BitSourceData:
  276. theOutputFormat->mBitsPerChannel = 20;
  277. break;
  278. case kTestFormatFlag_24BitSourceData:
  279. theOutputFormat->mBitsPerChannel = 24;
  280. break;
  281. case kTestFormatFlag_32BitSourceData:
  282. theOutputFormat->mBitsPerChannel = 32;
  283. break;
  284. default:
  285. return -1;
  286. break;
  287. }
  288. theOutputFormat->mFramesPerPacket = 1;
  289. theOutputFormat->mChannelsPerFrame = theInputFormat.mChannelsPerFrame;
  290. theOutputFormat->mBytesPerPacket = theOutputFormat->mBytesPerFrame = theOutputFormat->mBitsPerChannel != 20 ? theInputFormat.mChannelsPerFrame * ((theOutputFormat->mBitsPerChannel) >> 3) : (int32_t)(theInputFormat.mChannelsPerFrame * 2.5 + .5);
  291. theOutputFormat->mFormatFlags = kALACFormatFlagsNativeEndian;
  292. theOutputFormat->mReserved = 0;
  293. }
  294. return 0;
  295. }
  296. int32_t FindDataStart(FILE * inputFile, uint32_t inputFileType, int32_t * dataPos, int32_t * dataSize)
  297. {
  298. // returns the absolute position within the file
  299. int32_t currentPosition = ftell(inputFile); // record the current position
  300. uint8_t theReadBuffer[12];
  301. uint32_t chunkType = 0, fileSize = 0, chunkSize = 0;
  302. bool done = false;
  303. switch (inputFileType)
  304. {
  305. case 'WAVE':
  306. fseek(inputFile, 0, SEEK_SET); // start at 0
  307. fread(theReadBuffer, 1, 8, inputFile);
  308. fileSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
  309. fseek(inputFile, 12, SEEK_SET); // start at 12!
  310. while (!done && ((uint32_t)(ftell(inputFile)) < fileSize))
  311. {
  312. fread(theReadBuffer, 1, 8, inputFile);
  313. chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
  314. switch(chunkType)
  315. {
  316. case 'data':
  317. *dataPos = ftell(inputFile);
  318. // little endian size
  319. *dataSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
  320. done = true;
  321. break;
  322. default:
  323. chunkSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
  324. fseek(inputFile, chunkSize, SEEK_CUR);
  325. break;
  326. }
  327. }
  328. break;
  329. case 'caff':
  330. done = FindCAFFDataStart(inputFile, dataPos, dataSize);
  331. break;
  332. }
  333. fseek(inputFile, currentPosition, SEEK_SET); // start at 0
  334. if (!done) return -1;
  335. return 0;
  336. }
  337. int32_t EncodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize)
  338. {
  339. int32_t theInputPacketBytes = theInputFormat.mChannelsPerFrame * (theInputFormat.mBitsPerChannel >> 3) * theOutputFormat.mFramesPerPacket;
  340. int32_t theOutputPacketBytes = theInputPacketBytes + kALACMaxEscapeHeaderBytes;
  341. int32_t thePacketTableSize = 0, packetTablePos = 0, dataPos = 0, dataSizePos = 0, theBERSize = 0, packetTableSizePos;
  342. uint8_t * theReadBuffer = (uint8_t *)calloc(theInputPacketBytes, 1);
  343. uint8_t * theWriteBuffer = (uint8_t *)calloc(theOutputPacketBytes, 1);
  344. int32_t numBytes = 0;
  345. uint32_t packetTableBytesLeft = 0;
  346. int64_t numDataBytes = 0;
  347. port_CAFPacketTableHeader thePacketTableHeader;
  348. int32_t inputDataBytesRemaining = inputDataSize;
  349. uint8_t * theMagicCookie = NULL;
  350. uint32_t theMagicCookieSize = 0;
  351. ALACEncoder * theEncoder = new ALACEncoder;
  352. theEncoder->SetFrameSize(theOutputFormat.mFramesPerPacket);
  353. theEncoder->InitializeEncoder(theOutputFormat);
  354. // we only write out the caff header, the 'desc' chunk. the 'kuki' chunk, the 'pakt' chunk and the 'data' chunk
  355. // write out the caff header
  356. WriteCAFFcaffChunk(outputFile);
  357. // write out the desc chunk
  358. WriteCAFFdescChunk(outputFile, theOutputFormat);
  359. // get the magic cookie
  360. theMagicCookieSize = theEncoder->GetMagicCookieSize(theOutputFormat.mChannelsPerFrame);
  361. theMagicCookie = (uint8_t *)calloc(theMagicCookieSize, 1);
  362. theEncoder->GetMagicCookie(theMagicCookie, &theMagicCookieSize);
  363. // write out the kuki chunk
  364. WriteCAFFkukiChunk(outputFile, theMagicCookie, theMagicCookieSize);
  365. free(theMagicCookie);
  366. // We might be multi channel
  367. if (theOutputFormat.mChannelsPerFrame > 2)
  368. {
  369. WriteCAFFchanChunk(outputFile, GetALACChannelLayoutTag(theOutputFormat.mChannelsPerFrame));
  370. }
  371. // Figure out the maximum size and build the base pakt header
  372. BuildBasePacketTable(theInputFormat, inputDataSize, &thePacketTableSize, &thePacketTableHeader);
  373. packetTableBytesLeft = thePacketTableSize;
  374. // This could be substantially larger than either the read or write buffer, so allocate a block of memory here
  375. // all we're going to do is copy it to the file
  376. uint8_t * thePacketTableEntries = (uint8_t *)calloc (thePacketTableSize, 1);
  377. /* move */
  378. thePacketTableSize += kMinCAFFPacketTableHeaderSize;
  379. WriteCAFFpaktChunkHeader(outputFile, &thePacketTableHeader, thePacketTableSize);
  380. packetTableSizePos = packetTablePos = ftell(outputFile);
  381. packetTableSizePos -= (sizeof(int64_t) + kMinCAFFPacketTableHeaderSize);
  382. thePacketTableSize -= kMinCAFFPacketTableHeaderSize;
  383. fwrite (thePacketTableEntries, 1, thePacketTableSize, outputFile);
  384. free(thePacketTableEntries);
  385. // We'll write out the data chunk next. The 'data' size will start past the 'data' chunk identifier
  386. dataSizePos = ftell(outputFile) + sizeof(uint32_t);
  387. // Finally, write out the data chunk
  388. WriteCAFFdataChunk(outputFile);
  389. dataPos = ftell(outputFile);
  390. while (theInputPacketBytes <= inputDataBytesRemaining)
  391. {
  392. numBytes = fread(theReadBuffer, 1, theInputPacketBytes, inputFile);
  393. #if VERBOSE
  394. printf ("Read %i bytes\n", numBytes);
  395. #endif
  396. inputDataBytesRemaining -= numBytes;
  397. if ((theInputFormat.mFormatFlags & 0x02) != kALACFormatFlagsNativeEndian)
  398. {
  399. #if VERBOSE
  400. printf ("Byte Swapping!\n");
  401. #endif
  402. if (theInputFormat.mBitsPerChannel == 16)
  403. {
  404. uint16_t * theShort = (uint16_t *)theReadBuffer;
  405. for (int32_t i = 0; i < (numBytes >> 1); ++i)
  406. {
  407. Swap16(&(theShort[i]));
  408. }
  409. }
  410. else if (theInputFormat.mBitsPerChannel == 32)
  411. {
  412. uint32_t * theLong = (uint32_t *)theReadBuffer;
  413. for (int32_t i = 0; i < (numBytes >> 2); ++i)
  414. {
  415. Swap32(&(theLong[i]));
  416. }
  417. }
  418. else // covers both 20 and 24
  419. {
  420. for (int32_t i = 0; i < numBytes; i += 3)
  421. {
  422. Swap24(&(theReadBuffer[i]));
  423. }
  424. }
  425. }
  426. theEncoder->Encode(theInputFormat, theInputFormat, theReadBuffer, theWriteBuffer, &numBytes);
  427. GetBERInteger(numBytes, theReadBuffer, &theBERSize);
  428. fseek(outputFile, packetTablePos, SEEK_SET);
  429. fwrite(theReadBuffer, 1, theBERSize, outputFile);
  430. packetTablePos += theBERSize;
  431. packetTableBytesLeft -= theBERSize;
  432. fseek(outputFile, dataPos, SEEK_SET);
  433. fwrite(theWriteBuffer, 1, numBytes, outputFile);
  434. dataPos += numBytes;
  435. numDataBytes += numBytes;
  436. #if VERBOSE
  437. printf ("Writing %i bytes\n", numBytes);
  438. #endif
  439. }
  440. // encode the last partial packet
  441. if (inputDataBytesRemaining)
  442. {
  443. numBytes = fread(theReadBuffer, 1, inputDataBytesRemaining, inputFile);
  444. #if VERBOSE
  445. printf ("Last Packet! Read %i bytes\n", numBytes);
  446. #endif
  447. inputDataBytesRemaining -= numBytes;
  448. if ((theInputFormat.mFormatFlags & 0x02) != kALACFormatFlagsNativeEndian)
  449. {
  450. #if VERBOSE
  451. printf ("Byte Swapping!\n");
  452. #endif
  453. if (theInputFormat.mBitsPerChannel == 16)
  454. {
  455. uint16_t * theShort = (uint16_t *)theReadBuffer;
  456. for (int32_t i = 0; i < (numBytes >> 1); ++i)
  457. {
  458. Swap16(&(theShort[i]));
  459. }
  460. }
  461. else if (theInputFormat.mBitsPerChannel == 32)
  462. {
  463. uint32_t * theLong = (uint32_t *)theReadBuffer;
  464. for (int32_t i = 0; i < (numBytes >> 2); ++i)
  465. {
  466. Swap32(&(theLong[i]));
  467. }
  468. }
  469. else // covers both 20 and 24
  470. {
  471. for (int32_t i = 0; i < numBytes; i += 3)
  472. {
  473. Swap24(&(theReadBuffer[i]));
  474. }
  475. }
  476. }
  477. theEncoder->Encode(theInputFormat, theInputFormat, theReadBuffer, theWriteBuffer, &numBytes);
  478. GetBERInteger(numBytes, theReadBuffer, &theBERSize);
  479. fseek(outputFile, packetTablePos, SEEK_SET);
  480. fwrite(theReadBuffer, 1, theBERSize, outputFile);
  481. packetTablePos += theBERSize;
  482. packetTableBytesLeft -= theBERSize;
  483. fseek(outputFile, dataPos, SEEK_SET);
  484. fwrite(theWriteBuffer, 1, numBytes, outputFile);
  485. dataPos += numBytes;
  486. numDataBytes += numBytes;
  487. #if VERBOSE
  488. printf ("Writing %i bytes\n", numBytes);
  489. #endif
  490. }
  491. // cleanup -- if we have a lot of bytes left over in packet table, write a free chunk
  492. if (packetTableBytesLeft > sizeof(port_CAFChunkHeader)) // min size required to write
  493. {
  494. #if VERBOSE
  495. printf ("Writing %i free bytes\n", packetTableBytesLeft);
  496. #endif
  497. fseek(outputFile, packetTablePos, SEEK_SET);
  498. WriteCAFFfreeChunk(outputFile, packetTableBytesLeft);
  499. fseek(outputFile, packetTableSizePos, SEEK_SET);
  500. WriteCAFFChunkSize(outputFile, thePacketTableSize - packetTableBytesLeft + kMinCAFFPacketTableHeaderSize);
  501. }
  502. // write out the data size
  503. fseek(outputFile, dataSizePos, SEEK_SET);
  504. numDataBytes += kCAFFdataChunkEditsSize;
  505. #if VERBOSE
  506. printf ("numDataBytes == %i bytes\n", numDataBytes);
  507. #endif
  508. WriteCAFFChunkSize(outputFile, numDataBytes);
  509. delete theEncoder;
  510. free(theReadBuffer);
  511. free(theWriteBuffer);
  512. return 0;
  513. }
  514. // There's not a whole lot of difference between encode and decode on this level
  515. int32_t DecodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize, uint32_t outputFileType)
  516. {
  517. int32_t theInputPacketBytes = theInputFormat.mChannelsPerFrame * (theOutputFormat.mBitsPerChannel >> 3) * theInputFormat.mFramesPerPacket + kALACMaxEscapeHeaderBytes;
  518. int32_t theOutputPacketBytes = theInputPacketBytes - kALACMaxEscapeHeaderBytes;
  519. int32_t thePacketTableSize = 0, packetTablePos = 0, outputDataSizePos = 0, inputDataPos = 0;
  520. uint8_t * theReadBuffer = (uint8_t *)calloc(theInputPacketBytes, 1);
  521. uint8_t * theWriteBuffer = (uint8_t *)calloc(theOutputPacketBytes, 1);
  522. int32_t numBytes = 0;
  523. int64_t numDataBytes = 0;
  524. uint32_t numFrames = 0;
  525. BitBuffer theInputBuffer;
  526. uint8_t * theMagicCookie = NULL;
  527. uint32_t theMagicCookieSize = 0;
  528. ALACDecoder * theDecoder = new ALACDecoder;
  529. // We need to get the cookie from the file
  530. theMagicCookieSize = GetMagicCookieSizeFromCAFFkuki(inputFile);
  531. theMagicCookie = (uint8_t *)calloc(theMagicCookieSize, 1);
  532. GetMagicCookieFromCAFFkuki(inputFile, theMagicCookie, &theMagicCookieSize);
  533. // While we don't have a use for this here, if you were using arbitrary channel layouts, you'd need to run the following check:
  534. theDecoder->Init(theMagicCookie, theMagicCookieSize);
  535. free(theMagicCookie);
  536. BitBufferInit(&theInputBuffer, theReadBuffer, theInputPacketBytes);
  537. inputDataPos = ftell(inputFile);
  538. if (outputFileType != 'WAVE')
  539. {
  540. // we only write out the caff header, the 'desc' chunk and the 'data' chunk
  541. // write out the caff header
  542. WriteCAFFcaffChunk(outputFile);
  543. // write out the desc chunk
  544. WriteCAFFdescChunk(outputFile, theOutputFormat);
  545. // We might be multi channel
  546. if (theOutputFormat.mChannelsPerFrame > 2)
  547. {
  548. // we are not rearranging the output data
  549. WriteCAFFchanChunk(outputFile, CAFFChannelLayoutTags[theOutputFormat.mChannelsPerFrame - 1]);
  550. }
  551. // We'll write out the data chunk next. The 'data' size will start past the 'data' chunk identifier
  552. outputDataSizePos = ftell(outputFile) + sizeof(uint32_t);
  553. // Finally, write out the data chunk
  554. WriteCAFFdataChunk(outputFile);
  555. }
  556. else
  557. {
  558. // We're writing a mono or stereo WAVE file
  559. WriteWAVERIFFChunk(outputFile);
  560. WriteWAVEfmtChunk(outputFile, theOutputFormat);
  561. WriteWAVEdataChunk(outputFile);
  562. outputDataSizePos = ftell(outputFile) - sizeof(uint32_t);
  563. }
  564. // We do have to get the packet size from the packet table
  565. FindCAFFPacketTableStart(inputFile, &packetTablePos, &thePacketTableSize);
  566. fseek(inputFile, packetTablePos, SEEK_SET);
  567. numBytes = fread(theReadBuffer, 1, kMaxBERSize, inputFile);
  568. theInputPacketBytes = ReadBERInteger(theReadBuffer, &numBytes);
  569. packetTablePos += numBytes;
  570. fseek(inputFile, inputDataPos, SEEK_SET);
  571. inputDataPos += theInputPacketBytes;
  572. while ((theInputPacketBytes > 0) && ((size_t)theInputPacketBytes == fread(theReadBuffer, 1, theInputPacketBytes, inputFile)))
  573. {
  574. #if VERBOSE
  575. printf ("Read %i bytes\n", theInputPacketBytes);
  576. #endif
  577. theDecoder->Decode(&theInputBuffer, theWriteBuffer, theInputFormat.mFramesPerPacket, theInputFormat.mChannelsPerFrame, &numFrames);
  578. numBytes = numFrames * theOutputFormat.mBytesPerFrame;
  579. #if VERBOSE
  580. printf ("Writing %i bytes\n", numBytes);
  581. #endif
  582. fwrite(theWriteBuffer, 1, numBytes, outputFile);
  583. numDataBytes += numBytes;
  584. fseek(inputFile, packetTablePos, SEEK_SET);
  585. numBytes = fread(theReadBuffer, 1, kMaxBERSize, inputFile);
  586. theInputPacketBytes = ReadBERInteger(theReadBuffer, &numBytes);
  587. #if VERBOSE
  588. printf ("theInputPacketBytes == %i bytes\n", theInputPacketBytes);
  589. #endif
  590. packetTablePos += numBytes;
  591. fseek(inputFile, inputDataPos, SEEK_SET);
  592. inputDataPos += theInputPacketBytes;
  593. BitBufferReset(&theInputBuffer);
  594. }
  595. if (outputFileType != 'WAVE')
  596. {
  597. // cleanup -- write out the data size
  598. fseek(outputFile, outputDataSizePos, SEEK_SET);
  599. numDataBytes += kCAFFdataChunkEditsSize; // add in the edit bytes
  600. #if VERBOSE
  601. printf ("numDataBytes == %i bytes\n", numDataBytes);
  602. #endif
  603. WriteCAFFChunkSize(outputFile, numDataBytes);
  604. }
  605. else
  606. {
  607. // cleanup -- write out the data size
  608. fseek(outputFile, outputDataSizePos, SEEK_SET);
  609. WriteWAVEChunkSize(outputFile, (uint32_t)numDataBytes);
  610. // write out the file size
  611. fseek(outputFile, 4, SEEK_SET);
  612. WriteWAVEChunkSize(outputFile, numDataBytes + sizeof(outputFileType) + kWAVEdataChunkHeaderSize + kWAVEfmtChunkSize); // add in the size for 'WAVE', size of the data' chunk header and the 'fmt ' chunk
  613. }
  614. delete theDecoder;
  615. free(theReadBuffer);
  616. free(theWriteBuffer);
  617. return 0;
  618. }
  619. void GetOutputFileType(char * outputFileName, uint32_t * outputFileType)
  620. {
  621. char * typeStr = strrchr(outputFileName, '.');
  622. *outputFileType = 'caff';
  623. if (typeStr != NULL)
  624. {
  625. if (strlen(typeStr) == 4)
  626. {
  627. if (strcmp(typeStr, ".wav") == 0)
  628. {
  629. *outputFileType = 'WAVE';
  630. }
  631. }
  632. }
  633. }
  634. ALACChannelLayoutTag GetALACChannelLayoutTag(uint32_t inChannelsPerFrame)
  635. {
  636. return ALACChannelLayoutTags[inChannelsPerFrame - 1];
  637. }
  638. void WriteWAVERIFFChunk(FILE * outputFile)
  639. {
  640. uint8_t theReadBuffer[kWAVERIFFChunkSize] = {'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'A', 'V', 'E'};
  641. fwrite(theReadBuffer, 1, kWAVERIFFChunkSize, outputFile);
  642. }
  643. void WriteWAVEfmtChunk(FILE * outputFile, AudioFormatDescription theOutputFormat)
  644. {
  645. // we use a standard 'fmt ' chunk for our pcm data where 16 is the chunk size and 1 is the compression code
  646. uint8_t theBuffer[kWAVEfmtChunkSize] = {'f', 'm', 't', ' ', 16, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  647. uint32_t theSampleRate = theOutputFormat.mSampleRate;
  648. uint32_t theAverageBytesPerSecond = theSampleRate * theOutputFormat.mBytesPerFrame;
  649. theBuffer[10] = theOutputFormat.mChannelsPerFrame;
  650. theBuffer[12] = theSampleRate & 0xff;
  651. theBuffer[13] = (theSampleRate >> 8) & 0xff;
  652. theBuffer[14] = (theSampleRate >> 16) & 0xff;
  653. theBuffer[15] = theSampleRate >> 24;
  654. theBuffer[16] = theAverageBytesPerSecond & 0xff;
  655. theBuffer[17] = (theAverageBytesPerSecond >> 8) & 0xff;
  656. theBuffer[18] = (theAverageBytesPerSecond >> 16) & 0xff;
  657. theBuffer[19] = theAverageBytesPerSecond >> 24;
  658. theBuffer[20] = theOutputFormat.mBytesPerFrame;
  659. theBuffer[22] = theOutputFormat.mBitsPerChannel;
  660. fwrite(theBuffer, 1, kWAVEfmtChunkSize, outputFile);
  661. }
  662. void WriteWAVEdataChunk(FILE * outputFile)
  663. {
  664. uint8_t theBuffer[kWAVEdataChunkHeaderSize] = {'d', 'a', 't', 'a', 0, 0, 0, 0};
  665. fwrite(theBuffer, 1, kWAVEdataChunkHeaderSize, outputFile);
  666. }
  667. void WriteWAVEChunkSize(FILE * outputFile, uint32_t numDataBytes)
  668. {
  669. uint8_t theBuffer[4];
  670. theBuffer[0] = numDataBytes & 0xff;
  671. theBuffer[1] = (numDataBytes >> 8) & 0xff;
  672. theBuffer[2] = (numDataBytes >> 16) & 0xff;
  673. theBuffer[3] = (numDataBytes >> 24) & 0xff;
  674. fwrite(theBuffer, 1, 4, outputFile);
  675. }