libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmAudioFile.c 45KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmFloatTypes.h"
  4. #include "cmRpt.h"
  5. #include "cmErr.h"
  6. #include "cmCtx.h"
  7. #include "cmMem.h"
  8. #include "cmMallocDebug.h"
  9. #include "cmAudioFile.h"
  10. #include "cmMath.h"
  11. #include "cmFileSys.h"
  12. // #define _24to32_aif( p ) ((int)( ((p[0]>127?255:0) << 24) + (((int)p[0]) << 16) + (((int)p[1]) <<8) + p[2])) // no-swap equivalent
  13. // See note in:_cmAudioFileReadAiffHeader()
  14. // Note that this code byte swaps as it converts - this is to counter the byte swap that occurs in cmAudioFileReadInt().
  15. #define _24to32_aif( p ) ((int)( ((p[0]>127?255:0) << 0) + (((int)p[2]) << 24) + (((int)p[1]) <<16) + (((int)p[0]) << 8)))
  16. #define _24to32_wav( p ) ((int)( ((p[2]>127?255:0) << 24) + (((int)p[2]) << 16) + (((int)p[1]) <<8) + p[0]))
  17. #ifdef cmBIG_ENDIAN
  18. #define _cmAfSwap16(v) (v)
  19. #define _cmAfSwap32(v) (v)
  20. #define _cmAifSwapFl (0)
  21. #define _cmWavSwapFl (1)
  22. #else
  23. #define _cmAfSwap16(v) cmSwap16(v)
  24. #define _cmAfSwap32(v) cmSwap32(v)
  25. #define _cmAifSwapFl (1)
  26. #define _cmWavSwapFl (0)
  27. #endif
  28. enum
  29. {
  30. kAiffFileId = 'FORM',
  31. kAiffChkId = 'AIFF',
  32. kAifcChkId = 'AIFC',
  33. kSowtCompId = 'sowt',
  34. kNoneCompId = 'NONE',
  35. kWavFileId = 'FFIR',
  36. kWavChkId = 'EVAW',
  37. };
  38. enum { kWriteAudioGutsFl=0x01 };
  39. typedef struct
  40. {
  41. unsigned rc;
  42. const char* msg;
  43. } cmAudioErrRecd;
  44. typedef struct
  45. {
  46. cmErr_t err;
  47. FILE* fp; // file handle
  48. cmAudioFileInfo_t info; // audio file details
  49. unsigned curFrmIdx; // current frame offset
  50. unsigned fileByteCnt; // file byte cnt
  51. unsigned smpByteOffs; // byte offset of the first sample
  52. cmAudioFileMarker_t* markArray;
  53. unsigned flags;
  54. cmChar_t* fn;
  55. } cmAudioFileGuts;
  56. cmAudioErrRecd _cmAudioFileErrArray[] =
  57. {
  58. { kOkAfRC, "No Error." },
  59. { kOpenFailAfRC, "Audio file open failed."},
  60. { kReadFailAfRC, "Audio file read failed."},
  61. { kWriteFailAfRC, "Audio file write failed."},
  62. { kSeekFailAfRC, "Audio file seek failed."},
  63. { kCloseFailAfRC, "Audio file close failed."},
  64. { kNotAiffAfRC, "Not an audio file."},
  65. { kInvalidBitWidthAfRC, "Invalid audio file bit width."},
  66. { kInvalidFileModeAfRC, "Invalid audio file mode."},
  67. { kInvalidHandleAfRC, "Invalid audio file handle."},
  68. { kUnknownErrAfRC, "Uknown audio file error."}
  69. };
  70. cmAudioFileH_t cmNullAudioFileH = { NULL };
  71. cmAudioFileGuts* _cmAudioFileGutsPtr( cmAudioFileH_t h )
  72. {
  73. cmAudioFileGuts* p = (cmAudioFileGuts*)h.h;
  74. if( p == NULL )
  75. assert(p!=NULL);
  76. return p;
  77. }
  78. cmRC_t _cmAudioFileError( cmAudioFileGuts* p, cmRC_t rc )
  79. {
  80. if( rc > kUnknownErrAfRC )
  81. rc = kUnknownErrAfRC;
  82. cmErrMsg(&p->err,rc,"%s Error:%s",cmStringNullGuard(p->fn),_cmAudioFileErrArray[rc].msg);
  83. return rc;
  84. }
  85. cmAudioFileGuts* _cmAudioFileValidate( cmAudioFileH_t h, cmRC_t* rcPtr, bool writeFl )
  86. {
  87. *rcPtr = kOkAfRC;
  88. cmAudioFileGuts* p = _cmAudioFileGutsPtr(h);
  89. if( p == NULL )
  90. *rcPtr = kInvalidHandleAfRC;
  91. else
  92. if( cmIsFlag(p->flags,kWriteAudioGutsFl) != writeFl )
  93. *rcPtr = _cmAudioFileError( p, kInvalidFileModeAfRC );
  94. return *rcPtr == kOkAfRC ? p : NULL;
  95. }
  96. cmAudioFileGuts* _cmAudioFileReadGutsPtr( cmAudioFileH_t h, cmRC_t* rcPtr )
  97. { return _cmAudioFileValidate( h, rcPtr, false ); }
  98. cmAudioFileGuts* _cmAudioFileWriteGutsPtr( cmAudioFileH_t h, cmRC_t* rcPtr )
  99. { return _cmAudioFileValidate( h, rcPtr, true ); }
  100. cmRC_t _cmAudioFileSeek( cmAudioFileGuts* p, long byteOffset, int origin )
  101. {
  102. if( fseek(p->fp,byteOffset,origin) != 0 )
  103. return _cmAudioFileError(p,kSeekFailAfRC);
  104. return kOkAfRC;
  105. }
  106. cmRC_t _cmAudioFileRead( cmAudioFileGuts* p, void* eleBuf, unsigned bytesPerEle, unsigned eleCnt )
  107. {
  108. if( fread(eleBuf,bytesPerEle,eleCnt,p->fp) != eleCnt )
  109. return _cmAudioFileError(p,kReadFailAfRC);
  110. return kOkAfRC;
  111. }
  112. cmRC_t _cmAudioFileReadUInt32( cmAudioFileGuts* p, cmUInt32_t* valuePtr )
  113. {
  114. cmRC_t rc;
  115. if(( rc = _cmAudioFileRead(p, valuePtr, sizeof(*valuePtr), 1 )) != kOkAfRC )
  116. return rc;
  117. if( cmIsFlag(p->info.flags,kSwapAfFl) )
  118. *valuePtr = _cmAfSwap32(*valuePtr);
  119. return rc;
  120. }
  121. cmRC_t _cmAudioFileReadUInt16( cmAudioFileGuts* p, cmUInt16_t* valuePtr )
  122. {
  123. cmRC_t rc;
  124. if(( rc = _cmAudioFileRead(p, valuePtr, sizeof(*valuePtr), 1 )) != kOkAfRC )
  125. return rc;
  126. if( cmIsFlag(p->info.flags,kSwapAfFl) )
  127. *valuePtr = _cmAfSwap16(*valuePtr);
  128. return rc;
  129. }
  130. cmRC_t _cmAudioFileReadPascalString( cmAudioFileGuts* p, char s[kAudioFileLabelCharCnt] )
  131. {
  132. cmRC_t rc;
  133. unsigned char n;
  134. if((rc = _cmAudioFileRead(p,&n,sizeof(n),1)) != kOkAfRC )
  135. return rc;
  136. if((rc = _cmAudioFileRead(p,s,n,1)) != kOkAfRC )
  137. return rc;
  138. s[n] = '\0';
  139. if( n % 2 == 0 )
  140. rc = _cmAudioFileSeek(p,1,SEEK_CUR);
  141. return rc;
  142. }
  143. cmRC_t _cmAudioFileReadString( cmAudioFileGuts* p, char* s, unsigned sn )
  144. {
  145. cmRC_t rc;
  146. if((rc = _cmAudioFileRead(p,s,sn,1)) != kOkAfRC )
  147. return rc;
  148. return kOkAfRC;
  149. }
  150. cmRC_t _cmAudioFileReadX80( cmAudioFileGuts* p, double* x80Ptr )
  151. {
  152. unsigned char s[10];
  153. cmRC_t rc = kOkAfRC;
  154. if((rc = _cmAudioFileRead(p,s,10,1)) != kOkAfRC )
  155. return rc;
  156. *x80Ptr = cmX80ToDouble(s);
  157. return kOkAfRC;
  158. }
  159. cmRC_t _cmAudioFileReadChunkHdr( cmAudioFileGuts* p, cmUInt32_t* chkIdPtr, unsigned* chkByteCntPtr )
  160. {
  161. cmRC_t rc = kOkAfRC;
  162. *chkIdPtr = 0;
  163. *chkByteCntPtr = 0;
  164. if((rc = _cmAudioFileReadUInt32(p,chkIdPtr)) != kOkAfRC )
  165. return rc;
  166. if((rc = _cmAudioFileReadUInt32(p,chkByteCntPtr)) != kOkAfRC )
  167. return rc;
  168. // the actual on disk chunk size is always incrmented up to the next even integer
  169. *chkByteCntPtr += (*chkByteCntPtr) % 2;
  170. return rc;
  171. }
  172. cmRC_t _cmAudioFileReadAiffHeader( cmAudioFileGuts* p, unsigned constFormId, unsigned constAifId, bool swapFl )
  173. {
  174. cmRC_t rc = kOkAfRC;
  175. cmUInt32_t formId = 0;
  176. cmUInt32_t aifId = 0;
  177. unsigned chkByteCnt = 0;
  178. p->info.flags = 0;
  179. p->curFrmIdx = 0;
  180. p->fileByteCnt = 0;
  181. if((rc = _cmAudioFileSeek(p,0,SEEK_SET)) != kOkAfRC )
  182. return rc;
  183. // set the swap flags
  184. p->info.flags = cmEnaFlag(p->info.flags,kSwapAfFl, swapFl);
  185. p->info.flags = cmEnaFlag(p->info.flags,kSwapSamplesAfFl,swapFl);
  186. if((rc = _cmAudioFileReadChunkHdr(p,&formId,&p->fileByteCnt)) != kOkAfRC )
  187. return rc;
  188. //
  189. // use -Wno-multichar on GCC cmd line to disable the multi-char warning
  190. //
  191. // check the FORM/RIFF id
  192. if( formId != constFormId )
  193. return kNotAiffAfRC;
  194. // read the AIFF/WAVE id
  195. if((rc = _cmAudioFileReadChunkHdr(p,&aifId,&chkByteCnt)) != kOkAfRC )
  196. return rc;
  197. // check for the AIFC
  198. if( formId == kAiffFileId && aifId != constAifId )
  199. {
  200. if( aifId == kAifcChkId )
  201. p->info.flags = cmSetFlag(p->info.flags,kAifcAfFl);
  202. else
  203. return kNotAiffAfRC;
  204. }
  205. // set the audio file type flag
  206. if( aifId==kAiffChkId || aifId==kAifcChkId )
  207. p->info.flags = cmSetFlag(p->info.flags,kAiffAfFl);
  208. if( aifId==kWavChkId )
  209. p->info.flags = cmSetFlag(p->info.flags,kWavAfFl);
  210. return rc;
  211. }
  212. cmRC_t _cmAudioFileReadCommChunk( cmAudioFileGuts* p )
  213. {
  214. cmRC_t rc = kOkAfRC;
  215. cmUInt16_t ui16;
  216. cmUInt32_t ui32;
  217. if((rc = _cmAudioFileReadUInt16(p,&ui16)) != kOkAfRC )
  218. return rc;
  219. p->info.chCnt = ui16;
  220. if((rc = _cmAudioFileReadUInt32(p,&ui32)) != kOkAfRC )
  221. return rc;
  222. p->info.frameCnt = ui32;
  223. if((rc = _cmAudioFileReadUInt16(p,&ui16)) != kOkAfRC )
  224. return rc;
  225. p->info.bits = ui16;
  226. if((rc = _cmAudioFileReadX80(p,&p->info.srate)) != kOkAfRC )
  227. return rc;
  228. // if this is an AIFC format file ...
  229. if( cmIsFlag(p->info.flags,kAifcAfFl) )
  230. {
  231. if((rc = _cmAudioFileReadUInt32(p,&ui32)) != kOkAfRC )
  232. return rc;
  233. switch( ui32 )
  234. {
  235. case kNoneCompId:
  236. break;
  237. case kSowtCompId:
  238. // If the compression type is set to 'swot'
  239. // then the samples are written in little-endian (Intel) format
  240. // rather than the default big-endian format.
  241. p->info.flags = cmTogFlag(p->info.flags,kSwapSamplesAfFl);
  242. break;
  243. default:
  244. rc = _cmAudioFileError(p,kNotAiffAfRC );
  245. }
  246. }
  247. return rc;
  248. }
  249. cmRC_t _cmAudioFileReadSsndChunk( cmAudioFileGuts* p )
  250. {
  251. cmRC_t rc = kOkAfRC;
  252. cmUInt32_t smpOffs=0, smpBlkSize=0;
  253. if((rc = _cmAudioFileReadUInt32(p,&smpOffs)) != kOkAfRC )
  254. return rc;
  255. if((rc = _cmAudioFileReadUInt32(p,&smpBlkSize)) != kOkAfRC )
  256. return rc;
  257. if((rc = _cmAudioFileSeek(p,smpOffs, SEEK_CUR)) != kOkAfRC )
  258. return rc;
  259. p->smpByteOffs = ftell(p->fp);
  260. return rc;
  261. }
  262. cmRC_t _cmAudioFileReadMarkerChunk( cmAudioFileGuts* p )
  263. {
  264. cmRC_t rc = kOkAfRC;
  265. cmUInt16_t ui16;
  266. cmUInt32_t ui32;
  267. unsigned i;
  268. if((rc = _cmAudioFileReadUInt16(p,&ui16)) != kOkAfRC )
  269. return rc;
  270. p->info.markerCnt = ui16;
  271. assert(p->markArray == NULL);
  272. cmAudioFileMarker_t* m = cmMemAllocZ(cmAudioFileMarker_t,p->info.markerCnt);
  273. p->info.markerArray = m;
  274. for(i=0; i<p->info.markerCnt; ++i)
  275. {
  276. if((rc = _cmAudioFileReadUInt16(p,&ui16)) != kOkAfRC )
  277. return rc;
  278. m[i].id = ui16;
  279. if((rc = _cmAudioFileReadUInt32(p,&ui32)) != kOkAfRC )
  280. return rc;
  281. m[i].frameIdx = ui32;
  282. if((rc = _cmAudioFileReadPascalString(p,m[i].label)) != kOkAfRC )
  283. return rc;
  284. }
  285. return rc;
  286. }
  287. cmRC_t _cmAudioFileReadFmtChunk( cmAudioFileGuts* p )
  288. {
  289. cmRC_t rc = kOkAfRC;
  290. unsigned short fmtId, chCnt, blockAlign, bits;
  291. unsigned srate, bytesPerSec;
  292. if((rc = _cmAudioFileReadUInt16(p,&fmtId)) != kOkAfRC )
  293. return rc;
  294. if((rc = _cmAudioFileReadUInt16(p,&chCnt)) != kOkAfRC )
  295. return rc;
  296. if((rc = _cmAudioFileReadUInt32(p,&srate)) != kOkAfRC )
  297. return rc;
  298. if((rc = _cmAudioFileReadUInt32(p,&bytesPerSec)) != kOkAfRC )
  299. return rc;
  300. if((rc = _cmAudioFileReadUInt16(p,&blockAlign)) != kOkAfRC )
  301. return rc;
  302. if((rc = _cmAudioFileReadUInt16(p,&bits)) != kOkAfRC )
  303. return rc;
  304. p->info.chCnt = chCnt;
  305. p->info.bits = bits;
  306. p->info.srate = srate;
  307. // if the 'data' chunk was read before the 'fmt' chunk then info.frameCnt
  308. // holds the number of bytes in the data chunk
  309. if( p->info.frameCnt != 0 )
  310. p->info.frameCnt = p->info.frameCnt / (p->info.chCnt * p->info.bits/8);
  311. return rc;
  312. }
  313. cmRC_t _cmAudioFileReadDatcmhunk( cmAudioFileGuts* p, unsigned chkByteCnt )
  314. {
  315. // if the 'fmt' chunk was read before the 'data' chunk then info.chCnt is non-zero
  316. if( p->info.chCnt != 0 )
  317. p->info.frameCnt = chkByteCnt / (p->info.chCnt * p->info.bits/8);
  318. else
  319. p->info.frameCnt = chkByteCnt;
  320. p->smpByteOffs = ftell(p->fp);
  321. return kOkAfRC;
  322. }
  323. cmRC_t _cmAudioFileReadBextChunk( cmAudioFileGuts* p)
  324. {
  325. cmRC_t rc = kOkAfRC;
  326. if((rc = _cmAudioFileReadString(p,p->info.bextRecd.desc,kAfBextDescN)) != kOkAfRC )
  327. return rc;
  328. if((rc = _cmAudioFileReadString(p,p->info.bextRecd.origin,kAfBextOriginN)) != kOkAfRC )
  329. return rc;
  330. if((rc = _cmAudioFileReadString(p,p->info.bextRecd.originRef,kAfBextOriginRefN)) != kOkAfRC )
  331. return rc;
  332. if((rc = _cmAudioFileReadString(p,p->info.bextRecd.originDate,kAfBextOriginDateN)) != kOkAfRC )
  333. return rc;
  334. if((rc = _cmAudioFileReadString(p,p->info.bextRecd.originTime,kAfBextOriginTimeN)) != kOkAfRC )
  335. return rc;
  336. if((rc = _cmAudioFileReadUInt32(p,&p->info.bextRecd.timeRefLow)) != kOkAfRC )
  337. return rc;
  338. if((rc = _cmAudioFileReadUInt32(p,&p->info.bextRecd.timeRefHigh)) != kOkAfRC )
  339. return rc;
  340. return rc;
  341. }
  342. cmAudioFileH_t cmAudioFileNewOpen( const cmChar_t* fn, cmAudioFileInfo_t* afInfoPtr, cmRC_t* rcPtr, cmRpt_t* rpt )
  343. {
  344. cmAudioFileH_t h;
  345. cmRC_t rc = kOkAfRC;
  346. h.h = cmMemAllocZ( cmAudioFileGuts, 1 );
  347. cmErrSetup(&((cmAudioFileGuts*)h.h)->err,rpt,"Audio File");
  348. if( fn != NULL )
  349. if((rc = cmAudioFileOpen(h,fn,afInfoPtr)) != kOkAfRC )
  350. {
  351. if( rcPtr != NULL )
  352. *rcPtr = rc;
  353. cmAudioFileDelete(&h);
  354. }
  355. if( rcPtr != NULL )
  356. *rcPtr = rc;
  357. return h;
  358. }
  359. cmAudioFileH_t cmAudioFileNewCreate( const cmChar_t* fn, double srate, unsigned bits, unsigned chCnt, cmRC_t* rcPtr, cmRpt_t* rpt )
  360. {
  361. cmAudioFileH_t h;
  362. cmRC_t rc = kOkAfRC;
  363. h.h = cmMemAllocZ(cmAudioFileGuts,1);
  364. cmErrSetup(&((cmAudioFileGuts*)h.h)->err,rpt,"Audio File");
  365. if( fn != NULL )
  366. if((rc = cmAudioFileCreate(h,fn,srate,bits,chCnt)) != kOkAfRC )
  367. {
  368. if( rcPtr != NULL )
  369. *rcPtr = rc;
  370. cmAudioFileDelete(&h);
  371. }
  372. if( rcPtr != NULL )
  373. *rcPtr = rc;
  374. return h;
  375. }
  376. cmRC_t cmAudioFileOpen( cmAudioFileH_t h, const cmChar_t* fn, cmAudioFileInfo_t* infoPtr )
  377. {
  378. cmRC_t rc = kOkAfRC;
  379. cmAudioFileGuts* p = _cmAudioFileGutsPtr(h);
  380. // verify the file is closed before opening
  381. if( cmAudioFileIsOpen(h) )
  382. if((rc = cmAudioFileClose(&h)) != kOkAfRC )
  383. return rc;
  384. // zero the info record
  385. memset(&p->info,0,sizeof(p->info));
  386. // open the file
  387. if((p->fp = fopen(fn,"rb")) == NULL )
  388. {
  389. p->fn = (cmChar_t*)fn; // set the file name so that the error msg can use it
  390. rc = _cmAudioFileError(p,kOpenFailAfRC);
  391. p->fn = NULL;
  392. goto errLabel;
  393. }
  394. // read the file header
  395. if((rc = _cmAudioFileReadAiffHeader(p,kAiffFileId,kAiffChkId,_cmAifSwapFl)) != kOkAfRC )
  396. if((rc = _cmAudioFileReadAiffHeader(p,kWavFileId,kWavChkId,_cmWavSwapFl)) != kOkAfRC )
  397. goto errLabel;
  398. // seek past the file header
  399. if((rc = _cmAudioFileSeek(p,12,SEEK_SET)) != kOkAfRC )
  400. goto errLabel;
  401. // zero chCnt and frameCnt to allow the order of the 'data' and 'fmt' chunks to be noticed
  402. p->info.chCnt = 0;
  403. p->info.frameCnt = 0;
  404. while( ftell(p->fp ) < p->fileByteCnt )
  405. {
  406. unsigned chkId, chkByteCnt;
  407. if((rc = _cmAudioFileReadChunkHdr(p,&chkId,&chkByteCnt)) != kOkAfRC )
  408. goto errLabel;
  409. unsigned offs = ftell(p->fp);
  410. if( cmIsFlag(p->info.flags,kAiffAfFl) )
  411. switch(chkId)
  412. {
  413. case 'COMM':
  414. if((rc = _cmAudioFileReadCommChunk(p)) != kOkAfRC )
  415. goto errLabel;
  416. break;
  417. case 'SSND':
  418. if((rc = _cmAudioFileReadSsndChunk(p)) != kOkAfRC )
  419. goto errLabel;
  420. break;
  421. case 'MARK':
  422. if((rc = _cmAudioFileReadMarkerChunk(p)) != kOkAfRC )
  423. goto errLabel;
  424. break;
  425. }
  426. else
  427. switch(chkId)
  428. {
  429. case ' tmf':
  430. if((rc = _cmAudioFileReadFmtChunk(p)) != kOkAfRC )
  431. goto errLabel;
  432. break;
  433. case 'atad':
  434. if((rc = _cmAudioFileReadDatcmhunk(p,chkByteCnt)) != kOkAfRC )
  435. goto errLabel;
  436. break;
  437. case 'txeb':
  438. if((rc = _cmAudioFileReadBextChunk(p)) != kOkAfRC )
  439. goto errLabel;
  440. break;
  441. }
  442. // seek to the end of this chunk
  443. if((rc = _cmAudioFileSeek(p,offs+chkByteCnt,SEEK_SET)) != kOkAfRC )
  444. goto errLabel;
  445. }
  446. // seek to the first sample offset
  447. if((rc = _cmAudioFileSeek(p,p->smpByteOffs,SEEK_SET)) != kOkAfRC )
  448. goto errLabel;
  449. p->fn = cmMemResize( char, p->fn, strlen(fn)+1 );
  450. strcpy(p->fn,fn);
  451. if( infoPtr != NULL)
  452. memcpy(infoPtr,&p->info,sizeof(*infoPtr));
  453. return rc;
  454. errLabel:
  455. cmAudioFileClose(&h);
  456. return rc;
  457. }
  458. cmRC_t _cmAudioFileWriteBytes( cmAudioFileGuts* p, const void* b, unsigned bn )
  459. {
  460. cmRC_t rc = kOkAfRC;
  461. if( fwrite( b, bn, 1, p->fp ) != 1 )
  462. return _cmAudioFileError(p,kWriteFailAfRC);
  463. return rc;
  464. }
  465. cmRC_t _cmAudioFileWriteId( cmAudioFileGuts* p, const char* s )
  466. { return _cmAudioFileWriteBytes( p, s, strlen(s)) ; }
  467. cmRC_t _cmAudioFileWriteUInt32( cmAudioFileGuts* p, unsigned v )
  468. {
  469. v = _cmAfSwap32(v);
  470. return _cmAudioFileWriteBytes( p, &v, sizeof(v)) ;
  471. }
  472. cmRC_t _cmAudioFileWriteUInt16( cmAudioFileGuts* p, unsigned short v )
  473. {
  474. v = _cmAfSwap16(v);
  475. return _cmAudioFileWriteBytes( p, &v, sizeof(v)) ;
  476. }
  477. cmRC_t _cmAudioFileWriteHdr( cmAudioFileGuts* p )
  478. {
  479. cmRC_t rc = kOkAfRC;
  480. unsigned char srateX80[10];
  481. cmDoubleToX80( p->info.srate, srateX80 );
  482. unsigned hdrByteCnt = 54;
  483. unsigned ssndByteCnt = 8 + (p->info.chCnt * p->info.frameCnt * (p->info.bits/8));
  484. unsigned formByteCnt = hdrByteCnt + ssndByteCnt - 8;
  485. unsigned commByteCnt = 18;
  486. unsigned ssndSmpOffs = 0;
  487. unsigned ssndBlkSize = 0;
  488. if( cmIsOddU( ssndByteCnt ) )
  489. {
  490. formByteCnt++;
  491. }
  492. if(( rc = _cmAudioFileSeek( p, 0, SEEK_SET )) != kOkAfRC )
  493. return rc;
  494. if(( rc = _cmAudioFileWriteId( p, "FORM")) != kOkAfRC ) return rc;
  495. if(( rc = _cmAudioFileWriteUInt32( p, formByteCnt)) != kOkAfRC ) return rc;
  496. if(( rc = _cmAudioFileWriteId( p, "AIFF")) != kOkAfRC ) return rc;
  497. if(( rc = _cmAudioFileWriteId( p, "COMM")) != kOkAfRC ) return rc;
  498. if(( rc = _cmAudioFileWriteUInt32( p, commByteCnt)) != kOkAfRC ) return rc;
  499. if(( rc = _cmAudioFileWriteUInt16( p, p->info.chCnt)) != kOkAfRC ) return rc;
  500. if(( rc = _cmAudioFileWriteUInt32( p, p->info.frameCnt)) != kOkAfRC ) return rc;
  501. if(( rc = _cmAudioFileWriteUInt16( p, p->info.bits)) != kOkAfRC ) return rc;
  502. if(( rc = _cmAudioFileWriteBytes( p, &srateX80,10)) != kOkAfRC ) return rc;
  503. if(( rc = _cmAudioFileWriteId( p, "SSND")) != kOkAfRC ) return rc;
  504. if(( rc = _cmAudioFileWriteUInt32( p, ssndByteCnt)) != kOkAfRC ) return rc;
  505. if(( rc = _cmAudioFileWriteUInt32( p, ssndSmpOffs)) != kOkAfRC ) return rc;
  506. if(( rc = _cmAudioFileWriteUInt32( p, ssndBlkSize)) != kOkAfRC ) return rc;
  507. return rc;
  508. }
  509. cmRC_t cmAudioFileCreate( cmAudioFileH_t h, const cmChar_t* fn, double srate, unsigned bits, unsigned chCnt )
  510. {
  511. cmRC_t rc = kOkAfRC;
  512. cmAudioFileGuts* p = _cmAudioFileGutsPtr(h);
  513. cmFileSysPathPart_t* pp = NULL;
  514. // verify the file is closed before opening
  515. if( cmAudioFileIsOpen(h) )
  516. if((rc = cmAudioFileClose(&h)) != kOkAfRC )
  517. return rc;
  518. // all audio files are written as AIF's - if the file name is given some other extension then issue a warning
  519. if( strlen(fn) && ((pp = cmFsPathParts(fn)) != NULL) )
  520. {
  521. unsigned i;
  522. unsigned n = strlen(pp->extStr);
  523. cmChar_t ext[n+1];
  524. strcpy(ext,pp->extStr);
  525. // convert the extension to upper case
  526. for(i=0; i<n; ++i)
  527. ext[i] = toupper(ext[i]);
  528. if( strcmp(ext,"AIF") && strcmp(ext,"AIFF") )
  529. cmRptPrintf(p->err.rpt,"The AIF audio file '%s' is being written with a file extension other than 'AIF' or 'AIFF'.",cmStringNullGuard(fn));
  530. cmFsFreePathParts(pp);
  531. }
  532. // open the file
  533. if((p->fp = fopen(fn,"wb")) == NULL )
  534. {
  535. p->fn = (cmChar_t*)fn; // set the file name so that the error msg can use it
  536. rc = _cmAudioFileError(p,kOpenFailAfRC);
  537. p->fn = NULL;
  538. goto errLabel;
  539. }
  540. p->fn = cmMemResize( char, p->fn, strlen(fn)+1 );
  541. p->info.srate = srate;
  542. p->info.bits = bits;
  543. p->info.chCnt = chCnt;
  544. p->info.frameCnt = 0;
  545. p->flags = kWriteAudioGutsFl;
  546. strcpy(p->fn,fn);
  547. if((rc = _cmAudioFileWriteHdr( p )) != kOkAfRC )
  548. goto errLabel;
  549. return rc;
  550. errLabel:
  551. cmAudioFileClose(&h);
  552. return rc;
  553. }
  554. cmRC_t cmAudioFileClose( cmAudioFileH_t* h )
  555. {
  556. assert( h != NULL);
  557. cmAudioFileGuts* p = _cmAudioFileGutsPtr(*h);
  558. cmRC_t rc = kOkAfRC;
  559. if( p->fp == NULL )
  560. return kOkAfRC;
  561. if( cmIsFlag( p->flags, kWriteAudioGutsFl ) )
  562. if((rc = _cmAudioFileWriteHdr(p)) != kOkAfRC )
  563. return rc;
  564. if( fclose(p->fp) != 0 )
  565. rc = _cmAudioFileError(p,kCloseFailAfRC);
  566. else
  567. {
  568. p->fp = NULL;
  569. cmMemPtrFree( &(p->info.markerArray));
  570. memset(&p->info,0,sizeof(p->info));
  571. }
  572. return rc;
  573. }
  574. cmRC_t cmAudioFileDelete( cmAudioFileH_t* h)
  575. {
  576. assert(h!=NULL);
  577. cmRC_t rc = kOkAfRC;
  578. // prevent double deletes
  579. if( h->h == NULL )
  580. return kOkAfRC;
  581. cmAudioFileGuts* p = _cmAudioFileGutsPtr(*h);
  582. if( p->fp != NULL )
  583. rc = cmAudioFileClose(h);
  584. cmMemPtrFree(&p->fn);
  585. cmMemPtrFree(&(h->h));
  586. return rc;
  587. }
  588. bool cmAudioFileIsValid( cmAudioFileH_t h )
  589. { return h.h != NULL; }
  590. bool cmAudioFileIsOpen( cmAudioFileH_t h )
  591. {
  592. if( !cmAudioFileIsValid(h) )
  593. return false;
  594. return _cmAudioFileGutsPtr(h)->fp != NULL;
  595. }
  596. bool cmAudioFileIsEOF( cmAudioFileH_t h )
  597. {
  598. cmRC_t rc = kOkAfRC;
  599. cmAudioFileGuts* p = _cmAudioFileReadGutsPtr(h,&rc);
  600. return (rc != kOkAfRC) || (p==NULL) || (p->curFrmIdx >= p->info.frameCnt) || (p->fp==NULL) || feof(p->fp) ? true : false;
  601. }
  602. unsigned cmAudioFileTell( cmAudioFileH_t h )
  603. {
  604. cmRC_t rc = kOkAfRC;
  605. cmAudioFileGuts* p = _cmAudioFileReadGutsPtr(h,&rc);
  606. return (rc==kOkAfRC && p!=NULL) ? p->curFrmIdx : cmInvalidIdx;
  607. }
  608. cmRC_t cmAudioFileSeek( cmAudioFileH_t h, unsigned frmIdx )
  609. {
  610. cmRC_t rc = kOkAfRC;
  611. cmAudioFileGuts* p = _cmAudioFileReadGutsPtr(h,&rc);
  612. if( rc != kOkAfRC )
  613. return rc;
  614. if((rc = _cmAudioFileSeek(p,p->smpByteOffs + (frmIdx * p->info.chCnt * (p->info.bits/8)), SEEK_SET)) != kOkAfRC )
  615. return rc;
  616. p->curFrmIdx = frmIdx;
  617. return rc;
  618. }
  619. cmRC_t _cmAudioFileReadInt( cmAudioFileH_t h, unsigned totalFrmCnt, unsigned chIdx, unsigned chCnt, int* buf[], unsigned* actualFrmCntPtr, bool sumFl )
  620. {
  621. cmRC_t rc = kOkAfRC;
  622. cmAudioFileGuts* p = _cmAudioFileReadGutsPtr(h,&rc);
  623. if( rc != kOkAfRC )
  624. return rc;
  625. if( actualFrmCntPtr != NULL )
  626. *actualFrmCntPtr = 0;
  627. unsigned bps = p->info.bits / 8; // bytes per sample
  628. unsigned bpf = bps * p->info.chCnt; // bytes per file frame
  629. unsigned bufFrmCnt = cmMin(totalFrmCnt,cmAudioFile_MAX_FRAME_READ_CNT);
  630. unsigned bytesPerBuf = bufFrmCnt * bpf;
  631. unsigned char fbuf[ bytesPerBuf ]; // raw bytes buffer
  632. unsigned ci;
  633. unsigned frmCnt = 0;
  634. unsigned totalReadFrmCnt;
  635. int* ptrBuf[ chCnt ];
  636. for(ci=0; ci<chCnt; ++ci)
  637. ptrBuf[ci] = buf[ci];
  638. for(totalReadFrmCnt=0; totalReadFrmCnt<totalFrmCnt; totalReadFrmCnt+=frmCnt )
  639. {
  640. // don't read past the end of the file or past the end of the buffer
  641. frmCnt = cmMin( p->info.frameCnt - p->curFrmIdx, cmMin( totalFrmCnt-totalReadFrmCnt, bufFrmCnt ));
  642. // read the file frmCnt sample
  643. if((rc = _cmAudioFileRead(p,fbuf,frmCnt*bpf,1)) != kOkAfRC )
  644. return rc;
  645. if( actualFrmCntPtr != NULL )
  646. *actualFrmCntPtr += frmCnt;
  647. assert( chIdx+chCnt <= p->info.chCnt );
  648. for(ci=0; ci<chCnt; ++ci)
  649. {
  650. unsigned char* sp = fbuf + (ci+chIdx)*bps;
  651. int* dp = ptrBuf[ci];
  652. int* ep = dp + frmCnt;
  653. if( !sumFl )
  654. memset(dp,0,frmCnt*sizeof(int));
  655. // 8 bit AIF files use 'signed char' and WAV files use 'unsigned char' for the sample data type.
  656. if( p->info.bits == 8 )
  657. {
  658. if( cmIsFlag(p->info.flags,kAiffAfFl) )
  659. {
  660. for(; dp<ep; sp+=bpf,++dp)
  661. *dp += *(char*)sp;
  662. }
  663. else
  664. {
  665. for(; dp<ep; sp+=bpf,++dp)
  666. {
  667. int v = *(unsigned char*)sp;
  668. *dp += v -= 128;
  669. }
  670. }
  671. }
  672. // handle non-8 bit files here
  673. if( cmIsFlag(p->info.flags,kSwapSamplesAfFl) )
  674. {
  675. switch( p->info.bits )
  676. {
  677. case 8:
  678. break;
  679. case 16:
  680. for(; dp<ep; sp+=bpf,++dp)
  681. *dp += (short)_cmAfSwap16(*(short*)sp);
  682. break;
  683. case 24:
  684. if( cmIsFlag(p->info.flags,kAiffAfFl) )
  685. {
  686. for(; dp<ep; sp+=bpf,++dp)
  687. *dp += (int)(_cmAfSwap32(_24to32_aif(sp)));
  688. }
  689. else
  690. {
  691. for(; dp<ep; sp+=bpf,++dp)
  692. *dp += (int)(_cmAfSwap32(_24to32_wav(sp)));
  693. }
  694. break;
  695. case 32:
  696. for(; dp<ep; sp+=bpf,++dp)
  697. *dp += (int)_cmAfSwap32(*(int*)sp );
  698. break;
  699. }
  700. }
  701. else
  702. {
  703. switch(p->info.bits)
  704. {
  705. case 8:
  706. break;
  707. case 16:
  708. for(; dp<ep; sp+=bpf,++dp)
  709. *dp += *(short*)sp;
  710. break;
  711. case 24:
  712. if( cmIsFlag(p->info.flags,kAiffAfFl) )
  713. {
  714. for(; dp<ep; sp+=bpf,++dp)
  715. *dp += _24to32_aif(sp);
  716. }
  717. else
  718. {
  719. for(; dp<ep; sp+=bpf,++dp)
  720. *dp += _24to32_wav(sp);
  721. }
  722. break;
  723. case 32:
  724. for(; dp<ep; sp+=bpf,++dp)
  725. *dp += *(int*)sp;
  726. break;
  727. }
  728. ptrBuf[ci] = dp;
  729. assert( dp <= buf[ci] + totalFrmCnt );
  730. }
  731. /*
  732. dp = ptrBuf[ci];
  733. ep = dp + frmCnt;
  734. while(dp<ep)
  735. sum += (double)*dp++;
  736. */
  737. }
  738. p->curFrmIdx += frmCnt;
  739. }
  740. if( totalReadFrmCnt < totalFrmCnt )
  741. {
  742. for(ci=0; ci<chCnt; ++ci)
  743. memset(buf[ci] + frmCnt,0,(totalFrmCnt-totalReadFrmCnt)*sizeof(int));
  744. }
  745. //if( actualFrmCntPtr != NULL )
  746. // *actualFrmCntPtr = totalReadFrmCnt;
  747. //printf("SUM: %f %f swap:%i\n", sum, sum/(totalFrmCnt*chCnt), cmIsFlag(p->info.flags,kSwapAfFl));
  748. return rc;
  749. }
  750. cmRC_t _cmAudioFileReadRealSamples( cmAudioFileH_t h, unsigned totalFrmCnt, unsigned chIdx, unsigned chCnt, float** fbuf, double** dbuf, unsigned* actualFrmCntPtr, bool sumFl )
  751. {
  752. cmRC_t rc = kOkAfRC;
  753. cmAudioFileGuts* p = _cmAudioFileReadGutsPtr(h,&rc);
  754. if( rc != kOkAfRC )
  755. return rc;
  756. if( actualFrmCntPtr != NULL )
  757. *actualFrmCntPtr = 0;
  758. unsigned totalReadCnt = 0;
  759. unsigned bufFrmCnt = cmMin( totalFrmCnt, cmAudioFile_MAX_FRAME_READ_CNT );
  760. unsigned bufSmpCnt = bufFrmCnt * chCnt;
  761. float fltMaxSmpVal = 0;
  762. int buf[ bufSmpCnt ];
  763. int* ptrBuf[ chCnt ];
  764. float* fPtrBuf[ chCnt ];
  765. double* dPtrBuf[ chCnt ];
  766. unsigned i;
  767. unsigned frmCnt = 0;
  768. switch( p->info.bits )
  769. {
  770. case 8: fltMaxSmpVal = 0x80; break;
  771. case 16: fltMaxSmpVal = 0x8000; break;
  772. case 24: fltMaxSmpVal = 0x800000; break;
  773. case 32: fltMaxSmpVal = 0x80000000; break;
  774. default:
  775. return _cmAudioFileError(p,kInvalidBitWidthAfRC);
  776. }
  777. double dblMaxSmpVal = fltMaxSmpVal;
  778. // initialize the audio ptr buffers
  779. for(i=0; i<chCnt; ++i)
  780. {
  781. ptrBuf[i] = buf + (i*bufFrmCnt);
  782. if( dbuf != NULL )
  783. dPtrBuf[i] = dbuf[i];
  784. if( fbuf != NULL )
  785. fPtrBuf[i] = fbuf[i];
  786. }
  787. //
  788. for(totalReadCnt=0; totalReadCnt<totalFrmCnt && p->curFrmIdx < p->info.frameCnt; totalReadCnt+=frmCnt)
  789. {
  790. unsigned actualReadFrmCnt = 0;
  791. frmCnt = cmMin( p->info.frameCnt - p->curFrmIdx, cmMin( totalFrmCnt-totalReadCnt, bufFrmCnt ) );
  792. // fill the integer audio buffer from the file
  793. if((rc = _cmAudioFileReadInt( h, frmCnt, chIdx, chCnt, ptrBuf, &actualReadFrmCnt, false )) != kOkAfRC )
  794. return rc;
  795. if( actualFrmCntPtr != NULL )
  796. *actualFrmCntPtr += actualReadFrmCnt;
  797. // convert the integer buffer to floating point
  798. for(i=0; i<chCnt; ++i)
  799. {
  800. int* sp = ptrBuf[i];
  801. if( fbuf != NULL )
  802. {
  803. float* dp = fPtrBuf[i];
  804. float* ep = dp + frmCnt;
  805. if( sumFl )
  806. {
  807. for(; dp<ep; ++dp,++sp)
  808. *dp += ((float)*sp) / fltMaxSmpVal;
  809. }
  810. else
  811. {
  812. for(; dp<ep; ++dp,++sp)
  813. *dp = ((float)*sp) / fltMaxSmpVal;
  814. }
  815. assert( dp <= fbuf[i] + totalFrmCnt );
  816. fPtrBuf[i] = dp;
  817. }
  818. else
  819. {
  820. double* dp = dPtrBuf[i];
  821. double* ep = dp + frmCnt;
  822. if( sumFl )
  823. {
  824. for(; dp<ep; ++dp,++sp)
  825. *dp += ((double)*sp) / dblMaxSmpVal;
  826. }
  827. else
  828. {
  829. for(; dp<ep; ++dp,++sp)
  830. *dp = ((double)*sp) / dblMaxSmpVal;
  831. }
  832. assert( dp <= dbuf[i] + totalFrmCnt );
  833. dPtrBuf[i] = dp;
  834. }
  835. }
  836. }
  837. return rc;
  838. }
  839. cmRC_t _cmAudioFileReadFloat( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr, bool sumFl )
  840. {
  841. return _cmAudioFileReadRealSamples(h,frmCnt,chIdx,chCnt,buf, NULL, actualFrmCntPtr, sumFl );
  842. }
  843. cmRC_t _cmAudioFileReadDouble( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr, bool sumFl )
  844. {
  845. return _cmAudioFileReadRealSamples(h,frmCnt,chIdx,chCnt,NULL, buf, actualFrmCntPtr, sumFl );
  846. }
  847. cmRC_t cmAudioFileReadInt( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr )
  848. { return _cmAudioFileReadInt( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, false ); }
  849. cmRC_t cmAudioFileReadFloat( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr )
  850. { return _cmAudioFileReadFloat( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, false ); }
  851. cmRC_t cmAudioFileReadDouble( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr )
  852. { return _cmAudioFileReadDouble( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, false ); }
  853. cmRC_t cmAudioFileReadSumInt( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr )
  854. { return _cmAudioFileReadInt( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, true ); }
  855. cmRC_t cmAudioFileReadSumFloat( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr )
  856. { return _cmAudioFileReadFloat( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, true ); }
  857. cmRC_t cmAudioFileReadSumDouble( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr )
  858. { return _cmAudioFileReadDouble( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, true ); }
  859. cmRC_t _cmAudioFileGet( const char* fn, unsigned begFrmIdx, cmAudioFileH_t* hp, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  860. {
  861. cmRC_t rc = kOkAfRC;
  862. *hp = cmAudioFileNewOpen( fn, afInfoPtr, &rc, rpt );
  863. if( (cmAudioFileIsValid(*hp)==false) || (rc!=kOkAfRC) )
  864. return rc;
  865. if( begFrmIdx > 0 )
  866. if((rc = cmAudioFileSeek( *hp, begFrmIdx )) != kOkAfRC )
  867. cmAudioFileDelete(hp);
  868. return rc;
  869. }
  870. cmRC_t _cmAudioFileGetInt( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, bool sumFl, cmRpt_t* rpt )
  871. {
  872. cmRC_t rc0,rc1;
  873. cmAudioFileH_t h;
  874. if((rc0 = _cmAudioFileGet(fn,begFrmIdx,&h,afInfoPtr,rpt)) != kOkAfRC )
  875. return rc0;
  876. rc0 = _cmAudioFileReadInt(h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, sumFl );
  877. if((rc1=cmAudioFileDelete(&h)) != kOkAfRC && rc0==kOkAfRC )
  878. rc0 = rc1;
  879. return rc0;
  880. }
  881. cmRC_t _cmAudioFileGetFloat( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, bool sumFl, cmRpt_t* rpt )
  882. {
  883. cmRC_t rc0,rc1;
  884. cmAudioFileH_t h;
  885. if((rc0 = _cmAudioFileGet(fn,begFrmIdx,&h,afInfoPtr,rpt)) != kOkAfRC )
  886. return rc0;
  887. rc0 = _cmAudioFileReadFloat(h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, sumFl );
  888. if((rc1=cmAudioFileDelete(&h)) != kOkAfRC && rc0==kOkAfRC )
  889. rc0 = rc1;
  890. return rc0;
  891. }
  892. cmRC_t _cmAudioFileGetDouble( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, bool sumFl, cmRpt_t* rpt )
  893. {
  894. cmRC_t rc0,rc1;
  895. cmAudioFileH_t h;
  896. if((rc0 = _cmAudioFileGet(fn,begFrmIdx,&h,afInfoPtr,rpt)) != kOkAfRC )
  897. return rc0;
  898. rc0 = _cmAudioFileReadDouble(h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, sumFl );
  899. if((rc1=cmAudioFileDelete(&h)) != kOkAfRC && rc0==kOkAfRC )
  900. rc0 = rc1;
  901. return rc0;
  902. }
  903. cmRC_t cmAudioFileGetInt( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  904. { return _cmAudioFileGetInt( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, false, rpt ); }
  905. cmRC_t cmAudioFileGetFloat( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  906. { return _cmAudioFileGetFloat( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, false, rpt ); }
  907. cmRC_t cmAudioFileGetDouble( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  908. { return _cmAudioFileGetDouble( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, false, rpt); }
  909. cmRC_t cmAudioFileGetSumInt( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  910. { return _cmAudioFileGetInt( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, true, rpt ); }
  911. cmRC_t cmAudioFileGetSumFloat( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  912. { return _cmAudioFileGetFloat( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, true, rpt ); }
  913. cmRC_t cmAudioFileGetSumDouble( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  914. { return _cmAudioFileGetDouble( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, true, rpt); }
  915. cmRC_t cmAudioFileWriteInt( cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, int** srcPtrPtr )
  916. {
  917. cmRC_t rc = kOkAfRC;
  918. cmAudioFileGuts* p = _cmAudioFileWriteGutsPtr(h,&rc );
  919. if( rc != kOkAfRC )
  920. return rc;
  921. unsigned bytesPerSmp = p->info.bits / 8;
  922. unsigned bufFrmCnt = 1024;
  923. unsigned bufByteCnt = bufFrmCnt * bytesPerSmp;
  924. unsigned ci;
  925. unsigned wrFrmCnt = 0;
  926. char buf[ bufByteCnt * chCnt ];
  927. while( wrFrmCnt < frmCnt )
  928. {
  929. unsigned n = cmMin( frmCnt-wrFrmCnt, bufFrmCnt );
  930. for(ci=0; ci<chCnt; ++ci)
  931. {
  932. const int* sbp = srcPtrPtr[ci] + wrFrmCnt;
  933. const int* sep = sbp + n;
  934. switch( p->info.bits )
  935. {
  936. case 8:
  937. {
  938. char* dbp = buf + ci;
  939. for(; sbp < sep; dbp+=chCnt )
  940. *dbp = (char)*sbp++;
  941. }
  942. break;
  943. case 16:
  944. {
  945. short* dbp = (short*)buf;
  946. for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
  947. *dbp = _cmAfSwap16((short)*sbp);
  948. }
  949. break;
  950. case 24:
  951. {
  952. unsigned char* dbp = (unsigned char*)buf;
  953. for( dbp+=(ci*3); sbp < sep; dbp+=(3*chCnt), ++sbp)
  954. {
  955. unsigned char* s = (unsigned char*)sbp;
  956. dbp[0] = s[2];
  957. dbp[1] = s[1];
  958. dbp[2] = s[0];
  959. }
  960. }
  961. break;
  962. case 32:
  963. {
  964. int* dbp = (int*)buf;
  965. for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
  966. *dbp = _cmAfSwap32(*sbp);
  967. }
  968. break;
  969. default:
  970. { assert(0);}
  971. }
  972. }
  973. wrFrmCnt+=n;
  974. if( fwrite( buf, n*bytesPerSmp*chCnt, 1, p->fp ) != 1)
  975. {
  976. rc = _cmAudioFileError(p,kWriteFailAfRC);
  977. break;
  978. }
  979. }
  980. p->info.frameCnt += wrFrmCnt;
  981. return rc;
  982. }
  983. cmRC_t _cmAudioFileWriteRealSamples( cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, const void* srcPtrPtr, unsigned realSmpByteCnt )
  984. {
  985. cmRC_t rc = kOkAfRC;
  986. cmAudioFileGuts* p = _cmAudioFileWriteGutsPtr(h,&rc );
  987. if( rc != kOkAfRC )
  988. return rc;
  989. unsigned bufFrmCnt = 1024;
  990. unsigned wrFrmCnt = 0;
  991. unsigned i = 0;
  992. int maxSmpVal = 0;
  993. int buf[ chCnt * bufFrmCnt ];
  994. int* srcCh[ chCnt ];
  995. for(i=0; i<chCnt; ++i)
  996. srcCh[i] = buf + (i*bufFrmCnt);
  997. switch( p->info.bits )
  998. {
  999. case 8: maxSmpVal = 0x7f; break;
  1000. case 16: maxSmpVal = 0x7fff; break;
  1001. case 24: maxSmpVal = 0x7fffff; break;
  1002. case 32: maxSmpVal = 0x7fffffb0; break; // Note: the full range is not used for 32 bit numbers
  1003. default: // because it was found to cause difficult to detect overflows
  1004. { assert(0); } // when the signal approached full scale.
  1005. }
  1006. // duplicate the audio buffer ptr array - this will allow the buffer ptr's to be changed
  1007. // during the float to int conversion without changing the ptrs passed in from the client
  1008. const void* ptrArray[ chCnt ];
  1009. memcpy(ptrArray,srcPtrPtr,sizeof(ptrArray));
  1010. const float** sfpp = (const float**)ptrArray;
  1011. const double** sdpp = (const double**)ptrArray;
  1012. while( wrFrmCnt < frmCnt )
  1013. {
  1014. unsigned n = cmMin( frmCnt - wrFrmCnt, bufFrmCnt );
  1015. for(i=0; i<chCnt; ++i)
  1016. {
  1017. int* obp = srcCh[i];
  1018. switch( realSmpByteCnt )
  1019. {
  1020. case 4:
  1021. {
  1022. const float* sbp = sfpp[i];
  1023. const float* sep = sbp + n;
  1024. for(;sbp<sep; ++sbp)
  1025. {
  1026. *obp++ = (int)fmaxf(-maxSmpVal,fminf(maxSmpVal, *sbp * maxSmpVal));
  1027. }
  1028. sfpp[i] = sbp;
  1029. }
  1030. break;
  1031. case 8:
  1032. {
  1033. const double* sbp = sdpp[i];
  1034. const double* sep = sbp + n;
  1035. for(; sbp<sep; ++sbp)
  1036. {
  1037. *obp++ = (int)fmax(-maxSmpVal,fmin(maxSmpVal,*sbp * maxSmpVal));
  1038. }
  1039. sdpp[i] = sbp;
  1040. }
  1041. break;
  1042. default:
  1043. { assert(0); }
  1044. }
  1045. }
  1046. if((rc = cmAudioFileWriteInt( h, n, chCnt, srcCh )) != kOkAfRC )
  1047. break;
  1048. wrFrmCnt += n;
  1049. }
  1050. return rc;
  1051. }
  1052. cmRC_t cmAudioFileWriteFloat( cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, float** bufPtrPtr )
  1053. { return _cmAudioFileWriteRealSamples(h,frmCnt,chCnt,bufPtrPtr,sizeof(float)); }
  1054. cmRC_t cmAudioFileWriteDouble( cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, double** bufPtrPtr )
  1055. { return _cmAudioFileWriteRealSamples(h,frmCnt,chCnt,bufPtrPtr,sizeof(double)); }
  1056. cmRC_t cmAudioFileMinMaxMean( cmAudioFileH_t h, unsigned chIdx, cmSample_t* minPtr, cmSample_t* maxPtr, cmSample_t* meanPtr )
  1057. {
  1058. assert( minPtr != NULL && maxPtr != NULL && meanPtr != NULL );
  1059. *minPtr = -cmSample_MAX;
  1060. *maxPtr = cmSample_MAX;
  1061. *meanPtr = 0;
  1062. cmRC_t rc = kOkAfRC;
  1063. cmAudioFileGuts* p = _cmAudioFileReadGutsPtr(h,&rc );
  1064. if( rc != kOkAfRC )
  1065. return rc;
  1066. unsigned orgFrmIdx = p->curFrmIdx;
  1067. if((rc = cmAudioFileSeek(h,0)) != kOkAfRC )
  1068. return rc;
  1069. *minPtr = cmSample_MAX;
  1070. *maxPtr = -cmSample_MAX;
  1071. unsigned bufN = 1024;
  1072. cmSample_t buf[ bufN ];
  1073. unsigned frmCnt = 0;
  1074. unsigned actualFrmCnt;
  1075. cmSample_t* bufPtr[1] = { &buf[0] };
  1076. for(; frmCnt<p->info.frameCnt; frmCnt+=actualFrmCnt)
  1077. {
  1078. actualFrmCnt = 0;
  1079. unsigned n = cmMin( p->info.frameCnt-frmCnt, bufN );
  1080. if((rc = cmAudioFileReadSample(h, n, chIdx, 1, bufPtr, &actualFrmCnt)) != kOkAfRC )
  1081. return rc;
  1082. const cmSample_t* sbp = buf;
  1083. const cmSample_t* sep = buf + actualFrmCnt;
  1084. for(; sbp < sep; ++sbp )
  1085. {
  1086. *meanPtr += *sbp;
  1087. if( *minPtr > *sbp )
  1088. *minPtr = *sbp;
  1089. if( *maxPtr < *sbp )
  1090. *maxPtr = *sbp;
  1091. }
  1092. }
  1093. if( frmCnt > 0 )
  1094. *meanPtr /= frmCnt;
  1095. else
  1096. *minPtr = *maxPtr = 0;
  1097. return cmAudioFileSeek( h, orgFrmIdx );
  1098. }
  1099. cmRC_t cmAudioFileWriteFileInt( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, int** bufPtrPtr, cmRpt_t* rpt )
  1100. {
  1101. cmRC_t rc0, rc1;
  1102. cmAudioFileH_t h = cmAudioFileNewCreate(fn, srate, bits, chCnt, &rc0, rpt );
  1103. if( (cmAudioFileIsValid(h)==false) || (rc0!=kOkAfRC))
  1104. return rc0;
  1105. rc0 = cmAudioFileWriteInt( h, frmCnt, chCnt, bufPtrPtr );
  1106. if(((rc1 = cmAudioFileDelete(&h))!=kOkAfRC) && (rc0!=kOkAfRC))
  1107. rc0 = rc1;
  1108. return rc0;
  1109. }
  1110. cmRC_t cmAudioFileWriteFileFloat( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, float** bufPtrPtr, cmRpt_t* rpt )
  1111. {
  1112. cmRC_t rc0, rc1;
  1113. cmAudioFileH_t h = cmAudioFileNewCreate(fn, srate, bits, chCnt, &rc0, rpt );
  1114. if( (cmAudioFileIsValid(h)==false) || (rc0!=kOkAfRC))
  1115. return rc0;
  1116. rc0 = cmAudioFileWriteFloat( h, frmCnt, chCnt, bufPtrPtr );
  1117. if(((rc1 = cmAudioFileDelete(&h))!=kOkAfRC) && (rc0!=kOkAfRC))
  1118. rc0 = rc1;
  1119. return rc0;
  1120. }
  1121. cmRC_t cmAudioFileWriteFileDouble( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, double** bufPtrPtr, cmRpt_t* rpt )
  1122. {
  1123. cmRC_t rc0, rc1;
  1124. cmAudioFileH_t h = cmAudioFileNewCreate(fn, srate, bits, chCnt, &rc0, rpt );
  1125. if( (cmAudioFileIsValid(h)==false) || (rc0!=kOkAfRC))
  1126. return rc0;
  1127. rc0 = cmAudioFileWriteDouble( h, frmCnt, chCnt, bufPtrPtr );
  1128. if(((rc1 = cmAudioFileDelete(&h))!=kOkAfRC) && (rc0!=kOkAfRC))
  1129. rc0 = rc1;
  1130. return rc0;
  1131. }
  1132. cmRC_t cmAudioFileMinMaxMeanFn( const cmChar_t* fn, unsigned chIdx, cmSample_t* minPtr, cmSample_t* maxPtr, cmSample_t* meanPtr, cmRpt_t* rpt )
  1133. {
  1134. cmRC_t rc0 = kOkAfRC;
  1135. cmRC_t rc1;
  1136. cmAudioFileH_t afH = cmAudioFileNewOpen( fn, NULL, &rc0, rpt );
  1137. if( rc0 != kOkAfRC )
  1138. return rc0;
  1139. rc0 = cmAudioFileMinMaxMean( afH, chIdx, minPtr, maxPtr, meanPtr );
  1140. rc1 = cmAudioFileDelete(&afH);
  1141. return rc0 != kOkAfRC ? rc0 : rc1;
  1142. }
  1143. const cmChar_t* cmAudioFileName( cmAudioFileH_t h )
  1144. {
  1145. cmRC_t rc;
  1146. cmAudioFileGuts* p = _cmAudioFileReadGutsPtr(h,&rc );
  1147. if( rc != kOkAfRC )
  1148. return NULL;
  1149. return p->fn;
  1150. }
  1151. const char* cmAudioFileErrorMsg( unsigned rc )
  1152. {
  1153. unsigned i;
  1154. for(i=0; _cmAudioFileErrArray[i].rc != kUnknownErrAfRC; ++i )
  1155. if( _cmAudioFileErrArray[i].rc == rc )
  1156. break;
  1157. return _cmAudioFileErrArray[i].msg;
  1158. }
  1159. cmRC_t cmAudioFileGetInfo( const cmChar_t* fn, cmAudioFileInfo_t* infoPtr, cmRpt_t* rpt )
  1160. {
  1161. cmRC_t rc = kOkAfRC;
  1162. cmAudioFileH_t afH = cmAudioFileNewOpen( fn, infoPtr, &rc, rpt );
  1163. if( rc != kOkAfRC )
  1164. return rc;
  1165. return cmAudioFileDelete(&afH);
  1166. }
  1167. void cmAudioFilePrintInfo( const cmAudioFileInfo_t* infoPtr, cmRpt_t* rpt )
  1168. {
  1169. char* typeStr = "AIFF";
  1170. char* swapStr = "";
  1171. char* aifcStr = "";
  1172. unsigned i;
  1173. if( cmIsFlag(infoPtr->flags,kWavAfFl) )
  1174. typeStr = "WAV";
  1175. if( cmIsFlag(infoPtr->flags,kSwapAfFl) )
  1176. swapStr = "Swap:On";
  1177. if( cmIsFlag(infoPtr->flags,kAifcAfFl))
  1178. aifcStr = "AIFC";
  1179. cmRptPrintf(rpt,"bits:%i chs:%i srate:%f frames:%i type:%s %s %s\n", infoPtr->bits, infoPtr->chCnt, infoPtr->srate, infoPtr->frameCnt, typeStr, swapStr, aifcStr );
  1180. for(i=0; i<infoPtr->markerCnt; ++i)
  1181. cmRptPrintf(rpt,"%i %i %s\n", infoPtr->markerArray[i].id, infoPtr->markerArray[i].frameIdx, infoPtr->markerArray[i].label);
  1182. if( strlen(infoPtr->bextRecd.desc) )
  1183. cmRptPrintf(rpt,"Bext Desc:%s\n",infoPtr->bextRecd.desc );
  1184. if( strlen(infoPtr->bextRecd.origin) )
  1185. cmRptPrintf(rpt,"Bext Origin:%s\n",infoPtr->bextRecd.origin );
  1186. if( strlen(infoPtr->bextRecd.originRef) )
  1187. cmRptPrintf(rpt,"Bext Origin Ref:%s\n",infoPtr->bextRecd.originRef );
  1188. if( strlen(infoPtr->bextRecd.originDate) )
  1189. cmRptPrintf(rpt,"Bext Origin Date:%s\n",infoPtr->bextRecd.originDate );
  1190. if( strlen(infoPtr->bextRecd.originTime ) )
  1191. cmRptPrintf(rpt,"Bext Origin Time:%s\n",infoPtr->bextRecd.originTime );
  1192. cmRptPrintf(rpt,"Bext time high:%i low:%i 0x%x%x\n",infoPtr->bextRecd.timeRefHigh,infoPtr->bextRecd.timeRefLow, infoPtr->bextRecd.timeRefHigh,infoPtr->bextRecd.timeRefLow);
  1193. }
  1194. cmRC_t cmAudioFileReport( cmAudioFileH_t h, cmRpt_t* rpt, unsigned frmIdx, unsigned frmCnt )
  1195. {
  1196. cmRC_t rc = kOkAfRC;
  1197. cmAudioFileGuts* p = _cmAudioFileReadGutsPtr(h,&rc);
  1198. if( rc != kOkAfRC )
  1199. return rc;
  1200. cmRptPrintf(rpt,"function cm_audio_file_test()\n");
  1201. cmRptPrintf(rpt,"#{\n");
  1202. cmAudioFilePrintInfo(&p->info,rpt);
  1203. cmRptPrintf(rpt,"#}\n");
  1204. float buf[ p->info.chCnt * frmCnt ];
  1205. float* bufPtr[p->info.chCnt];
  1206. unsigned i,j,cmtFrmCnt=0;
  1207. for(i=0; i<p->info.chCnt; ++i)
  1208. bufPtr[i] = buf + (i*frmCnt);
  1209. if((rc = cmAudioFileSeek(h,frmIdx)) != kOkAfRC )
  1210. return rc;
  1211. if((rc= cmAudioFileReadFloat(h,frmCnt,0,p->info.chCnt,bufPtr,&cmtFrmCnt )) != kOkAfRC)
  1212. return rc;
  1213. cmRptPrintf(rpt,"m = [\n");
  1214. for(i=0; i<frmCnt; i++)
  1215. {
  1216. for(j=0; j<p->info.chCnt; ++j)
  1217. cmRptPrintf(rpt,"%f ", bufPtr[j][i] );
  1218. cmRptPrintf(rpt,"\n");
  1219. }
  1220. cmRptPrintf(rpt,"];\nplot(m)\nendfunction\n");
  1221. return rc;
  1222. }
  1223. cmRC_t cmAudioFileReportFn( const cmChar_t* fn, unsigned frmIdx, unsigned frmCnt, cmRpt_t* rpt )
  1224. {
  1225. cmAudioFileInfo_t info;
  1226. cmRC_t rc;
  1227. cmAudioFileH_t h = cmAudioFileNewOpen( fn, &info, &rc, rpt );
  1228. if(rc == kOkAfRC )
  1229. {
  1230. cmAudioFileReport(h,rpt,frmIdx,frmCnt);
  1231. }
  1232. return cmAudioFileDelete(&h);
  1233. }
  1234. /// [cmAudioFileExample]
  1235. void cmAudioFileTest( const cmChar_t* audioFn, const cmChar_t* outFn, cmRpt_t* rpt )
  1236. {
  1237. cmAudioFileInfo_t afInfo;
  1238. cmRC_t cmRC;
  1239. // open an audio file
  1240. cmAudioFileH_t afH = cmAudioFileNewOpen( audioFn, &afInfo, &cmRC, rpt );
  1241. if( cmRC != kOkAfRC || cmAudioFileIsValid(afH)==false )
  1242. {
  1243. cmRptPrintf(rpt,"Unable to open the audio file:%s\n",audioFn);
  1244. return;
  1245. }
  1246. // print the header information and one seconds worth of samples
  1247. //cmAudioFileReport( afH, rpt, 66000, (unsigned)afInfo.srate);
  1248. cmAudioFileReport( afH, rpt, 0, 0);
  1249. // close and delete the audio file handle
  1250. cmAudioFileDelete(&afH);
  1251. }
  1252. /// [cmAudioFileExample]