The channel map in ss_ins works again (Closes: #1049).
[ahxm.git] / midi_song.c
blob29f24fb5bd17f51a81f491dc67b8a0dccca2f4f0
1 /*
3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2005 Angel Ortega <angel@triptico.com>
6 midi_song.c - MIDI song event stream management
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 http://www.triptico.com
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
32 #include <time.h>
33 #include <unistd.h>
35 #include "ss_core.h" /* for CHANNELS */
36 #include "song.h"
38 /*******************
39 Data
40 ********************/
42 struct midi_ev_generic
44 song_ev_type type; /* event type */
45 int msecs; /* time in milliseconds */
46 int trk_id; /* track id */
47 int channel; /* MIDI channel */
50 struct midi_ev_program
52 song_ev_type type; /* SONG_EV_MIDI_PROGRAM */
53 int msecs;
54 int trk_id;
55 int channel;
56 int program; /* MIDI program number */
59 struct midi_ev_note_off
61 song_ev_type type; /* SONG_EV_NOTE_OFF */
62 int msecs;
63 int trk_id;
64 int channel;
65 int note; /* MIDI note */
68 struct midi_ev_note_on
70 song_ev_type type; /* SONG_EV_NOTE_ON */
71 int msecs;
72 int trk_id;
73 int channel;
74 int note; /* MIDI note */
75 int vel; /* velocity (volume) */
78 union midi_ev
80 struct midi_ev_generic generic;
81 struct midi_ev_program midi_program;
82 struct midi_ev_note_on note_on;
83 struct midi_ev_note_off note_off;
87 /* the MIDI song stream */
89 static union midi_ev * midi_song=NULL;
90 static int n_midi_ev=0;
92 /* the MIDI tracks: just a track/channel table */
94 #define MIDI_TRACK_NUM 256
95 static int track_channel[MIDI_TRACK_NUM];
97 /* MIDI message types */
99 #define MIDI_MSG_NOTE_ON 0x90
100 #define MIDI_MSG_NOTE_OFF 0x80
101 #define MIDI_MSG_CONTROLLER 0xB0
102 #define MIDI_MSG_PROGRAM 0xC0
104 /* MIDI device fd */
105 int midi_fd=2;
108 /*******************
109 Code
110 ********************/
112 static void add_midi_ev(union midi_ev * e)
113 /* adds a MIDI song event */
115 n_midi_ev++;
117 /* reallocs */
118 midi_song=(union midi_ev *)realloc(midi_song,
119 n_midi_ev * sizeof(union midi_ev));
121 /* store */
122 memcpy(&midi_song[n_midi_ev - 1], e, sizeof(union midi_ev));
126 static int midi_ev_cmp_by_time(const void * v1, const void * v2)
127 /* MIDI song event compare function for qsort(), by time (for playing) */
129 struct midi_ev_generic * e1;
130 struct midi_ev_generic * e2;
132 e1=(struct midi_ev_generic *)v1; e2=(struct midi_ev_generic *)v2;
134 if(e1->msecs == e2->msecs)
135 return(e1->type - e2->type);
137 return(e1->msecs - e2->msecs);
141 static int midi_song_convert_events(void)
142 /* converts generic song_ev events to MIDI events */
144 union song_ev * e;
145 union midi_ev me;
146 int msecs, msecs_ac;
147 int time_ac;
148 int num, den;
149 double mspw;
150 int n;
151 int b_track=-1;
153 /* resets the MIDI stream */
154 if(midi_song != NULL)
156 free(midi_song);
157 midi_song=NULL;
160 n_midi_ev=0;
162 /* sorts the song */
163 song_sort();
165 mspw=0;
166 msecs_ac=0;
167 time_ac=0;
168 num=den=4;
170 /* sets the default track channels sparsely */
171 for(n=0;n < MIDI_TRACK_NUM;n++)
172 track_channel[n]=n % 16;
174 /* travels the song events generating MIDI song events */
175 for(n=0;n < _n_song_ev;n++)
177 /* gets the song event */
178 e=&_song[n];
180 /* calculates the msecs */
181 msecs=((e->generic.time - time_ac) * mspw) + msecs_ac;
183 /* generic event data */
184 me.generic.type=e->generic.type;
185 me.generic.msecs=msecs;
186 me.generic.trk_id=e->generic.trk_id;
188 /* if it's not a generic message, set MIDI channel */
189 if(e->generic.trk_id >= 0)
190 me.generic.channel=track_channel[e->generic.trk_id];
192 /* account the biggest track number seen */
193 if(b_track < e->generic.trk_id) b_track=e->generic.trk_id;
195 switch(e->generic.type)
197 case SONG_EV_TEMPO:
199 /* updates accumulations */
200 msecs_ac += msecs;
201 time_ac += e->generic.time;
203 /* calculates milliseconds-per-whole based on new tempo */
204 mspw = 1000.0 * 60.0;
205 mspw /= (e->tempo.tempo / 4.0);
207 break;
209 case SONG_EV_METER:
211 /* just store the values */
212 num=e->meter.num;
213 den=e->meter.den;
215 break;
217 case SONG_EV_MEASURE:
219 printf("measure boundary check (must be 0): %d\n",
220 ((int) e->generic.time * num) % den);
222 break;
224 case SONG_EV_MIDI_CHANNEL:
226 /* stores the channel for this track */
227 track_channel[e->midi_channel.trk_id]=
228 e->midi_channel.channel - 1;
229 break;
231 case SONG_EV_NOTE:
233 /* convert to note on / off pairs */
235 me.note_on.type=SONG_EV_NOTE_ON;
236 me.note_on.note=e->note.note;
237 me.note_on.vel=(int)(e->note.vol * 127.0);
239 add_midi_ev(&me);
241 msecs += (int)(e->note.len * mspw);
243 me.note_off.type=SONG_EV_NOTE_OFF;
244 me.note_off.msecs=msecs;
246 add_midi_ev(&me);
247 break;
249 case SONG_EV_MIDI_PROGRAM:
251 /* set MIDI program (instrument) */
252 me.midi_program.program=e->midi_program.program;
254 add_midi_ev(&me);
255 break;
257 case SONG_EV_SS_NOTE_ON_BY_TIME:
258 case SONG_EV_SS_WAV:
259 case SONG_EV_SS_PAT:
260 case SONG_EV_SS_SUSTAIN:
261 case SONG_EV_SS_CHANNEL_MAP:
262 case SONG_EV_SS_EFF_DELAY:
263 case SONG_EV_SS_EFF_ECHO:
264 case SONG_EV_SS_EFF_COMB:
265 case SONG_EV_SS_EFF_ALLPASS:
266 case SONG_EV_SS_EFF_FLANGER:
267 case SONG_EV_SS_EFF_WOBBLE:
268 case SONG_EV_SS_EFF_SQWOBBLE:
269 case SONG_EV_SS_EFF_FADER:
270 case SONG_EV_SS_EFF_REVERB:
272 /* softsynth events are ignored */
273 break;
275 case SONG_EV_NOTE_ON:
276 case SONG_EV_NOTE_OFF:
277 case SONG_EV_END:
279 /* never found in generic song streams */
280 break;
284 /* generates an end of event mark, a time after the last one */
285 me.generic.type=SONG_EV_END;
286 me.generic.msecs=msecs + 1000;
287 add_midi_ev(&me);
289 /* return the number of tracks */
290 return(b_track + 1);
294 int midi_song_play(void)
296 union midi_ev * e;
297 int msecs, msecs_p, msecs_d;
298 int go;
299 int n_tracks;
300 struct timespec ts;
301 unsigned char midimsg[10];
303 /* convert the song to MIDI events */
304 n_tracks=midi_song_convert_events();
306 /* sort by time */
307 qsort(midi_song, n_midi_ev, sizeof(union midi_ev), midi_ev_cmp_by_time);
309 msecs=msecs_p=0;
310 go=1;
311 e=midi_song;
313 /* loop the events */
314 while(go)
316 /* process all events for this exact time */
317 while(e->generic.msecs == msecs)
319 switch(e->generic.type)
321 case SONG_EV_NOTE_ON:
323 midimsg[0]=MIDI_MSG_NOTE_ON|e->note_on.channel;
324 midimsg[1]=e->note_on.note;
325 midimsg[2]=e->note_on.vel;
327 write(midi_fd, midimsg, 3);
329 break;
331 case SONG_EV_NOTE_OFF:
333 midimsg[0]=MIDI_MSG_NOTE_OFF|e->note_off.channel;
334 midimsg[1]=e->note_off.note;
335 midimsg[2]=0;
337 write(midi_fd, midimsg, 3);
339 break;
341 case SONG_EV_MIDI_PROGRAM:
343 midimsg[0]=MIDI_MSG_PROGRAM|e->midi_program.channel;
344 midimsg[1]=e->midi_program.program;
346 write(midi_fd, midimsg, 2);
348 break;
350 case SONG_EV_END:
352 go=0;
353 break;
355 default:
356 /* ignore the rest */
357 break;
360 /* next event */
361 e++;
364 if(!go)
365 break;
367 /* get time of next event */
368 msecs_p=msecs;
369 msecs=e->generic.msecs;
370 msecs_d=msecs - msecs_p;
372 /* calculate the time to sleep */
373 ts.tv_sec=(time_t) msecs_d / 1000;
374 ts.tv_nsec=(long) ((msecs_d * 1000000) % 1000000000);
376 nanosleep(&ts, NULL);
379 return(0);