1 /* $Id: hmiplay.c,v 1.2 2003/03/13 00:20:21 btb Exp $ */
2 /*
3 * HMI midi playing routines by Jani Frilander
4 *
5 * External device support by Patrick McCarthy
6 *
7 * Ported to d1x/sdl_threads by Matthew Mueller
8 *
9 */
10
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <signal.h>
17 #include <linux/soundcard.h>
18 #include <sys/ioctl.h>
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/ipc.h>
22 #include <sys/msg.h>
23 #include "music.h"
24 #include "cfile.h"
25
26 #include <SDL_thread.h>
27
28 //#define WANT_AWE32 1
29
30 #ifdef WANT_AWE32
31 #include <linux/awe_voice.h>
32 #endif
33
34 //#define WANT_MPU401 1
35
36 #ifdef WANT_MPU401
37 #define MIDI_MESSAGE2(a,b) { \
38 SEQ_MIDIOUT(synth_dev,a); \
39 SEQ_MIDIOUT(synth_dev,b); \
40 }
41
42 #define MIDI_MESSAGE3(a,b,c) { \
43 SEQ_MIDIOUT(synth_dev,a); \
44 SEQ_MIDIOUT(synth_dev,b); \
45 SEQ_MIDIOUT(synth_dev,c); \
46 }
47 #endif
48
49 SEQ_DEFINEBUF(1024);
50
51 int drumflag = 1<<9;
52 int seqfd;
53 int synth_dev;
54 int program[16];
55 int stop;
56 double volume=1;
57
58 int ipc_queue_id = -1;
59 struct msgbuf *snd;
60
61 SDL_Thread *player_thread=NULL;
62
63 Voice_info *voices;
64 unsigned char *data=NULL;
65
66 struct synth_info card_info;
67
seqbuf_dump()68 void seqbuf_dump()
69 {
70 if (_seqbufptr)
71 {
72 if (write(seqfd, _seqbuf, _seqbufptr) == -1)
73 {
74 perror ("Error writing sequencer device");
75 SDL_KillThread(player_thread);
76 }
77 }
78 _seqbufptr = 0;
79 }
80
my_quit()81 void my_quit()
82 {
83 // printf("goodbye\n");//#####
84 // exit(0);
85 }
86
seq_init()87 int seq_init()
88 {
89 int nrmidis,nrsynths,i;
90
91 if ((seqfd = open(SEQ_DEV, O_WRONLY, 0)) < 0)
92 {
93 perror ("Error opening sequencer device");
94 return (-1);
95 }
96
97 if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrsynths) == -1)
98 {
99 perror ("There is no soundcard");
100 return (-1);
101 }
102
103 if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &nrmidis) == -1)
104 {
105 perror ("There is no soundcard");
106 return (-1);
107 }
108
109
110 if(nrsynths < 1 && nrmidis < 1)
111 {
112 printf("No synth or midi device!\n");
113 return -1;
114 }
115
116 synth_dev = 0;
117
118 //Check if we have wavetable synth device
119 for (i=0; i < nrsynths; i++)
120 {
121 card_info.device = i;
122 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
123 {
124 perror("cannot get info on soundcard");
125 return (-1);
126 }
127
128 if (card_info.synth_type == SYNTH_TYPE_SAMPLE)
129 {
130 synth_dev = i;
131 break;
132 }
133 }
134
135 #ifdef WANT_AWE32
136 for (i=0; i < nrsynths; i++)
137 {
138 card_info.device = i;
139 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
140 {
141 perror("cannot get info on soundcard");
142 return (-1);
143 }
144
145 if (card_info.synth_type==SYNTH_TYPE_SAMPLE
146 &&card_info.synth_subtype==SAMPLE_TYPE_AWE32) {
147 synth_dev = i;
148 break;
149 }
150 }
151 #endif
152
153 #ifdef WANT_MPU401
154 for (i=0; i < nrmidis; i++)
155 {
156 struct midi_info cinfo;
157 cinfo.device = i;
158 if (ioctl(seqfd, SNDCTL_MIDI_INFO, &cinfo) == -1)
159 {
160 perror("cannot get info on soundcard");
161 return (-1);
162 }
163
164 // Just take first available for now.
165 card_info.synth_type=SYNTH_TYPE_MIDI;
166 card_info.device=i;
167 synth_dev=i;
168 break;
169 }
170
171 if (card_info.synth_type!=SYNTH_TYPE_MIDI) {
172 #endif
173
174 card_info.device = synth_dev;
175 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
176 {
177 perror("cannot get info on soundcard");
178 return (-1);
179 }
180
181 #ifdef WANT_MPU401
182 }
183
184 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
185 // Insert some sort of midi reset here later.
186 } else
187 #endif
188 #ifdef WANT_AWE32
189 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
190 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
191 {
192 AWE_SET_CHANNEL_MODE(synth_dev,1);
193 AWE_DRUM_CHANNELS(synth_dev,drumflag);
194 }
195 else
196 #endif
197 {
198 voices = malloc(sizeof(Voice_info)*card_info.nr_voices);
199 for (i=0;i<card_info.nr_voices;i++)
200 {
201 voices[i].note = -1;
202 voices[i].channel = -1;
203 }
204 }
205
206 return(0);
207 }
208
seq_close()209 void seq_close()
210 {
211 SEQ_DUMPBUF();
212 ioctl(seqfd,SNDCTL_SEQ_SYNC);
213 close(seqfd);
214 free(voices);
215 }
216
set_program(int channel,int pgm)217 void set_program(int channel, int pgm)
218 {
219 #ifdef WANT_AWE32
220 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
221 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
222 {
223 SEQ_SET_PATCH(synth_dev,channel,pgm);
224 }
225 else
226 #endif
227 program[channel]=pgm;
228 }
229
start_note(int channel,int note,int vel)230 void start_note(int channel, int note, int vel)
231 {
232 int i;
233
234 #ifdef WANT_AWE32
235 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
236 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
237 {
238 SEQ_START_NOTE(synth_dev,channel,note,vel);
239 }
240 else
241 #endif
242 {
243 for (i=0; i<card_info.nr_voices;i++)
244 if ((voices[i].note == -1) && (voices[i].channel == -1))
245 break;
246 if (i != card_info.nr_voices)
247 {
248 voices[i].note = note;
249 voices[i].channel = channel;
250 if (((1<<channel) & drumflag)) /* drum note */
251 {
252 SEQ_SET_PATCH(synth_dev, i, note + 128);
253 }
254 else
255 {
256 SEQ_SET_PATCH(synth_dev, i, program[channel]);
257 }
258 SEQ_START_NOTE(synth_dev, i, note, vel);
259 }
260 }
261 }
262
stop_note(int channel,int note,int vel)263 void stop_note(int channel, int note, int vel)
264 {
265 int i;
266
267 #ifdef WANT_AWE32
268 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
269 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
270 {
271 SEQ_STOP_NOTE(synth_dev,channel,note,vel);
272 }
273 else
274 #endif
275 {
276 for (i=0; i<card_info.nr_voices;i++)
277 if ((voices[i].note == note) && (voices[i].channel == channel))
278 break;
279 if (i != card_info.nr_voices)
280 {
281 voices[i].note = -1;
282 voices[i].channel = -1;
283 SEQ_STOP_NOTE(synth_dev,i,note,vel);
284 }
285 }
286 }
287
set_control(int channel,int ctrl,int value)288 void set_control(int channel,int ctrl,int value)
289 {
290 int i;
291
292 #ifdef WANT_AWE32
293 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
294 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
295 {
296 SEQ_CONTROL(synth_dev,channel,ctrl,value);
297 }
298 else
299 #endif
300 {
301 for (i=0; i<card_info.nr_voices;i++)
302 if (voices[i].channel == channel)
303 if (ctrl == CTL_MAIN_VOLUME)
304 SEQ_MAIN_VOLUME(synth_dev,i,value);
305 }
306 }
307
set_pitchbend(int channel,int bend)308 void set_pitchbend(int channel, int bend)
309 {
310 int i;
311
312 #ifdef WANT_AWE32
313 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
314 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
315 {
316 SEQ_BENDER(synth_dev,channel,bend);
317 }
318 else
319 #endif
320 {
321 for (i=0; i<card_info.nr_voices;i++)
322 if (voices[i].channel == channel)
323 {
324 /*SEQ_BENDER_RANGE(synth_dev, i, 200);*/
325 SEQ_BENDER(synth_dev, i, bend);
326 }
327 }
328 }
329
set_key_pressure(int channel,int note,int vel)330 void set_key_pressure(int channel, int note, int vel)
331 {
332 int i;
333
334 #ifdef WANT_AWE32
335 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
336 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
337 {
338 AWE_KEY_PRESSURE(synth_dev,channel,note,vel);
339 }
340 else
341 #endif
342 {
343 for (i=0; i<card_info.nr_voices;i++)
344 if ((voices[i].note == note) && (voices[i].channel == channel))
345 SEQ_KEY_PRESSURE(synth_dev,i,note,vel);
346 }
347 }
348
set_chn_pressure(int channel,int vel)349 void set_chn_pressure(int channel, int vel)
350 {
351 int i;
352
353 #ifdef WANT_AWE32
354 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
355 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
356 {
357 AWE_CHN_PRESSURE(synth_dev,channel,vel);
358 }
359 else
360 #endif
361 {
362 for (i=0; i<card_info.nr_voices;i++)
363 if (voices[i].channel == channel)
364 SEQ_CHN_PRESSURE(synth_dev,i,vel);
365 }
366 }
367
stop_all()368 void stop_all()
369 {
370 int i;
371
372 #ifdef WANT_AWE32
373 int j;
374 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
375 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
376 {
377 for (i=0; i<16;i++)
378 for (j=0;j<128;j++)
379 SEQ_STOP_NOTE(synth_dev,i,j,0);
380 }
381 else
382 #endif
383 #ifdef WANT_MPU401
384 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
385 } else
386 #endif
387 {
388 for (i=0; i<card_info.nr_voices;i++)
389 SEQ_STOP_NOTE(synth_dev,i,voices[i].note,0);
390 }
391 }
392
get_dtime(unsigned char * data,int * pos)393 int get_dtime(unsigned char *data, int *pos)
394 {
395 char buf;
396 int result;
397 result =0;
398
399 buf = data[*pos];
400 *pos +=1;
401 result = (0x7f & buf);
402
403 if (!(buf & 0x80))
404 {
405 buf = data[*pos];
406 *pos +=1;
407 result |=(int) (((int) 0x7f & (int) buf)<<7);
408 if (!(buf & 0x80))
409 {
410 buf = data[*pos];
411 *pos +=1;
412 result |=(int) (((int) 0x7f & (int) buf)<<14);
413 if (!(buf & 0x80))
414 {
415 buf = data[*pos];
416 *pos +=1;
417 result |=(int) (((int) 0x7f & (int) buf)<<21);
418 }
419 }
420 }
421
422 return result;
423 }
424
do_track_event(unsigned char * data,int * pos)425 int do_track_event(unsigned char *data, int *pos)
426 {
427 char channel;
428 unsigned char buf[5];
429
430 buf[0]=data[*pos];
431 *pos +=1;
432 channel = buf[0] & 0xf;
433 #ifdef WANT_MPU401
434 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
435 switch((buf[0]&0xf0)) {
436 case 0x80:
437 case 0x90:
438 case 0xa0:
439 case 0xb0:
440 case 0xe0:
441 buf[1]=data[*pos]; *pos+=1;
442 buf[2]=data[*pos]; *pos+=1;
443 MIDI_MESSAGE3(buf[0],buf[1],buf[2]);
444 break;
445 case 0xc0:
446 case 0xd0:
447 buf[1]=data[*pos]; *pos+=1;
448 MIDI_MESSAGE3(buf[0],0,buf[1]);
449 break;
450 case 0xf0:
451 return 1;
452 default:
453 return 3;
454 }
455 seqbuf_dump();
456 return 0;
457 }
458 #endif
459
460 switch((buf[0] & 0xf0))
461 {
462 case 0x80:
463 buf[1]=data[*pos];
464 *pos +=1;
465 buf[2]=data[*pos];
466 *pos +=1;
467 stop_note((int) channel, (int) buf[1], (int) buf[2]);
468 break;
469 case 0x90:
470 buf[1]=data[*pos];
471 *pos +=1;
472 buf[2]=data[*pos];
473 *pos +=1;
474 if(buf[2] == 0)
475 {
476 stop_note((int) channel, (int) buf[1], (int) buf[2]);
477 }
478 else
479 {
480 start_note((int) channel, (int) buf[1], (int) buf[2]);
481 }
482 break;
483 case 0xa0:
484 buf[1]=data[*pos];
485 *pos +=1;
486 buf[2]=data[*pos];
487 *pos +=1;
488 set_key_pressure((int) channel, (int) buf[1], (int) buf[2]);
489 break;
490 case 0xb0:
491 buf[1]=data[*pos];
492 *pos +=1;
493 buf[2]=data[*pos];
494 *pos +=1;
495 set_control((int) channel, (int) buf[1], (int) buf[2]);
496 break;
497 case 0xe0:
498 buf[1]=data[*pos];
499 *pos +=1;
500 buf[2]=data[*pos];
501 *pos +=1;
502 set_pitchbend((int) channel, (int) ((buf[2] << 7) + buf[1]));
503 break;
504 case 0xc0:
505 buf[1]=data[*pos];
506 *pos +=1;
507 set_program((int) channel, (int) buf[1] );
508 break;
509 case 0xd0:
510 buf[1]=data[*pos];
511 *pos +=1;
512 set_chn_pressure((int) channel, (int) buf[1]);
513 break;
514 case 0xf0:
515 return 1;
516 default:
517 return 3;
518 }
519 seqbuf_dump();
520 return 0;
521 }
522
send_ipc(char * message)523 void send_ipc(char *message)
524 {
525 printf ("sendipc %s\n", message);//##########3
526 if (ipc_queue_id<0)
527 {
528 ipc_queue_id=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's',
529 IPC_CREAT | 0660);
530 snd=malloc(sizeof(long) + 32);
531 snd->mtype=1;
532 player_thread=SDL_CreateThread(play_hmi, NULL);
533 // player_pid = play_hmi();
534 }
535 if (strlen(message) < 16)
536 {
537 sprintf(snd->mtext,"%s",message);
538 msgsnd(ipc_queue_id,snd,16,0);
539 }
540 }
541
kill_ipc()542 void kill_ipc()
543 {
544 // send_ipc("q");
545 // kill(player_pid,SIGTERM);
546 msgctl( ipc_queue_id, IPC_RMID, 0);
547 free(snd);
548 ipc_queue_id = -1;
549 // player_pid = 0;
550 }
551
do_ipc(int qid,struct msgbuf * buf,int flags)552 int do_ipc(int qid, struct msgbuf *buf, int flags)
553 {
554 int ipc_read;
555 CFILE *fptr;
556 int l=0;
557
558 ipc_read = msgrcv(qid,buf,16,0,flags | MSG_NOERROR);
559
560 switch (ipc_read)
561 {
562 case -1:
563 if (errno == ENOMSG)
564 break;
565 perror("IPC trouble");
566 break;
567 case 0:
568 break;
569 default:
570 printf ("do_ipc %s\n", buf->mtext);//##########3
571 switch (buf->mtext[0])
572 {
573 case 'v':
574 volume=(double) ((double) buf->mtext[0]/127.0);
575 break;
576 case 'p':
577 fptr=cfopen((buf->mtext+1),"rb");
578 if(fptr != NULL)
579 {
580 l = cfilelength(fptr);
581 data=realloc(data,(size_t) l);
582 cfread(data, l, 1, fptr);
583 cfclose(fptr);
584 printf ("good. fpr=%p l=%i data=%p\n", fptr, l, data);//##########3
585 }
586 stop = 0;
587 break;
588 case 's':
589 stop = 2;
590 break;
591 case 'q':
592 // SDL_KillThread(player_thread);
593 break;
594 }
595 }
596
597 return ipc_read;
598 }
599
play_hmi(void * arg)600 void play_hmi (void * arg)
601 {
602 int i;
603 int pos = 0x308;
604 int n_chunks = 0;
605 int low_dtime;
606 int low_chunk;
607 int csec;
608 // pid_t loc_pid;
609 int qid;
610 int ipc_read = 0;
611 int k=0;
612
613 struct msgbuf *rcv;
614
615 Track_info *t_info;
616
617 printf ("play_hmi\n");//#########
618
619 stop = 0;
620 ipc_read=0;
621 // loc_pid=fork();
622
623 /* switch (loc_pid)
624 {
625 case 0:
626 break;
627 case -1:
628 return -1;
629 default:
630 atexit(kill_ipc);
631 return loc_pid;
632 }*/
633
634 // signal(SIGTERM, my_quit);
635 rcv=malloc(sizeof(long) + 16);
636
637 rcv->mtype=1;
638 rcv->mtext[0]='0';
639
640 sleep(2);
641
642 qid=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's', 0660);
643 if(qid == -1)
644 {
645 return;
646 }
647
648 do
649 {
650 ipc_read=do_ipc(qid,rcv,0);
651 }
652 while(rcv->mtext[0] != 'p');
653
654 stop=0;
655 rcv->mtext[0] = '0';
656
657 seq_init();
658
659 n_chunks=data[0x30];
660
661 t_info = malloc(sizeof(Track_info)*n_chunks);
662
663 while(1)
664 {
665
666 for(i=0;i<n_chunks;i++)
667 {
668 t_info[i].position = pos + 12;
669 t_info[i].status = PLAYING;
670 t_info[i].time = get_dtime(data,&t_info[i].position);
671 pos += (( (0xff & data[pos + 5]) << 8 ) + (0xff & data[pos + 4]));
672 }
673
674 SEQ_START_TIMER();
675 do
676 {
677 low_chunk = -1;
678 k++;
679 i=0;
680 do
681 {
682 if (t_info[i].status == PLAYING)
683 low_chunk = i;
684 i++;
685 }
686 while((low_chunk <=0) && (i<n_chunks));
687
688 if (low_chunk == -1)
689 break;
690
691 low_dtime = t_info[low_chunk].time;
692
693 for(i=1;i<n_chunks;i++)
694 {
695 if ((t_info[i].time < low_dtime) &&
696 (t_info[i].status == PLAYING))
697 {
698 low_dtime = t_info[i].time;
699 low_chunk = i;
700 }
701 }
702
703 if (low_dtime < 0)
704 printf("Serious warning: d_time negative!!!!!!\n");
705
706 csec = 0.86 * low_dtime;
707
708 //flush sequencer buffer after 20 events
709 if (k == 20)
710 {
711 ioctl(seqfd, SNDCTL_SEQ_SYNC);
712 k = 0;
713 }
714
715 SEQ_WAIT_TIME(csec);
716
717 t_info[low_chunk].status = do_track_event(data,&t_info[low_chunk].position);
718
719 if (t_info[low_chunk].status == 3)
720 {
721 printf("Error playing data in chunk %d\n",low_chunk);
722 t_info[low_chunk].status = STOPPED;
723 }
724
725 if (t_info[low_chunk].status == PLAYING)
726 t_info[low_chunk].time += get_dtime(data,&t_info[low_chunk].position);
727
728 //Check if the song has reached the end
729 stop = t_info[0].status;
730 for(i=1;i<n_chunks;i++)
731 stop &= t_info[i].status;
732
733 if((do_ipc(qid,rcv,IPC_NOWAIT) > 0) && (rcv->mtext[0]=='p'))
734 {
735 n_chunks=data[0x30];
736 t_info = realloc(t_info,sizeof(Track_info)*n_chunks);
737 stop = 1;
738 rcv->mtext[0] = '0';
739 stop_all();
740 }
741 }
742 while(!stop);
743 SEQ_STOP_TIMER();
744 if( stop == 2)
745 {
746 stop_all();
747 do
748 {
749 ipc_read=do_ipc(qid,rcv,0);
750 }
751 while(rcv->mtext[0] != 'p');
752 rcv->mtext[0] = '0';
753 n_chunks=data[0x30];
754 t_info = realloc(t_info,sizeof(Track_info)*n_chunks);
755 stop = 0;
756 }
757 pos=0x308;
758 }
759 free(data);
760 free(t_info);
761 free(rcv);
762
763 }
764
digi_play_midi_song(char * filename,char * melodic_bank,char * drum_bank,int loop)765 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {
766 char buf[128];
767
768 sprintf(buf,"p%s",filename);
769 send_ipc(buf);
770 }
digi_set_midi_volume(int mvolume)771 void digi_set_midi_volume( int mvolume ) {
772 char buf[128];
773
774 sprintf(buf,"v%i",mvolume);
775 send_ipc(buf);
776 }
777