libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmAudioFile.c 52KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951
  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. #include "cmRptFile.h"
  13. // #define _24to32_aif( p ) ((int)( ((p[0]>127?255:0) << 24) + (((int)p[0]) << 16) + (((int)p[1]) <<8) + p[2])) // no-swap equivalent
  14. // See note in:_cmAudioFileReadFileHdr()
  15. // Note that this code byte swaps as it converts - this is to counter the byte swap that occurs in cmAudioFileReadInt().
  16. #define _24to32_aif( p ) ((int)( ((p[0]>127?255:0) << 0) + (((int)p[2]) << 24) + (((int)p[1]) <<16) + (((int)p[0]) << 8)))
  17. #define _24to32_wav( p ) ((int)( ((p[2]>127?255:0) << 24) + (((int)p[2]) << 16) + (((int)p[1]) <<8) + p[0]))
  18. #define _cmAfSwap16(v) cmSwap16(v)
  19. #define _cmAfSwap32(v) cmSwap32(v)
  20. #ifdef cmBIG_ENDIAN
  21. #define _cmAifSwapFl (0)
  22. #define _cmWavSwapFl (1)
  23. #else
  24. #define _cmAifSwapFl (1)
  25. #define _cmWavSwapFl (0)
  26. #endif
  27. enum
  28. {
  29. kAiffFileId = 'FORM',
  30. kAiffChkId = 'AIFF',
  31. kAifcChkId = 'AIFC',
  32. kSowtCompId = 'sowt',
  33. kNoneCompId = 'NONE',
  34. kWavFileId = 'FFIR',
  35. kWavChkId = 'EVAW',
  36. };
  37. enum { kWriteAudioGutsFl=0x01 };
  38. typedef struct
  39. {
  40. unsigned rc;
  41. const char* msg;
  42. } cmAudioErrRecd;
  43. typedef struct
  44. {
  45. cmErr_t err;
  46. FILE* fp; // file handle
  47. cmAudioFileInfo_t info; // audio file details
  48. unsigned curFrmIdx; // current frame offset
  49. unsigned fileByteCnt; // file byte cnt
  50. unsigned smpByteOffs; // byte offset of the first sample
  51. cmAudioFileMarker_t* markArray;
  52. unsigned flags;
  53. cmChar_t* fn;
  54. } cmAf_t;
  55. cmAudioErrRecd _cmAudioFileErrArray[] =
  56. {
  57. { kOkAfRC, "No Error." },
  58. { kOpenFailAfRC, "Audio file open failed."},
  59. { kReadFailAfRC, "Audio file read failed."},
  60. { kWriteFailAfRC, "Audio file write failed."},
  61. { kSeekFailAfRC, "Audio file seek failed."},
  62. { kCloseFailAfRC, "Audio file close failed."},
  63. { kNotAiffAfRC, "Not an audio file."},
  64. { kInvalidBitWidthAfRC, "Invalid audio file bit width."},
  65. { kInvalidFileModeAfRC, "Invalid audio file mode."},
  66. { kInvalidHandleAfRC, "Invalid audio file handle."},
  67. { kInvalidChCountAfRC, "Invalid channel index or count."},
  68. { kUnknownErrAfRC, "Uknown audio file error."}
  69. };
  70. cmAudioFileH_t cmNullAudioFileH = { NULL };
  71. cmAf_t* _cmAudioFileHandleToPtr( cmAudioFileH_t h )
  72. {
  73. cmAf_t* p = (cmAf_t*)h.h;
  74. if( p == NULL )
  75. assert(p!=NULL);
  76. return p;
  77. }
  78. cmRC_t _cmAudioFileError( cmAf_t* 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. cmAf_t* _cmAudioFileValidate( cmAudioFileH_t h, cmRC_t* rcPtr, bool writeFl )
  86. {
  87. *rcPtr = kOkAfRC;
  88. cmAf_t* p = _cmAudioFileHandleToPtr(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. cmAf_t* _cmAudioFileReadGutsPtr( cmAudioFileH_t h, cmRC_t* rcPtr )
  97. { return _cmAudioFileValidate( h, rcPtr, false ); }
  98. cmAf_t* _cmAudioFileWriteGutsPtr( cmAudioFileH_t h, cmRC_t* rcPtr )
  99. { return _cmAudioFileValidate( h, rcPtr, true ); }
  100. cmRC_t _cmAudioFileSeek( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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 _cmAudioFileReadFileHdr( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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( cmAf_t* 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( cmAf_t, 1 );
  347. cmErrSetup(&((cmAf_t*)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(cmAf_t,1);
  364. cmErrSetup(&((cmAf_t*)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( cmAf_t* p, const cmChar_t* fn, const char* fileModeStr )
  377. {
  378. cmRC_t rc = kOkAfRC;
  379. // zero the info record
  380. memset(&p->info,0,sizeof(p->info));
  381. // open the file
  382. if((p->fp = fopen(fn,fileModeStr)) == NULL )
  383. {
  384. p->fn = (cmChar_t*)fn; // set the file name so that the error msg can use it
  385. rc = _cmAudioFileError(p,kOpenFailAfRC);
  386. p->fn = NULL;
  387. goto errLabel;
  388. }
  389. // read the file header
  390. if((rc = _cmAudioFileReadFileHdr(p,kAiffFileId,kAiffChkId,_cmAifSwapFl)) != kOkAfRC )
  391. if((rc = _cmAudioFileReadFileHdr(p,kWavFileId,kWavChkId,_cmWavSwapFl)) != kOkAfRC )
  392. goto errLabel;
  393. // seek past the file header
  394. if((rc = _cmAudioFileSeek(p,12,SEEK_SET)) != kOkAfRC )
  395. goto errLabel;
  396. // zero chCnt and frameCnt to allow the order of the 'data' and 'fmt' chunks to be noticed
  397. p->info.chCnt = 0;
  398. p->info.frameCnt = 0;
  399. while( ftell(p->fp ) < p->fileByteCnt )
  400. {
  401. unsigned chkId, chkByteCnt;
  402. if((rc = _cmAudioFileReadChunkHdr(p,&chkId,&chkByteCnt)) != kOkAfRC )
  403. goto errLabel;
  404. unsigned offs = ftell(p->fp);
  405. if( cmIsFlag(p->info.flags,kAiffAfFl) )
  406. switch(chkId)
  407. {
  408. case 'COMM':
  409. if((rc = _cmAudioFileReadCommChunk(p)) != kOkAfRC )
  410. goto errLabel;
  411. break;
  412. case 'SSND':
  413. if((rc = _cmAudioFileReadSsndChunk(p)) != kOkAfRC )
  414. goto errLabel;
  415. break;
  416. case 'MARK':
  417. if((rc = _cmAudioFileReadMarkerChunk(p)) != kOkAfRC )
  418. goto errLabel;
  419. break;
  420. }
  421. else
  422. switch(chkId)
  423. {
  424. case ' tmf':
  425. if((rc = _cmAudioFileReadFmtChunk(p)) != kOkAfRC )
  426. goto errLabel;
  427. break;
  428. case 'atad':
  429. if((rc = _cmAudioFileReadDatcmhunk(p,chkByteCnt)) != kOkAfRC )
  430. goto errLabel;
  431. break;
  432. case 'txeb':
  433. if((rc = _cmAudioFileReadBextChunk(p)) != kOkAfRC )
  434. goto errLabel;
  435. break;
  436. }
  437. // seek to the end of this chunk
  438. if((rc = _cmAudioFileSeek(p,offs+chkByteCnt,SEEK_SET)) != kOkAfRC )
  439. goto errLabel;
  440. }
  441. errLabel:
  442. if( rc!=kOkAfRC && p->fp != NULL )
  443. {
  444. fclose(p->fp);
  445. p->fp = NULL;
  446. }
  447. return rc;
  448. }
  449. cmRC_t cmAudioFileOpen( cmAudioFileH_t h, const cmChar_t* fn, cmAudioFileInfo_t* infoPtr )
  450. {
  451. cmRC_t rc = kOkAfRC;
  452. cmAf_t* p = _cmAudioFileHandleToPtr(h);
  453. // verify the file is closed before opening
  454. if( cmAudioFileIsOpen(h) )
  455. if((rc = cmAudioFileClose(&h)) != kOkAfRC )
  456. return rc;
  457. // read the file header
  458. if((rc = _cmAudioFileOpen(p, fn, "rb" )) != kOkAfRC )
  459. goto errLabel;
  460. // seek to the first sample offset
  461. if((rc = _cmAudioFileSeek(p,p->smpByteOffs,SEEK_SET)) != kOkAfRC )
  462. goto errLabel;
  463. p->fn = cmMemResize( char, p->fn, strlen(fn)+1 );
  464. strcpy(p->fn,fn);
  465. if( infoPtr != NULL)
  466. memcpy(infoPtr,&p->info,sizeof(*infoPtr));
  467. return rc;
  468. errLabel:
  469. cmAudioFileClose(&h);
  470. return rc;
  471. }
  472. cmRC_t _cmAudioFileWriteBytes( cmAf_t* p, const void* b, unsigned bn )
  473. {
  474. cmRC_t rc = kOkAfRC;
  475. if( fwrite( b, bn, 1, p->fp ) != 1 )
  476. return _cmAudioFileError(p,kWriteFailAfRC);
  477. return rc;
  478. }
  479. cmRC_t _cmAudioFileWriteId( cmAf_t* p, const char* s )
  480. { return _cmAudioFileWriteBytes( p, s, strlen(s)) ; }
  481. cmRC_t _cmAudioFileWriteUInt32( cmAf_t* p, unsigned v )
  482. {
  483. if( cmIsFlag(p->info.flags,kSwapAfFl) )
  484. v = _cmAfSwap32(v);
  485. return _cmAudioFileWriteBytes( p, &v, sizeof(v)) ;
  486. }
  487. cmRC_t _cmAudioFileWriteUInt16( cmAf_t* p, unsigned short v )
  488. {
  489. if( cmIsFlag(p->info.flags,kSwapAfFl) )
  490. v = _cmAfSwap16(v);
  491. return _cmAudioFileWriteBytes( p, &v, sizeof(v)) ;
  492. }
  493. cmRC_t _cmAudioFileWriteAiffHdr( cmAf_t* p )
  494. {
  495. cmRC_t rc = kOkAfRC;
  496. unsigned char srateX80[10];
  497. cmDoubleToX80( p->info.srate, srateX80 );
  498. unsigned hdrByteCnt = 54;
  499. unsigned ssndByteCnt = 8 + (p->info.chCnt * p->info.frameCnt * (p->info.bits/8));
  500. unsigned formByteCnt = hdrByteCnt + ssndByteCnt - 8;
  501. unsigned commByteCnt = 18;
  502. unsigned ssndSmpOffs = 0;
  503. unsigned ssndBlkSize = 0;
  504. if( cmIsOddU( ssndByteCnt ) )
  505. {
  506. formByteCnt++;
  507. }
  508. if(( rc = _cmAudioFileSeek( p, 0, SEEK_SET )) != kOkAfRC )
  509. return rc;
  510. if(( rc = _cmAudioFileWriteId( p, "FORM")) != kOkAfRC ) return rc;
  511. if(( rc = _cmAudioFileWriteUInt32( p, formByteCnt)) != kOkAfRC ) return rc;
  512. if(( rc = _cmAudioFileWriteId( p, "AIFF")) != kOkAfRC ) return rc;
  513. if(( rc = _cmAudioFileWriteId( p, "COMM")) != kOkAfRC ) return rc;
  514. if(( rc = _cmAudioFileWriteUInt32( p, commByteCnt)) != kOkAfRC ) return rc;
  515. if(( rc = _cmAudioFileWriteUInt16( p, p->info.chCnt)) != kOkAfRC ) return rc;
  516. if(( rc = _cmAudioFileWriteUInt32( p, p->info.frameCnt)) != kOkAfRC ) return rc;
  517. if(( rc = _cmAudioFileWriteUInt16( p, p->info.bits)) != kOkAfRC ) return rc;
  518. if(( rc = _cmAudioFileWriteBytes( p, &srateX80,10)) != kOkAfRC ) return rc;
  519. if(( rc = _cmAudioFileWriteId( p, "SSND")) != kOkAfRC ) return rc;
  520. if(( rc = _cmAudioFileWriteUInt32( p, ssndByteCnt)) != kOkAfRC ) return rc;
  521. if(( rc = _cmAudioFileWriteUInt32( p, ssndSmpOffs)) != kOkAfRC ) return rc;
  522. if(( rc = _cmAudioFileWriteUInt32( p, ssndBlkSize)) != kOkAfRC ) return rc;
  523. return rc;
  524. }
  525. cmRC_t _cmAudioFileWriteWavHdr( cmAf_t* p )
  526. {
  527. cmRC_t rc = kOkAfRC;
  528. short chCnt = p->info.chCnt;
  529. unsigned frmCnt = p->info.frameCnt;
  530. short bits = p->info.bits;
  531. unsigned srate = p->info.srate;
  532. short fmtId = 1;
  533. unsigned bytesPerSmp = bits/8;
  534. unsigned hdrByteCnt = 36;
  535. unsigned fmtByteCnt = 16;
  536. unsigned blockAlignCnt = chCnt * bytesPerSmp;
  537. unsigned sampleCnt = chCnt * frmCnt;
  538. unsigned dataByteCnt = sampleCnt * bytesPerSmp;
  539. if(( rc = _cmAudioFileSeek( p, 0, SEEK_SET )) != kOkAfRC )
  540. return rc;
  541. if((rc = _cmAudioFileWriteId( p, "RIFF")) != kOkAfRC ) goto errLabel;
  542. if((rc = _cmAudioFileWriteUInt32( p, hdrByteCnt + dataByteCnt)) != kOkAfRC ) goto errLabel;
  543. if((rc = _cmAudioFileWriteId( p, "WAVE")) != kOkAfRC ) goto errLabel;
  544. if((rc = _cmAudioFileWriteId( p, "fmt ")) != kOkAfRC ) goto errLabel;
  545. if((rc = _cmAudioFileWriteUInt32( p, fmtByteCnt)) != kOkAfRC ) goto errLabel;
  546. if((rc = _cmAudioFileWriteUInt16( p, fmtId)) != kOkAfRC ) goto errLabel;
  547. if((rc = _cmAudioFileWriteUInt16( p, chCnt)) != kOkAfRC ) goto errLabel;
  548. if((rc = _cmAudioFileWriteUInt32( p, srate)) != kOkAfRC ) goto errLabel;
  549. if((rc = _cmAudioFileWriteUInt32( p, srate * blockAlignCnt)) != kOkAfRC ) goto errLabel;
  550. if((rc = _cmAudioFileWriteUInt16( p, blockAlignCnt)) != kOkAfRC ) goto errLabel;
  551. if((rc = _cmAudioFileWriteUInt16( p, bits)) != kOkAfRC ) goto errLabel;
  552. if((rc = _cmAudioFileWriteId( p, "data")) != kOkAfRC ) goto errLabel;
  553. if((rc = _cmAudioFileWriteUInt32( p, dataByteCnt)) != kOkAfRC ) goto errLabel;
  554. errLabel:
  555. return rc;
  556. }
  557. cmRC_t _cmAudioFileWriteHdr( cmAf_t* p )
  558. {
  559. if( cmIsFlag(p->info.flags,kWavAfFl) )
  560. return _cmAudioFileWriteWavHdr(p);
  561. return _cmAudioFileWriteAiffHdr(p);
  562. }
  563. cmRC_t cmAudioFileCreate( cmAudioFileH_t h, const cmChar_t* fn, double srate, unsigned bits, unsigned chCnt )
  564. {
  565. cmRC_t rc = kOkAfRC;
  566. cmAf_t* p = _cmAudioFileHandleToPtr(h);
  567. cmFileSysPathPart_t* pp = NULL;
  568. // verify the file is closed before opening
  569. if( cmAudioFileIsOpen(h) )
  570. if((rc = cmAudioFileClose(&h)) != kOkAfRC )
  571. return rc;
  572. // all audio files are written as AIF's or WAV's -
  573. // if the file name is given some other extension then issue a warning and write an AIF.
  574. if( fn!=NULL && strlen(fn) && ((pp = cmFsPathParts(fn)) != NULL) )
  575. {
  576. unsigned i;
  577. unsigned n = pp->extStr==NULL ? 0 : strlen(pp->extStr);
  578. cmChar_t ext[n+1];
  579. if( pp->extStr != NULL )
  580. {
  581. strcpy(ext,pp->extStr);
  582. // convert the extension to upper case
  583. for(i=0; i<n; ++i)
  584. ext[i] = toupper(ext[i]);
  585. }
  586. // determine the file type to write
  587. if( cmIsFlag(p->info.flags,kWavAfFl) || strcmp(ext,"WAV")==0 )
  588. {
  589. p->info.flags = cmSetFlag(p->info.flags,kWavAfFl);
  590. p->info.flags = cmClrFlag(p->info.flags,kAiffAfFl);
  591. }
  592. else
  593. {
  594. if( pp->extStr==NULL || (strcmp(ext,"AIF") && strcmp(ext,"AIFF")) )
  595. cmRptPrintf(p->err.rpt,"The AIF audio file '%s' is being written with a file extension other than 'AIF' or 'AIFF'.",cmStringNullGuard(fn));
  596. p->info.flags = cmClrFlag(p->info.flags,kWavAfFl);
  597. p->info.flags = cmSetFlag(p->info.flags,kAiffAfFl);
  598. }
  599. cmFsFreePathParts(pp);
  600. }
  601. // open the file for writing
  602. if((p->fp = fopen(fn,"wb")) == NULL )
  603. {
  604. p->fn = (cmChar_t*)fn; // set the file name so that the error msg can use it
  605. rc = _cmAudioFileError(p,kOpenFailAfRC);
  606. p->fn = NULL;
  607. goto errLabel;
  608. }
  609. p->fn = cmMemResize( char, p->fn, strlen(fn)+1 );
  610. p->info.srate = srate;
  611. p->info.bits = bits;
  612. p->info.chCnt = chCnt;
  613. p->info.frameCnt = 0;
  614. p->flags = kWriteAudioGutsFl;
  615. // set the swap flags
  616. bool swapFl = cmIsFlag(p->info.flags,kWavAfFl) ? _cmWavSwapFl : _cmAifSwapFl;
  617. p->info.flags = cmEnaFlag(p->info.flags,kSwapAfFl, swapFl);
  618. p->info.flags = cmEnaFlag(p->info.flags,kSwapSamplesAfFl,swapFl);
  619. strcpy(p->fn,fn);
  620. if((rc = _cmAudioFileWriteHdr(p)) != kOkAfRC )
  621. goto errLabel;
  622. return rc;
  623. errLabel:
  624. cmAudioFileClose(&h);
  625. return rc;
  626. }
  627. cmRC_t cmAudioFileClose( cmAudioFileH_t* h )
  628. {
  629. assert( h != NULL);
  630. cmAf_t* p = _cmAudioFileHandleToPtr(*h);
  631. cmRC_t rc = kOkAfRC;
  632. if( p->fp == NULL )
  633. return kOkAfRC;
  634. if( cmIsFlag( p->flags, kWriteAudioGutsFl ) )
  635. if((rc = _cmAudioFileWriteHdr(p)) != kOkAfRC )
  636. return rc;
  637. if( fclose(p->fp) != 0 )
  638. rc = _cmAudioFileError(p,kCloseFailAfRC);
  639. else
  640. {
  641. p->fp = NULL;
  642. cmMemPtrFree( &(p->info.markerArray));
  643. memset(&p->info,0,sizeof(p->info));
  644. }
  645. return rc;
  646. }
  647. cmRC_t cmAudioFileDelete( cmAudioFileH_t* h)
  648. {
  649. assert(h!=NULL);
  650. cmRC_t rc = kOkAfRC;
  651. // prevent double deletes
  652. if( h->h == NULL )
  653. return kOkAfRC;
  654. cmAf_t* p = _cmAudioFileHandleToPtr(*h);
  655. if( p->fp != NULL )
  656. rc = cmAudioFileClose(h);
  657. cmMemPtrFree(&p->fn);
  658. cmMemPtrFree(&(h->h));
  659. return rc;
  660. }
  661. bool cmAudioFileIsValid( cmAudioFileH_t h )
  662. { return h.h != NULL; }
  663. bool cmAudioFileIsOpen( cmAudioFileH_t h )
  664. {
  665. if( !cmAudioFileIsValid(h) )
  666. return false;
  667. return _cmAudioFileHandleToPtr(h)->fp != NULL;
  668. }
  669. bool cmAudioFileIsEOF( cmAudioFileH_t h )
  670. {
  671. cmRC_t rc = kOkAfRC;
  672. cmAf_t* p = _cmAudioFileReadGutsPtr(h,&rc);
  673. return (rc != kOkAfRC) || (p==NULL) || (p->curFrmIdx >= p->info.frameCnt) || (p->fp==NULL) || feof(p->fp) ? true : false;
  674. }
  675. unsigned cmAudioFileTell( cmAudioFileH_t h )
  676. {
  677. cmRC_t rc = kOkAfRC;
  678. cmAf_t* p = _cmAudioFileReadGutsPtr(h,&rc);
  679. return (rc==kOkAfRC && p!=NULL) ? p->curFrmIdx : cmInvalidIdx;
  680. }
  681. cmRC_t cmAudioFileSeek( cmAudioFileH_t h, unsigned frmIdx )
  682. {
  683. cmRC_t rc = kOkAfRC;
  684. cmAf_t* p = _cmAudioFileReadGutsPtr(h,&rc);
  685. if( rc != kOkAfRC )
  686. return rc;
  687. if((rc = _cmAudioFileSeek(p,p->smpByteOffs + (frmIdx * p->info.chCnt * (p->info.bits/8)), SEEK_SET)) != kOkAfRC )
  688. return rc;
  689. p->curFrmIdx = frmIdx;
  690. return rc;
  691. }
  692. cmRC_t _cmAudioFileReadInt( cmAudioFileH_t h, unsigned totalFrmCnt, unsigned chIdx, unsigned chCnt, int* buf[], unsigned* actualFrmCntPtr, bool sumFl )
  693. {
  694. cmRC_t rc = kOkAfRC;
  695. cmAf_t* p = _cmAudioFileReadGutsPtr(h,&rc);
  696. if( rc != kOkAfRC )
  697. return rc;
  698. if( chIdx+chCnt > p->info.chCnt )
  699. return _cmAudioFileError(p,kInvalidChCountAfRC);
  700. if( actualFrmCntPtr != NULL )
  701. *actualFrmCntPtr = 0;
  702. unsigned bps = p->info.bits / 8; // bytes per sample
  703. unsigned bpf = bps * p->info.chCnt; // bytes per file frame
  704. unsigned bufFrmCnt = cmMin(totalFrmCnt,cmAudioFile_MAX_FRAME_READ_CNT);
  705. unsigned bytesPerBuf = bufFrmCnt * bpf;
  706. unsigned char fbuf[ bytesPerBuf ]; // raw bytes buffer
  707. unsigned ci;
  708. unsigned frmCnt = 0;
  709. unsigned totalReadFrmCnt;
  710. int* ptrBuf[ chCnt ];
  711. for(ci=0; ci<chCnt; ++ci)
  712. ptrBuf[ci] = buf[ci];
  713. for(totalReadFrmCnt=0; totalReadFrmCnt<totalFrmCnt; totalReadFrmCnt+=frmCnt )
  714. {
  715. // don't read past the end of the file or past the end of the buffer
  716. frmCnt = cmMin( p->info.frameCnt - p->curFrmIdx, cmMin( totalFrmCnt-totalReadFrmCnt, bufFrmCnt ));
  717. // read the file frmCnt sample
  718. if((rc = _cmAudioFileRead(p,fbuf,frmCnt*bpf,1)) != kOkAfRC )
  719. return rc;
  720. if( actualFrmCntPtr != NULL )
  721. *actualFrmCntPtr += frmCnt;
  722. assert( chIdx+chCnt <= p->info.chCnt );
  723. for(ci=0; ci<chCnt; ++ci)
  724. {
  725. unsigned char* sp = fbuf + (ci+chIdx)*bps;
  726. int* dp = ptrBuf[ci];
  727. int* ep = dp + frmCnt;
  728. if( !sumFl )
  729. memset(dp,0,frmCnt*sizeof(int));
  730. // 8 bit AIF files use 'signed char' and WAV files use 'unsigned char' for the sample data type.
  731. if( p->info.bits == 8 )
  732. {
  733. if( cmIsFlag(p->info.flags,kAiffAfFl) )
  734. {
  735. for(; dp<ep; sp+=bpf,++dp)
  736. *dp += *(char*)sp;
  737. }
  738. else
  739. {
  740. for(; dp<ep; sp+=bpf,++dp)
  741. {
  742. int v = *(unsigned char*)sp;
  743. *dp += v -= 128;
  744. }
  745. }
  746. }
  747. // handle non-8 bit files here
  748. if( cmIsFlag(p->info.flags,kSwapSamplesAfFl) )
  749. {
  750. switch( p->info.bits )
  751. {
  752. case 8:
  753. break;
  754. case 16:
  755. for(; dp<ep; sp+=bpf,++dp)
  756. *dp += (short)_cmAfSwap16(*(short*)sp);
  757. break;
  758. case 24:
  759. if( cmIsFlag(p->info.flags,kAiffAfFl) )
  760. {
  761. for(; dp<ep; sp+=bpf,++dp)
  762. *dp += (int)(_cmAfSwap32(_24to32_aif(sp)));
  763. }
  764. else
  765. {
  766. for(; dp<ep; sp+=bpf,++dp)
  767. *dp += (int)(_cmAfSwap32(_24to32_wav(sp)));
  768. }
  769. break;
  770. case 32:
  771. for(; dp<ep; sp+=bpf,++dp)
  772. *dp += (int)_cmAfSwap32(*(int*)sp );
  773. break;
  774. }
  775. }
  776. else
  777. {
  778. switch(p->info.bits)
  779. {
  780. case 8:
  781. break;
  782. case 16:
  783. for(; dp<ep; sp+=bpf,++dp)
  784. *dp += *(short*)sp;
  785. break;
  786. case 24:
  787. if( cmIsFlag(p->info.flags,kAiffAfFl) )
  788. {
  789. for(; dp<ep; sp+=bpf,++dp)
  790. *dp += _24to32_aif(sp);
  791. }
  792. else
  793. {
  794. for(; dp<ep; sp+=bpf,++dp)
  795. *dp += _24to32_wav(sp);
  796. }
  797. break;
  798. case 32:
  799. for(; dp<ep; sp+=bpf,++dp)
  800. *dp += *(int*)sp;
  801. break;
  802. }
  803. ptrBuf[ci] = dp;
  804. assert( dp <= buf[ci] + totalFrmCnt );
  805. }
  806. /*
  807. dp = ptrBuf[ci];
  808. ep = dp + frmCnt;
  809. while(dp<ep)
  810. sum += (double)*dp++;
  811. */
  812. }
  813. p->curFrmIdx += frmCnt;
  814. }
  815. if( totalReadFrmCnt < totalFrmCnt )
  816. {
  817. for(ci=0; ci<chCnt; ++ci)
  818. memset(buf[ci] + frmCnt,0,(totalFrmCnt-totalReadFrmCnt)*sizeof(int));
  819. }
  820. //if( actualFrmCntPtr != NULL )
  821. // *actualFrmCntPtr = totalReadFrmCnt;
  822. //printf("SUM: %f %f swap:%i\n", sum, sum/(totalFrmCnt*chCnt), cmIsFlag(p->info.flags,kSwapAfFl));
  823. return rc;
  824. }
  825. cmRC_t _cmAudioFileReadRealSamples( cmAudioFileH_t h, unsigned totalFrmCnt, unsigned chIdx, unsigned chCnt, float** fbuf, double** dbuf, unsigned* actualFrmCntPtr, bool sumFl )
  826. {
  827. cmRC_t rc = kOkAfRC;
  828. cmAf_t* p = _cmAudioFileReadGutsPtr(h,&rc);
  829. if( rc != kOkAfRC )
  830. return rc;
  831. if( actualFrmCntPtr != NULL )
  832. *actualFrmCntPtr = 0;
  833. unsigned totalReadCnt = 0;
  834. unsigned bufFrmCnt = cmMin( totalFrmCnt, cmAudioFile_MAX_FRAME_READ_CNT );
  835. unsigned bufSmpCnt = bufFrmCnt * chCnt;
  836. float fltMaxSmpVal = 0;
  837. int buf[ bufSmpCnt ];
  838. int* ptrBuf[ chCnt ];
  839. float* fPtrBuf[ chCnt ];
  840. double* dPtrBuf[ chCnt ];
  841. unsigned i;
  842. unsigned frmCnt = 0;
  843. switch( p->info.bits )
  844. {
  845. case 8: fltMaxSmpVal = 0x80; break;
  846. case 16: fltMaxSmpVal = 0x8000; break;
  847. case 24: fltMaxSmpVal = 0x800000; break;
  848. case 32: fltMaxSmpVal = 0x80000000; break;
  849. default:
  850. return _cmAudioFileError(p,kInvalidBitWidthAfRC);
  851. }
  852. double dblMaxSmpVal = fltMaxSmpVal;
  853. // initialize the audio ptr buffers
  854. for(i=0; i<chCnt; ++i)
  855. {
  856. ptrBuf[i] = buf + (i*bufFrmCnt);
  857. if( dbuf != NULL )
  858. dPtrBuf[i] = dbuf[i];
  859. if( fbuf != NULL )
  860. fPtrBuf[i] = fbuf[i];
  861. }
  862. //
  863. for(totalReadCnt=0; totalReadCnt<totalFrmCnt && p->curFrmIdx < p->info.frameCnt; totalReadCnt+=frmCnt)
  864. {
  865. unsigned actualReadFrmCnt = 0;
  866. frmCnt = cmMin( p->info.frameCnt - p->curFrmIdx, cmMin( totalFrmCnt-totalReadCnt, bufFrmCnt ) );
  867. // fill the integer audio buffer from the file
  868. if((rc = _cmAudioFileReadInt( h, frmCnt, chIdx, chCnt, ptrBuf, &actualReadFrmCnt, false )) != kOkAfRC )
  869. return rc;
  870. if( actualFrmCntPtr != NULL )
  871. *actualFrmCntPtr += actualReadFrmCnt;
  872. // convert the integer buffer to floating point
  873. for(i=0; i<chCnt; ++i)
  874. {
  875. int* sp = ptrBuf[i];
  876. if( fbuf != NULL )
  877. {
  878. float* dp = fPtrBuf[i];
  879. float* ep = dp + frmCnt;
  880. if( sumFl )
  881. {
  882. for(; dp<ep; ++dp,++sp)
  883. *dp += ((float)*sp) / fltMaxSmpVal;
  884. }
  885. else
  886. {
  887. for(; dp<ep; ++dp,++sp)
  888. *dp = ((float)*sp) / fltMaxSmpVal;
  889. }
  890. assert( dp <= fbuf[i] + totalFrmCnt );
  891. fPtrBuf[i] = dp;
  892. }
  893. else
  894. {
  895. double* dp = dPtrBuf[i];
  896. double* ep = dp + frmCnt;
  897. if( sumFl )
  898. {
  899. for(; dp<ep; ++dp,++sp)
  900. *dp += ((double)*sp) / dblMaxSmpVal;
  901. }
  902. else
  903. {
  904. for(; dp<ep; ++dp,++sp)
  905. *dp = ((double)*sp) / dblMaxSmpVal;
  906. }
  907. assert( dp <= dbuf[i] + totalFrmCnt );
  908. dPtrBuf[i] = dp;
  909. }
  910. }
  911. }
  912. return rc;
  913. }
  914. cmRC_t _cmAudioFileReadFloat( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr, bool sumFl )
  915. {
  916. return _cmAudioFileReadRealSamples(h,frmCnt,chIdx,chCnt,buf, NULL, actualFrmCntPtr, sumFl );
  917. }
  918. cmRC_t _cmAudioFileReadDouble( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr, bool sumFl )
  919. {
  920. return _cmAudioFileReadRealSamples(h,frmCnt,chIdx,chCnt,NULL, buf, actualFrmCntPtr, sumFl );
  921. }
  922. cmRC_t cmAudioFileReadInt( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr )
  923. { return _cmAudioFileReadInt( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, false ); }
  924. cmRC_t cmAudioFileReadFloat( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr )
  925. { return _cmAudioFileReadFloat( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, false ); }
  926. cmRC_t cmAudioFileReadDouble( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr )
  927. { return _cmAudioFileReadDouble( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, false ); }
  928. cmRC_t cmAudioFileReadSumInt( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr )
  929. { return _cmAudioFileReadInt( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, true ); }
  930. cmRC_t cmAudioFileReadSumFloat( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr )
  931. { return _cmAudioFileReadFloat( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, true ); }
  932. cmRC_t cmAudioFileReadSumDouble( cmAudioFileH_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr )
  933. { return _cmAudioFileReadDouble( h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, true ); }
  934. cmRC_t _cmAudioFileGet( const char* fn, unsigned begFrmIdx, cmAudioFileH_t* hp, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  935. {
  936. cmRC_t rc = kOkAfRC;
  937. *hp = cmAudioFileNewOpen( fn, afInfoPtr, &rc, rpt );
  938. if( (cmAudioFileIsValid(*hp)==false) || (rc!=kOkAfRC) )
  939. return rc;
  940. if( begFrmIdx > 0 )
  941. if((rc = cmAudioFileSeek( *hp, begFrmIdx )) != kOkAfRC )
  942. cmAudioFileDelete(hp);
  943. return rc;
  944. }
  945. 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 )
  946. {
  947. cmRC_t rc0,rc1;
  948. cmAudioFileH_t h;
  949. if((rc0 = _cmAudioFileGet(fn,begFrmIdx,&h,afInfoPtr,rpt)) != kOkAfRC )
  950. return rc0;
  951. rc0 = _cmAudioFileReadInt(h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, sumFl );
  952. if((rc1=cmAudioFileDelete(&h)) != kOkAfRC && rc0==kOkAfRC )
  953. rc0 = rc1;
  954. return rc0;
  955. }
  956. 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 )
  957. {
  958. cmRC_t rc0,rc1;
  959. cmAudioFileH_t h;
  960. if((rc0 = _cmAudioFileGet(fn,begFrmIdx,&h,afInfoPtr,rpt)) != kOkAfRC )
  961. return rc0;
  962. rc0 = _cmAudioFileReadFloat(h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, sumFl );
  963. if((rc1=cmAudioFileDelete(&h)) != kOkAfRC && rc0==kOkAfRC )
  964. rc0 = rc1;
  965. return rc0;
  966. }
  967. 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 )
  968. {
  969. cmRC_t rc0,rc1;
  970. cmAudioFileH_t h;
  971. if((rc0 = _cmAudioFileGet(fn,begFrmIdx,&h,afInfoPtr,rpt)) != kOkAfRC )
  972. return rc0;
  973. rc0 = _cmAudioFileReadDouble(h, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, sumFl );
  974. if((rc1=cmAudioFileDelete(&h)) != kOkAfRC && rc0==kOkAfRC )
  975. rc0 = rc1;
  976. return rc0;
  977. }
  978. cmRC_t cmAudioFileGetInt( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  979. { return _cmAudioFileGetInt( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, false, rpt ); }
  980. cmRC_t cmAudioFileGetFloat( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  981. { return _cmAudioFileGetFloat( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, false, rpt ); }
  982. cmRC_t cmAudioFileGetDouble( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  983. { return _cmAudioFileGetDouble( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, false, rpt); }
  984. cmRC_t cmAudioFileGetSumInt( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  985. { return _cmAudioFileGetInt( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, true, rpt ); }
  986. cmRC_t cmAudioFileGetSumFloat( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  987. { return _cmAudioFileGetFloat( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, true, rpt ); }
  988. cmRC_t cmAudioFileGetSumDouble( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr, cmAudioFileInfo_t* afInfoPtr, cmRpt_t* rpt )
  989. { return _cmAudioFileGetDouble( fn, begFrmIdx, frmCnt, chIdx, chCnt, buf, actualFrmCntPtr, afInfoPtr, true, rpt); }
  990. cmRC_t cmAudioFileWriteInt( cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, int** srcPtrPtr )
  991. {
  992. cmRC_t rc = kOkAfRC;
  993. cmAf_t* p = _cmAudioFileWriteGutsPtr(h,&rc );
  994. if( rc != kOkAfRC )
  995. return rc;
  996. unsigned bytesPerSmp = p->info.bits / 8;
  997. unsigned bufFrmCnt = 1024;
  998. unsigned bufByteCnt = bufFrmCnt * bytesPerSmp;
  999. unsigned ci;
  1000. unsigned wrFrmCnt = 0;
  1001. char buf[ bufByteCnt * chCnt ];
  1002. while( wrFrmCnt < frmCnt )
  1003. {
  1004. unsigned n = cmMin( frmCnt-wrFrmCnt, bufFrmCnt );
  1005. // interleave each channel into buf[]
  1006. for(ci=0; ci<chCnt; ++ci)
  1007. {
  1008. // get the begin and end source pointers
  1009. const int* sbp = srcPtrPtr[ci] + wrFrmCnt;
  1010. const int* sep = sbp + n;
  1011. // 8 bit samples can't be byte swapped
  1012. if( p->info.bits == 8 )
  1013. {
  1014. char* dbp = buf + ci;
  1015. for(; sbp < sep; dbp+=chCnt )
  1016. *dbp = (char)*sbp++;
  1017. }
  1018. else
  1019. {
  1020. // if the samples do need to be byte swapped
  1021. if( cmIsFlag(p->info.flags,kSwapSamplesAfFl) )
  1022. {
  1023. switch( p->info.bits )
  1024. {
  1025. case 16:
  1026. {
  1027. short* dbp = (short*)buf;
  1028. for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
  1029. *dbp = _cmAfSwap16((short)*sbp);
  1030. }
  1031. break;
  1032. case 24:
  1033. {
  1034. unsigned char* dbp = (unsigned char*)buf;
  1035. for( dbp+=(ci*3); sbp < sep; dbp+=(3*chCnt), ++sbp)
  1036. {
  1037. unsigned char* s = (unsigned char*)sbp;
  1038. dbp[0] = s[2];
  1039. dbp[1] = s[1];
  1040. dbp[2] = s[0];
  1041. }
  1042. }
  1043. break;
  1044. case 32:
  1045. {
  1046. int* dbp = (int*)buf;
  1047. for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
  1048. *dbp = _cmAfSwap32(*sbp);
  1049. }
  1050. break;
  1051. default:
  1052. { assert(0);}
  1053. }
  1054. }
  1055. else // interleave without byte swapping
  1056. {
  1057. switch( p->info.bits )
  1058. {
  1059. case 16:
  1060. {
  1061. short* dbp = (short*)buf;
  1062. for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
  1063. *dbp = (short)*sbp;
  1064. }
  1065. break;
  1066. case 24:
  1067. {
  1068. unsigned char* dbp = (unsigned char*)buf;
  1069. for( dbp+=(ci*3); sbp < sep; dbp+=(3*chCnt), ++sbp)
  1070. {
  1071. unsigned char* s = (unsigned char*)sbp;
  1072. dbp[0] = s[0];
  1073. dbp[1] = s[1];
  1074. dbp[2] = s[2];
  1075. }
  1076. }
  1077. break;
  1078. case 32:
  1079. {
  1080. int* dbp = (int*)buf;
  1081. for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
  1082. *dbp = *sbp;
  1083. }
  1084. break;
  1085. default:
  1086. { assert(0);}
  1087. } // switch
  1088. } // don't swap
  1089. } // 8 bits
  1090. } // ch
  1091. // advance the source pointer index
  1092. wrFrmCnt+=n;
  1093. if( fwrite( buf, n*bytesPerSmp*chCnt, 1, p->fp ) != 1)
  1094. {
  1095. rc = _cmAudioFileError(p,kWriteFailAfRC);
  1096. break;
  1097. }
  1098. } // while
  1099. p->info.frameCnt += wrFrmCnt;
  1100. return rc;
  1101. }
  1102. cmRC_t _cmAudioFileWriteRealSamples( cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, const void* srcPtrPtr, unsigned realSmpByteCnt )
  1103. {
  1104. cmRC_t rc = kOkAfRC;
  1105. cmAf_t* p = _cmAudioFileWriteGutsPtr(h,&rc );
  1106. if( rc != kOkAfRC )
  1107. return rc;
  1108. unsigned bufFrmCnt = 1024;
  1109. unsigned wrFrmCnt = 0;
  1110. unsigned i = 0;
  1111. int maxSmpVal = 0;
  1112. int buf[ chCnt * bufFrmCnt ];
  1113. int* srcCh[ chCnt ];
  1114. for(i=0; i<chCnt; ++i)
  1115. srcCh[i] = buf + (i*bufFrmCnt);
  1116. switch( p->info.bits )
  1117. {
  1118. case 8: maxSmpVal = 0x7f; break;
  1119. case 16: maxSmpVal = 0x7fff; break;
  1120. case 24: maxSmpVal = 0x7fffff; break;
  1121. case 32: maxSmpVal = 0x7fffffb0; break; // Note: the full range is not used for 32 bit numbers
  1122. default: // because it was found to cause difficult to detect overflows
  1123. { assert(0); } // when the signal approached full scale.
  1124. }
  1125. // duplicate the audio buffer ptr array - this will allow the buffer ptr's to be changed
  1126. // during the float to int conversion without changing the ptrs passed in from the client
  1127. const void* ptrArray[ chCnt ];
  1128. memcpy(ptrArray,srcPtrPtr,sizeof(ptrArray));
  1129. const float** sfpp = (const float**)ptrArray;
  1130. const double** sdpp = (const double**)ptrArray;
  1131. while( wrFrmCnt < frmCnt )
  1132. {
  1133. unsigned n = cmMin( frmCnt - wrFrmCnt, bufFrmCnt );
  1134. for(i=0; i<chCnt; ++i)
  1135. {
  1136. int* obp = srcCh[i];
  1137. switch( realSmpByteCnt )
  1138. {
  1139. case 4:
  1140. {
  1141. const float* sbp = sfpp[i];
  1142. const float* sep = sbp + n;
  1143. for(;sbp<sep; ++sbp)
  1144. {
  1145. *obp++ = (int)fmaxf(-maxSmpVal,fminf(maxSmpVal, *sbp * maxSmpVal));
  1146. }
  1147. sfpp[i] = sbp;
  1148. }
  1149. break;
  1150. case 8:
  1151. {
  1152. const double* sbp = sdpp[i];
  1153. const double* sep = sbp + n;
  1154. for(; sbp<sep; ++sbp)
  1155. {
  1156. *obp++ = (int)fmax(-maxSmpVal,fmin(maxSmpVal,*sbp * maxSmpVal));
  1157. }
  1158. sdpp[i] = sbp;
  1159. }
  1160. break;
  1161. default:
  1162. { assert(0); }
  1163. }
  1164. }
  1165. if((rc = cmAudioFileWriteInt( h, n, chCnt, srcCh )) != kOkAfRC )
  1166. break;
  1167. wrFrmCnt += n;
  1168. }
  1169. return rc;
  1170. }
  1171. cmRC_t cmAudioFileWriteFloat( cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, float** bufPtrPtr )
  1172. { return _cmAudioFileWriteRealSamples(h,frmCnt,chCnt,bufPtrPtr,sizeof(float)); }
  1173. cmRC_t cmAudioFileWriteDouble( cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, double** bufPtrPtr )
  1174. { return _cmAudioFileWriteRealSamples(h,frmCnt,chCnt,bufPtrPtr,sizeof(double)); }
  1175. cmRC_t cmAudioFileMinMaxMean( cmAudioFileH_t h, unsigned chIdx, cmSample_t* minPtr, cmSample_t* maxPtr, cmSample_t* meanPtr )
  1176. {
  1177. assert( minPtr != NULL && maxPtr != NULL && meanPtr != NULL );
  1178. *minPtr = -cmSample_MAX;
  1179. *maxPtr = cmSample_MAX;
  1180. *meanPtr = 0;
  1181. cmRC_t rc = kOkAfRC;
  1182. cmAf_t* p = _cmAudioFileReadGutsPtr(h,&rc );
  1183. if( rc != kOkAfRC )
  1184. return rc;
  1185. unsigned orgFrmIdx = p->curFrmIdx;
  1186. if((rc = cmAudioFileSeek(h,0)) != kOkAfRC )
  1187. return rc;
  1188. *minPtr = cmSample_MAX;
  1189. *maxPtr = -cmSample_MAX;
  1190. unsigned bufN = 1024;
  1191. cmSample_t buf[ bufN ];
  1192. unsigned frmCnt = 0;
  1193. unsigned actualFrmCnt;
  1194. cmSample_t* bufPtr[1] = { &buf[0] };
  1195. for(; frmCnt<p->info.frameCnt; frmCnt+=actualFrmCnt)
  1196. {
  1197. actualFrmCnt = 0;
  1198. unsigned n = cmMin( p->info.frameCnt-frmCnt, bufN );
  1199. if((rc = cmAudioFileReadSample(h, n, chIdx, 1, bufPtr, &actualFrmCnt)) != kOkAfRC )
  1200. return rc;
  1201. const cmSample_t* sbp = buf;
  1202. const cmSample_t* sep = buf + actualFrmCnt;
  1203. for(; sbp < sep; ++sbp )
  1204. {
  1205. *meanPtr += *sbp;
  1206. if( *minPtr > *sbp )
  1207. *minPtr = *sbp;
  1208. if( *maxPtr < *sbp )
  1209. *maxPtr = *sbp;
  1210. }
  1211. }
  1212. if( frmCnt > 0 )
  1213. *meanPtr /= frmCnt;
  1214. else
  1215. *minPtr = *maxPtr = 0;
  1216. return cmAudioFileSeek( h, orgFrmIdx );
  1217. }
  1218. cmRC_t cmAudioFileWriteFileInt( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, int** bufPtrPtr, cmRpt_t* rpt )
  1219. {
  1220. cmRC_t rc0, rc1;
  1221. cmAudioFileH_t h = cmAudioFileNewCreate(fn, srate, bits, chCnt, &rc0, rpt );
  1222. if( (cmAudioFileIsValid(h)==false) || (rc0!=kOkAfRC))
  1223. return rc0;
  1224. rc0 = cmAudioFileWriteInt( h, frmCnt, chCnt, bufPtrPtr );
  1225. if(((rc1 = cmAudioFileDelete(&h))!=kOkAfRC) && (rc0!=kOkAfRC))
  1226. rc0 = rc1;
  1227. return rc0;
  1228. }
  1229. cmRC_t cmAudioFileWriteFileFloat( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, float** bufPtrPtr, cmRpt_t* rpt )
  1230. {
  1231. cmRC_t rc0, rc1;
  1232. cmAudioFileH_t h = cmAudioFileNewCreate(fn, srate, bits, chCnt, &rc0, rpt );
  1233. if( (cmAudioFileIsValid(h)==false) || (rc0!=kOkAfRC))
  1234. return rc0;
  1235. rc0 = cmAudioFileWriteFloat( h, frmCnt, chCnt, bufPtrPtr );
  1236. if(((rc1 = cmAudioFileDelete(&h))!=kOkAfRC) && (rc0!=kOkAfRC))
  1237. rc0 = rc1;
  1238. return rc0;
  1239. }
  1240. cmRC_t cmAudioFileWriteFileDouble( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, double** bufPtrPtr, cmRpt_t* rpt )
  1241. {
  1242. cmRC_t rc0, rc1;
  1243. cmAudioFileH_t h = cmAudioFileNewCreate(fn, srate, bits, chCnt, &rc0, rpt );
  1244. if( (cmAudioFileIsValid(h)==false) || (rc0!=kOkAfRC))
  1245. return rc0;
  1246. rc0 = cmAudioFileWriteDouble( h, frmCnt, chCnt, bufPtrPtr );
  1247. if(((rc1 = cmAudioFileDelete(&h))!=kOkAfRC) && (rc0!=kOkAfRC))
  1248. rc0 = rc1;
  1249. return rc0;
  1250. }
  1251. cmRC_t cmAudioFileMinMaxMeanFn( const cmChar_t* fn, unsigned chIdx, cmSample_t* minPtr, cmSample_t* maxPtr, cmSample_t* meanPtr, cmRpt_t* rpt )
  1252. {
  1253. cmRC_t rc0 = kOkAfRC;
  1254. cmRC_t rc1;
  1255. cmAudioFileH_t afH = cmAudioFileNewOpen( fn, NULL, &rc0, rpt );
  1256. if( rc0 != kOkAfRC )
  1257. return rc0;
  1258. rc0 = cmAudioFileMinMaxMean( afH, chIdx, minPtr, maxPtr, meanPtr );
  1259. rc1 = cmAudioFileDelete(&afH);
  1260. return rc0 != kOkAfRC ? rc0 : rc1;
  1261. }
  1262. const cmChar_t* cmAudioFileName( cmAudioFileH_t h )
  1263. {
  1264. cmRC_t rc;
  1265. cmAf_t* p = _cmAudioFileReadGutsPtr(h,&rc );
  1266. if( rc != kOkAfRC )
  1267. return NULL;
  1268. return p->fn;
  1269. }
  1270. const char* cmAudioFileErrorMsg( unsigned rc )
  1271. {
  1272. unsigned i;
  1273. for(i=0; _cmAudioFileErrArray[i].rc != kUnknownErrAfRC; ++i )
  1274. if( _cmAudioFileErrArray[i].rc == rc )
  1275. break;
  1276. return _cmAudioFileErrArray[i].msg;
  1277. }
  1278. cmRC_t cmAudioFileGetInfo( const cmChar_t* fn, cmAudioFileInfo_t* infoPtr, cmRpt_t* rpt )
  1279. {
  1280. cmRC_t rc = kOkAfRC;
  1281. cmAudioFileH_t afH = cmAudioFileNewOpen( fn, infoPtr, &rc, rpt );
  1282. if( rc != kOkAfRC )
  1283. return rc;
  1284. return cmAudioFileDelete(&afH);
  1285. }
  1286. void cmAudioFilePrintInfo( const cmAudioFileInfo_t* infoPtr, cmRpt_t* rpt )
  1287. {
  1288. char* typeStr = "AIFF";
  1289. char* swapStr = "";
  1290. char* aifcStr = "";
  1291. unsigned i;
  1292. if( cmIsFlag(infoPtr->flags,kWavAfFl) )
  1293. typeStr = "WAV";
  1294. if( cmIsFlag(infoPtr->flags,kSwapAfFl) )
  1295. swapStr = "Swap:On";
  1296. if( cmIsFlag(infoPtr->flags,kAifcAfFl))
  1297. aifcStr = "AIFC";
  1298. 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 );
  1299. for(i=0; i<infoPtr->markerCnt; ++i)
  1300. cmRptPrintf(rpt,"%i %i %s\n", infoPtr->markerArray[i].id, infoPtr->markerArray[i].frameIdx, infoPtr->markerArray[i].label);
  1301. if( strlen(infoPtr->bextRecd.desc) )
  1302. cmRptPrintf(rpt,"Bext Desc:%s\n",infoPtr->bextRecd.desc );
  1303. if( strlen(infoPtr->bextRecd.origin) )
  1304. cmRptPrintf(rpt,"Bext Origin:%s\n",infoPtr->bextRecd.origin );
  1305. if( strlen(infoPtr->bextRecd.originRef) )
  1306. cmRptPrintf(rpt,"Bext Origin Ref:%s\n",infoPtr->bextRecd.originRef );
  1307. if( strlen(infoPtr->bextRecd.originDate) )
  1308. cmRptPrintf(rpt,"Bext Origin Date:%s\n",infoPtr->bextRecd.originDate );
  1309. if( strlen(infoPtr->bextRecd.originTime ) )
  1310. cmRptPrintf(rpt,"Bext Origin Time:%s\n",infoPtr->bextRecd.originTime );
  1311. cmRptPrintf(rpt,"Bext time high:%i low:%i 0x%x%x\n",infoPtr->bextRecd.timeRefHigh,infoPtr->bextRecd.timeRefLow, infoPtr->bextRecd.timeRefHigh,infoPtr->bextRecd.timeRefLow);
  1312. }
  1313. cmRC_t cmAudioFileReport( cmAudioFileH_t h, cmRpt_t* rpt, unsigned frmIdx, unsigned frmCnt )
  1314. {
  1315. cmRC_t rc = kOkAfRC;
  1316. cmAf_t* p = _cmAudioFileReadGutsPtr(h,&rc);
  1317. if( rc != kOkAfRC )
  1318. return rc;
  1319. cmRptPrintf(rpt,"function cm_audio_file_test()\n");
  1320. cmRptPrintf(rpt,"#{\n");
  1321. cmAudioFilePrintInfo(&p->info,rpt);
  1322. cmRptPrintf(rpt,"#}\n");
  1323. float buf[ p->info.chCnt * frmCnt ];
  1324. float* bufPtr[p->info.chCnt];
  1325. unsigned i,j,cmtFrmCnt=0;
  1326. for(i=0; i<p->info.chCnt; ++i)
  1327. bufPtr[i] = buf + (i*frmCnt);
  1328. if((rc = cmAudioFileSeek(h,frmIdx)) != kOkAfRC )
  1329. return rc;
  1330. if((rc= cmAudioFileReadFloat(h,frmCnt,0,p->info.chCnt,bufPtr,&cmtFrmCnt )) != kOkAfRC)
  1331. return rc;
  1332. cmRptPrintf(rpt,"m = [\n");
  1333. for(i=0; i<frmCnt; i++)
  1334. {
  1335. for(j=0; j<p->info.chCnt; ++j)
  1336. cmRptPrintf(rpt,"%f ", bufPtr[j][i] );
  1337. cmRptPrintf(rpt,"\n");
  1338. }
  1339. cmRptPrintf(rpt,"];\nplot(m)\nendfunction\n");
  1340. return rc;
  1341. }
  1342. cmRC_t cmAudioFileReportFn( const cmChar_t* fn, unsigned frmIdx, unsigned frmCnt, cmRpt_t* rpt )
  1343. {
  1344. cmAudioFileInfo_t info;
  1345. cmRC_t rc;
  1346. cmAudioFileH_t h = cmAudioFileNewOpen( fn, &info, &rc, rpt );
  1347. if(rc == kOkAfRC )
  1348. {
  1349. cmAudioFileReport(h,rpt,frmIdx,frmCnt);
  1350. }
  1351. return cmAudioFileDelete(&h);
  1352. }
  1353. cmRC_t cmAudioFileReportInfo( cmCtx_t* ctx, const cmChar_t* audioFn, const cmChar_t* rptFn )
  1354. {
  1355. cmRC_t rc = kOkAfRC;
  1356. cmRptFileH_t rptH = cmRptFileNullHandle;
  1357. cmAudioFileInfo_t afInfo;
  1358. memset(&afInfo,0,sizeof(afInfo));
  1359. cmAudioFileH_t afH = cmAudioFileNewOpen( audioFn, &afInfo, &rc, &ctx->rpt );
  1360. if( rc != kOkAfRC )
  1361. {
  1362. rc = cmErrMsg(&ctx->err,rc,"Audio file '%s' open failed.",cmStringNullGuard(audioFn));
  1363. goto errLabel;
  1364. }
  1365. if(( rc = cmRptFileCreate(ctx, &rptH, rptFn, NULL )) != kOkRfRC )
  1366. {
  1367. rc = cmErrMsg(&ctx->err,kRptFileFailAfRC,"Unable to open the report file: %s\n",cmStringNullGuard(rptFn));
  1368. goto errLabel;
  1369. }
  1370. cmAudioFilePrintInfo(&afInfo,cmRptFileRpt(rptH));
  1371. errLabel:
  1372. cmRptFileClose(&rptH);
  1373. cmAudioFileDelete(&afH);
  1374. return rc;
  1375. }
  1376. cmRC_t cmAudioFileSetSrate( const cmChar_t* fn, unsigned srate )
  1377. {
  1378. cmRC_t rc = kOkAfRC;
  1379. cmAf_t af;
  1380. cmAf_t* p = &af;
  1381. memset(&af,0,sizeof(af));
  1382. if((rc = _cmAudioFileOpen(p, fn, "r+b")) != kOkAfRC )
  1383. goto errLabel;
  1384. if( p->info.srate != srate )
  1385. {
  1386. // change the sample rate
  1387. p->info.srate = srate;
  1388. // write the file header
  1389. if((rc = _cmAudioFileWriteHdr(p)) != kOkAfRC )
  1390. goto errLabel;
  1391. }
  1392. errLabel:
  1393. if( p->fp != NULL )
  1394. fclose(p->fp);
  1395. return rc;
  1396. }
  1397. void _cmAudioFileTest( const cmChar_t* audioFn, cmRpt_t* rpt )
  1398. {
  1399. cmAudioFileInfo_t afInfo;
  1400. cmRC_t cmRC;
  1401. // open an audio file
  1402. cmAudioFileH_t afH = cmAudioFileNewOpen( audioFn, &afInfo, &cmRC, rpt );
  1403. if( cmRC != kOkAfRC || cmAudioFileIsValid(afH)==false )
  1404. {
  1405. cmRptPrintf(rpt,"Unable to open the audio file:%s\n",audioFn);
  1406. return;
  1407. }
  1408. // print the header information and one seconds worth of samples
  1409. //cmAudioFileReport( afH, rpt, 66000, (unsigned)afInfo.srate);
  1410. cmAudioFileReport( afH, rpt, 0, 0);
  1411. // close and delete the audio file handle
  1412. cmAudioFileDelete(&afH);
  1413. }
  1414. cmRC_t cmAudioFileSine( cmCtx_t* ctx, const cmChar_t* fn, double srate, unsigned bits, double hz, double gain, double secs )
  1415. {
  1416. cmRC_t rc = kOkAfRC;
  1417. unsigned bN = srate * secs;
  1418. cmSample_t* b = cmMemAlloc(cmSample_t,bN);
  1419. unsigned chCnt = 1;
  1420. unsigned i;
  1421. for(i=0; i<bN; ++i)
  1422. b[i] = gain * sin(2.0*M_PI*hz*i/srate);
  1423. if((rc = cmAudioFileWriteFileFloat(fn, srate, bits, bN, chCnt, &b, &ctx->rpt)) != kOkAfRC)
  1424. return rc;
  1425. return rc;
  1426. }
  1427. /// [cmAudioFileExample]
  1428. void cmAudioFileTest(cmCtx_t* ctx, int argc, const char* argv[])
  1429. {
  1430. switch( argc )
  1431. {
  1432. case 3:
  1433. //_cmAudioFileTest(argv[2],&ctx->rpt);
  1434. cmAudioFileReportFn(argv[2],0,0,&ctx->rpt);
  1435. break;
  1436. case 4:
  1437. {
  1438. errno = 0;
  1439. long srate = strtol(argv[3], NULL, 10);
  1440. if( srate == 0 && errno != 0 )
  1441. cmRptPrintf(&ctx->rpt,"Invalid sample rate argument to cmAudioFileTest().");
  1442. else
  1443. cmAudioFileSetSrate(argv[2],srate);
  1444. }
  1445. break;
  1446. case 8:
  1447. {
  1448. errno = 0;
  1449. double srate = strtod(argv[3],NULL);
  1450. unsigned bits = strtol(argv[4],NULL,10);
  1451. double hz = strtod(argv[5],NULL);
  1452. double gain = strtod(argv[6],NULL);
  1453. double secs = strtod(argv[7],NULL);
  1454. if( errno != 0 )
  1455. cmRptPrintf(&ctx->rpt,"Invalid arg. to cmAudioFileTest().");
  1456. cmAudioFileSine( ctx, argv[2], srate, bits, hz, gain, secs );
  1457. }
  1458. break;
  1459. default:
  1460. cmRptPrintf(&ctx->rpt,"Invalid argument count to cmAudioFileTest().");
  1461. break;
  1462. }
  1463. }
  1464. /// [cmAudioFileExample]