Browse Source

cmAudioFile.h/c : Added cmAudioFileSetSRate(), cmAudioFileSine() and chnaged cmAudioFileTest() to take a variable argument list.

Added the ability to write WAV files.
cmAudioFileCreate() now creates a WAV or AIF header based on the file name extension.
master
Kevin Larke 9 years ago
parent
commit
072831b32a
2 changed files with 364 additions and 139 deletions
  1. 352
    137
      cmAudioFile.c
  2. 12
    2
      cmAudioFile.h

+ 352
- 137
cmAudioFile.c View File

@@ -12,20 +12,19 @@
12 12
 
13 13
 
14 14
 // #define _24to32_aif( p ) ((int)( ((p[0]>127?255:0) << 24) + (((int)p[0]) << 16) +  (((int)p[1]) <<8) + p[2]))  // no-swap equivalent
15
-// See note in:_cmAudioFileReadAiffHeader()
15
+// See note in:_cmAudioFileReadFileHdr()
16 16
 // Note that this code byte swaps as it converts - this is to counter the byte swap that occurs in cmAudioFileReadInt().
17 17
 #define _24to32_aif( p ) ((int)( ((p[0]>127?255:0) <<  0) + (((int)p[2]) << 24) +  (((int)p[1]) <<16) + (((int)p[0]) << 8)))
18 18
 
19 19
 #define _24to32_wav( p ) ((int)( ((p[2]>127?255:0) << 24) + (((int)p[2]) << 16) +  (((int)p[1]) <<8) + p[0]))
20 20
 
21
+#define _cmAfSwap16(v)  cmSwap16(v)
22
+#define _cmAfSwap32(v)  cmSwap32(v)
23
+
21 24
 #ifdef cmBIG_ENDIAN
22
-#define _cmAfSwap16(v)  (v)
23
-#define _cmAfSwap32(v)  (v)
24 25
 #define _cmAifSwapFl    (0)
25 26
 #define _cmWavSwapFl    (1)
26 27
 #else
27
-#define _cmAfSwap16(v)  cmSwap16(v)
28
-#define _cmAfSwap32(v)  cmSwap32(v)
29 28
 #define _cmAifSwapFl    (1)
30 29
 #define _cmWavSwapFl    (0)
31 30
 #endif
@@ -61,7 +60,7 @@ typedef struct
61 60
   cmAudioFileMarker_t* markArray;
62 61
   unsigned             flags;
63 62
   cmChar_t*            fn;
64
-} cmAudioFileGuts;
63
+} cmAf_t;
65 64
 
66 65
 cmAudioErrRecd _cmAudioFileErrArray[] = 
67 66
 {
@@ -81,9 +80,9 @@ cmAudioErrRecd _cmAudioFileErrArray[] =
81 80
 
82 81
 cmAudioFileH_t cmNullAudioFileH = { NULL };
83 82
 
84
-cmAudioFileGuts* _cmAudioFileGutsPtr( cmAudioFileH_t h )
83
+cmAf_t* _cmAudioFileHandleToPtr( cmAudioFileH_t h )
85 84
 {
86
-  cmAudioFileGuts* p = (cmAudioFileGuts*)h.h;
85
+  cmAf_t* p = (cmAf_t*)h.h;
87 86
   
88 87
   if( p == NULL )
89 88
     assert(p!=NULL);
@@ -91,7 +90,7 @@ cmAudioFileGuts* _cmAudioFileGutsPtr( cmAudioFileH_t h )
91 90
   return p;
92 91
 }
93 92
 
94
-cmRC_t _cmAudioFileError( cmAudioFileGuts* p, cmRC_t rc )
93
+cmRC_t _cmAudioFileError( cmAf_t* p, cmRC_t rc )
95 94
 {
96 95
   if( rc > kUnknownErrAfRC )
97 96
     rc = kUnknownErrAfRC;
@@ -100,11 +99,11 @@ cmRC_t _cmAudioFileError( cmAudioFileGuts* p, cmRC_t rc )
100 99
   return rc;
101 100
 }
102 101
 
103
-cmAudioFileGuts* _cmAudioFileValidate( cmAudioFileH_t h, cmRC_t* rcPtr, bool writeFl )
102
+cmAf_t* _cmAudioFileValidate( cmAudioFileH_t h, cmRC_t* rcPtr, bool writeFl )
104 103
 {
105 104
   *rcPtr = kOkAfRC;
106 105
 
107
-  cmAudioFileGuts* p = _cmAudioFileGutsPtr(h);
106
+  cmAf_t* p = _cmAudioFileHandleToPtr(h);
108 107
 
109 108
   if( p == NULL )
110 109
     *rcPtr =  kInvalidHandleAfRC;
@@ -116,22 +115,22 @@ cmAudioFileGuts* _cmAudioFileValidate( cmAudioFileH_t h, cmRC_t* rcPtr, bool wri
116 115
   return *rcPtr == kOkAfRC ? p : NULL;
117 116
 }
118 117
 
119
-cmAudioFileGuts* _cmAudioFileReadGutsPtr( cmAudioFileH_t h, cmRC_t* rcPtr )
118
+cmAf_t* _cmAudioFileReadGutsPtr( cmAudioFileH_t h, cmRC_t* rcPtr )
120 119
 { return _cmAudioFileValidate( h, rcPtr, false ); }
121 120
 
122
-cmAudioFileGuts* _cmAudioFileWriteGutsPtr( cmAudioFileH_t h, cmRC_t* rcPtr )
121
+cmAf_t* _cmAudioFileWriteGutsPtr( cmAudioFileH_t h, cmRC_t* rcPtr )
123 122
 { return _cmAudioFileValidate( h, rcPtr, true ); }
124 123
 
125 124
 
126 125
 
127
-cmRC_t _cmAudioFileSeek( cmAudioFileGuts* p, long byteOffset, int origin )
126
+cmRC_t _cmAudioFileSeek( cmAf_t* p, long byteOffset, int origin )
128 127
 {
129 128
   if( fseek(p->fp,byteOffset,origin) != 0 )
130 129
     return _cmAudioFileError(p,kSeekFailAfRC);
131 130
   return kOkAfRC;
132 131
 }
133 132
 
134
-cmRC_t _cmAudioFileRead( cmAudioFileGuts* p, void* eleBuf, unsigned bytesPerEle, unsigned eleCnt )
133
+cmRC_t _cmAudioFileRead( cmAf_t* p, void* eleBuf, unsigned bytesPerEle, unsigned eleCnt )
135 134
 {
136 135
   if( fread(eleBuf,bytesPerEle,eleCnt,p->fp) != eleCnt )
137 136
     return _cmAudioFileError(p,kReadFailAfRC);
@@ -139,13 +138,12 @@ cmRC_t _cmAudioFileRead( cmAudioFileGuts* p, void* eleBuf, unsigned bytesPerEle,
139 138
   return kOkAfRC;
140 139
 }
141 140
 
142
-cmRC_t _cmAudioFileReadUInt32( cmAudioFileGuts* p, cmUInt32_t* valuePtr )
141
+cmRC_t _cmAudioFileReadUInt32( cmAf_t* p, cmUInt32_t* valuePtr )
143 142
 {
144 143
   cmRC_t rc;
145 144
 
146 145
   if(( rc = _cmAudioFileRead(p, valuePtr, sizeof(*valuePtr), 1 )) != kOkAfRC )
147 146
     return rc;
148
-
149 147
     
150 148
   if( cmIsFlag(p->info.flags,kSwapAfFl) )
151 149
       *valuePtr = _cmAfSwap32(*valuePtr);
@@ -154,7 +152,7 @@ cmRC_t _cmAudioFileReadUInt32( cmAudioFileGuts* p, cmUInt32_t* valuePtr )
154 152
 } 
155 153
 
156 154
 
157
-cmRC_t _cmAudioFileReadUInt16( cmAudioFileGuts* p, cmUInt16_t* valuePtr )
155
+cmRC_t _cmAudioFileReadUInt16( cmAf_t* p, cmUInt16_t* valuePtr )
158 156
 {
159 157
   cmRC_t rc;
160 158
 
@@ -167,7 +165,7 @@ cmRC_t _cmAudioFileReadUInt16( cmAudioFileGuts* p, cmUInt16_t* valuePtr )
167 165
   return rc;
168 166
 } 
169 167
 
170
-cmRC_t _cmAudioFileReadPascalString( cmAudioFileGuts* p, char s[kAudioFileLabelCharCnt] )
168
+cmRC_t _cmAudioFileReadPascalString( cmAf_t* p, char s[kAudioFileLabelCharCnt] )
171 169
 {
172 170
   cmRC_t rc;
173 171
   unsigned char n;
@@ -186,7 +184,7 @@ cmRC_t _cmAudioFileReadPascalString( cmAudioFileGuts* p, char s[kAudioFileLabelC
186 184
   return rc;
187 185
 }
188 186
 
189
-cmRC_t _cmAudioFileReadString( cmAudioFileGuts* p, char* s, unsigned sn )
187
+cmRC_t _cmAudioFileReadString( cmAf_t* p, char* s, unsigned sn )
190 188
 {
191 189
   cmRC_t rc;
192 190
   if((rc = _cmAudioFileRead(p,s,sn,1)) != kOkAfRC )
@@ -195,7 +193,7 @@ cmRC_t _cmAudioFileReadString( cmAudioFileGuts* p, char* s, unsigned sn )
195 193
   return kOkAfRC;
196 194
 }
197 195
 
198
-cmRC_t _cmAudioFileReadX80( cmAudioFileGuts* p, double* x80Ptr )
196
+cmRC_t _cmAudioFileReadX80( cmAf_t* p, double* x80Ptr )
199 197
 {
200 198
   unsigned char s[10];
201 199
   cmRC_t rc = kOkAfRC;
@@ -207,7 +205,7 @@ cmRC_t _cmAudioFileReadX80( cmAudioFileGuts* p, double* x80Ptr )
207 205
   return kOkAfRC;
208 206
 }
209 207
 
210
-cmRC_t _cmAudioFileReadChunkHdr( cmAudioFileGuts* p, cmUInt32_t* chkIdPtr, unsigned* chkByteCntPtr )
208
+cmRC_t _cmAudioFileReadChunkHdr( cmAf_t* p, cmUInt32_t* chkIdPtr, unsigned* chkByteCntPtr )
211 209
 {
212 210
   cmRC_t rc      = kOkAfRC;
213 211
 
@@ -226,7 +224,7 @@ cmRC_t _cmAudioFileReadChunkHdr( cmAudioFileGuts* p, cmUInt32_t* chkIdPtr, unsig
226 224
   return rc;
227 225
 }
228 226
 
229
-cmRC_t _cmAudioFileReadAiffHeader( cmAudioFileGuts* p, unsigned constFormId, unsigned constAifId, bool swapFl )
227
+cmRC_t _cmAudioFileReadFileHdr( cmAf_t* p, unsigned constFormId, unsigned constAifId, bool swapFl )
230 228
 {
231 229
   cmRC_t     rc         = kOkAfRC;
232 230
   cmUInt32_t formId     = 0;
@@ -280,7 +278,7 @@ cmRC_t _cmAudioFileReadAiffHeader( cmAudioFileGuts* p, unsigned constFormId, uns
280 278
   return rc;
281 279
 }
282 280
 
283
-cmRC_t _cmAudioFileReadCommChunk( cmAudioFileGuts* p )
281
+cmRC_t _cmAudioFileReadCommChunk( cmAf_t* p )
284 282
 {
285 283
   cmRC_t rc = kOkAfRC;
286 284
   cmUInt16_t ui16;
@@ -330,7 +328,7 @@ cmRC_t _cmAudioFileReadCommChunk( cmAudioFileGuts* p )
330 328
   return rc;
331 329
 }
332 330
 
333
-cmRC_t _cmAudioFileReadSsndChunk( cmAudioFileGuts* p )
331
+cmRC_t _cmAudioFileReadSsndChunk( cmAf_t* p )
334 332
 {
335 333
   cmRC_t rc = kOkAfRC;
336 334
 
@@ -350,7 +348,7 @@ cmRC_t _cmAudioFileReadSsndChunk( cmAudioFileGuts* p )
350 348
   return rc;
351 349
 }
352 350
 
353
-cmRC_t _cmAudioFileReadMarkerChunk( cmAudioFileGuts* p )
351
+cmRC_t _cmAudioFileReadMarkerChunk( cmAf_t* p )
354 352
 {
355 353
   cmRC_t rc = kOkAfRC;
356 354
 
@@ -388,7 +386,7 @@ cmRC_t _cmAudioFileReadMarkerChunk( cmAudioFileGuts* p )
388 386
   return rc;
389 387
 }
390 388
 
391
-cmRC_t _cmAudioFileReadFmtChunk( cmAudioFileGuts* p )
389
+cmRC_t _cmAudioFileReadFmtChunk( cmAf_t* p )
392 390
 {
393 391
   cmRC_t rc = kOkAfRC;
394 392
   unsigned short fmtId, chCnt, blockAlign, bits;
@@ -424,7 +422,7 @@ cmRC_t _cmAudioFileReadFmtChunk( cmAudioFileGuts* p )
424 422
   return rc;
425 423
 }
426 424
 
427
-cmRC_t _cmAudioFileReadDatcmhunk( cmAudioFileGuts* p, unsigned chkByteCnt )
425
+cmRC_t _cmAudioFileReadDatcmhunk( cmAf_t* p, unsigned chkByteCnt )
428 426
 {
429 427
   // if the 'fmt' chunk was read before the 'data' chunk then info.chCnt is non-zero
430 428
   if( p->info.chCnt != 0 )
@@ -437,7 +435,7 @@ cmRC_t _cmAudioFileReadDatcmhunk( cmAudioFileGuts* p, unsigned chkByteCnt )
437 435
   return kOkAfRC;
438 436
 }
439 437
 
440
-cmRC_t _cmAudioFileReadBextChunk( cmAudioFileGuts* p)
438
+cmRC_t _cmAudioFileReadBextChunk( cmAf_t* p)
441 439
 {
442 440
   cmRC_t rc = kOkAfRC;
443 441
 
@@ -472,8 +470,8 @@ cmAudioFileH_t cmAudioFileNewOpen( const cmChar_t* fn, cmAudioFileInfo_t* afInfo
472 470
   cmAudioFileH_t h;
473 471
   cmRC_t       rc        = kOkAfRC;
474 472
 
475
-  h.h = cmMemAllocZ( cmAudioFileGuts, 1 );  
476
-  cmErrSetup(&((cmAudioFileGuts*)h.h)->err,rpt,"Audio File");
473
+  h.h = cmMemAllocZ( cmAf_t, 1 );  
474
+  cmErrSetup(&((cmAf_t*)h.h)->err,rpt,"Audio File");
477 475
 
478 476
   if( fn != NULL )
479 477
     if((rc = cmAudioFileOpen(h,fn,afInfoPtr)) != kOkAfRC )
@@ -496,8 +494,8 @@ cmAudioFileH_t cmAudioFileNewCreate( const cmChar_t* fn, double srate, unsigned
496 494
   cmAudioFileH_t h;
497 495
   cmRC_t rc = kOkAfRC;
498 496
 
499
-  h.h = cmMemAllocZ(cmAudioFileGuts,1);
500
-  cmErrSetup(&((cmAudioFileGuts*)h.h)->err,rpt,"Audio File");
497
+  h.h = cmMemAllocZ(cmAf_t,1);
498
+  cmErrSetup(&((cmAf_t*)h.h)->err,rpt,"Audio File");
501 499
   
502 500
   if( fn != NULL )
503 501
     if((rc = cmAudioFileCreate(h,fn,srate,bits,chCnt)) != kOkAfRC )
@@ -515,23 +513,15 @@ cmAudioFileH_t cmAudioFileNewCreate( const cmChar_t* fn, double srate, unsigned
515 513
   return h;    
516 514
 }
517 515
 
518
-cmRC_t     cmAudioFileOpen(  cmAudioFileH_t h, const cmChar_t* fn, cmAudioFileInfo_t* infoPtr )
516
+cmRC_t _cmAudioFileOpen( cmAf_t* p, const cmChar_t* fn, const char* fileModeStr )
519 517
 {
520 518
   cmRC_t rc = kOkAfRC;
521
-
522
-  cmAudioFileGuts* p = _cmAudioFileGutsPtr(h);
523
-
524
-  // verify the file is closed before opening
525
-  if( cmAudioFileIsOpen(h) )
526
-    if((rc = cmAudioFileClose(&h)) != kOkAfRC )
527
-      return rc;
528
-
519
+  
529 520
   // zero the info record
530 521
   memset(&p->info,0,sizeof(p->info));
531 522
 
532
-
533 523
   // open the file
534
-  if((p->fp = fopen(fn,"rb")) == NULL )
524
+  if((p->fp = fopen(fn,fileModeStr)) == NULL )
535 525
   {
536 526
     p->fn = (cmChar_t*)fn; // set the file name so that the error msg can use it
537 527
     rc    = _cmAudioFileError(p,kOpenFailAfRC);
@@ -540,8 +530,8 @@ cmRC_t     cmAudioFileOpen(  cmAudioFileH_t h, const cmChar_t* fn, cmAudioFileIn
540 530
   }
541 531
 
542 532
   // read the file header
543
-  if((rc = _cmAudioFileReadAiffHeader(p,kAiffFileId,kAiffChkId,_cmAifSwapFl)) != kOkAfRC )
544
-    if((rc = _cmAudioFileReadAiffHeader(p,kWavFileId,kWavChkId,_cmWavSwapFl)) != kOkAfRC )
533
+  if((rc = _cmAudioFileReadFileHdr(p,kAiffFileId,kAiffChkId,_cmAifSwapFl)) != kOkAfRC )
534
+    if((rc = _cmAudioFileReadFileHdr(p,kWavFileId,kWavChkId,_cmWavSwapFl)) != kOkAfRC )
545 535
       goto errLabel;
546 536
   
547 537
   // seek past the file header
@@ -603,6 +593,32 @@ cmRC_t     cmAudioFileOpen(  cmAudioFileH_t h, const cmChar_t* fn, cmAudioFileIn
603 593
       goto errLabel;
604 594
   }
605 595
 
596
+ errLabel:
597
+  if( rc!=kOkAfRC && p->fp != NULL )
598
+  {
599
+    fclose(p->fp);
600
+    p->fp = NULL;
601
+  }
602
+
603
+  return rc;
604
+}
605
+
606
+
607
+cmRC_t     cmAudioFileOpen(  cmAudioFileH_t h, const cmChar_t* fn, cmAudioFileInfo_t* infoPtr )
608
+{
609
+  cmRC_t rc = kOkAfRC;
610
+
611
+  cmAf_t* p = _cmAudioFileHandleToPtr(h);
612
+
613
+  // verify the file is closed before opening
614
+  if( cmAudioFileIsOpen(h) )
615
+    if((rc = cmAudioFileClose(&h)) != kOkAfRC )
616
+      return rc;
617
+
618
+  // read the file header
619
+  if((rc = _cmAudioFileOpen(p, fn, "rb" )) != kOkAfRC )
620
+    goto errLabel;
621
+
606 622
   // seek to the first sample offset
607 623
   if((rc = _cmAudioFileSeek(p,p->smpByteOffs,SEEK_SET)) != kOkAfRC )
608 624
     goto errLabel;
@@ -617,11 +633,10 @@ cmRC_t     cmAudioFileOpen(  cmAudioFileH_t h, const cmChar_t* fn, cmAudioFileIn
617 633
 
618 634
  errLabel:
619 635
   cmAudioFileClose(&h);
620
-  return rc;
621
-  
636
+  return rc;  
622 637
 }
623 638
 
624
-cmRC_t   _cmAudioFileWriteBytes( cmAudioFileGuts* p, const void* b, unsigned bn )
639
+cmRC_t   _cmAudioFileWriteBytes( cmAf_t* p, const void* b, unsigned bn )
625 640
 {
626 641
   cmRC_t rc = kOkAfRC;
627 642
   if( fwrite( b, bn, 1, p->fp ) != 1 )
@@ -630,23 +645,27 @@ cmRC_t   _cmAudioFileWriteBytes( cmAudioFileGuts* p, const void* b, unsigned bn
630 645
   return rc;
631 646
 }
632 647
 
633
-cmRC_t _cmAudioFileWriteId( cmAudioFileGuts* p, const char* s )
648
+cmRC_t _cmAudioFileWriteId( cmAf_t* p, const char* s )
634 649
 {  return _cmAudioFileWriteBytes( p,  s, strlen(s)) ; }
635 650
 
636
-cmRC_t _cmAudioFileWriteUInt32( cmAudioFileGuts* p, unsigned v )
651
+cmRC_t _cmAudioFileWriteUInt32( cmAf_t* p, unsigned v )
637 652
 {
638
-  v = _cmAfSwap32(v);
653
+  if( cmIsFlag(p->info.flags,kSwapAfFl) )
654
+    v = _cmAfSwap32(v);
655
+  
639 656
   return _cmAudioFileWriteBytes( p, &v, sizeof(v)) ; 
640 657
 }
641 658
 
642
-cmRC_t _cmAudioFileWriteUInt16( cmAudioFileGuts* p, unsigned short v )
643
-{  
644
-  v = _cmAfSwap16(v);
659
+cmRC_t _cmAudioFileWriteUInt16( cmAf_t* p, unsigned short v )
660
+{
661
+  if( cmIsFlag(p->info.flags,kSwapAfFl) )
662
+    v = _cmAfSwap16(v);
663
+  
645 664
   return _cmAudioFileWriteBytes( p, &v, sizeof(v)) ; 
646 665
 
647 666
 }
648 667
 
649
-cmRC_t   _cmAudioFileWriteHdr( cmAudioFileGuts* p )
668
+cmRC_t _cmAudioFileWriteAiffHdr( cmAf_t* p )
650 669
 {
651 670
   cmRC_t        rc = kOkAfRC;
652 671
   unsigned char srateX80[10];
@@ -685,18 +704,63 @@ cmRC_t   _cmAudioFileWriteHdr( cmAudioFileGuts* p )
685 704
   return rc;
686 705
 }
687 706
 
707
+cmRC_t _cmAudioFileWriteWavHdr( cmAf_t* p )
708
+{
709
+  cmRC_t   rc            = kOkAfRC;
710
+  short    chCnt         = p->info.chCnt;
711
+  unsigned frmCnt        = p->info.frameCnt;
712
+  short    bits          = p->info.bits;
713
+  unsigned srate         = p->info.srate;
714
+  short    fmtId         = 1;
715
+  unsigned bytesPerSmp   = bits/8;
716
+  unsigned hdrByteCnt    = 36;
717
+  unsigned fmtByteCnt    = 16;
718
+  unsigned blockAlignCnt = chCnt * bytesPerSmp;
719
+  unsigned sampleCnt     = chCnt * frmCnt;
720
+  unsigned dataByteCnt   = sampleCnt * bytesPerSmp;
721
+
722
+  if(( rc = _cmAudioFileSeek( p, 0, SEEK_SET )) != kOkAfRC )
723
+    return rc;
724
+
725
+  if((rc = _cmAudioFileWriteId(     p, "RIFF"))                   != kOkAfRC ) goto errLabel;
726
+  if((rc = _cmAudioFileWriteUInt32( p, hdrByteCnt + dataByteCnt)) != kOkAfRC ) goto errLabel;
727
+  if((rc = _cmAudioFileWriteId(     p, "WAVE"))                   != kOkAfRC ) goto errLabel;
728
+  if((rc = _cmAudioFileWriteId(     p, "fmt "))                   != kOkAfRC ) goto errLabel;
729
+  if((rc = _cmAudioFileWriteUInt32( p, fmtByteCnt))               != kOkAfRC ) goto errLabel;
730
+  if((rc = _cmAudioFileWriteUInt16( p, fmtId))                    != kOkAfRC ) goto errLabel;
731
+  if((rc = _cmAudioFileWriteUInt16( p, chCnt))                    != kOkAfRC ) goto errLabel;
732
+  if((rc = _cmAudioFileWriteUInt32( p, srate))                    != kOkAfRC ) goto errLabel;
733
+  if((rc = _cmAudioFileWriteUInt32( p, srate * blockAlignCnt))    != kOkAfRC ) goto errLabel;
734
+  if((rc = _cmAudioFileWriteUInt16( p, blockAlignCnt))            != kOkAfRC ) goto errLabel;
735
+  if((rc = _cmAudioFileWriteUInt16( p, bits))                     != kOkAfRC ) goto errLabel;
736
+  if((rc = _cmAudioFileWriteId(     p, "data"))                   != kOkAfRC ) goto errLabel;
737
+  if((rc = _cmAudioFileWriteUInt32( p, dataByteCnt))              != kOkAfRC ) goto errLabel;
738
+
739
+ errLabel:
740
+  return rc;
741
+}
742
+
743
+cmRC_t _cmAudioFileWriteHdr( cmAf_t* p )
744
+{
745
+  if( cmIsFlag(p->info.flags,kWavAfFl) )
746
+    return _cmAudioFileWriteWavHdr(p);
747
+
748
+  return _cmAudioFileWriteAiffHdr(p);
749
+}
750
+
688 751
 cmRC_t     cmAudioFileCreate(  cmAudioFileH_t h, const cmChar_t* fn, double srate, unsigned bits, unsigned chCnt )
689 752
 {
690
-  cmRC_t           rc  = kOkAfRC;
691
-  cmAudioFileGuts* p   = _cmAudioFileGutsPtr(h);
692
-  cmFileSysPathPart_t* pp = NULL;
753
+  cmRC_t               rc     = kOkAfRC;
754
+  cmAf_t*              p      = _cmAudioFileHandleToPtr(h);
755
+  cmFileSysPathPart_t* pp     = NULL;
693 756
 
694 757
   // verify the file is closed before opening
695 758
   if( cmAudioFileIsOpen(h) )
696 759
     if((rc = cmAudioFileClose(&h)) != kOkAfRC )
697 760
       return rc;
698 761
 
699
-  // all audio files are written as AIF's - if the file name is given some other extension then issue a warning
762
+  // all audio files are written as AIF's or WAV's -
763
+  // if the file name is given some other extension then issue a warning and write an AIF.
700 764
   if( fn!=NULL && strlen(fn) && ((pp = cmFsPathParts(fn)) != NULL) )
701 765
   {
702 766
     unsigned i;
@@ -712,13 +776,25 @@ cmRC_t     cmAudioFileCreate(  cmAudioFileH_t h, const cmChar_t* fn, double srat
712 776
         ext[i] = toupper(ext[i]);
713 777
     }
714 778
 
715
-    if( pp->extStr==NULL || (strcmp(ext,"AIF") && strcmp(ext,"AIFF")) )
716
-      cmRptPrintf(p->err.rpt,"The AIF audio file '%s' is being written with a file extension other than 'AIF' or 'AIFF'.",cmStringNullGuard(fn));
779
+    // determine the file type to write
780
+    if( cmIsFlag(p->info.flags,kWavAfFl) || strcmp(ext,"WAV")==0 )
781
+    {
782
+      p->info.flags = cmSetFlag(p->info.flags,kWavAfFl);
783
+      p->info.flags = cmClrFlag(p->info.flags,kAiffAfFl);      
784
+    }
785
+    else
786
+    {
787
+      if( pp->extStr==NULL || (strcmp(ext,"AIF") && strcmp(ext,"AIFF")) )
788
+        cmRptPrintf(p->err.rpt,"The AIF audio file '%s' is being written with a file extension other than 'AIF' or 'AIFF'.",cmStringNullGuard(fn));
717 789
       
790
+      p->info.flags = cmClrFlag(p->info.flags,kWavAfFl);
791
+      p->info.flags = cmSetFlag(p->info.flags,kAiffAfFl);
792
+    }
793
+    
718 794
     cmFsFreePathParts(pp);
719 795
   }
720 796
 
721
-  // open the file
797
+  // open the file for writing
722 798
   if((p->fp = fopen(fn,"wb")) == NULL )
723 799
   {
724 800
     p->fn = (cmChar_t*)fn; // set the file name so that the error msg can use it
@@ -727,18 +803,25 @@ cmRC_t     cmAudioFileCreate(  cmAudioFileH_t h, const cmChar_t* fn, double srat
727 803
     goto errLabel;
728 804
   }
729 805
 
730
-  p->fn = cmMemResize( char, p->fn, strlen(fn)+1 );
806
+  p->fn            = cmMemResize( char, p->fn, strlen(fn)+1 );
731 807
   p->info.srate    = srate;
732 808
   p->info.bits     = bits;
733 809
   p->info.chCnt    = chCnt;
734 810
   p->info.frameCnt = 0;
735 811
   p->flags         = kWriteAudioGutsFl;
812
+
813
+    // set the swap flags
814
+  bool swapFl = cmIsFlag(p->info.flags,kWavAfFl) ?  _cmWavSwapFl :  _cmAifSwapFl;
815
+
816
+  p->info.flags = cmEnaFlag(p->info.flags,kSwapAfFl,       swapFl);
817
+  p->info.flags = cmEnaFlag(p->info.flags,kSwapSamplesAfFl,swapFl);
818
+
736 819
   
737 820
   strcpy(p->fn,fn);
738 821
 
739
-  if((rc = _cmAudioFileWriteHdr( p )) != kOkAfRC )
822
+  if((rc = _cmAudioFileWriteHdr(p)) != kOkAfRC )
740 823
     goto errLabel;
741
-
824
+    
742 825
   return rc;
743 826
 
744 827
  errLabel:
@@ -751,7 +834,7 @@ cmRC_t     cmAudioFileClose( cmAudioFileH_t* h )
751 834
 {
752 835
   assert( h != NULL);
753 836
 
754
-  cmAudioFileGuts* p  = _cmAudioFileGutsPtr(*h);
837
+  cmAf_t* p  = _cmAudioFileHandleToPtr(*h);
755 838
   cmRC_t         rc = kOkAfRC;
756 839
 
757 840
   if( p->fp == NULL )
@@ -785,7 +868,7 @@ cmRC_t     cmAudioFileDelete( cmAudioFileH_t* h)
785 868
   if( h->h == NULL )
786 869
     return kOkAfRC;
787 870
 
788
-  cmAudioFileGuts* p = _cmAudioFileGutsPtr(*h);
871
+  cmAf_t* p = _cmAudioFileHandleToPtr(*h);
789 872
 
790 873
   if( p->fp != NULL )
791 874
     rc = cmAudioFileClose(h);
@@ -805,28 +888,28 @@ bool     cmAudioFileIsOpen( cmAudioFileH_t h )
805 888
   if( !cmAudioFileIsValid(h) )
806 889
     return false;
807 890
  
808
-  return _cmAudioFileGutsPtr(h)->fp != NULL;
891
+  return _cmAudioFileHandleToPtr(h)->fp != NULL;
809 892
 }
810 893
 
811 894
 
812 895
 bool   cmAudioFileIsEOF(      cmAudioFileH_t h )
813 896
 {
814 897
   cmRC_t           rc = kOkAfRC;
815
-  cmAudioFileGuts* p  = _cmAudioFileReadGutsPtr(h,&rc);
898
+  cmAf_t* p  = _cmAudioFileReadGutsPtr(h,&rc);
816 899
   return  (rc != kOkAfRC) || (p==NULL) || (p->curFrmIdx >= p->info.frameCnt) || (p->fp==NULL) ||  feof(p->fp) ? true : false;
817 900
 }
818 901
 
819 902
 unsigned   cmAudioFileTell(       cmAudioFileH_t h )
820 903
 {
821 904
   cmRC_t           rc = kOkAfRC;
822
-  cmAudioFileGuts* p  = _cmAudioFileReadGutsPtr(h,&rc);
905
+  cmAf_t* p  = _cmAudioFileReadGutsPtr(h,&rc);
823 906
   return (rc==kOkAfRC && p!=NULL) ? p->curFrmIdx : cmInvalidIdx;
824 907
 }
825 908
 
826 909
 cmRC_t     cmAudioFileSeek(       cmAudioFileH_t h, unsigned frmIdx )
827 910
 {
828 911
   cmRC_t           rc = kOkAfRC;
829
-  cmAudioFileGuts* p  = _cmAudioFileReadGutsPtr(h,&rc);
912
+  cmAf_t* p  = _cmAudioFileReadGutsPtr(h,&rc);
830 913
   
831 914
   if( rc != kOkAfRC )
832 915
     return rc;
@@ -840,12 +923,10 @@ cmRC_t     cmAudioFileSeek(       cmAudioFileH_t h, unsigned frmIdx )
840 923
 
841 924
 }
842 925
 
843
-
844
-
845 926
 cmRC_t _cmAudioFileReadInt( cmAudioFileH_t h, unsigned totalFrmCnt, unsigned chIdx, unsigned chCnt, int* buf[], unsigned* actualFrmCntPtr, bool sumFl )
846 927
 {
847 928
   cmRC_t           rc  = kOkAfRC;
848
-  cmAudioFileGuts* p   = _cmAudioFileReadGutsPtr(h,&rc);
929
+  cmAf_t* p   = _cmAudioFileReadGutsPtr(h,&rc);
849 930
 
850 931
   if( rc != kOkAfRC )
851 932
     return rc;  
@@ -1013,7 +1094,7 @@ cmRC_t _cmAudioFileReadInt( cmAudioFileH_t h, unsigned totalFrmCnt, unsigned chI
1013 1094
 cmRC_t _cmAudioFileReadRealSamples(  cmAudioFileH_t h, unsigned totalFrmCnt, unsigned chIdx, unsigned chCnt, float**  fbuf, double** dbuf, unsigned* actualFrmCntPtr, bool sumFl )
1014 1095
 {
1015 1096
   cmRC_t           rc = kOkAfRC;
1016
-  cmAudioFileGuts* p  = _cmAudioFileReadGutsPtr(h,&rc);
1097
+  cmAf_t* p  = _cmAudioFileReadGutsPtr(h,&rc);
1017 1098
 
1018 1099
   if( rc != kOkAfRC )
1019 1100
     return rc;
@@ -1243,83 +1324,132 @@ cmRC_t     cmAudioFileGetSumDouble( const char* fn, unsigned begFrmIdx, unsigned
1243 1324
 
1244 1325
 
1245 1326
 
1246
-cmRC_t    cmAudioFileWriteInt(    cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, int**    srcPtrPtr )
1327
+cmRC_t    cmAudioFileWriteInt(    cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, int** srcPtrPtr )
1247 1328
 {
1248
-  cmRC_t           rc          = kOkAfRC;
1249
-  cmAudioFileGuts* p           = _cmAudioFileWriteGutsPtr(h,&rc );
1329
+  cmRC_t  rc = kOkAfRC;
1330
+  cmAf_t* p  = _cmAudioFileWriteGutsPtr(h,&rc );
1250 1331
 
1251 1332
   if( rc != kOkAfRC )
1252 1333
     return rc;
1253 1334
 
1254
-  unsigned         bytesPerSmp =  p->info.bits / 8;
1255
-  unsigned         bufFrmCnt   = 1024;
1256
-  unsigned         bufByteCnt  = bufFrmCnt * bytesPerSmp;
1257
-  unsigned         ci;
1258
-  unsigned         wrFrmCnt    = 0;
1259
-  char buf[ bufByteCnt * chCnt ];
1335
+  unsigned bytesPerSmp = p->info.bits / 8;
1336
+  unsigned bufFrmCnt   = 1024;
1337
+  unsigned bufByteCnt  = bufFrmCnt * bytesPerSmp;
1338
+  unsigned ci;
1339
+  unsigned wrFrmCnt    = 0;
1340
+  char     buf[ bufByteCnt * chCnt ];
1260 1341
   
1261 1342
   while( wrFrmCnt < frmCnt )
1262 1343
   {
1263 1344
     unsigned n = cmMin( frmCnt-wrFrmCnt, bufFrmCnt );
1264 1345
 
1346
+    // interleave each channel into buf[]
1265 1347
     for(ci=0; ci<chCnt; ++ci)
1266 1348
     {
1349
+      // get the begin and end source pointers
1267 1350
       const int* sbp = srcPtrPtr[ci] + wrFrmCnt;
1268 1351
       const int* sep = sbp + n;
1269 1352
 
1270
-      switch( p->info.bits )
1353
+      // 8 bit samples can't be byte swapped
1354
+      if( p->info.bits == 8 )
1271 1355
       {
1272
-        case 8:
1356
+        char*  dbp = buf + ci;
1357
+        for(; sbp < sep; dbp+=chCnt )
1358
+          *dbp = (char)*sbp++;             
1359
+      }
1360
+      else
1361
+      {
1362
+        // if the samples do need to be byte swapped
1363
+        if( cmIsFlag(p->info.flags,kSwapSamplesAfFl) )
1364
+        {
1365
+          switch( p->info.bits )
1273 1366
           {
1274
-            char*  dbp = buf + ci;
1275
-            for(; sbp < sep; dbp+=chCnt )
1276
-              *dbp = (char)*sbp++;             
1277
-          }
1278
-          break;
1367
+            case 16:
1368
+              {
1369
+                short*  dbp = (short*)buf;
1370
+                for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
1371
+                  *dbp = _cmAfSwap16((short)*sbp);
1372
+              }
1373
+              break;
1374
+
1375
+            case 24:
1376
+              {
1377
+                unsigned char* dbp = (unsigned char*)buf;
1378
+                for( dbp+=(ci*3); sbp < sep; dbp+=(3*chCnt), ++sbp)
1379
+                {
1380
+                  unsigned char* s = (unsigned char*)sbp;
1381
+                  dbp[0] = s[2];
1382
+                  dbp[1] = s[1];
1383
+                  dbp[2] = s[0];
1384
+                }
1385
+              }
1386
+              break;
1387
+          
1279 1388
 
1280
-        case 16:
1281
-          {
1282
-            short*  dbp = (short*)buf;
1283
-            for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
1284
-              *dbp = _cmAfSwap16((short)*sbp);
1285
-          }
1286
-          break;
1389
+            case 32:
1390
+              {
1391
+                int*  dbp = (int*)buf;
1392
+                for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
1393
+                  *dbp = _cmAfSwap32(*sbp);
1394
+              }
1395
+              break;
1287 1396
 
1288
-        case 24:
1289
-          {
1290
-            unsigned char* dbp = (unsigned char*)buf;
1291
-            for( dbp+=(ci*3); sbp < sep; dbp+=(3*chCnt), ++sbp)
1292
-            {
1293
-              unsigned char* s = (unsigned char*)sbp;
1294
-              dbp[0] = s[2];
1295
-              dbp[1] = s[1];
1296
-              dbp[2] = s[0];
1297
-            }
1298
-          }
1299
-          break;
1300
-          
1397
+            default:
1398
+              { assert(0);}
1399
+          } 
1301 1400
 
1302
-        case 32:
1401
+        }
1402
+        else // interleave without byte swapping
1403
+        {
1404
+          switch( p->info.bits )
1303 1405
           {
1304
-            int*  dbp = (int*)buf;
1305
-            for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
1306
-              *dbp = _cmAfSwap32(*sbp);
1307
-          }
1308
-          break;
1309
-
1310
-        default:
1311
-          { assert(0);}
1312
-      }
1313
-    }
1406
+            case 16:
1407
+              {
1408
+                short*  dbp = (short*)buf;
1409
+                for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
1410
+                  *dbp = (short)*sbp;
1411
+              }
1412
+              break;
1413
+              
1414
+            case 24:
1415
+              {
1416
+                unsigned char* dbp = (unsigned char*)buf;
1417
+                for( dbp+=(ci*3); sbp < sep; dbp+=(3*chCnt), ++sbp)
1418
+                {
1419
+                  unsigned char* s = (unsigned char*)sbp;
1420
+                  dbp[0] = s[0];
1421
+                  dbp[1] = s[1];
1422
+                  dbp[2] = s[2];
1423
+                }
1424
+              }
1425
+              break;
1426
+          
1314 1427
 
1428
+            case 32:
1429
+              {
1430
+                int*  dbp = (int*)buf;
1431
+                for(dbp+=ci; sbp < sep; dbp+=chCnt, ++sbp )
1432
+                  *dbp = *sbp;
1433
+              }
1434
+              break;
1435
+
1436
+            default:
1437
+              { assert(0);}
1438
+          } // switch
1439
+        } // don't swap
1440
+      } // 8 bits
1441
+    } // ch
1442
+
1443
+    // advance the source pointer index
1315 1444
     wrFrmCnt+=n;
1316 1445
 
1317 1446
     if( fwrite( buf, n*bytesPerSmp*chCnt, 1, p->fp ) != 1)
1318 1447
     {
1319
-      rc = _cmAudioFileError(p,kWriteFailAfRC);
1320
-      break;
1448
+        rc = _cmAudioFileError(p,kWriteFailAfRC);
1449
+        break;
1321 1450
     }
1322
-  }
1451
+    
1452
+  } // while
1323 1453
 
1324 1454
   p->info.frameCnt += wrFrmCnt;
1325 1455
 
@@ -1329,7 +1459,7 @@ cmRC_t    cmAudioFileWriteInt(    cmAudioFileH_t h, unsigned frmCnt, unsigned ch
1329 1459
 cmRC_t    _cmAudioFileWriteRealSamples( cmAudioFileH_t h, unsigned frmCnt, unsigned chCnt, const void*  srcPtrPtr, unsigned realSmpByteCnt )
1330 1460
 {
1331 1461
   cmRC_t           rc        = kOkAfRC;
1332
-  cmAudioFileGuts* p         = _cmAudioFileWriteGutsPtr(h,&rc );
1462
+  cmAf_t* p         = _cmAudioFileWriteGutsPtr(h,&rc );
1333 1463
 
1334 1464
   if( rc != kOkAfRC )
1335 1465
     return rc;
@@ -1428,7 +1558,7 @@ cmRC_t     cmAudioFileMinMaxMean( cmAudioFileH_t h, unsigned chIdx, cmSample_t*
1428 1558
   *meanPtr = 0;
1429 1559
 
1430 1560
   cmRC_t           rc = kOkAfRC;
1431
-  cmAudioFileGuts* p  = _cmAudioFileReadGutsPtr(h,&rc );
1561
+  cmAf_t* p  = _cmAudioFileReadGutsPtr(h,&rc );
1432 1562
 
1433 1563
   if( rc != kOkAfRC )
1434 1564
     return rc;
@@ -1548,7 +1678,7 @@ cmRC_t cmAudioFileMinMaxMeanFn( const cmChar_t* fn, unsigned chIdx, cmSample_t*
1548 1678
 const cmChar_t* cmAudioFileName( cmAudioFileH_t h )
1549 1679
 {
1550 1680
   cmRC_t rc;
1551
-  cmAudioFileGuts* p  = _cmAudioFileReadGutsPtr(h,&rc );
1681
+  cmAf_t* p  = _cmAudioFileReadGutsPtr(h,&rc );
1552 1682
 
1553 1683
   if( rc != kOkAfRC )
1554 1684
     return NULL;
@@ -1568,8 +1698,6 @@ const char* cmAudioFileErrorMsg( unsigned rc )
1568 1698
 
1569 1699
 }
1570 1700
 
1571
-
1572
-
1573 1701
 cmRC_t cmAudioFileGetInfo(   const cmChar_t* fn, cmAudioFileInfo_t* infoPtr, cmRpt_t* rpt  )
1574 1702
 {
1575 1703
   cmRC_t rc = kOkAfRC;
@@ -1625,8 +1753,8 @@ void   cmAudioFilePrintInfo( const cmAudioFileInfo_t* infoPtr, cmRpt_t* rpt )
1625 1753
 
1626 1754
 cmRC_t     cmAudioFileReport( cmAudioFileH_t h, cmRpt_t* rpt, unsigned frmIdx, unsigned frmCnt )
1627 1755
 {
1628
-  cmRC_t           rc = kOkAfRC;
1629
-  cmAudioFileGuts* p  = _cmAudioFileReadGutsPtr(h,&rc);
1756
+  cmRC_t  rc = kOkAfRC;
1757
+  cmAf_t* p  = _cmAudioFileReadGutsPtr(h,&rc);
1630 1758
   
1631 1759
   if( rc != kOkAfRC )
1632 1760
     return rc;
@@ -1676,12 +1804,38 @@ cmRC_t     cmAudioFileReportFn( const cmChar_t* fn, unsigned frmIdx, unsigned fr
1676 1804
   return cmAudioFileDelete(&h);
1677 1805
 }
1678 1806
 
1679
-/// [cmAudioFileExample]
1807
+cmRC_t     cmAudioFileSetSrate( const cmChar_t* fn, unsigned srate )
1808
+{
1809
+  cmRC_t  rc = kOkAfRC;
1810
+  cmAf_t  af;
1811
+  cmAf_t* p  = &af;
1812
+
1813
+  memset(&af,0,sizeof(af));
1814
+
1815
+  if((rc = _cmAudioFileOpen(p, fn, "r+b")) != kOkAfRC )
1816
+    goto errLabel;  
1817
+
1818
+  if( p->info.srate != srate )
1819
+  {
1820
+    // change the sample rate
1821
+    p->info.srate = srate;
1822
+
1823
+    // write the file header
1824
+    if((rc = _cmAudioFileWriteHdr(p)) != kOkAfRC )
1825
+      goto errLabel;
1826
+  }
1827
+  
1828
+ errLabel:
1829
+  if( p->fp != NULL )
1830
+    fclose(p->fp);
1831
+  
1832
+  return rc;
1833
+}
1680 1834
 
1681
-void cmAudioFileTest( const cmChar_t* audioFn, const cmChar_t* outFn, cmRpt_t* rpt )
1835
+void _cmAudioFileTest( const cmChar_t* audioFn, cmRpt_t* rpt )
1682 1836
 {
1683
-  cmAudioFileInfo_t  afInfo;
1684
-  cmRC_t           cmRC;
1837
+  cmAudioFileInfo_t afInfo;
1838
+  cmRC_t            cmRC;
1685 1839
 
1686 1840
   // open an audio file
1687 1841
   cmAudioFileH_t     afH   = cmAudioFileNewOpen( audioFn, &afInfo, &cmRC, rpt ); 
@@ -1698,7 +1852,68 @@ void cmAudioFileTest( const cmChar_t* audioFn, const cmChar_t* outFn, cmRpt_t* r
1698 1852
 
1699 1853
   // close and delete the audio file handle
1700 1854
   cmAudioFileDelete(&afH);
1855
+}
1856
+
1857
+cmRC_t     cmAudioFileSine( cmCtx_t* ctx, const cmChar_t* fn, double srate, unsigned bits, double hz, double gain, double secs )
1858
+{
1859
+  cmRC_t      rc    = kOkAfRC;
1860
+  unsigned    bN    = srate * secs;
1861
+  cmSample_t* b     = cmMemAlloc(cmSample_t,bN);
1862
+  unsigned    chCnt = 1;
1863
+
1864
+  unsigned    i;
1865
+  for(i=0; i<bN; ++i)
1866
+    b[i] = gain * sin(2.0*M_PI*hz*i/srate);
1701 1867
 
1868
+  if((rc = cmAudioFileWriteFileFloat(fn, srate, bits, bN, chCnt, &b, &ctx->rpt)) != kOkAfRC)
1869
+    return rc;
1702 1870
 
1871
+  return rc;
1703 1872
 }
1873
+
1874
+/// [cmAudioFileExample]
1875
+
1876
+void cmAudioFileTest(cmCtx_t* ctx, int argc, const char* argv[])
1877
+{
1878
+  switch( argc )
1879
+  {
1880
+    case 3:
1881
+      //_cmAudioFileTest(argv[2],&ctx->rpt);
1882
+      cmAudioFileReportFn(argv[2],0,0,&ctx->rpt);
1883
+      break;
1884
+      
1885
+    case 4:
1886
+      {
1887
+        errno = 0;
1888
+        long srate =  strtol(argv[3], NULL, 10);
1889
+        if( srate == 0 && errno != 0 )
1890
+          cmRptPrintf(&ctx->rpt,"Invalid sample rate argument to cmAudioFileTest().");
1891
+        else
1892
+          cmAudioFileSetSrate(argv[2],srate);                
1893
+      }
1894
+      break;
1895
+
1896
+    case 8:
1897
+      {
1898
+        errno = 0;
1899
+        double   srate = strtod(argv[3],NULL);
1900
+        unsigned bits  = strtol(argv[4],NULL,10);
1901
+        double   hz    = strtod(argv[5],NULL);
1902
+        double   gain  = strtod(argv[6],NULL);
1903
+        double   secs  = strtod(argv[7],NULL);
1904
+        
1905
+        if( errno != 0 )
1906
+          cmRptPrintf(&ctx->rpt,"Invalid arg. to cmAudioFileTest().");
1907
+        
1908
+        cmAudioFileSine( ctx, argv[2], srate, bits,  hz, gain,  secs );
1909
+      }
1910
+      break;
1911
+
1912
+    default:
1913
+      cmRptPrintf(&ctx->rpt,"Invalid argument count to cmAudioFileTest().");
1914
+      break;
1915
+  }
1916
+}
1917
+
1918
+
1704 1919
 /// [cmAudioFileExample]

+ 12
- 2
cmAudioFile.h View File

@@ -129,7 +129,8 @@ extern "C" {
129 129
   /// reopened with the new file.
130 130
   cmRC_t     cmAudioFileOpen(       cmAudioFileH_t h, const cmChar_t* fn, cmAudioFileInfo_t* infoPtr );
131 131
 
132
-  /// Open an audio file for writing.
132
+  /// Open an audio file for writing.  The type of the audio file, AIF or WAV
133
+  /// is determined by the file name extension.
133 134
   cmRC_t     cmAudioFileCreate(     
134 135
     cmAudioFileH_t h,    ///< Handle returned from an earlier call to cmAudioFileNewCreate() or cmAudioFileNewOpen().
135 136
     const cmChar_t* fn,  ///< File name of the new file.
@@ -295,10 +296,19 @@ extern "C" {
295 296
   cmRC_t     cmAudioFileReportFn( const cmChar_t* fn, unsigned frmIdx, unsigned frmCnt, cmRpt_t* rpt );
296 297
   ///@}
297 298
 
299
+  /// Change the sample rate value in the header.  Note that this function does not resample the audio
300
+  /// signal it simply changes the value of the sample rate in the header.
301
+  cmRC_t     cmAudioFileSetSrate( const cmChar_t* audioFn, unsigned srate );
302
+
303
+  // Generate a sine tone and write it to a file.
304
+  cmRC_t     cmAudioFileSine( cmCtx_t* ctx, const cmChar_t* fn, double srate, unsigned bits, double hz, double gain, double secs );
305
+
306
+
298 307
   /// Testing and example routine for functions in cmAudioFile.h.
299 308
   /// Also see cmProcTest.c cmAudioFileReadWriteTest()
300
-  void       cmAudioFileTest( const cmChar_t* audioFn, const cmChar_t* outFn, cmRpt_t* rpt );
309
+  void       cmAudioFileTest( cmCtx_t* ctx, int argc, const char* argv[] );
301 310
 
311
+  
302 312
 #ifdef __cplusplus
303 313
 }
304 314
 #endif

Loading…
Cancel
Save