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

cmAudioPortFile.c 7.5KB

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