Browse Source

cmMidiFile.h/c : Added cmMidiFileGenSvgFile()

master
kevin 7 years ago
parent
commit
a37e2e2c71
2 changed files with 104 additions and 2 deletions
  1. 96
    0
      cmMidiFile.c
  2. 8
    2
      cmMidiFile.h

+ 96
- 0
cmMidiFile.c View File

@@ -8,8 +8,11 @@
8 8
 #include "cmMallocDebug.h"
9 9
 #include "cmLinkedHeap.h"
10 10
 #include "cmTime.h"
11
+#include "cmText.h"
11 12
 #include "cmMidi.h"
12 13
 #include "cmMidiFile.h"
14
+#include "cmSvgWriter.h"
15
+
13 16
 
14 17
 #ifdef cmBIG_ENDIAN
15 18
 #define mfSwap16(v)  (v)
@@ -1975,6 +1978,99 @@ cmMfRC_t cmMidiFileGenPlotFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmCh
1975 1978
   return rc;
1976 1979
 }
1977 1980
 
1981
+cmMfRC_t cmMidiFileGenSvgFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outSvgFn, const cmChar_t* cssFn )
1982
+{
1983
+  cmMfRC_t                 rc   = kOkMfRC;
1984
+  cmSvgH_t                 svgH = cmSvgNullHandle;
1985
+  cmMidiFileH_t            mfH  = cmMidiFileNullHandle;
1986
+  unsigned                 msgN = 0;
1987
+  const cmMidiTrackMsg_t**       msgs = NULL;
1988
+  unsigned noteHeight = 10;
1989
+  double micros_per_sec = 1000.0;
1990
+  unsigned i;
1991
+
1992
+  if((rc = cmMidiFileOpen(ctx,&mfH,midiFn)) != kOkMfRC )
1993
+  {
1994
+    rc = cmErrMsg(&ctx->err,rc,"Unable to open the MIDI file '%s'.",cmStringNullGuard(midiFn));
1995
+    goto errLabel;
1996
+  }
1997
+
1998
+ cmMidiFileCalcNoteDurations( mfH );
1999
+
2000
+  msgN = cmMidiFileMsgCount(mfH);
2001
+  msgs = cmMidiFileMsgArray(mfH);
2002
+
2003
+  
2004
+  if( cmSvgWriterAlloc(ctx,&svgH) != kOkSvgRC )
2005
+  {
2006
+    rc = cmErrMsg(&ctx->err,kSvgFailMfRC,"Unable to create the MIDI SVG output file '%s'.",cmStringNullGuard(outSvgFn));
2007
+    goto errLabel;
2008
+  }
2009
+
2010
+
2011
+  for(i=0; i<msgN && rc==kOkMfRC; ++i)    
2012
+    if( msgs[i]->status == kNoteOnMdId && msgs[i]->u.chMsgPtr->d1 > 0 )
2013
+    {
2014
+      const cmMidiTrackMsg_t* m = msgs[i];
2015
+
2016
+      
2017
+      if( cmSvgWriterRect(svgH, m->amicro/micros_per_sec, m->u.chMsgPtr->d0 * noteHeight,  m->u.chMsgPtr->durMicros/micros_per_sec,  noteHeight-1, "note" ) != kOkSvgRC )
2018
+        rc = kSvgFailMfRC;
2019
+
2020
+      const cmChar_t* t0 = cmMidiToSciPitch(m->u.chMsgPtr->d0,NULL,0);
2021
+
2022
+      if( cmSvgWriterText(svgH, (m->amicro + (m->u.chMsgPtr->durMicros/2)) / micros_per_sec, m->u.chMsgPtr->d0 * noteHeight, t0, "text" ) != kOkSvgRC )
2023
+        rc = kSvgFailMfRC;
2024
+
2025
+    }
2026
+
2027
+  if( rc != kOkMfRC )
2028
+  {
2029
+    cmErrMsg(&ctx->err,rc,"SVG Shape insertion failed.");
2030
+    goto errLabel;
2031
+  }
2032
+  
2033
+  unsigned             dN = 0;
2034
+  cmMidiFileDensity_t* dV = cmMidiFileNoteDensity( mfH, &dN );
2035
+  double               t0 = 0;
2036
+  double               y0 = 64.0;
2037
+  cmChar_t*            tx = NULL;
2038
+  
2039
+  for(i=0; i<dN; ++i)
2040
+  {
2041
+    const cmMidiTrackMsg_t* m;
2042
+
2043
+    if((m = _cmMidiFileUidToMsg( _cmMidiFileHandleToPtr(mfH), dV[i].uid )) == NULL )
2044
+      rc = cmErrMsg(&ctx->err,kUidNotFoundMfRC,"The MIDI msg form UID:%i was not found.",dV[i].uid);
2045
+    else
2046
+    {
2047
+      double t1 = m->amicro / micros_per_sec;
2048
+      double y1 = dV[i].density * noteHeight;
2049
+      
2050
+      cmSvgWriterLine(svgH, t0, y0, t1, y1, "density" );
2051
+      cmSvgWriterText(svgH, t1, y1, tx = cmTsPrintfP(tx,"%i",dV[i].density),"dtext");
2052
+
2053
+      t0 = t1;
2054
+      y0 = y1;
2055
+
2056
+    }
2057
+  }
2058
+
2059
+  cmMemFree(dV);
2060
+  cmMemFree(tx);
2061
+  
2062
+  if( rc == kOkMfRC )
2063
+    if( cmSvgWriterWrite(svgH,cssFn,outSvgFn) != kOkSvgRC )
2064
+      rc = cmErrMsg(&ctx->err,kSvgFailMfRC,"SVG file write to '%s' failed.",cmStringNullGuard(outSvgFn));
2065
+
2066
+
2067
+ errLabel:
2068
+  cmMidiFileClose(&mfH);
2069
+  cmSvgWriterFree(&svgH);
2070
+  
2071
+  return rc;
2072
+}
2073
+
1978 2074
 void cmMidiFilePrintControlNumbers( cmCtx_t* ctx, const char* fn )
1979 2075
 {
1980 2076
   cmMidiFileH_t h = cmMidiFileNullHandle;

+ 8
- 2
cmMidiFile.h View File

@@ -117,7 +117,8 @@ extern "C" {
117 117
     kLargeDeltaTickMfRC, // 12 (a large delta tick value was filtered)
118 118
     kUidNotFoundMfRC,    // 13
119 119
     kUidNotANoteMsgMfRC, // 14
120
-    kInvalidTrkIndexMfRC // 15
120
+    kInvalidTrkIndexMfRC,// 15
121
+    kSvgFailMfRC         // 16
121 122
   };
122 123
 
123 124
   extern cmMidiFileH_t cmMidiFileNullHandle;
@@ -220,11 +221,16 @@ extern "C" {
220 221
     unsigned           density;
221 222
     
222 223
   } cmMidiFileDensity_t;
223
-  cmMidiFileDensity_t* cmMidiFileNoteTimeDensity( cmMidiFileH_t h, unsigned* cntRef );
224
+
225
+  // Generate the note onset density measure for each note in the MIDI file.
226
+  // Delete the returned memory with a call to cmMemFree().
227
+  cmMidiFileDensity_t* cmMidiFileNoteDensity( cmMidiFileH_t h, unsigned* cntRef );
224 228
 
225 229
   // Generate a piano-roll plot description file which can be displayed with cmXScore.m
226 230
   cmMfRC_t             cmMidiFileGenPlotFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outFn );
227 231
 
232
+  cmMfRC_t             cmMidiFileGenSvgFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outSvgFn, const cmChar_t* cssFn );
233
+
228 234
   void                  cmMidiFileTest( const char* fn, cmCtx_t* ctx );
229 235
 
230 236
 

Loading…
Cancel
Save