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 51KB

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