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.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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;
  27. unsigned pixN;
  28. cmSample_t* fMinV;
  29. cmSample_t* fMaxV;
  30. int* iMinV;
  31. int* iMaxV;
  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( cmGrVExtIsNotNullOrEmpty(&drExt) )
  44. {
  45. // get the extents of the visible portion of the audio object
  46. cmGrVExt_VtoP( grH, cmGrPlotObjHandle(op->oH), &drExt, &op->pext);
  47. // store the count of horizontal pixels
  48. op->pixN = op->pext.sz.w;
  49. // allocate a cache to hold the image data
  50. unsigned byteCnt = op->pixN * 2 * sizeof(int) + op->pixN * 2 * sizeof(cmSample_t);
  51. op->mem = cmMemResize(char,op->mem,byteCnt);
  52. op->fMinV = (cmSample_t*)op->mem;
  53. op->fMaxV = op->fMinV + op->pixN;
  54. op->iMinV = (int*)(op->fMaxV + op->pixN);
  55. op->iMaxV = op->iMinV + op->pixN;
  56. assert( op->iMaxV + op->pixN == op->mem + byteCnt );
  57. // locate the offset into the file of the first sample to be displayed
  58. unsigned si = 0;
  59. if( drExt.loc.x > objExt.loc.x )
  60. si = drExt.loc.x - objExt.loc.x;
  61. // get the floating point audio summary signal
  62. if( cmAfmFileGetSummary( op->afH, op->chIdx, si, drExt.sz.w, op->fMinV, op->fMaxV, op->pixN ) != kOkAfmRC )
  63. {
  64. const cmChar_t* afn = cmAudioFileName( cmAfmFileHandle(op->afH));
  65. rc = cmErrMsg( cmGrPlotErr( cmGrPlotObjMgrHandle(op->oH) ), kRsrcFailGrPlRC, "Audio file summary read failure on '%s'.",afn);
  66. goto errLabel;
  67. }
  68. unsigned i;
  69. // convert the summary to pixels values
  70. for(i=0; i<op->pixN; ++i)
  71. {
  72. // Note the reversal of min and max during the conversion.
  73. op->iMaxV[i] = cmGrY_VtoP( grH, grObjH, op->fMinV[i] );
  74. op->iMinV[i] = cmGrY_VtoP( grH, grObjH, op->fMaxV[i] );
  75. }
  76. }
  77. errLabel:
  78. return rc;
  79. }
  80. bool _cmGrPlObjAfRender( cmGrObjFuncArgs_t* args, cmGrDcH_t dcH )
  81. {
  82. cmGrPlObjAf_t* op = (cmGrPlObjAf_t*)args->cbArg;
  83. if( _cmGrPlObjAfCalcImage(op, args->grH ) == kOkGrPlRC )
  84. {
  85. int i;
  86. cmGrPExt_t pext;
  87. cmGrPhysExtents( args->grH, &pext);
  88. cmGrDcSetColor(dcH, cmGrPlotObjCurLineColor(op->oH));
  89. // draw a horz line at y=0
  90. int y0 = cmGrY_VtoP( args->grH, cmGrPlotObjHandle(op->oH), 0.0 );
  91. cmGrDcDrawLine(dcH, cmGrPExtL(&op->pext), y0, cmGrPExtR(&op->pext) , y0 );
  92. // draw a vertical line for each
  93. for(i=0; i<op->pixN; ++i)
  94. cmGrDcDrawLine(dcH, op->pext.loc.x+i, op->iMinV[i], op->pext.loc.x+i, op->iMaxV[i] );
  95. // draw a rectangle around the entire audio clip
  96. cmGrDcDrawRect(dcH, op->pext.loc.x, cmGrPExtT(&pext), op->pext.sz.w, cmGrPExtB(&pext) );
  97. // draw the file label
  98. cmGrDcDrawTextJustify( dcH, cmGrPlotObjFontFamily(op->oH), cmGrPlotObjFontSize(op->oH), cmGrPlotObjFontStyle(op->oH), cmGrPlotObjLabel(op->oH), &op->pext, kHorzCtrJsGrFl | kTopJsGrFl );
  99. }
  100. return true;
  101. }
  102. bool _cmGrPlObjAfIsInside( cmGrObjFuncArgs_t* args, int px, int py, cmGrV_t vx, cmGrV_t vy )
  103. {
  104. cmGrPlObjAf_t* op = (cmGrPlObjAf_t*)args->cbArg;
  105. if( cmGrPExtIsXyInside( &op->pext, px, py ) )
  106. {
  107. px -= op->pext.loc.x;
  108. if( 0 <= px && px < op->pixN )
  109. return op->iMinV[px] <= py && py <= op->iMaxV[px];
  110. }
  111. return false;
  112. }
  113. void _cmGrPlObjAfDestroy( cmGrObjFuncArgs_t* args )
  114. {
  115. cmGrPlObjAf_t* op = (cmGrPlObjAf_t*)args->cbArg;
  116. args->cbArg = op->destroyCbArg;
  117. op->destroyCbFunc(args);
  118. cmMemFree(op->mem);
  119. cmMemFree(op);
  120. }
  121. cmGrPlRC_t cmGrPlotAudioFileObjCreate(
  122. cmGrPlObjH_t oH,
  123. cmAfmFileH_t afH,
  124. unsigned audioChIdx )
  125. {
  126. cmGrPlObjAf_t* op = cmMemAllocZ(cmGrPlObjAf_t,1);
  127. op->oH = oH;
  128. op->afH = afH;
  129. op->chIdx = audioChIdx;
  130. cmGrObjH_t grObjH = cmGrPlotObjHandle(op->oH);
  131. op->renderCbFunc = cmGrObjRenderCbFunc(grObjH);
  132. op->renderCbArg = cmGrObjRenderCbArg(grObjH);
  133. cmGrObjSetRenderCb( grObjH, _cmGrPlObjAfRender, op );
  134. op->destroyCbFunc = cmGrObjDestroyCbFunc(grObjH);
  135. op->destroyCbArg = cmGrObjDestroyCbArg(grObjH);
  136. cmGrObjSetDestroyCb( grObjH, _cmGrPlObjAfDestroy, op );
  137. op->isInsideCbFunc = cmGrObjIsInsideCbFunc(grObjH);
  138. op->isInsideCbArg = cmGrObjIsInsideCbArg(grObjH);
  139. cmGrObjSetIsInsideCb( grObjH, _cmGrPlObjAfIsInside, op );
  140. cmGrPlotObjSetUserPtr(oH,op);
  141. return kOkGrPlRC;
  142. }