CAFFileALAC.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  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. // CAFFileALAC.cpp
  10. //
  11. // Copyright 2011 Apple Inc. All rights reserved.
  12. //
  13. #include <stdio.h>
  14. #include "CAFFileALAC.h"
  15. #include "EndianPortable.h"
  16. #define kSizeOfChanAtomPlusChannelLayout 24
  17. int32_t FindCAFFPacketTableStart(FILE * inputFile, int32_t * paktPos, int32_t * paktSize)
  18. {
  19. // returns the absolute position within the file
  20. int32_t currentPosition = ftell(inputFile); // record the current position
  21. uint8_t theReadBuffer[12];
  22. uint32_t chunkType = 0, chunkSize = 0;
  23. bool done = false;
  24. int32_t bytesRead = 8;
  25. fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
  26. while (!done && bytesRead > 0) // no file size here
  27. {
  28. bytesRead = fread(theReadBuffer, 1, 12, inputFile);
  29. chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
  30. switch(chunkType)
  31. {
  32. case 'pakt':
  33. *paktPos = ftell(inputFile) + kMinCAFFPacketTableHeaderSize;
  34. // big endian size
  35. *paktSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
  36. done = true;
  37. break;
  38. default:
  39. chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
  40. fseek(inputFile, chunkSize, SEEK_CUR);
  41. break;
  42. }
  43. }
  44. fseek(inputFile, currentPosition, SEEK_SET); // start at 0
  45. return 0;
  46. }
  47. void WriteCAFFcaffChunk(FILE * outputFile)
  48. {
  49. uint8_t theReadBuffer[8] = {'c', 'a', 'f', 'f', 0, 1, 0, 0};
  50. fwrite(theReadBuffer, 1, 8, outputFile);
  51. }
  52. void WriteCAFFdescChunk(FILE * outputFile, AudioFormatDescription theOutputFormat)
  53. {
  54. port_CAFAudioDescription theDescription;
  55. uint32_t tempFormatFlags = theOutputFormat.mFormatFlags;
  56. uint8_t theReadBuffer[12] = {'d', 'e', 's', 'c', 0, 0, 0, 0, 0, 0, 0, 0};
  57. if (theOutputFormat.mFormatID == kALACFormatLinearPCM)
  58. {
  59. if (kALACFormatFlagsNativeEndian > 0) // kALACFormatFlagsNativeEndian is 2 on a big endian machine, 0 on little
  60. {
  61. tempFormatFlags = 0;
  62. }
  63. else
  64. {
  65. tempFormatFlags = k_port_CAFLinearPCMFormatFlagIsLittleEndian;
  66. }
  67. }
  68. theDescription.mSampleRate = SwapFloat64NtoB(theOutputFormat.mSampleRate);
  69. theDescription.mFormatID = Swap32NtoB(theOutputFormat.mFormatID);
  70. theDescription.mFormatFlags = Swap32NtoB(tempFormatFlags);
  71. theDescription.mBytesPerPacket = Swap32NtoB(theOutputFormat.mBytesPerPacket);
  72. theDescription.mFramesPerPacket = Swap32NtoB(theOutputFormat.mFramesPerPacket);
  73. theDescription.mChannelsPerFrame = Swap32NtoB(theOutputFormat.mChannelsPerFrame);
  74. theDescription.mBitsPerChannel = Swap32NtoB(theOutputFormat.mBitsPerChannel);
  75. theReadBuffer[11] = sizeof(port_CAFAudioDescription);
  76. fwrite(theReadBuffer, 1, 12, outputFile);
  77. fwrite(&theDescription, 1, sizeof(port_CAFAudioDescription), outputFile);
  78. }
  79. void WriteCAFFdataChunk(FILE * outputFile)
  80. {
  81. uint8_t theReadBuffer[16] = {'d', 'a', 't', 'a', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
  82. fwrite(theReadBuffer, 1, 16, outputFile);
  83. }
  84. void WriteCAFFkukiChunk(FILE * outputFile, void * inCookie, uint32_t inCookieSize)
  85. {
  86. uint8_t thekukiHeaderBuffer[12] = {'k', 'u', 'k', 'i', 0, 0, 0, 0, 0, 0, 0, 0};
  87. thekukiHeaderBuffer[11] = inCookieSize;
  88. fwrite(thekukiHeaderBuffer, 1, 12, outputFile);
  89. fwrite(inCookie, 1, inCookieSize, outputFile);
  90. }
  91. void WriteCAFFChunkSize(FILE * outputFile, int64_t numDataBytes)
  92. {
  93. uint8_t theBuffer[8];
  94. theBuffer[0] = (numDataBytes >> 56) & 0xff;
  95. theBuffer[1] = (numDataBytes >> 48) & 0xff;
  96. theBuffer[2] = (numDataBytes >> 40) & 0xff;
  97. theBuffer[3] = (numDataBytes >> 32) & 0xff;
  98. theBuffer[4] = (numDataBytes >> 24) & 0xff;
  99. theBuffer[5] = (numDataBytes >> 16) & 0xff;
  100. theBuffer[6] = (numDataBytes >> 8) & 0xff;
  101. theBuffer[7] = numDataBytes & 0xff;
  102. fwrite(theBuffer, 1, 8, outputFile);
  103. }
  104. void WriteCAFFchanChunk(FILE * outputFile, uint32_t inChannelTag)
  105. {
  106. uint8_t theBuffer[24] = {'c', 'h', 'a', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  107. theBuffer[11] = sizeof(ALACAudioChannelLayout);
  108. theBuffer[12] = inChannelTag >> 24;
  109. theBuffer[13] = (inChannelTag >> 16) & 0xff;
  110. theBuffer[14] = (inChannelTag >> 8) & 0xff;
  111. theBuffer[15] = inChannelTag & 0xff;
  112. fwrite(theBuffer, 1, 24, outputFile);
  113. }
  114. void WriteCAFFfreeChunk(FILE * outputFile, uint32_t theSize)
  115. {
  116. uint8_t theBuffer[12] = {'f', 'r', 'e', 'e', 0, 0, 0, 0, 0, 0, 0, 0};
  117. uint32_t i = 0;
  118. uint32_t theAdjustedSize = theSize - sizeof(port_CAFChunkHeader);
  119. if (theSize > theAdjustedSize) // cause we might have wrapped theAdjustedSize
  120. {
  121. theBuffer[8] = theAdjustedSize >> 24;
  122. theBuffer[9] = (theAdjustedSize >> 16) & 0xff;
  123. theBuffer[10] = (theAdjustedSize >> 8) & 0xff;
  124. theBuffer[11] = theAdjustedSize & 0xff;
  125. fwrite(theBuffer, 1, 12, outputFile);
  126. for (i = 0; i < theAdjustedSize; ++i)
  127. {
  128. fwrite(&(theBuffer[4]), 1, 1, outputFile);
  129. }
  130. }
  131. }
  132. void WriteCAFFpaktChunkHeader(FILE * outputFile, port_CAFPacketTableHeader * thePacketTableHeader, uint32_t thePacketTableSize)
  133. {
  134. uint8_t theBuffer[12];
  135. // Endian swap!
  136. thePacketTableHeader->mNumberPackets = Swap64NtoB(thePacketTableHeader->mNumberPackets);
  137. thePacketTableHeader->mNumberValidFrames = Swap64NtoB(thePacketTableHeader->mNumberValidFrames);
  138. thePacketTableHeader->mPrimingFrames = Swap32NtoB(thePacketTableHeader->mPrimingFrames);
  139. thePacketTableHeader->mRemainderFrames = Swap32NtoB(thePacketTableHeader->mRemainderFrames);
  140. // write out the pakt chunk -- big endian!
  141. theBuffer[0] = 'p';
  142. theBuffer[1] = 'a';
  143. theBuffer[2] = 'k';
  144. theBuffer[3] = 't';
  145. theBuffer[4] = 0;
  146. theBuffer[5] = 0;
  147. theBuffer[6] = 0;
  148. theBuffer[7] = 0;
  149. theBuffer[8] = thePacketTableSize >> 24;
  150. theBuffer[9] = (thePacketTableSize >> 16) & 0xff;
  151. theBuffer[10] = (thePacketTableSize >> 8) & 0xff;
  152. theBuffer[11] = thePacketTableSize & 0xff;
  153. fwrite(theBuffer, 1, 12, outputFile);
  154. fwrite(thePacketTableHeader, 1, kMinCAFFPacketTableHeaderSize, outputFile);
  155. }
  156. void GetBERInteger(int32_t theOriginalValue, uint8_t * theBuffer, int32_t * theBERSize)
  157. {
  158. if ((theOriginalValue & 0x7f) == theOriginalValue)
  159. {
  160. *theBERSize = 1;
  161. theBuffer[0] = theOriginalValue;
  162. }
  163. else if ((theOriginalValue & 0x3fff) == theOriginalValue)
  164. {
  165. *theBERSize = 2;
  166. theBuffer[0] = theOriginalValue >> 7;
  167. theBuffer[0] |= 0x80;
  168. theBuffer[1] = theOriginalValue & 0x7f;
  169. }
  170. else if ((theOriginalValue & 0x1fffff) == theOriginalValue)
  171. {
  172. *theBERSize = 3;
  173. theBuffer[0] = theOriginalValue >> 14;
  174. theBuffer[0] |= 0x80;
  175. theBuffer[1] = (theOriginalValue >> 7) & 0x7f;
  176. theBuffer[1] |= 0x80;
  177. theBuffer[2] = theOriginalValue & 0x7f;
  178. }
  179. else if ((theOriginalValue & 0x0fffffff) == theOriginalValue)
  180. {
  181. *theBERSize = 4;
  182. theBuffer[0] = theOriginalValue >> 21;
  183. theBuffer[0] |= 0x80;
  184. theBuffer[1] = (theOriginalValue >> 14) & 0x7f;
  185. theBuffer[1] |= 0x80;
  186. theBuffer[2] = (theOriginalValue >> 7) & 0x7f;
  187. theBuffer[2] |= 0x80;
  188. theBuffer[3] = theOriginalValue & 0x7f;
  189. }
  190. else
  191. {
  192. *theBERSize = 5;
  193. theBuffer[0] = theOriginalValue >> 28;
  194. theBuffer[0] |= 0x80;
  195. theBuffer[1] = (theOriginalValue >> 21) & 0x7f;
  196. theBuffer[1] |= 0x80;
  197. theBuffer[2] = (theOriginalValue >> 14) & 0x7f;
  198. theBuffer[2] |= 0x80;
  199. theBuffer[3] = (theOriginalValue >> 7) & 0x7f;
  200. theBuffer[3] |= 0x80;
  201. theBuffer[4] = theOriginalValue & 0x7f;
  202. }
  203. }
  204. uint32_t ReadBERInteger(uint8_t * theInputBuffer, int32_t * ioNumBytes)
  205. {
  206. uint32_t theAnswer = 0;
  207. uint8_t theData;
  208. int32_t size = 0;
  209. do
  210. {
  211. theData = theInputBuffer[size];
  212. theAnswer = (theAnswer << 7) | (theData & 0x7F);
  213. if (++size > 5)
  214. {
  215. size = 0xFFFFFFFF;
  216. return 0;
  217. }
  218. }
  219. while(((theData & 0x80) != 0) && (size <= *ioNumBytes));
  220. *ioNumBytes = size;
  221. return theAnswer;
  222. }
  223. int32_t BuildBasePacketTable(AudioFormatDescription theInputFormat, int32_t inputDataSize, int32_t * theMaxPacketTableSize, port_CAFPacketTableHeader * thePacketTableHeader)
  224. {
  225. int32_t theMaxPacketSize = 0, theByteSizeTableEntry = 0;
  226. // fill out the header
  227. thePacketTableHeader->mNumberValidFrames = inputDataSize/((theInputFormat.mBitsPerChannel >> 3) * theInputFormat.mChannelsPerFrame);
  228. thePacketTableHeader->mNumberPackets = thePacketTableHeader->mNumberValidFrames/kALACDefaultFramesPerPacket;
  229. thePacketTableHeader->mPrimingFrames = 0;
  230. thePacketTableHeader->mRemainderFrames = thePacketTableHeader->mNumberValidFrames - thePacketTableHeader->mNumberPackets * kALACDefaultFramesPerPacket;
  231. thePacketTableHeader->mRemainderFrames = kALACDefaultFramesPerPacket - thePacketTableHeader->mRemainderFrames;
  232. if (thePacketTableHeader->mRemainderFrames) thePacketTableHeader->mNumberPackets += 1;
  233. // Ok, we have to assume the worst case scenario for packet sizes
  234. theMaxPacketSize = (theInputFormat.mBitsPerChannel >> 3) * theInputFormat.mChannelsPerFrame * kALACDefaultFramesPerPacket + kALACMaxEscapeHeaderBytes;
  235. if (theMaxPacketSize < 16384)
  236. {
  237. theByteSizeTableEntry = 2;
  238. }
  239. else
  240. {
  241. theByteSizeTableEntry = 3;
  242. }
  243. *theMaxPacketTableSize = theByteSizeTableEntry * thePacketTableHeader->mNumberPackets;
  244. return 0;
  245. }
  246. uint32_t GetMagicCookieSizeFromCAFFkuki(FILE * inputFile)
  247. {
  248. // returns to the current absolute position within the file
  249. int32_t currentPosition = ftell(inputFile); // record the current position
  250. uint8_t theReadBuffer[sizeof(ALACSpecificConfig)];
  251. uint32_t chunkType = 0, chunkSize = 0;
  252. bool done = false;
  253. int32_t bytesRead = sizeof(port_CAFFileHeader);
  254. uint32_t theCookieSize = 0;
  255. fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
  256. while (!done && bytesRead > 0) // no file size here
  257. {
  258. bytesRead = fread(theReadBuffer, 1, 12, inputFile);
  259. chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
  260. switch(chunkType)
  261. {
  262. case 'kuki':
  263. {
  264. theCookieSize = theReadBuffer[11];
  265. done = true;
  266. break;
  267. }
  268. default:
  269. chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
  270. fseek(inputFile, chunkSize, SEEK_CUR);
  271. break;
  272. }
  273. }
  274. fseek(inputFile, currentPosition, SEEK_SET); // start at 0
  275. if (!done) return -1;
  276. return theCookieSize;
  277. }
  278. // gets the kuki chunk from a caff file
  279. int32_t GetMagicCookieFromCAFFkuki(FILE * inputFile, uint8_t * outMagicCookie, uint32_t * ioMagicCookieSize)
  280. {
  281. // returns to the current absolute position within the file
  282. int32_t currentPosition = ftell(inputFile); // record the current position
  283. uint8_t theReadBuffer[12];
  284. uint32_t chunkType = 0, chunkSize = 0;
  285. bool done = false, cookieFound = false;
  286. int32_t bytesRead = sizeof(port_CAFFileHeader);
  287. uint32_t theStoredCookieSize = 0;
  288. fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
  289. while (!done && bytesRead > 0) // no file size here
  290. {
  291. bytesRead = fread(theReadBuffer, 1, 12, inputFile);
  292. chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
  293. switch(chunkType)
  294. {
  295. case 'kuki':
  296. {
  297. theStoredCookieSize = theReadBuffer[11];
  298. if (*ioMagicCookieSize >= theStoredCookieSize)
  299. {
  300. fread(outMagicCookie, 1, theStoredCookieSize, inputFile);
  301. *ioMagicCookieSize = theStoredCookieSize;
  302. cookieFound = true;
  303. }
  304. else
  305. {
  306. *ioMagicCookieSize = 0;
  307. }
  308. done = true;
  309. break;
  310. }
  311. default:
  312. chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
  313. fseek(inputFile, chunkSize, SEEK_CUR);
  314. break;
  315. }
  316. }
  317. fseek(inputFile, currentPosition, SEEK_SET); // start at 0
  318. if (!done || !cookieFound) return -1;
  319. return 0;
  320. }
  321. bool FindCAFFDataStart(FILE * inputFile, int32_t * dataPos, int32_t * dataSize)
  322. {
  323. bool done = false;
  324. int32_t bytesRead = 8;
  325. uint32_t chunkType = 0, chunkSize = 0;
  326. uint8_t theBuffer[12];
  327. fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
  328. while (!done && bytesRead > 0) // no file size here
  329. {
  330. bytesRead = fread(theBuffer, 1, 12, inputFile);
  331. chunkType = ((int32_t)(theBuffer[0]) << 24) + ((int32_t)(theBuffer[1]) << 16) + ((int32_t)(theBuffer[2]) << 8) + theBuffer[3];
  332. switch(chunkType)
  333. {
  334. case 'data':
  335. *dataPos = ftell(inputFile) + sizeof(uint32_t); // skip the edits
  336. // big endian size
  337. *dataSize = ((int32_t)(theBuffer[8]) << 24) + ((int32_t)(theBuffer[9]) << 16) + ((int32_t)(theBuffer[10]) << 8) + theBuffer[11];
  338. *dataSize -= 4; // the edits are included in the size
  339. done = true;
  340. break;
  341. default:
  342. chunkSize = ((int32_t)(theBuffer[8]) << 24) + ((int32_t)(theBuffer[9]) << 16) + ((int32_t)(theBuffer[10]) << 8) + theBuffer[11];
  343. fseek(inputFile, chunkSize, SEEK_CUR);
  344. break;
  345. }
  346. }
  347. return done;
  348. }
  349. bool GetCAFFdescFormat(FILE * inputFile, AudioFormatDescription * theInputFormat)
  350. {
  351. bool done = false;
  352. uint32_t theChunkSize = 0, theChunkType = 0;
  353. uint8_t theReadBuffer[32];
  354. fseek(inputFile, 4, SEEK_CUR); // skip 4 bytes
  355. while (!done)
  356. {
  357. fread(theReadBuffer, 1, 4, inputFile);
  358. theChunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
  359. switch (theChunkType)
  360. {
  361. case 'desc':
  362. fseek(inputFile, 8, SEEK_CUR); // skip 8 bytes
  363. fread(theReadBuffer, 1, sizeof(port_CAFAudioDescription), inputFile);
  364. theInputFormat->mFormatID = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFormatID);
  365. theInputFormat->mChannelsPerFrame = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mChannelsPerFrame);
  366. theInputFormat->mSampleRate = SwapFloat64BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mSampleRate);
  367. theInputFormat->mBitsPerChannel = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mBitsPerChannel);
  368. theInputFormat->mFormatFlags = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFormatFlags);
  369. theInputFormat->mBytesPerPacket = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mBytesPerPacket);
  370. if (theInputFormat->mFormatID == kALACFormatAppleLossless)
  371. {
  372. theInputFormat->mBytesPerFrame = 0;
  373. }
  374. else
  375. {
  376. theInputFormat->mBytesPerFrame = theInputFormat->mBytesPerPacket;
  377. if ((theInputFormat->mFormatFlags & 0x02) == 0x02)
  378. {
  379. theInputFormat->mFormatFlags &= 0xfffffffc;
  380. }
  381. else
  382. {
  383. theInputFormat->mFormatFlags |= 0x02;
  384. }
  385. }
  386. theInputFormat->mFramesPerPacket = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFramesPerPacket);
  387. theInputFormat->mReserved = 0;
  388. done = true;
  389. break;
  390. default:
  391. // read the size and skip
  392. fread(theReadBuffer, 1, 8, inputFile);
  393. theChunkSize = ((int32_t)(theReadBuffer[4]) << 24) + ((int32_t)(theReadBuffer[5]) << 16) + ((int32_t)(theReadBuffer[6]) << 8) + theReadBuffer[7];
  394. fseek(inputFile, theChunkSize, SEEK_CUR);
  395. break;
  396. }
  397. }
  398. return done;
  399. }