libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmAudDspIF.c 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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 "cmFileSys.h"
  10. #include "cmJson.h"
  11. #include "cmThread.h"
  12. #include "dsp/cmDspValue.h"
  13. #include "cmMsgProtocol.h"
  14. #include "cmAudDspIF.h"
  15. cmAiH_t cmAiNullHandle = cmSTATIC_NULL_HANDLE;
  16. typedef struct
  17. {
  18. cmErr_t err;
  19. cmAdIfParm_t parms;
  20. cmJsonH_t jsH;
  21. } cmAi_t;
  22. cmAi_t* _cmAiHandleToPtr( cmAiH_t h )
  23. {
  24. cmAi_t* p = (cmAi_t*)h.h;
  25. assert(p != NULL);
  26. return p;
  27. }
  28. // Dispatch a message to the client application.
  29. // This function is called from within cmTsQueueDequeueMsg() which is called
  30. // by cmAdIfDispatchMsgToHost().
  31. cmRC_t _cmAiDispatchMsgToClient(void* cbDataPtr, unsigned msgByteCnt, const void* msgDataPtr )
  32. {
  33. cmAi_t* p = (cmAi_t*)cbDataPtr;
  34. cmDspUiHdr_t* m = (cmDspUiHdr_t*)msgDataPtr;
  35. cmRC_t rc = cmOkRC;
  36. switch( m->uiId )
  37. {
  38. case kStatusSelAsId:
  39. {
  40. // handle a status mesage
  41. const char* base = (const char*)msgDataPtr;
  42. const cmAudioSysStatus_t* st = (const cmAudioSysStatus_t*)(base + (2 * sizeof(unsigned)));
  43. const double* iMeterArray = (const double*)(st + 1);
  44. const double* oMeterArray = iMeterArray + st->iMeterCnt;
  45. rc = p->parms.dispatchRecd.statusFunc(p->parms.dispatchRecd.cbDataPtr, st, iMeterArray, oMeterArray );
  46. }
  47. break;
  48. case kSsInitSelAsId:
  49. {
  50. // handle an ssInit message
  51. const cmAudioSysSsInitMsg_t* sip = (const cmAudioSysSsInitMsg_t*)msgDataPtr;
  52. const char* iDevLabel = (const char*)(sip+1);
  53. const char* oDevLabel = iDevLabel + strlen(iDevLabel) + 1;
  54. rc = p->parms.dispatchRecd.ssInitFunc(p->parms.dispatchRecd.cbDataPtr, sip, iDevLabel, oDevLabel );
  55. }
  56. break;
  57. case kUiSelAsId:
  58. {
  59. bool jsFl = false;
  60. cmDsvRC_t rc = kOkDsvRC;
  61. // if the value associated with this msg is a mtx then set
  62. // its mtx data area pointer to just after the msg header.
  63. if( cmDsvIsJson(&m->value) )
  64. {
  65. rc = cmDsvDeserializeJson(&m->value,p->jsH);
  66. jsFl = true;
  67. }
  68. else
  69. rc = cmDsvDeserializeInPlace(&m->value,msgByteCnt-sizeof(cmDspUiHdr_t));
  70. if( rc != kOkDsvRC )
  71. cmErrMsg(&p->err,kDeserialFailAiRC,"Deserialize failed.");
  72. else
  73. rc = p->parms.dispatchRecd.uiFunc(p->parms.dispatchRecd.cbDataPtr,m);
  74. if( jsFl )
  75. cmJsonClearTree(p->jsH);
  76. }
  77. break;
  78. default:
  79. cmErrMsg(&p->err,kUnknownMsgTypeAiRC,"The message type %i is unknown.",m->uiId);
  80. break;
  81. }
  82. return rc;
  83. }
  84. cmAiRC_t _cmAdIfReadCfgFile( cmAi_t* p, cmCtx_t* ctx )
  85. {
  86. cmAiRC_t rc = kOkAiRC;
  87. const cmChar_t* sysJsFn = NULL;
  88. cmJsonH_t jsH = cmJsonNullHandle;
  89. cmJsonNode_t* audDspNodePtr = NULL;
  90. //const cmChar_t* errLabelPtr = NULL;
  91. // form the audio dsp resource file name
  92. if((sysJsFn = cmFsMakeFn( cmFsPrefsDir(),cmAudDspSys_FILENAME,NULL,NULL)) == NULL )
  93. {
  94. rc = cmErrMsg(&p->err,kFileSysFailAiRC,"Unable to form the audio dsp system resource file name.");
  95. goto errLabel;
  96. }
  97. // open the audio dsp resource file
  98. if(cmJsonInitializeFromFile(&jsH,sysJsFn,ctx) != kOkJsRC )
  99. {
  100. rc = cmErrMsg(&p->err,kJsonFailAiRC,"Unable to open the audio dsp resource file: '%s'.",cmStringNullGuard(sysJsFn));
  101. goto errLabel;
  102. }
  103. // locate the aud_dsp container object
  104. if( cmJsonNodeMember( cmJsonRoot(jsH), "aud_dsp", &audDspNodePtr ) != kOkJsRC )
  105. {
  106. rc = cmErrMsg(&p->err,kJsonFailAiRC,"The audio DSP system resource file '%s' does not contain an 'aud_dsp' object.",cmStringNullGuard(sysJsFn));
  107. goto errLabel;
  108. }
  109. /*
  110. // locate the read the aud_dsp sub-elements
  111. if( cmJsonMemberValues( audDspNodePtr, &errLabelPtr,
  112. "msgQueueByteCnt", kIntTId, &p->msgQueueByteCnt,
  113. NULL ) != kOkJsRC )
  114. {
  115. rc = cmErrMsg(&p->err,kJsonFailAiRC,"Syntax error while parsing the top level fields in the audio DSP system resource file:%s.",cmStringNullGuard(sysJsFn));
  116. goto errLabel;
  117. }
  118. */
  119. errLabel:
  120. if( cmJsonFinalize(&jsH) != kOkJsRC )
  121. rc = cmErrMsg(&p->err,kJsonFailAiRC,"JSON finalization failed.");
  122. if( sysJsFn != NULL )
  123. cmFsFreeFn(sysJsFn);
  124. return rc;
  125. }
  126. cmAiRC_t _cmAdIfSendIntMsg(cmAiH_t h, unsigned selId, unsigned asSubIdx, unsigned flags, unsigned iv, double dv, const cmChar_t* str )
  127. {
  128. cmAi_t* p = _cmAiHandleToPtr( h );
  129. cmDspValue_t v;
  130. if(str != NULL )
  131. cmDsvSetStrcz(&v,str);
  132. else
  133. if(iv == cmInvalidIdx )
  134. cmDsvSetDouble(&v,dv);
  135. else
  136. cmDsvSetUInt(&v,iv);
  137. if( cmMsgSend(&p->err,asSubIdx,kUiSelAsId,selId,flags,cmInvalidId,cmInvalidId,&v,p->parms.audDspFunc,p->parms.audDspFuncDataPtr) != kOkMsgRC )
  138. return cmErrMsg(&p->err,kSendFailAiRC,"The integer message sel id:%i value:%i transmission failed.",selId,iv);
  139. return kOkAiRC;
  140. }
  141. cmAiRC_t _cmAdIfFree( cmAi_t* p )
  142. {
  143. cmAiRC_t rc = kOkAiRC;
  144. if( cmJsonFinalize(&p->jsH) != kOkJsRC )
  145. {
  146. rc = cmErrMsg(&p->err,kJsonFailAiRC,"JSON finalization failed.");
  147. goto errLabel;
  148. }
  149. cmMemFree(p);
  150. errLabel:
  151. return rc;
  152. }
  153. cmAiRC_t cmAdIfAllocate( cmCtx_t* ctx, cmAiH_t* hp, const cmAdIfParm_t* parms )
  154. {
  155. cmAiRC_t rc;
  156. if((rc = cmAdIfFree(hp)) != kOkAiRC )
  157. return rc;
  158. cmAi_t* p = cmMemAllocZ(cmAi_t,1);
  159. cmErrSetup(&p->err,&ctx->rpt,"Audio DSP Interface");
  160. p->parms = *parms;
  161. // read the system configuration file
  162. if((rc = _cmAdIfReadCfgFile(p, ctx )) != kOkAiRC )
  163. goto errLabel;
  164. // initialize a JSON tree for use in deserializing JSON messages
  165. if((rc = cmJsonInitialize( &p->jsH, ctx )) != kOkJsRC )
  166. {
  167. rc = cmErrMsg(&p->err,kJsonFailAiRC,"JSON initialization failed.");
  168. goto errLabel;
  169. }
  170. hp->h = p;
  171. errLabel:
  172. if( rc != kOkAiRC )
  173. _cmAdIfFree(p);
  174. return rc;
  175. }
  176. cmAiRC_t cmAdIfFree( cmAiH_t* hp )
  177. {
  178. cmAiRC_t rc = kOkAiRC;
  179. if( hp==NULL || cmAdIfIsValid(*hp)==false )
  180. return kOkAiRC;
  181. cmAi_t* p = _cmAiHandleToPtr(*hp);
  182. if((rc = _cmAdIfFree(p)) != kOkAiRC )
  183. return rc;
  184. hp->h = NULL;
  185. return rc;
  186. }
  187. bool cmAdIfIsValid( cmAiH_t h )
  188. { return h.h != NULL; }
  189. cmAiRC_t cmAdIfRecvAudDspMsg( cmAiH_t h, unsigned msgByteCnt, const void* msg )
  190. {
  191. cmAi_t* p = _cmAiHandleToPtr(h);
  192. cmAiRC_t rc = kOkAiRC;
  193. _cmAiDispatchMsgToClient(p,msgByteCnt,msg);
  194. return rc;
  195. }
  196. cmAiRC_t cmAdIfDeviceReport( cmAiH_t h )
  197. { return _cmAdIfSendIntMsg(h,kDevReportDuiId,cmInvalidIdx,0,cmInvalidIdx,0.0,NULL); }
  198. cmAiRC_t cmAdIfSetAudioSysCfg( cmAiH_t h, unsigned asCfgIdx )
  199. { return _cmAdIfSendIntMsg(h,kSetAudioCfgDuiId,cmInvalidIdx,0,asCfgIdx,0.0,NULL); }
  200. cmAiRC_t cmAdIfSetAudioDevice( cmAiH_t h, unsigned asSubIdx, bool inputFl, unsigned devIdx )
  201. { return _cmAdIfSendIntMsg(h,kSetAudioDevDuiId,asSubIdx,inputFl,devIdx,0.0,NULL); }
  202. cmAiRC_t cmAdIfSetSampleRate( cmAiH_t h, unsigned asSubIdx, double srate )
  203. { return _cmAdIfSendIntMsg(h,kSetSampleRateDuiId,asSubIdx,0,cmInvalidIdx,srate,NULL); }
  204. cmAiRC_t cmAdIfLoadProgram( cmAiH_t h, unsigned asSubIdx, unsigned pgmIdx )
  205. { return _cmAdIfSendIntMsg(h,kSetPgmDuiId,asSubIdx,0,pgmIdx,0.0,NULL); }
  206. cmAiRC_t cmAdIfPrintPgm( cmAiH_t h,unsigned asSubIdx, const cmChar_t* fn )
  207. { return _cmAdIfSendIntMsg(h,kPrintPgmDuiId,asSubIdx,0,cmInvalidIdx,0.0,fn); }
  208. cmAiRC_t cmAdIfEnableAudio( cmAiH_t h, bool enableFl )
  209. { return _cmAdIfSendIntMsg(h,kEnableDuiId,cmInvalidIdx,enableFl,cmInvalidIdx,0.0,NULL); }
  210. cmAiRC_t cmAdIfEnableStatusNotify( cmAiH_t h, bool enableFl )
  211. { return _cmAdIfSendIntMsg(h,kSetNotifyEnableDuiId,cmInvalidIdx,enableFl,cmInvalidIdx,0.0,NULL); }
  212. cmAiRC_t cmAdIfSendMsgToAudioDSP(
  213. cmAiH_t h,
  214. unsigned asSubIdx,
  215. unsigned msgTypeId,
  216. unsigned selId,
  217. unsigned flags,
  218. unsigned instId,
  219. unsigned instVarId,
  220. const cmDspValue_t* valPtr )
  221. {
  222. cmAiRC_t rc = kOkAiRC;
  223. cmAi_t* p = _cmAiHandleToPtr(h);
  224. if( cmMsgSend( &p->err, asSubIdx, msgTypeId,selId,flags,instId,instVarId,valPtr, p->parms.audDspFunc, p->parms.audDspFuncDataPtr ) != kOkMsgRC )
  225. rc = cmErrMsg(&p->err, kSendFailAiRC, "A UI message intened for the the audio DSP system was not successfully delivered.");
  226. return rc;
  227. }
  228. cmAiRC_t cmAdIfDispatchMsgToHost( cmAiH_t h )
  229. { return _cmAdIfSendIntMsg(h,kClientMsgPollDuiId,cmInvalidIdx,0,cmInvalidIdx,0.0,NULL); }