libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmAudioPortFile.c 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #include "cmGlobal.h"
  2. #include "cmRpt.h"
  3. #include "cmErr.h"
  4. #include "cmCtx.h"
  5. #include "cmMem.h"
  6. #include "cmMallocDebug.h"
  7. #include "cmAudioPort.h"
  8. #include "cmAudioPortFile.h"
  9. #include "cmAudioFileDev.h"
  10. typedef struct
  11. {
  12. cmAfdH_t devH;
  13. } cmApDev_t;
  14. typedef struct
  15. {
  16. cmErr_t err;
  17. cmApDev_t* devArray;
  18. unsigned devCnt;
  19. } cmApf_t;
  20. cmApf_t* _cmApf = NULL;
  21. cmApRC_t cmApFileInitialize( cmRpt_t* rpt, unsigned baseApDevIdx )
  22. {
  23. cmApRC_t rc;
  24. if((rc = cmApFileFinalize()) != kOkApRC )
  25. return rc;
  26. _cmApf = cmMemAllocZ(cmApf_t,1);
  27. cmErrSetup(&_cmApf->err,rpt,"Audio Port File");
  28. return rc;
  29. }
  30. cmApRC_t cmApFileFinalize()
  31. {
  32. cmApRC_t rc = kOkApRC;
  33. if( _cmApf == NULL )
  34. return kOkApRC;
  35. unsigned i;
  36. for(i=0; i<_cmApf->devCnt; ++i)
  37. {
  38. cmApRC_t rc0;
  39. if((rc0 = cmApFileDeviceDestroy(i)) != kOkApRC )
  40. rc = rc0;
  41. }
  42. cmMemPtrFree(&_cmApf->devArray);
  43. _cmApf->devCnt = 0;
  44. cmMemPtrFree(&_cmApf);
  45. return rc;
  46. }
  47. unsigned cmApFileDeviceCreate(
  48. const cmChar_t* devLabel,
  49. const cmChar_t* iFn,
  50. const cmChar_t* oFn,
  51. unsigned oBits,
  52. unsigned oChCnt )
  53. {
  54. unsigned i;
  55. // find an available device slot
  56. for(i=0; i<_cmApf->devCnt; ++i)
  57. if( cmAudioFileDevIsValid( _cmApf->devArray[i].devH ) == false )
  58. break;
  59. // if no device slot is availd ...
  60. if( i == _cmApf->devCnt )
  61. {
  62. // ... create a new one
  63. _cmApf->devArray = cmMemResizePZ(cmApDev_t, _cmApf->devArray, _cmApf->devCnt+1);
  64. ++_cmApf->devCnt;
  65. }
  66. // open the file device
  67. if( cmAudioFileDevInitialize( &_cmApf->devArray[i].devH, devLabel, i, iFn, oFn, oBits, oChCnt, _cmApf->err.rpt ) != kOkAfdRC )
  68. {
  69. cmErrMsg(&_cmApf->err,kAudioPortFileFailApRC,"The audio file device initialization failed.");
  70. i = cmInvalidIdx;
  71. }
  72. return i;
  73. }
  74. cmApRC_t cmApFileDeviceDestroy( unsigned devIdx )
  75. {
  76. if( cmAudioFileDevFinalize( &_cmApf->devArray[devIdx].devH ) != kOkAfdRC )
  77. return cmErrMsg(&_cmApf->err,kAudioPortFileFailApRC,"The audio file device finalize failed.");
  78. return kOkApRC;
  79. }
  80. unsigned cmApFileDeviceCount()
  81. { return _cmApf->devCnt; }
  82. const char* cmApFileDeviceLabel( unsigned devIdx )
  83. {
  84. assert( devIdx < cmApFileDeviceCount());
  85. return cmAudioFileDevLabel( _cmApf->devArray[devIdx].devH );
  86. }
  87. unsigned cmApFileDeviceChannelCount( unsigned devIdx, bool inputFl )
  88. {
  89. assert( devIdx < cmApFileDeviceCount());
  90. return cmAudioFileDevChannelCount( _cmApf->devArray[devIdx].devH, inputFl );
  91. }
  92. double cmApFileDeviceSampleRate( unsigned devIdx )
  93. {
  94. assert( devIdx < cmApFileDeviceCount());
  95. return cmAudioFileDevSampleRate( _cmApf->devArray[devIdx].devH );
  96. }
  97. unsigned cmApFileDeviceFramesPerCycle( unsigned devIdx, bool inputFl )
  98. {
  99. assert( devIdx < cmApFileDeviceCount());
  100. return cmAudioFileDevFramesPerCycle( _cmApf->devArray[devIdx].devH, inputFl );
  101. }
  102. cmApRC_t cmApFileDeviceSetup(
  103. unsigned devIdx,
  104. double srate,
  105. unsigned framesPerCycle,
  106. cmApCallbackPtr_t callbackPtr,
  107. void* userCbPtr )
  108. {
  109. assert( devIdx < cmApFileDeviceCount());
  110. if( cmAudioFileDevSetup( _cmApf->devArray[devIdx].devH,srate,framesPerCycle,callbackPtr,userCbPtr) != kOkAfdRC )
  111. return cmErrMsg(&_cmApf->err,kAudioPortFileFailApRC,"The audio file device setup failed.");
  112. return kOkApRC;
  113. }
  114. cmApRC_t cmApFileDeviceStart( unsigned devIdx )
  115. {
  116. assert( devIdx < cmApFileDeviceCount());
  117. if( cmAudioFileDevStart( _cmApf->devArray[devIdx].devH ) != kOkAfdRC )
  118. return cmErrMsg(&_cmApf->err,kAudioPortFileFailApRC,"The audio file device setup failed.");
  119. return kOkApRC;
  120. }
  121. cmApRC_t cmApFileDeviceStop( unsigned devIdx )
  122. {
  123. assert( devIdx < cmApFileDeviceCount());
  124. if( cmAudioFileDevStop( _cmApf->devArray[devIdx].devH ) != kOkAfdRC )
  125. return cmErrMsg(&_cmApf->err,kAudioPortFileFailApRC,"The audio file device setup failed.");
  126. return kOkApRC;
  127. }
  128. bool cmApFileDeviceIsStarted( unsigned devIdx )
  129. {
  130. assert( devIdx < cmApFileDeviceCount());
  131. return cmAudioFileDevIsStarted( _cmApf->devArray[devIdx].devH );
  132. }
  133. void cmApFileReport( cmRpt_t* rpt )
  134. {
  135. unsigned i;
  136. for(i=0; _cmApf->devCnt; ++i)
  137. {
  138. cmRptPrintf(rpt,"%i: ",i);
  139. cmAudioFileDevReport( _cmApf->devArray[i].devH, rpt );
  140. cmRptPrintf(rpt,"\n");
  141. }
  142. }
  143. // device callback function used with cmAudioPortFileTest() note that this assumes
  144. // that the packet buffer contain non-interleaved data.
  145. void _cmApFileTestCb(
  146. cmApAudioPacket_t* inPktArray,
  147. unsigned inPktCnt,
  148. cmApAudioPacket_t* outPktArray,
  149. unsigned outPktCnt )
  150. {
  151. cmApAudioPacket_t* ip = inPktArray;
  152. cmApAudioPacket_t* op = outPktArray;
  153. unsigned opi = 0;
  154. unsigned ipi = 0;
  155. unsigned oci = 0;
  156. unsigned ici = 0;
  157. while(1)
  158. {
  159. if( ici == ip->chCnt)
  160. {
  161. ici = 0;
  162. if( ++ipi >= inPktCnt )
  163. break;
  164. ip = inPktArray + ipi;
  165. }
  166. if( oci == op->chCnt )
  167. {
  168. oci = 0;
  169. if( ++opi >= outPktCnt )
  170. break;
  171. ip = outPktArray + opi;
  172. }
  173. assert( ip->audioFramesCnt == op->audioFramesCnt );
  174. assert( cmIsFlag(ip->flags,kInterleavedApFl)==false && cmIsFlag(ip->flags,kInterleavedApFl)==false );
  175. cmApSample_t* ibp = ((cmApSample_t*)ip->audioBytesPtr) + (ip->audioFramesCnt*ici);
  176. cmApSample_t* obp = ((cmApSample_t*)op->audioBytesPtr) + (op->audioFramesCnt*oci);
  177. memcpy(obp,ibp,ip->audioFramesCnt*sizeof(cmApSample_t));
  178. ++ici;
  179. ++oci;
  180. }
  181. }
  182. void cmApFileTest( cmRpt_t* rpt )
  183. {
  184. unsigned dev0Idx;
  185. const cmChar_t* promptStr = "apf> q=quit 1=start 0=stop\n";
  186. const cmChar_t* label0 = "file0";
  187. const cmChar_t* i0Fn = "/home/kevin/media/audio/McGill-1/1 Audio Track.aiff";
  188. const cmChar_t* o0Fn = "/home/kevin/temp/afd1.aif";
  189. unsigned o0Bits = 16;
  190. unsigned o0ChCnt = 2;
  191. double srate = 44100;
  192. unsigned framesPerCycle = 512;
  193. // initialize audio port file API
  194. if( cmApFileInitialize(rpt,0) != kOkApRC )
  195. return;
  196. // create an audio port file
  197. if((dev0Idx = cmApFileDeviceCreate(label0,i0Fn,o0Fn,o0Bits,o0ChCnt)) == cmInvalidIdx )
  198. goto errLabel;
  199. // configure an audio port file
  200. if( cmApFileDeviceSetup( dev0Idx, srate, framesPerCycle, _cmApFileTestCb, NULL ) != kOkAfdRC )
  201. goto errLabel;
  202. char c;
  203. fputs(promptStr,stderr);
  204. fflush(stdin);
  205. while((c=getchar()) != 'q')
  206. {
  207. switch(c)
  208. {
  209. case '0': cmApFileDeviceStart(dev0Idx); break;
  210. case '1': cmApFileDeviceStop(dev0Idx); break;
  211. }
  212. fputs(promptStr,stderr);
  213. fflush(stdin);
  214. c = 0;
  215. }
  216. errLabel:
  217. //cmApFileDeviceDestroy(dev0Idx);
  218. cmApFileFinalize();
  219. }