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.

cmGrPlotAudio.c 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #include "cmGlobal.h"
  2. #include "cmFloatTypes.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmMem.h"
  7. #include "cmMallocDebug.h"
  8. #include "cmGr.h"
  9. #include "cmGrDevCtx.h"
  10. #include "cmGrPlot.h"
  11. #include "cmAudioFile.h"
  12. #include "cmAudioFileMgr.h"
  13. #include "cmGrPlotAudio.h"
  14. typedef struct
  15. {
  16. cmGrPlObjH_t oH;
  17. cmAfmFileH_t afH;
  18. unsigned chIdx;
  19. cmGrRenderObjCb_t renderCbFunc;
  20. void* renderCbArg;
  21. cmGrDestroyObjCb_t destroyCbFunc;
  22. void* destroyCbArg;
  23. cmGrIsInsideObjCb_t isInsideCbFunc;
  24. void* isInsideCbArg;
  25. void* mem; //
  26. cmGrPExt_t pext; // extents of the visible portion of this audio object
  27. unsigned pixN; // count of pixel columns used by this audio object
  28. cmSample_t* fMinV; // fMinV[pixN] = min sample value for each visible column
  29. cmSample_t* fMaxV; // fMaxV[pixN] = max sample value for each visible column
  30. int* iMinV; // iMinV[pixN] = top pixel for each column line
  31. int* iMaxV; // iMaxV[pixN] = bottom pixel for each column line
  32. } cmGrPlObjAf_t;
  33. cmGrPlRC_t _cmGrPlObjAfCalcImage( cmGrPlObjAf_t* op, cmGrH_t grH )
  34. {
  35. cmGrPlRC_t rc = kOkGrPlRC;
  36. cmGrObjH_t grObjH = cmGrPlotObjHandle(op->oH);
  37. cmGrVExt_t vwExt,objExt,drExt;
  38. // get the intersection of the view and this audio object
  39. cmGrViewExtents( grH, &vwExt );
  40. cmGrPlotObjVExt( op->oH, &objExt );
  41. cmGrVExtIntersect(&drExt,&vwExt,&objExt);
  42. // if the audio object is visible
  43. if( cmGrVExtIsNullOrEmpty(&drExt) )
  44. {
  45. cmGrPExtSetNull(&op->pext);
  46. op->pixN = 0;
  47. }
  48. else
  49. {
  50. // get the extents of the visible portion of the audio object
  51. cmGrVExt_VtoP( grH, cmGrPlotObjHandle(op->oH), &drExt, &op->pext);
  52. // store the count of horizontal pixels
  53. op->pixN = op->pext.sz.w;
  54. // allocate a cache to hold the image data
  55. unsigned byteCnt = op->pixN * 2 * sizeof(int) + op->pixN * 2 * sizeof(cmSample_t);
  56. op->mem = cmMemResize(char,op->mem,byteCnt);
  57. op->fMinV = (cmSample_t*)op->mem;
  58. op->fMaxV = op->fMinV + op->pixN;
  59. op->iMinV = (int*)(op->fMaxV + op->pixN);
  60. op->iMaxV = op->iMinV + op->pixN;
  61. assert( op->iMaxV + op->pixN == op->mem + byteCnt );
  62. // locate the offset into the file of the first sample to be displayed
  63. unsigned si = 0;
  64. if( drExt.loc.x > objExt.loc.x )
  65. si = drExt.loc.x - objExt.loc.x;
  66. // get the floating point audio summary signal
  67. if( cmAfmFileGetSummary( op->afH, op->chIdx, si, drExt.sz.w, op->fMinV, op->fMaxV, op->pixN ) != kOkAfmRC )
  68. {
  69. const cmChar_t* afn = cmAudioFileName( cmAfmFileHandle(op->afH));
  70. rc = cmErrMsg( cmGrPlotErr( cmGrPlotObjMgrHandle(op->oH) ), kRsrcFailGrPlRC, "Audio file summary read failure on '%s'.",afn);
  71. goto errLabel;
  72. }
  73. unsigned i;
  74. // convert the summary to pixels values
  75. for(i=0; i<op->pixN; ++i)
  76. {
  77. // Note the reversal of min and max during the conversion.
  78. op->iMaxV[i] = cmGrY_VtoP( grH, grObjH, op->fMinV[i] );
  79. op->iMinV[i] = cmGrY_VtoP( grH, grObjH, op->fMaxV[i] );
  80. }
  81. }
  82. errLabel:
  83. return rc;
  84. }
  85. bool _cmGrPlObjAfRender( cmGrObjFuncArgs_t* args, cmGrDcH_t dcH )
  86. {
  87. cmGrPlObjAf_t* op = (cmGrPlObjAf_t*)args->cbArg;
  88. if( _cmGrPlObjAfCalcImage(op, args->grH ) == kOkGrPlRC )
  89. {
  90. int i;
  91. cmGrPExt_t pext;
  92. cmGrPhysExtents( args->grH, &pext);
  93. cmGrDcSetColor(dcH, cmGrPlotObjCurLineColor(op->oH));
  94. // draw a horz line at y=0
  95. int y0 = cmGrY_VtoP( args->grH, cmGrPlotObjHandle(op->oH), 0.0 );
  96. cmGrDcDrawLine(dcH, cmGrPExtL(&op->pext), y0, cmGrPExtR(&op->pext) , y0 );
  97. // draw a vertical line for each
  98. for(i=0; i<op->pixN; ++i)
  99. cmGrDcDrawLine(dcH, op->pext.loc.x+i, op->iMinV[i], op->pext.loc.x+i, op->iMaxV[i] );
  100. // draw a rectangle around the entire audio clip
  101. cmGrDcDrawRect(dcH, op->pext.loc.x, cmGrPExtT(&pext), op->pext.sz.w, cmGrPExtB(&pext) );
  102. // draw the file label
  103. cmGrDcDrawTextJustify( dcH, cmGrPlotObjFontFamily(op->oH), cmGrPlotObjFontSize(op->oH), cmGrPlotObjFontStyle(op->oH), cmGrPlotObjLabel(op->oH), &op->pext, kHorzCtrJsGrFl | kTopJsGrFl );
  104. }
  105. return true;
  106. }
  107. bool _cmGrPlObjAfIsInside( cmGrObjFuncArgs_t* args, unsigned evtFlags, int px, int py, cmGrV_t vx, cmGrV_t vy )
  108. {
  109. cmGrPlObjAf_t* op = (cmGrPlObjAf_t*)args->cbArg;
  110. if( cmGrPExtIsXyInside( &op->pext, px, py ) )
  111. {
  112. px -= op->pext.loc.x;
  113. if( 0 <= px && px < op->pixN )
  114. return op->iMinV[px] <= py && py <= op->iMaxV[px];
  115. }
  116. return false;
  117. }
  118. void _cmGrPlObjAfDestroy( cmGrObjFuncArgs_t* args )
  119. {
  120. cmGrPlObjAf_t* op = (cmGrPlObjAf_t*)args->cbArg;
  121. args->cbArg = op->destroyCbArg;
  122. op->destroyCbFunc(args);
  123. cmMemFree(op->mem);
  124. cmMemFree(op);
  125. }
  126. cmGrPlRC_t cmGrPlotAudioFileObjCreate(
  127. cmGrPlObjH_t oH,
  128. cmAfmFileH_t afH,
  129. unsigned audioChIdx )
  130. {
  131. cmGrPlObjAf_t* op = cmMemAllocZ(cmGrPlObjAf_t,1);
  132. op->oH = oH;
  133. op->afH = afH;
  134. op->chIdx = audioChIdx;
  135. cmGrObjH_t grObjH = cmGrPlotObjHandle(op->oH);
  136. op->renderCbFunc = cmGrObjRenderCbFunc(grObjH);
  137. op->renderCbArg = cmGrObjRenderCbArg(grObjH);
  138. cmGrObjSetRenderCb( grObjH, _cmGrPlObjAfRender, op );
  139. op->destroyCbFunc = cmGrObjDestroyCbFunc(grObjH);
  140. op->destroyCbArg = cmGrObjDestroyCbArg(grObjH);
  141. cmGrObjSetDestroyCb( grObjH, _cmGrPlObjAfDestroy, op );
  142. op->isInsideCbFunc = cmGrObjIsInsideCbFunc(grObjH);
  143. op->isInsideCbArg = cmGrObjIsInsideCbArg(grObjH);
  144. cmGrObjSetIsInsideCb( grObjH, _cmGrPlObjAfIsInside, op );
  145. cmGrPlotObjSetUserPtr(oH,op);
  146. return kOkGrPlRC;
  147. }