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.

cmAudioPortFile.c 7.4KB

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