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.

cmGrPlotAudio.c 5.6KB

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