~ubuntu-branches/ubuntu/oneiric/denemo/oneiric

« back to all changes in this revision

Viewing changes to src/importmidi.c

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2010-10-27 08:00:18 UTC
  • mfrom: (1.2.7 upstream) (3.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20101027080018-suwj9ozy99d0a5a2
Tags: 0.8.16-1ubuntu1
* Merge with Debian testing (LP: #638617), Ubuntu remaining changes:
  - debian/patches/ubuntuize.diff:
    + Provide a Ubuntu-specific customization.
  - debian/patches/fix_desktop.diff:
    + Add missing trailing semicolon.
    + Add MIME types.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 * (c) 2003-2005 AJAnderson
5
5
 *
6
6
 *      TODO
7
 
 *  
8
 
 *  check to see if memory used by malloc is freed
9
 
 *  clean up/optimise code
10
 
 *  add functions to add notes to chords
11
 
 *  create a define to initialize mididata->*?
12
7
 *
13
 
 *  change lastoff name to cursor_time
14
8
 *  multi voice support
15
9
 *  lyrics 
16
10
 *  triplet support
18
12
 */
19
13
 
20
14
#include <stdlib.h>
 
15
#include <stdint.h>
21
16
#include <math.h>
22
17
#include <string.h>
23
18
#include <assert.h>
25
20
#include "importmidi.h"
26
21
#include "staffops.h"
27
22
#include "smf.h"
 
23
#include "view.h"
 
24
#include "utils.h"
 
25
#include "file.h"
 
26
#include "commandfuncs.h"
 
27
#include "processstaffname.h"
28
28
 
29
29
#define TEXT                    0x01
30
30
#define COPYRIGHT               0X02
43
43
#define PCH_WHEEL               0xE0
44
44
#define SYS_EXCLUSIVE_MESSAGE1  0xF0
45
45
#define META_EVENT              0xFF
46
 
//0x0F ??
47
46
 
48
47
typedef struct notetype
49
48
{
50
49
        gint notetype;
51
50
        gint numofdots;
52
 
        gint tied;
53
51
}notetype;
54
52
 
55
 
typedef struct nstack 
56
 
{
57
 
        GList *chordnotes; /* list of notes that go along with that object */
58
 
        gint pitch;     /* base pitch or lowest pitch possibly redundant because of chordnotes */
59
 
        gint timeon;  /* tick number when the note starts*/
60
 
        gint on_delta_time; /* Is this NEEDED? this is time between last event and this notes start */
61
 
        gint duration; /* length of time in ticks */ 
62
 
        gint tracknum;  
63
 
}nstack;
64
 
 
65
 
typedef struct midicallback
66
 
{
67
 
        DenemoGUI *gui;
68
 
        nstack *currentnote; /* current note being processed */
69
 
        GList *notestack; /* polyphonic voices notes that need reprocessing */
70
 
        gint leftover; /* note/rest value that is leftover across the measure */
71
 
        gint bartime; /* time relative to barlength 0-barlength */
72
 
        gint delta_time; /* distance between notes */
73
 
        gint barlength; /* amount of time in measure */
74
 
        gint lastoff; /* starttime + duration. The time when the note is finished */
75
 
        gint event_number; /* smf event number that is currently being processed */
76
 
        gint key;   /* current key sig */
77
 
        gint track; /* the current track that is being read */
78
 
        smf_t *smf;
79
 
        smf_track_t *selected_track;
80
 
}midicallback;
81
 
 
82
53
typedef struct harmonic
83
54
{
84
55
        gint pitch;
85
56
        gint enshift;
86
57
}harmonic;
87
58
 
88
 
struct harmonic enharmonic(gint input, gint key);
89
 
static int readtrack(midicallback *mididata);
90
 
void dotimesig(gint numerator, gint denominator, midicallback *mididata);
91
 
void dokeysig(gint key, gint isminor, midicallback *mididata);
92
 
void dotempo(gint tempo,  midicallback *mididata);
93
 
void dotrackname(gchar *name, midicallback *mididata);
94
 
void doinstrname(gchar *name, midicallback *mididata);
95
 
void donoteon(midicallback *mididata, gint pitchon, gint velocity, gint timeon);
96
 
void donoteoff(midicallback *mididata);
97
 
struct notetype ConvertLength(gint duration, midicallback *mididata);
98
 
void ProcessNoteStack(midicallback *mididata);
99
 
void process_list(midicallback *mididata);
100
59
 
101
60
static void
102
61
note_from_int(char *buf, int note_number)
110
69
        sprintf(buf, "%s%d", names[note], octave);
111
70
}
112
71
 
113
 
static int
114
 
cmd_load(midicallback *mididata, char *file_name)
115
 
{
116
 
        if (mididata->smf != NULL)
117
 
                smf_delete(mididata->smf);
118
 
 
119
 
        mididata->selected_track = NULL;
120
 
 
121
 
        mididata->smf = smf_load(file_name);
122
 
        if (mididata->smf == NULL) {
123
 
                g_critical("Couldn't load '%s'.", file_name);
124
 
 
125
 
                mididata->smf = smf_new();
126
 
                if (mididata->smf == NULL) {
127
 
                        g_critical("Cannot initialize smf_t.");
128
 
                        return -1;
129
 
                }
130
 
 
131
 
                return -2;
132
 
        }
133
 
 
134
 
        g_message("File '%s' loaded.", file_name);
135
 
        g_message("%s.", smf_decode(mididata->smf));
136
 
 
137
 
        mididata->selected_track = smf_get_track_by_number(mididata->smf, 1);
138
 
 
139
 
        return 0;
 
72
static harmonic
 
73
enharmonic (gint input, gint key)
 
74
{
 
75
  harmonic local;
 
76
  local.pitch = (input / 12) - 5;
 
77
  local.enshift = input % 12;
 
78
  
 
79
  switch (local.enshift)
 
80
    {
 
81
    case 0:                     //c
 
82
      {
 
83
        local.pitch = (key > 6) ? (-1 + local.pitch * 7) : (local.pitch * 7);
 
84
        local.enshift = (key > 6) ? (1) : (0);
 
85
        break;
 
86
      }
 
87
    case 1:                     //c#
 
88
      {
 
89
        local.pitch = (key < -3) ? (1 + local.pitch * 7) : (local.pitch * 7);
 
90
        local.enshift = (key < -3) ? (-1) : (1);
 
91
        break;
 
92
      }
 
93
    case 2:                     //D
 
94
      {
 
95
        local.pitch = 1 + local.pitch * 7;
 
96
        local.enshift = 0;
 
97
        break;
 
98
      }
 
99
    case 3:                     //D#
 
100
      {
 
101
        local.pitch =
 
102
          (key < -1) ? (2 + local.pitch * 7) : (1 + local.pitch * 7);
 
103
        local.enshift = (key < -1) ? (-1) : (1);
 
104
        break;
 
105
      }
 
106
    case 4:                     //E
 
107
      {
 
108
        local.pitch =
 
109
          (key < -6) ? (3 + local.pitch * 7) : (2 + local.pitch * 7);
 
110
        local.enshift = (key < -6) ? (-1) : (0);
 
111
        break;
 
112
      }
 
113
    case 5:                     //F
 
114
      {
 
115
        local.pitch =
 
116
          (key > 5) ? (2 + local.pitch * 7) : (3 + local.pitch * 7);
 
117
        local.enshift = (key > 5) ? (1) : (0);
 
118
        break;
 
119
      }
 
120
    case 6:                     //F#
 
121
      {
 
122
        local.pitch =
 
123
          (key < -4) ? (4 + local.pitch * 7) : (3 + local.pitch * 7);
 
124
        local.enshift = (key < -4) ? (-1) : (1);
 
125
        break;
 
126
      }
 
127
    case 7:                     //G
 
128
      {
 
129
        local.pitch = 4 + local.pitch * 7;
 
130
        local.enshift = 0;
 
131
        break;
 
132
      }
 
133
    case 8:                     //G#
 
134
      {
 
135
        local.pitch =
 
136
          (key < -2) ? (5 + local.pitch * 7) : (4 + local.pitch * 7);
 
137
        local.enshift = (key < -2) ? (-1) : (1);
 
138
        break;
 
139
      }
 
140
    case 9:                     //A
 
141
      {
 
142
        local.pitch = 5 + local.pitch * 7;
 
143
        local.enshift = 0;
 
144
        break;
 
145
      }
 
146
    case 10:                    //A#
 
147
      {
 
148
        local.pitch =
 
149
          (key < 0) ? (6 + local.pitch * 7) : (5 + local.pitch * 7);
 
150
        local.enshift = (key < 0) ? (-1) : (1);
 
151
        break;
 
152
      }
 
153
    case 11:                    //B
 
154
      {
 
155
        local.pitch =
 
156
          (key < -5) ? (7 + local.pitch * 7) : (6 + local.pitch * 7);
 
157
        local.enshift = (key < -5) ? (-1) : (0);
 
158
        break;
 
159
      }
 
160
    };
 
161
  return local;
 
162
}
 
163
 
 
164
static void
 
165
ConvertLength(gint ppqn, gint duration, notetype *pnotetype){
 
166
 /*convert length to 2 = quarter, 1 = half, 0 = whole etc...... */
 
167
        /* quarter = 384, half = 768, whole = 1536*/
 
168
  
 
169
  gint notetype = 0;
 
170
  gint numofdots = 0;
 
171
  gint leftover = 0;
 
172
  gint dsq = (4 * ppqn);
 
173
  g_debug("\nDuration = %d ticks\n", duration);
 
174
  
 
175
  while ((dsq >> notetype) > duration)
 
176
          notetype++;
 
177
          
 
178
  leftover = duration - (dsq >> notetype); 
 
179
  if((dsq >> notetype+1)>0)
 
180
    while (leftover >= (dsq >> (notetype +1))){
 
181
      leftover -= (dsq >> (notetype +1));
 
182
      numofdots++;
 
183
    }
 
184
  
 
185
  pnotetype->notetype = notetype;
 
186
  pnotetype->numofdots = numofdots;
 
187
}
 
188
 
 
189
/**
 
190
 * Insert time signature into current staff 
 
191
 *
 
192
 */
 
193
static void
 
194
dotimesig (gint numerator, gint denominator)
 
195
{
 
196
  DenemoGUI *gui = Denemo.gui;
 
197
  /*only does initial TS */
 
198
  DenemoStaff *curstaffstruct = (DenemoStaff *) gui->si->currentstaff->data;
 
199
 
 
200
  curstaffstruct->timesig.time1 = numerator;
 
201
  curstaffstruct->timesig.time2 = denominator;
 
202
}
 
203
 
 
204
/**
 
205
 * Insert key signature into the current staff
 
206
 *
 
207
 */
 
208
static void
 
209
dokeysig (gint isminor, gint key)
 
210
{
 
211
  DenemoGUI *gui = Denemo.gui;
 
212
  if (key > 7)
 
213
    key = key - 256;            /*get flat key num, see keysigdialog.cpp */
 
214
#ifdef DEBUG
 
215
  g_print("\nkey = %d\n", key); 
 
216
#endif
 
217
  DenemoStaff *curstaffstruct = (DenemoStaff *) gui->si->currentstaff->data;
 
218
  curstaffstruct->keysig.number = key;
 
219
  curstaffstruct->keysig.isminor = isminor;
 
220
  dnm_setinitialkeysig (curstaffstruct, key, isminor);
 
221
}
 
222
 
 
223
static void
 
224
dotempo (gint tempo)
 
225
 
226
  DenemoGUI *gui = Denemo.gui;
 
227
  gui->si->tempo = (gint) (6.0e7 / (double) tempo);
 
228
}
 
229
 
 
230
static void
 
231
dotrackname (gchar *name)
 
232
{
 
233
  DenemoGUI *gui = Denemo.gui;
 
234
  DenemoStaff *curstaffstruct = (DenemoStaff *) gui->si->currentstaff->data;
 
235
  
 
236
  curstaffstruct->denemo_name->str = g_strdup(name);
 
237
}
 
238
 
 
239
static void
 
240
doinstrname (gchar* name)
 
241
{
 
242
  DenemoGUI *gui = Denemo.gui;
 
243
  DenemoStaff *curstaffstruct = (DenemoStaff *) gui->si->currentstaff->data;
 
244
 
 
245
  curstaffstruct->midi_instrument->str = g_strdup(name);
 
246
}
 
247
 
 
248
static void
 
249
insert_rest_into_score(notetype length)
 
250
{
 
251
  DenemoGUI *gui = Denemo.gui;
 
252
  gint i;
 
253
 
 
254
  switch (length.notetype)
 
255
  {
 
256
     case 0:
 
257
       insert_rest_0key (gui);
 
258
       break;
 
259
     case 1:
 
260
       insert_rest_1key (gui);
 
261
       break;
 
262
     case 2:
 
263
       insert_rest_2key (gui);
 
264
       break;
 
265
     case 3:
 
266
       insert_rest_3key (gui);
 
267
       break;
 
268
     case 4:
 
269
       insert_rest_4key (gui);
 
270
       break;
 
271
     case 5:
 
272
       insert_rest_5key (gui);
 
273
       break;
 
274
     case 6:
 
275
       insert_rest_6key (gui);
 
276
       break;
 
277
     default:
 
278
       insert_rest_2key (gui);
 
279
       break;
 
280
  }
 
281
  displayhelper (gui);
 
282
 
 
283
  /* add dots */
 
284
  for (i=0;i<length.numofdots;i++)
 
285
    add_dot_key (gui);
 
286
}
 
287
 
 
288
static void 
 
289
AddRest(gint ppqn, gint duration)
 
290
{
 
291
  gint rest;
 
292
  gint ticks;
 
293
  if (duration == 0)
 
294
    return;
 
295
  rest = duration;
 
296
 
 
297
  while (rest){
 
298
    notetype length;
 
299
    ConvertLength(ppqn, rest, &length);
 
300
    insert_rest_into_score(length);
 
301
    ticks = ConvertNoteType2ticks(ppqn, &length);
 
302
    rest -= ticks;
 
303
  }
 
304
}
 
305
 
 
306
static void
 
307
insert_note_into_score(gint pitch, notetype length)
 
308
{
 
309
  DenemoGUI *gui = Denemo.gui;
 
310
  DenemoStaff *curstaffstruct = (DenemoStaff *) gui->si->currentstaff->data;
 
311
  gint i;
 
312
 
 
313
  /* 0-8 accepted bellow */
 
314
  DenemoScriptParam param;
 
315
  switch(length.notetype) {
 
316
  case 0:
 
317
      InsertDur0(NULL, &param);
 
318
      break;
 
319
  case 1:
 
320
      InsertDur1(NULL, &param);
 
321
      break;
 
322
  case 2:
 
323
      InsertDur2(NULL, &param);
 
324
      break;
 
325
  case 3:
 
326
      InsertDur3(NULL, &param);
 
327
      break;
 
328
  case 4:
 
329
      InsertDur4(NULL, &param);
 
330
      break;
 
331
  case 5:
 
332
      InsertDur5(NULL, &param);
 
333
      break;
 
334
  case 6:
 
335
      InsertDur6(NULL, &param);
 
336
      break;
 
337
  case 7:
 
338
      InsertDur7(NULL, &param);
 
339
      break;
 
340
  default:
 
341
      InsertDur2(NULL, &param);
 
342
      g_warning("Cannot handle size %d",length.notetype);
 
343
      break;
 
344
  }
 
345
  g_debug("DenemoScriptParam = %d",param.status);
 
346
  /* get correct note name */
 
347
  gint key = curstaffstruct->keysig.number;
 
348
  harmonic enote = enharmonic (pitch, (gint) key);
 
349
  gchar *name =  mid_c_offsettolily (enote.pitch, enote.enshift);
 
350
  
 
351
  /* Rename note to the correct note */
 
352
  gchar *accidental = g_strdup_printf("(d-ChangeChordNotes \"%s\")", name);
 
353
  call_out_to_guile(accidental);
 
354
  g_free(accidental);
 
355
  /* Add dots */
 
356
  for (i=0;i<length.numofdots;i++)
 
357
    add_dot_key (gui);
 
358
 
 
359
  displayhelper(gui);
 
360
}
 
361
 
 
362
static void
 
363
AddNote(gint ppqn, gint pitch, gint duration)
 
364
{
 
365
  if (duration == 0)
 
366
    return;
 
367
  notetype length;
 
368
  ConvertLength(ppqn, duration, &length);
 
369
  insert_note_into_score(pitch, length);
 
370
}
 
371
 
 
372
static smf_t*
 
373
cmd_load(gchar *file_name)
 
374
{
 
375
  smf_t *smf;
 
376
        
 
377
  smf = smf_load(file_name);
 
378
  if (smf == NULL) {
 
379
    g_critical("Couldn't load '%s'.", file_name);
 
380
    return NULL;
 
381
  }
 
382
  g_message("File '%s' loaded.", file_name);
 
383
  g_message("%s.", smf_decode(smf));
 
384
 
 
385
  return smf;
140
386
}
141
387
 
142
388
#define BUFFER_SIZE 1024
143
389
 
144
 
static int
145
 
show_event(smf_event_t *event)
146
 
{
147
 
        int off = 0, i;
148
 
        char *decoded, *type;
149
 
 
150
 
        if (smf_event_is_metadata(event))
151
 
                type = "Metadata";
152
 
        else
153
 
                type = "Event";
154
 
        
155
 
        decoded = smf_event_decode(event);
156
 
 
157
 
        if (decoded == NULL) {
158
 
                decoded = malloc(BUFFER_SIZE);
159
 
                if (decoded == NULL) {
160
 
                        g_critical("show_event: malloc failed.");
161
 
                        return -1;
162
 
                }
163
 
 
164
 
                off += snprintf(decoded + off, BUFFER_SIZE - off, "Unknown event:");
165
 
 
166
 
                for (i = 0; i < event->midi_buffer_length && i < 5; i++)
167
 
                        off += snprintf(decoded + off, BUFFER_SIZE - off, " 0x%x", event->midi_buffer[i]);
168
 
        }
169
 
 
170
 
        g_message("%d: %s: %s, %f seconds, %d pulses, %d delta pulses", event->event_number, type, decoded,
171
 
                event->time_seconds, event->time_pulses, event->delta_time_pulses);
172
 
 
173
 
        free(decoded);
174
 
 
175
 
        return 0;
176
 
}
177
 
 
178
390
void
179
 
decode_metadata(const smf_event_t *event, midicallback *mididata)
 
391
decode_metadata(const smf_event_t *event)
180
392
{
181
393
        int off = 0, mspqn, flats, isminor;
182
394
        char *buf;
198
410
 
199
411
                case META_TRACK_NAME:
200
412
                        //return smf_event_decode_textual(event, "Sequence/Track Name");
201
 
                        dotrackname(smf_event_extract_text(event),mididata);
 
413
                        dotrackname(smf_event_extract_text(event));
202
414
 
203
415
                case META_INSTR_NAME:
204
416
                        //printf("\nInstrument text = %s\n", smf_string_from_event(event));
205
 
                        doinstrname(smf_event_extract_text(event), mididata);
 
417
                        doinstrname(smf_event_extract_text(event));
206
418
                case 0x05:
207
419
                        //return smf_event_decode_textual(event, "Lyric");
208
420
 
263
475
 
264
476
                        mspqn = (event->midi_buffer[3] << 16) + (event->midi_buffer[4] << 8) + event->midi_buffer[5];
265
477
                        
266
 
                        dotempo(mspqn, mididata);
 
478
                        dotempo(mspqn);
267
479
 
268
480
                        break;
269
481
 
277
489
                                goto error;
278
490
                        }
279
491
 
280
 
                        dotimesig(event->midi_buffer[3], (int)pow(2, event->midi_buffer[4]), mididata);
 
492
                        dotimesig(event->midi_buffer[3], (int)pow(2, event->midi_buffer[4]));
281
493
                        break;
282
494
 
283
495
                case META_KEYSIG:
294
506
                                goto error;
295
507
                        }
296
508
 
297
 
                        dokeysig(isminor, flats, mididata);
 
509
                        dokeysig(isminor, flats);
298
510
                        break;
299
511
 
300
512
                case 0x7F:
310
522
        free(buf);
311
523
}
312
524
 
 
525
/** 
 
526
 * extremely simple quantizer that rounds 
 
527
 * to the closest granule size
 
528
 */
 
529
static gint
 
530
round2granule(gint tick)
 
531
{
 
532
  gint smallestgrain = 48; 
 
533
  gdouble div = ((gdouble) tick / (gdouble) smallestgrain);
 
534
  return smallestgrain * (gint) round(div);
 
535
}
 
536
 
 
537
/**
 
538
 * Process note off command
 
539
 */
 
540
void
 
541
donoteoff (const smf_event_t *event)
 
542
{
 
543
  gint duration;
 
544
  gint ppqn; 
 
545
  
 
546
  ppqn = event->track->smf->ppqn;
 
547
  duration = event->delta_time_pulses;
 
548
  duration = round2granule(duration);
 
549
  AddNote(ppqn, event->midi_buffer[1], duration);
 
550
}
 
551
 
 
552
/**
 
553
 * Process note on command 
 
554
 */
 
555
void
 
556
donoteon (const smf_event_t *event)
 
557
{
 
558
  gint ppqn;
 
559
  ppqn = event->track->smf->ppqn;
 
560
  if (event->delta_time_pulses)
 
561
    AddRest(ppqn, round2granule(event->delta_time_pulses));
 
562
}
 
563
 
313
564
void 
314
 
decode_midi_event(const smf_event_t *event, midicallback *mididata)
 
565
decode_midi_event(const smf_event_t *event)
315
566
{
316
 
        int off = 0, channel;
317
 
        char note[5];
 
567
        gint off = 0, channel;
 
568
        gchar note[5];
318
569
 
319
570
        /* + 1, because user-visible channels used to be in range <1-16>. */
320
571
        channel = (event->midi_buffer[0] & 0x0F) + 1;
324
575
                        note_from_int(note, event->midi_buffer[1]);
325
576
                        g_debug("\nNote Off channel %d note %s velocity %d\n", 
326
577
                                        channel, note, event->midi_buffer[2]);
327
 
                        donoteoff (mididata);
 
578
                        donoteoff (event);
328
579
                        break;
329
580
 
330
581
                case NOTE_ON:
331
582
                        note_from_int(note, event->midi_buffer[1]);
332
583
                        g_debug("\nNote On channel %d note %s velocity %d\n", 
333
584
                                        channel, note, event->midi_buffer[2]);
334
 
                        mididata->delta_time = event->delta_time_pulses;
335
 
                        mididata->event_number = event->event_number;
336
 
                        donoteon(mididata,  event->midi_buffer[1],  event->midi_buffer[2], event->time_pulses);
 
585
 
 
586
                        if (event->midi_buffer[2])
 
587
                          donoteon(event);
 
588
                        else
 
589
                          donoteoff(event);
337
590
                        break;
338
591
 
339
592
                case AFTERTOUCH:
368
621
}
369
622
 
370
623
static int
371
 
process_midi(smf_event_t *event, midicallback *mididata)
372
 
{
373
 
        int off = 0, i;
374
 
 
375
 
        if (smf_event_is_metadata(event))
376
 
                decode_metadata(event, mididata);
377
 
        else
378
 
                decode_midi_event(event, mididata);
379
 
        
380
 
        return 0;
381
 
}
382
 
 
383
 
static int
384
 
readtrack(midicallback *mididata)
385
 
{
386
 
        smf_event_t *event;
387
 
 
388
 
        if (mididata->selected_track == NULL) {
389
 
                g_critical("No track");
390
 
                return -1;
391
 
        }
392
 
 
393
 
        smf_rewind(mididata->smf);
 
624
process_midi(smf_event_t *event)
 
625
{
 
626
  if (smf_event_is_metadata(event))
 
627
    decode_metadata(event);
 
628
  else
 
629
    decode_midi_event(event);
 
630
                
 
631
  return 0;
 
632
}
 
633
 
 
634
gint
 
635
process_track(smf_track_t *track) 
 
636
{
 
637
  smf_event_t *event;
 
638
  smf_t *smf = track->smf;//tracks can't be processed except inside an smf_t so create one if needed
 
639
  gboolean delete_smf_after = FALSE;
 
640
  if(smf==NULL){
 
641
    delete_smf_after = TRUE;
 
642
    smf = smf_new();
 
643
    smf_add_track(smf, track);
 
644
    smf_rewind(smf);
 
645
  }
 
646
  while (event = smf_track_get_next_event(track)) 
 
647
    process_midi(event);
 
648
  if(delete_smf_after) {
 
649
    smf_track_remove_from_smf(track);
 
650
    smf_delete(smf);
 
651
  }
 
652
}
 
653
 
 
654
void AddStaff(){
 
655
  call_out_to_guile("(d-AddAfter)");
 
656
}
 
657
 
 
658
static gint
 
659
readtrack(smf_t *smf)
 
660
{
 
661
  smf_event_t *event;
 
662
  smf_track_t *selected_track;
 
663
  gint track;
 
664
 
 
665
  smf_rewind(smf); 
394
666
       
395
 
        while (mididata->track <= mididata->smf->number_of_tracks){     
396
 
          /* process polyphonic voices */
397
 
          if (mididata->notestack != NULL)
398
 
                ProcessNoteStack(mididata);
399
 
          mididata->selected_track = smf_get_track_by_number(mididata->smf, mididata->track);
400
 
          while ((event = smf_track_get_next_event(mididata->selected_track)) != NULL) {
401
 
#ifdef DEBUG
402
 
                /* print midi event */
403
 
                show_event(event);
404
 
#endif
405
 
                /* Do something with the event */
406
 
                process_midi(event, mididata);
407
 
          }
408
 
          mididata->track++;
409
 
        }
410
 
        smf_rewind(mididata->smf);
411
 
 
412
 
        return 0;
413
 
}
414
 
 
415
 
/* TODO consolidate this into one function */
416
 
void
417
 
new_dnm_object(midicallback *mididata, nstack *currentnote, notetype length, gboolean is_note){
418
 
        DenemoObject *mudela_obj_new;
419
 
        mudela_obj_new = dnm_newchord (length.notetype, length.numofdots, length.tied);
420
 
        if (is_note){
421
 
          harmonic enote = enharmonic ((int) mididata->currentnote->pitch,mididata->key);
422
 
          dnm_addtone (mudela_obj_new, enote.pitch, enote.enshift, mididata->gui->si->cursorclef);
423
 
          while (mididata->currentnote->chordnotes){
424
 
                  struct harmonic enote = enharmonic ((int) 
425
 
                                 mididata->currentnote->chordnotes->data,mididata->key);
426
 
                  dnm_addtone (mudela_obj_new, enote.pitch, enote.enshift, mididata->gui->si->cursorclef);              
427
 
                  mididata->currentnote->chordnotes = g_list_remove_link(mididata->currentnote->chordnotes, 
428
 
                                  g_list_first (mididata->currentnote->chordnotes));
429
 
          }
430
 
        }
431
 
        object_insert (mididata->gui, mudela_obj_new);  
432
 
}
433
 
 
434
 
/**
435
 
 * Insert time signature into current staff 
436
 
 *
437
 
 */
438
 
void
439
 
dotimesig (gint numerator, gint denominator, midicallback *mididata)
440
 
{
441
 
  /*only does initial TS */
442
 
  DenemoStaff *curstaffstruct = (DenemoStaff *) mididata->gui->si->currentstaff->data;
443
 
 
444
 
  curstaffstruct->timesig.time1 = numerator;
445
 
  curstaffstruct->timesig.time2 = denominator;
446
 
 
447
 
  mididata->barlength = mididata->smf->ppqn * 4 * numerator / denominator;
448
 
}
449
 
 
450
 
/**
451
 
 * Insert key signature into the current staff
452
 
 *
453
 
 */
454
 
void
455
 
dokeysig (gint isminor, gint key, midicallback *mididata)
456
 
{
457
 
 
458
 
  if (key > 7)
459
 
    key = key - 256;            /*get flat key num, see keysigdialog.cpp */
460
 
#ifdef DEBUG
461
 
  g_print("\nkey = %d\n", key); 
462
 
#endif
463
 
  mididata->key = key;
464
 
  DenemoStaff *curstaffstruct = (DenemoStaff *) mididata->gui->si->currentstaff->data;
465
 
  curstaffstruct->keysig.number = key;
466
 
  curstaffstruct->keysig.isminor = isminor;
467
 
  dnm_setinitialkeysig (curstaffstruct, key, isminor);
468
 
}
469
 
 
470
 
void
471
 
dotempo (gint tempo, midicallback *mididata)
472
 
473
 
  mididata->gui->si->tempo = (gint) (6.0e7 / (double) tempo);
474
 
}
475
 
 
476
 
void
477
 
dotrackname (gchar *name, midicallback *mididata)
478
 
{
479
 
  DenemoStaff *curstaffstruct = (DenemoStaff *) mididata->gui->si->currentstaff->data;
480
 
  
481
 
  curstaffstruct->denemo_name->str = g_strdup(name);
482
 
  dnm_set_lily_name (curstaffstruct->denemo_name, curstaffstruct->lily_name);
483
 
}
484
 
 
485
 
void
486
 
doinstrname (gchar* name,  midicallback *mididata)
487
 
{
488
 
  DenemoStaff *curstaffstruct = (DenemoStaff *) mididata->gui->si->currentstaff->data;
489
 
 
490
 
  curstaffstruct->midi_instrument->str = g_strdup(name);
491
 
}
492
 
 
493
 
static nstack *
494
 
stack (gint pitch, gint timeon, gint delta_time, gint duration, gint tracknum)
495
 
{
496
 
  nstack *mystack = (nstack *)g_malloc0(sizeof(nstack));
497
 
  mystack->pitch = pitch;
498
 
  mystack->timeon = timeon;
499
 
  mystack->on_delta_time = delta_time;
500
 
  mystack->duration = duration;
501
 
  mystack->tracknum = tracknum;
502
 
  return mystack;
503
 
}
504
 
 
505
 
/**
506
 
 * Process note on command 
507
 
 */
508
 
void
509
 
donoteon (midicallback *mididata, gint pitchon, gint velocity, gint timeon)
510
 
{
511
 
  gint delta_time = mididata->delta_time; /*is this needed????*/
512
 
  
513
 
  /* add a note to the stack */
514
 
  Get_Smf_Note_OFF(pitchon, timeon, delta_time, mididata);
515
 
#ifdef DEBUG
516
 
  g_print ("\npitchon = %d timeon = %d event = %d\n", (gint) pitchon, (gint) timeon, (gint) mididata->event_number);
517
 
#endif
518
 
}
519
 
 
520
 
/**
521
 
 * Process note off command
522
 
 */
523
 
void
524
 
donoteoff (midicallback *mididata)
525
 
{
526
 
  nstack *currentnote = mididata->currentnote;
527
 
  if (currentnote != NULL){
528
 
        /*process the note found*/
529
 
        process_list(mididata); 
530
 
        g_free(mididata->currentnote);
531
 
  }
532
 
  mididata->currentnote = NULL; 
533
 
}
534
 
 
535
 
gboolean
536
 
ChordToneCheck(midicallback *mididata, gint pitch, gint timeon, gint delta_time, gint duration){
537
 
  nstack *currentnote = mididata->currentnote;  
538
 
  gint tracknum = (int) mididata->track;
539
 
 
540
 
  if ((currentnote->timeon == timeon) &&
541
 
     (currentnote->duration == duration)){
542
 
          g_print("\n***Same Duration and timeon***\n");
543
 
          /* append note to GList */
544
 
          currentnote->chordnotes = g_list_append(currentnote->chordnotes, (gpointer)pitch);
545
 
          return TRUE;
546
 
  }
547
 
  else if ((currentnote->timeon <= timeon) && (timeon <= ((int) currentnote->timeon + (int) currentnote->duration))){
548
 
        g_print("\n***NOTE_ON colliding between a NOTE_ON and NOTE_OFF tracknum = %d***\n",tracknum);   
549
 
        /* append to voice glist */
550
 
        nstack *noteon = stack(pitch, timeon, delta_time, duration, tracknum);
551
 
        /* store noteon in mididata->notestack */
552
 
        mididata->notestack = g_list_append(mididata->notestack, noteon);
553
 
        return FALSE;
554
 
  }
555
 
  return FALSE;
 
667
  for (track=1;track <= smf->number_of_tracks;track++){ 
 
668
    selected_track = smf_get_track_by_number(smf, track);
 
669
    process_track(selected_track);
 
670
    if (track+1 <= smf->number_of_tracks)
 
671
      AddStaff();
 
672
  }
 
673
  return 0;
556
674
}
557
675
 
558
676
gint
559
 
Get_Smf_Note_OFF (gint pitch, gint timeon, gint delta_time, midicallback *mididata){
560
 
  gint event_number = mididata->event_number;
561
 
  smf_event_t *event;
562
 
  gint duration;
563
 
  gint tracknum = mididata->track;
564
 
  gboolean chordtone = FALSE;
565
 
 
566
 
  while ((event = smf_track_get_event_by_number(mididata->selected_track, event_number)) != NULL){
567
 
    if (((event->midi_buffer[0] & SYS_EXCLUSIVE_MESSAGE1) == NOTE_OFF) 
568
 
                    & (event->midi_buffer[1] == (int) pitch)){
569
 
        duration = event->time_pulses - timeon; 
570
 
        if (mididata->currentnote != NULL) 
571
 
           chordtone = ChordToneCheck(mididata, pitch, timeon, delta_time, duration);
572
 
        if (!chordtone){
573
 
          /* store note in mididata->currentnote */
574
 
          mididata->currentnote = stack(pitch, timeon, delta_time, duration, tracknum);
575
 
        }
576
 
        g_print("\nFound corresponding note off to pitch %d timeon = %d duration = %d\n", (gint) pitch, timeon, (gint) duration);
577
 
        break;
578
 
    }
579
 
    event_number++;
580
 
  }
581
 
  return 0;
582
 
}
583
 
 
584
 
harmonic
585
 
enharmonic (gint input, gint key)
586
 
{
587
 
  harmonic local;
588
 
  local.pitch = (input / 12) - 5;
589
 
  local.enshift = input % 12;
590
 
  
591
 
  switch (local.enshift)
592
 
    {
593
 
    case 0:                     //c
594
 
      {
595
 
        local.pitch = (key > 6) ? (-1 + local.pitch * 7) : (local.pitch * 7);
596
 
        local.enshift = (key > 6) ? (1) : (0);
597
 
        break;
598
 
      }
599
 
    case 1:                     //c#
600
 
      {
601
 
        local.pitch = (key < -3) ? (1 + local.pitch * 7) : (local.pitch * 7);
602
 
        local.enshift = (key < -3) ? (-1) : (1);
603
 
        break;
604
 
      }
605
 
    case 2:                     //D
606
 
      {
607
 
        local.pitch = 1 + local.pitch * 7;
608
 
        local.enshift = 0;
609
 
        break;
610
 
      }
611
 
    case 3:                     //D#
612
 
      {
613
 
        local.pitch =
614
 
          (key < -1) ? (2 + local.pitch * 7) : (1 + local.pitch * 7);
615
 
        local.enshift = (key < -1) ? (-1) : (1);
616
 
        break;
617
 
      }
618
 
    case 4:                     //E
619
 
      {
620
 
        local.pitch =
621
 
          (key < -6) ? (3 + local.pitch * 7) : (2 + local.pitch * 7);
622
 
        local.enshift = (key < -6) ? (-1) : (0);
623
 
        break;
624
 
      }
625
 
    case 5:                     //F
626
 
      {
627
 
        local.pitch =
628
 
          (key > 5) ? (2 + local.pitch * 7) : (3 + local.pitch * 7);
629
 
        local.enshift = (key > 5) ? (1) : (0);
630
 
        break;
631
 
      }
632
 
    case 6:                     //F#
633
 
      {
634
 
        local.pitch =
635
 
          (key < -4) ? (4 + local.pitch * 7) : (3 + local.pitch * 7);
636
 
        local.enshift = (key < -4) ? (-1) : (1);
637
 
        break;
638
 
      }
639
 
    case 7:                     //G
640
 
      {
641
 
        local.pitch = 4 + local.pitch * 7;
642
 
        local.enshift = 0;
643
 
        break;
644
 
      }
645
 
    case 8:                     //G#
646
 
      {
647
 
        local.pitch =
648
 
          (key < -2) ? (5 + local.pitch * 7) : (4 + local.pitch * 7);
649
 
        local.enshift = (key < -2) ? (-1) : (1);
650
 
        break;
651
 
      }
652
 
    case 9:                     //A
653
 
      {
654
 
        local.pitch = 5 + local.pitch * 7;
655
 
        local.enshift = 0;
656
 
        break;
657
 
      }
658
 
    case 10:                    //A#
659
 
      {
660
 
        local.pitch =
661
 
          (key < 0) ? (6 + local.pitch * 7) : (5 + local.pitch * 7);
662
 
        local.enshift = (key < 0) ? (-1) : (1);
663
 
        break;
664
 
      }
665
 
    case 11:                    //B
666
 
      {
667
 
        local.pitch =
668
 
          (key < -5) ? (7 + local.pitch * 7) : (6 + local.pitch * 7);
669
 
        local.enshift = (key < -5) ? (-1) : (0);
670
 
        break;
671
 
      }
672
 
    };
673
 
  return local;
674
 
}
675
 
int
676
 
ConvertNoteType2ticks(midicallback *mididata, notetype *gnotetype){
 
677
ConvertNoteType2ticks(gint ppqn, notetype *gnotetype){
677
678
  gint ticks;
678
 
  gint PPQN = mididata->smf->ppqn;
679
679
  gint notetype = (int) gnotetype->notetype;
680
680
  gint numofdots = (int) gnotetype->numofdots;
681
 
  gint dsq = (4 * PPQN);
 
681
  gint dsq = (4 * ppqn);
682
682
  gint i = 0;
683
683
 
684
684
  ticks = dsq >> notetype;
685
685
  while (i++ < numofdots) 
686
 
    ticks += dsq >> notetype + 1;
 
686
    ticks += dsq >> (notetype + 1);
687
687
 
688
688
  return ticks;
689
689
}
690
690
 
691
 
notetype ConvertLength(gint duration, midicallback *mididata){
692
 
 /*convert length to 2 = quarter, 1 = half, 0 = whole etc...... */
693
 
        /* quarter = 384, half = 768, whole = 1536*/
694
 
  notetype gnotetype;
695
 
  gint PPQN = mididata->smf->ppqn;
696
 
  gint notetype = 0;
697
 
  gint numofdots = 0;
698
 
  gint tied = 0;
699
 
  gint leftover = 0;
700
 
  gint dsq = (4 * PPQN);
701
 
 
702
 
  
703
 
  while ((dsq >> notetype) > duration)
704
 
          notetype++;
705
 
          
706
 
  leftover = duration - (dsq >> notetype); 
707
 
 
708
 
  while (leftover >= (dsq >> (notetype +1))){
709
 
        leftover -= (dsq >> (notetype +1));
710
 
        numofdots++;
711
 
  }
712
 
  
713
 
  gnotetype.notetype = notetype;
714
 
  gnotetype.numofdots = numofdots;
715
 
  gnotetype.tied = leftover;
716
 
  return gnotetype;
717
 
}
718
 
 
719
 
/**
720
 
 * check to see if a new staff needs to be added
721
 
 */
722
 
void StaffCheck(midicallback *mididata){
723
 
  DenemoScore *si = mididata->gui->si;
724
 
  gint track = (int) mididata->currentnote->tracknum;
725
 
  gint currentstaffnum = si->currentstaffnum;
726
 
 
727
 
  if (track > currentstaffnum) /*if not first track add track */
728
 
    {
729
 
      si->currentstaffnum++;
730
 
      si->currentstaff = g_list_first (si->thescore); /* set the first track to be copied */
731
 
      newstaff (mididata->gui, ADDFROMLOAD, DENEMO_NONE); /* add track */
732
 
      si->currentstaff = g_list_last (si->thescore); /* make last staff the current */
733
 
      mididata->lastoff = 0;
734
 
      si->cursor_x = 0;
735
 
      mididata->bartime = 0;
736
 
      si->currentmeasurenum = 1;
737
 
    }
738
 
}
739
 
 
740
 
/** 
741
 
 * check
742
 
 * to see if we need to add a new measure 
743
 
 */
744
 
void MeasureCheck(midicallback *mididata){
745
 
  if (mididata->bartime >= mididata->barlength) 
746
 
  {                     /* mididata->bartime >= barlenth will be true if there are rests  or notes
747
 
                           going over end of measures. */
748
 
    if (!mididata->gui->si->currentmeasure->next)
749
 
      /* Add a measure and make it currentmeasure */
750
 
      mididata->gui->si->currentmeasure =
751
 
      dnm_addmeasures (mididata->gui->si, mididata->gui->si->currentmeasurenum, 1, 1);
752
 
    else
753
 
      mididata->gui->si->currentmeasure = mididata->gui->si->currentmeasure->next;
754
 
    /* Now the stuff that needs to be done for each case */
755
 
    mididata->gui->si->currentmeasurenum++;
756
 
    mididata->gui->si->currentobject = NULL;
757
 
    mididata->gui->si->cursor_x = 0;
758
 
    memcpy (mididata->gui->si->cursoraccs, mididata->gui->si->nextmeasureaccs, SEVENGINTS);
759
 
    memcpy (mididata->gui->si->curmeasureaccs, mididata->gui->si->nextmeasureaccs, SEVENGINTS);
760
 
    mididata->gui->si->curmeasureclef = mididata->gui->si->cursorclef;
761
 
    mididata->bartime = 0;
762
 
  }
763
 
}
764
 
 
765
 
void RestCheck(midicallback *mididata){
766
 
  gint rest = 0;
767
 
  gint PPQN = mididata->smf->ppqn;
768
 
  gint starttime = (int) mididata->currentnote->timeon;
769
 
  gint duration = (int) mididata->currentnote->duration;
770
 
  gint on_delta_time = (int) mididata->currentnote->on_delta_time;
771
 
  gint dsq = (4 * mididata->smf->ppqn);
772
 
 
773
 
  if (starttime > mididata->lastoff){
774
 
    rest = starttime - mididata->lastoff;
775
 
    if (mididata->bartime + on_delta_time  >= (mididata->barlength)){
776
 
      while(mididata->barlength - mididata->bartime){
777
 
        rest = mididata->barlength - mididata->bartime;
778
 
        struct notetype length = ConvertLength(rest, mididata);
779
 
        new_dnm_object(mididata, mididata->currentnote, length, FALSE);
780
 
        mididata->bartime += ConvertNoteType2ticks(mididata, &length);
781
 
        mididata->lastoff += ConvertNoteType2ticks(mididata, &length);
782
 
      } 
783
 
      process_list(mididata);                     
784
 
      rest = 0;/* I am not sure if this is the best choice here*/
785
 
    }
786
 
    if (rest){
787
 
        struct notetype length = ConvertLength(rest, mididata);
788
 
        new_dnm_object(mididata, mididata->currentnote, length, FALSE);
789
 
        mididata->bartime = mididata->bartime + ConvertNoteType2ticks(mididata, &length);
790
 
        mididata->lastoff += ConvertNoteType2ticks(mididata, &length);
791
 
        rest = 0;
792
 
    }
793
 
  }
794
 
}
795
 
 
796
 
/**
797
 
 * This takes a note and calculates if the note is to big to fit in the measure. 
798
 
 * If it is it fits what it can fit in the measure and ties it to the 
799
 
 * remainder in the next measure.
800
 
 */
801
 
void TiedNoteCheck(midicallback *mididata){
802
 
        gint duration = (int) mididata->currentnote->duration;
803
 
        gint barlength = (int) mididata->barlength;
804
 
  
805
 
        if ((mididata->bartime + duration) > barlength)
806
 
        {
807
 
                mididata->leftover = (int) (duration - (barlength - mididata->bartime));        /*tied over bar line */
808
 
                duration = (int) (barlength - mididata->bartime); /*new value that fits in bar*/
809
 
                mididata->currentnote->duration = duration; 
810
 
        }
811
 
        else 
812
 
                mididata->leftover = (int) 0;
813
 
}
814
 
 
815
 
void ProcessNote(midicallback *mididata) {
816
 
        DenemoScore *si = mididata->gui->si;
817
 
        gint starttime = (int) mididata->currentnote->timeon;
818
 
        gint lastoff = mididata->lastoff;
819
 
        gint duration = (int) mididata->currentnote->duration;
820
 
        gint pitch = (int) mididata->currentnote->pitch;
821
 
                
822
 
        /*if a noteon event happends just after anouther note finishes just add the next note */
823
 
        if (starttime == mididata->lastoff) {
824
 
                notetype length = ConvertLength(duration, mididata);
825
 
                length.tied = mididata->leftover;
826
 
                new_dnm_object (mididata, mididata->currentnote, length, TRUE);
827
 
                mididata->lastoff = starttime + duration;
828
 
                mididata->bartime += duration;
829
 
        }
830
 
        if (mididata->leftover){
831
 
                MeasureCheck(mididata);
832
 
                notetype tied_length = ConvertLength(mididata->leftover, mididata);
833
 
                new_dnm_object (mididata, mididata->currentnote, tied_length, TRUE);
834
 
                mididata->lastoff += mididata->leftover;
835
 
                mididata->bartime += mididata->leftover;
836
 
                mididata->leftover = 0;
837
 
        }
838
 
        /* if the starttime of noteon is not were we left off we need to do something */
839
 
        if ((starttime != mididata->lastoff) && (mididata->leftover !=0)){
840
 
                mididata->leftover = 0;
841
 
                mididata->currentnote->timeon = mididata->lastoff;
842
 
                process_list(mididata);
843
 
        }
844
 
}
845
 
 
846
 
void
847
 
ProcessNoteStack(midicallback *mididata){
848
 
        while (mididata->notestack){
849
 
                /* Assign the note to currentnote */
850
 
                mididata->currentnote = mididata->notestack->data; 
851
 
                /* send the note on for processing */
852
 
                process_list(mididata);
853
 
                /* remove note from list */
854
 
                mididata->notestack = g_list_remove_link(mididata->notestack,
855
 
                g_list_first (mididata->notestack));
856
 
        }
857
 
}
858
 
/**
859
 
 * Add notes to the current staff
860
 
 */
861
 
void
862
 
process_list(midicallback *mididata)
863
 
{
864
 
  /* check to see if we need to add a new staff */
865
 
  StaffCheck(mididata);
866
 
  /* check to see if we need to add a measure */
867
 
  MeasureCheck(mididata);       
868
 
  /*check for rests*/
869
 
  RestCheck(mididata);
870
 
  /*check for notes tied across measure*/
871
 
  TiedNoteCheck(mididata);      
872
 
  /* note processing stuff */
873
 
  ProcessNote(mididata);  
874
 
}
875
 
 
876
691
gint
877
692
importMidi (gchar *filename, DenemoGUI *gui)
878
693
{
879
 
  midicallback *mididata = (midicallback *)g_malloc0(sizeof(midicallback));
880
 
  mididata->selected_track = NULL;
881
 
  mididata->smf = NULL;
882
 
  mididata->gui = gui;
883
 
  mididata->bartime = 0;
884
 
  mididata->lastoff = 0;
885
 
  mididata->track = 1;
 
694
  smf_t *smf;
886
695
  gint ret = 0; // (-1 on failure)
887
696
 
888
697
  /* delete old data in the score */
889
 
  dnm_deletescore (NULL, gui);
890
 
 
 
698
  deletescore (NULL, gui);
891
699
  /* load the file */
892
 
  ret = cmd_load(mididata, filename);
 
700
  smf = cmd_load(filename);
 
701
  if(!smf)
 
702
    return -1;
893
703
  /* Read Track Data */ 
894
 
  readtrack(mididata);
895
 
 
896
 
  g_free(mididata);
 
704
  if (readtrack(smf))
 
705
    return -1;
 
706
  /* Delete data...Does it free it? */
 
707
  smf_delete(smf);
897
708
  return ret;
898
709
}