Browse Source

cmTakeSeqBldr.h/c : Initial commit.

master
Kevin Larke 9 years ago
parent
commit
b2dee6219f
2 changed files with 345 additions and 0 deletions
  1. 283
    0
      app/cmTakeSeqBldr.c
  2. 62
    0
      app/cmTakeSeqBldr.h

+ 283
- 0
app/cmTakeSeqBldr.c View File

@@ -0,0 +1,283 @@
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 "cmLinkedHeap.h"
10
+#include "cmJson.h"
11
+#include "cmTime.h"
12
+#include "cmMidi.h"
13
+#include "cmMidiFile.h"
14
+#include "cmAudioFile.h"
15
+#include "cmTimeLine.h"
16
+#include "cmSymTbl.h"
17
+#include "cmScore.h"
18
+#include "cmTakeSeqBldr.h"
19
+
20
+
21
+typedef struct cmNoteTsb_str
22
+{
23
+  unsigned mni;      // midi note index as an offset from the take marker
24
+  unsigned scEvtIdx; // score event index this not is assoc'd with or -1 if it did not match
25
+  unsigned flags;    // flags from cmScMatcherResult_t 
26
+} cmNoteTsb_t;
27
+
28
+typedef struct cmTakeTsb_str
29
+{
30
+  unsigned     markerUid;  // marker time line uid assoc'd with this take
31
+  cmNoteTsb_t* noteV;      // noteV[noteN] score to midi file map recd. array.
32
+  unsigned     noteN;  
33
+  bool         failFl;
34
+} cmTakeTsb_t;
35
+
36
+typedef struct
37
+{
38
+  cmCtx_t         ctx;
39
+  cmErr_t         err;
40
+  cmJsonH_t       jsH;
41
+  const cmChar_t* tlFn;
42
+  const cmChar_t* scFn;
43
+  cmTakeTsb_t*    takeV;
44
+  unsigned        takeN;
45
+} cmTsb_t;
46
+
47
+cmTakeSeqBldrH_t cmTakeSeqBldrNullHandle = cmSTATIC_NULL_HANDLE;
48
+
49
+cmTsb_t* _cmTsbHandleToPtr( cmTakeSeqBldrH_t h )
50
+{
51
+  cmTsb_t* p = (cmTsb_t*)h.h;
52
+  return p;
53
+}
54
+
55
+cmTsbRC_t _cmTsbFree( cmTsb_t* p )
56
+{
57
+  cmTsbRC_t       rc     = kOkTsbRC;
58
+
59
+  if( cmJsonFinalize(&p->jsH) != kOkJsRC )
60
+  {
61
+    rc = cmErrMsg(&p->err,kJsonFailTsbRC,"JSON object finalize failed.");
62
+    goto errLabel;
63
+  }
64
+
65
+  cmMemFree(p);
66
+
67
+ errLabel:
68
+  return rc;
69
+}
70
+
71
+
72
+cmTsbRC_t cmTakeSeqBldrAlloc( cmCtx_t* ctx, cmTakeSeqBldrH_t* hp )
73
+{
74
+  cmTsbRC_t rc;
75
+  if((rc = cmTakeSeqBldrFree(hp)) != kOkTsbRC )
76
+    return kOkTsbRC;
77
+
78
+  cmTsb_t* p  = cmMemAllocZ(cmTsb_t,1);
79
+
80
+  cmErrSetup(&p->err,&ctx->rpt,"TakeSeqBldr");
81
+
82
+  p->ctx = *ctx;
83
+  hp->h  = p;
84
+
85
+  
86
+
87
+  return rc;
88
+}
89
+
90
+cmTsbRC_t cmTakeSeqBldrAllocFn( cmCtx_t* ctx, cmTakeSeqBldrH_t* hp, const cmChar_t* tsbFn )
91
+{
92
+  cmTsbRC_t rc;
93
+  if((rc = cmTakeSeqBldrAlloc(ctx,hp)) != kOkTsbRC )
94
+    return rc;
95
+
96
+  if((rc = cmTakeSeqBldrInitialize(*hp,tsbFn)) != kOkTsbRC )
97
+    return rc;
98
+
99
+  return rc;
100
+}
101
+
102
+cmTsbRC_t cmTakeSeqBldrFree( cmTakeSeqBldrH_t* hp )
103
+{
104
+  cmRC_t rc = kOkTsbRC;
105
+
106
+  if( hp == NULL || cmTakeSeqBldrIsValid(*hp)==false )
107
+    return kOkTsbRC;
108
+
109
+  cmTsb_t* p = _cmTsbHandleToPtr(*hp);
110
+
111
+  if((rc = _cmTsbFree(p)) != kOkTsbRC )
112
+    return rc;
113
+
114
+  hp->h = NULL;
115
+
116
+  return rc;
117
+}
118
+
119
+bool cmTakeSeqBldrIsValid( cmTakeSeqBldrH_t h )
120
+{  return h.h != NULL; }
121
+
122
+
123
+cmTsbRC_t cmTakeSeqBldrInitialize( cmTakeSeqBldrH_t h, const cmChar_t* tsbFn )
124
+{
125
+  cmTsbRC_t       rc       = kOkTsbRC; 
126
+  cmTsb_t*        p        = _cmTsbHandleToPtr(h);
127
+  cmJsonNode_t*   tkArrObj = NULL;
128
+  cmJsRC_t        jsRC     = kOkJsRC;
129
+  const cmChar_t* errMsg   = NULL;
130
+  unsigned        i;
131
+ 
132
+  // initialize the TSB json object
133
+  if(( rc = cmJsonInitializeFromFile(&p->jsH,tsbFn,&p->ctx)) != kOkJsRC )
134
+  {
135
+    rc = cmErrMsg(&p->err,kJsonFailTsbRC,"The Take Sequence Builder JSON file object could not be initialized from '%s'.",cmStringNullGuard(tsbFn));
136
+    goto errLabel;
137
+  }
138
+
139
+  // parse the header
140
+  if((jsRC = cmJsonMemberValues( cmJsonRoot(p->jsH), &errMsg,
141
+        "tlFn",kStringTId,&p->tlFn,
142
+        "scFn",kStringTId,&p->scFn,
143
+        "takeArray",kArrayTId | kOptArgJsFl,&tkArrObj,
144
+        0 )) != kOkJsRC )
145
+  {
146
+    if( jsRC == kNodeNotFoundJsRC && errMsg != NULL )
147
+      rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file header parse failed missing required field:'%s'",errMsg);
148
+    else
149
+      rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file header parse failed.");
150
+  }
151
+
152
+  // count of take records
153
+  unsigned      tkArrN = cmJsonChildCount(tkArrObj);
154
+
155
+  // array of take records
156
+  p->takeV  = cmMemAllocZ(cmTakeTsb_t,tkArrN);
157
+
158
+  // for each take record
159
+  for(i=0; i<tkArrN; ++i)
160
+  {
161
+    cmJsonNode_t* takeObj    = NULL;
162
+    cmJsonNode_t* noteArrObj = NULL;
163
+    unsigned      j;
164
+
165
+    // get a pointer to the take record JSON object
166
+    if((takeObj = cmJsonArrayElement(tkArrObj,i)) == NULL )
167
+    {
168
+      rc = cmErrMsg(&p->err,kParseFailTsbRC,"Take record header at index %i access failed.",i);
169
+      goto errLabel;
170
+    }
171
+
172
+    // parse the take record
173
+    if((jsRC = cmJsonMemberValues( takeObj, &errMsg,
174
+          "markerUid",kIntTId,   &p->takeV[i].markerUid,
175
+          "failFl",   kIntTId,   &p->takeV[i].failFl,
176
+          "array",    kArrayTId, &noteArrObj,
177
+          0)) != kOkJsRC )
178
+    {
179
+      if( jsRC == kNodeNotFoundJsRC && errMsg != NULL )
180
+        rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file take record parse failed missing required field:'%s'",errMsg);
181
+      else
182
+        rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file take record parse failed.");      
183
+    }
184
+
185
+    // get the count of note records
186
+    p->takeV[i].noteN = cmJsonChildCount(noteArrObj);
187
+    
188
+    // allocate a note record array for this take
189
+    p->takeV[i].noteV = cmMemAllocZ(cmNoteTsb_t, p->takeV[i].noteN);
190
+
191
+    // for each note record
192
+    for(j=0; j<p->takeV[i].noteN; ++j)
193
+    {
194
+      cmJsonNode_t* noteObj = NULL;
195
+      
196
+      // get the note record JSON object
197
+      if((noteObj = cmJsonArrayElement(noteArrObj,j)) == NULL )
198
+      {
199
+        rc = cmErrMsg(&p->err,kParseFailTsbRC,"Access failed for note record at index %i at take index %i.",j,i);
200
+        goto errLabel;
201
+      }
202
+
203
+      // parse the note record
204
+      if((jsRC = cmJsonMemberValues( noteObj, &errMsg,
205
+            "mni",      kIntTId, &p->takeV[i].noteV[j].mni,
206
+            "scEvtIdx", kIntTId, &p->takeV[i].noteV[j].scEvtIdx,
207
+            "flags",    kIntTId, &p->takeV[i].noteV[j].flags,
208
+            0)) != kOkJsRC )
209
+      {
210
+        if( jsRC == kNodeNotFoundJsRC && errMsg != NULL )
211
+          rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file note record parse failed missing required field:'%s'",errMsg);
212
+        else
213
+          rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file note record parse failed.");              
214
+      }
215
+    }
216
+  }
217
+  
218
+ errLabel:
219
+  return rc;
220
+}
221
+
222
+cmTsbRC_t cmTakeSeqBldrLoadSection( cmTakeSeqBldrH_t h, unsigned tlMarkUid, bool overwriteFL )
223
+{
224
+  cmTsbRC_t rc = kOkTsbRC;
225
+  return rc;
226
+}
227
+
228
+cmTsbRC_t cmTakeSeqBldrUnloadSection( cmTakeSeqBldrH_t h, unsigned tlMarkUid )
229
+{
230
+  cmTsbRC_t rc = kOkTsbRC;
231
+  return rc;
232
+}
233
+  
234
+cmTsbRC_t cmTakeSeqBldrInsertScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId )
235
+{
236
+  cmTsbRC_t rc = kOkTsbRC;
237
+  return rc;
238
+}
239
+
240
+cmTsbRC_t cmTakeSeqBldrRemoveScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId )
241
+{
242
+  cmTsbRC_t rc = kOkTsbRC;
243
+  return rc;
244
+}
245
+
246
+cmTsbRC_t cmTakeSeqBldrSelectEnable( cmTakeSeqBldrH_t h, unsigned flags, unsigned id, bool selectFl )
247
+{
248
+  cmTsbRC_t rc = kOkTsbRC;
249
+  return rc;
250
+}
251
+
252
+cmTsbRC_t cmTakeSeqBldrEnableNote( cmTakeSeqBldrH_t h, unsigned ssqId, bool enableFl )
253
+{
254
+  cmTsbRC_t rc = kOkTsbRC;
255
+  return rc;
256
+}
257
+
258
+cmTsbRC_t cmTakeSeqBldrMoveNote(   cmTakeSeqBldrH_t h, unsigned ssqId, int deltaSmpIdx )
259
+{
260
+  cmTsbRC_t rc = kOkTsbRC;
261
+  return rc;
262
+}
263
+
264
+cmTsbRC_t cmTakeSeqBldrWriteMidiFile( cmTakeSeqBldrH_t h, const char* fn )
265
+{
266
+  cmTsbRC_t rc = kOkTsbRC;
267
+  return rc;
268
+}
269
+
270
+cmTsbRC_t cmTakeSeqBldrTest( cmCtx_t* ctx )
271
+{
272
+  const cmChar_t*  tsbFn = "/home/kevin/src/cmkc/src/kc/data/assoc0.js";
273
+  cmTakeSeqBldrH_t tsbH  = cmTakeSeqBldrNullHandle;
274
+  cmTsbRC_t        tsbRC = kOkTsbRC;
275
+
276
+  if((tsbRC = cmTakeSeqBldrAllocFn(ctx, &tsbH, tsbFn )) != kOkTsbRC )
277
+    return cmErrMsg(&ctx->err,tsbRC,"TSB Allocate and parse '%s' failed.",tsbFn);
278
+
279
+  if((tsbRC = cmTakeSeqBldrFree(&tsbH)) != kOkTsbRC )
280
+    return cmErrMsg(&ctx->err,tsbRC,"TSB Free failed.");
281
+
282
+  return tsbRC;
283
+}

+ 62
- 0
app/cmTakeSeqBldr.h View File

@@ -0,0 +1,62 @@
1
+#ifndef cmTakeSeqBldr_h
2
+#define cmTakeSeqBldr_h
3
+
4
+#ifdef __cplusplus
5
+extern "C" {
6
+#endif
7
+
8
+
9
+  enum
10
+  {
11
+    kOkTsbRC = cmOkRC,
12
+    kJsonFailTsbRC,
13
+    kParseFailTsbRC
14
+  };
15
+
16
+  typedef cmRC_t     cmTsbRC_t;
17
+  typedef cmHandle_t cmTakeSeqBldrH_t;
18
+
19
+  extern cmTakeSeqBldrH_t cmTakeSeqBldrNullHandle;
20
+
21
+  cmTsbRC_t cmTakeSeqBldrAlloc(   cmCtx_t* ctx, cmTakeSeqBldrH_t* hp );
22
+  cmTsbRC_t cmTakeSeqBldrAllocFn( cmCtx_t* ctx, cmTakeSeqBldrH_t* hp, const cmChar_t* tsbFn );
23
+
24
+  cmTsbRC_t cmTakeSeqBldrFree( cmTakeSeqBldrH_t* hp );
25
+
26
+  bool      cmTakeSeqBldrIsValid( cmTakeSeqBldrH_t h );
27
+
28
+  cmTsbRC_t cmTakeSeqBldrInitialize( cmTakeSeqBldrH_t h, const cmChar_t* tsbFn );
29
+
30
+  // Load a group of notes delinated by a time-line marker into the sequence.
31
+  // If notes overlap with existing notes according to their 'scEvtIdx' attribute:
32
+  //   a. If 'overWriteFl' is set then the incoming overlapped notes are enabled 
33
+  //      and the existing overlapped notes are disabled, otherwise the incoming
34
+  //      overlapped notes are disabled and the existing notes remain enabled.
35
+  //   b. The incoming section is time aligned with the first or last existing 
36
+  //      note depending on whether the new section aligns best with the beginning
37
+  //      or ending of the existing notes.
38
+  //
39
+  // If no overlapping notes exist then the incoming section is aligned by estimating
40
+  // the alignment with existing notes using the score alone.
41
+  cmTsbRC_t cmTakeSeqBldrLoadSection(   cmTakeSeqBldrH_t h, unsigned tlMarkUid, bool overwriteFL );
42
+  cmTsbRC_t cmTakeSeqBldrUnloadSection( cmTakeSeqBldrH_t h, unsigned tlMarkUid );
43
+  
44
+  // Fill in missing notes from the score. 
45
+  cmTsbRC_t cmTakeSeqBldrInsertScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId );
46
+  cmTsbRC_t cmTakeSeqBldrRemoveScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId );
47
+
48
+  enum { kMarkTsbFl = 0x01, kTlNoteTsbFl=0x02, kScoreNoteTsbFl = 0x04, kPedalTsbFl = 0x08 };
49
+  cmTsbRC_t cmTakeSeqBldrSelectEnable( cmTakeSeqBldrH_t h, unsigned flags, unsigned id, bool selectFl );
50
+  cmTsbRC_t cmTakeSeqBldrEnableNote( cmTakeSeqBldrH_t h, unsigned ssqId, bool enableFl );
51
+
52
+  cmTsbRC_t cmTakeSeqBldrMoveNote(   cmTakeSeqBldrH_t h, unsigned ssqId, int deltaSmpIdx );
53
+
54
+  cmTsbRC_t cmTakeSeqBldrWriteMidiFile( cmTakeSeqBldrH_t h, const char* fn );
55
+
56
+  cmTsbRC_t cmTakeSeqBldrTest( cmCtx_t* ctx );
57
+
58
+#ifdef __cplusplus
59
+}
60
+#endif
61
+
62
+#endif

Loading…
Cancel
Save