1 /* HMI midi playing routines by Jani Frilander
3 * External device support by Patrick McCarthy
5 * Ported to d1x/sdl_threads by Matthew Mueller
14 #include <linux/soundcard.h>
15 #include <sys/ioctl.h>
17 #include <sys/types.h>
23 #include <SDL_thread.h>
25 //#define WANT_AWE32 1
28 #include <linux/awe_voice.h>
31 //#define WANT_MPU401 1
34 #define MIDI_MESSAGE2(a,b) { \
35 SEQ_MIDIOUT(synth_dev,a); \
36 SEQ_MIDIOUT(synth_dev,b); \
39 #define MIDI_MESSAGE3(a,b,c) { \
40 SEQ_MIDIOUT(synth_dev,a); \
41 SEQ_MIDIOUT(synth_dev,b); \
42 SEQ_MIDIOUT(synth_dev,c); \
55 int ipc_queue_id = -1;
58 SDL_Thread *player_thread=NULL;
61 unsigned char *data=NULL;
63 struct synth_info card_info;
69 if (write(seqfd, _seqbuf, _seqbufptr) == -1)
71 perror ("Error writing sequencer device");
72 SDL_KillThread(player_thread);
80 // printf("goodbye\n");//#####
86 int nrmidis,nrsynths,i;
88 if ((seqfd = open(SEQ_DEV, O_WRONLY, 0)) < 0)
90 perror ("Error opening sequencer device");
94 if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrsynths) == -1)
96 perror ("There is no soundcard");
100 if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &nrmidis) == -1)
102 perror ("There is no soundcard");
107 if(nrsynths < 1 && nrmidis < 1)
109 printf("No synth or midi device!\n");
115 //Check if we have wavetable synth device
116 for (i=0; i < nrsynths; i++)
118 card_info.device = i;
119 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
121 perror("cannot get info on soundcard");
125 if (card_info.synth_type == SYNTH_TYPE_SAMPLE)
133 for (i=0; i < nrsynths; i++)
135 card_info.device = i;
136 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
138 perror("cannot get info on soundcard");
142 if (card_info.synth_type==SYNTH_TYPE_SAMPLE
143 &&card_info.synth_subtype==SAMPLE_TYPE_AWE32) {
151 for (i=0; i < nrmidis; i++)
153 struct midi_info cinfo;
155 if (ioctl(seqfd, SNDCTL_MIDI_INFO, &cinfo) == -1)
157 perror("cannot get info on soundcard");
161 // Just take first available for now.
162 card_info.synth_type=SYNTH_TYPE_MIDI;
168 if (card_info.synth_type!=SYNTH_TYPE_MIDI) {
171 card_info.device = synth_dev;
172 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
174 perror("cannot get info on soundcard");
181 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
182 // Insert some sort of midi reset here later.
186 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
187 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
189 AWE_SET_CHANNEL_MODE(synth_dev,1);
190 AWE_DRUM_CHANNELS(synth_dev,drumflag);
195 voices = malloc(sizeof(Voice_info)*card_info.nr_voices);
196 for (i=0;i<card_info.nr_voices;i++)
199 voices[i].channel = -1;
209 ioctl(seqfd,SNDCTL_SEQ_SYNC);
214 void set_program(int channel, int pgm)
217 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
218 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
220 SEQ_SET_PATCH(synth_dev,channel,pgm);
224 program[channel]=pgm;
227 void start_note(int channel, int note, int vel)
232 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
233 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
235 SEQ_START_NOTE(synth_dev,channel,note,vel);
240 for (i=0; i<card_info.nr_voices;i++)
241 if ((voices[i].note == -1) && (voices[i].channel == -1))
243 if (i != card_info.nr_voices)
245 voices[i].note = note;
246 voices[i].channel = channel;
247 if (((1<<channel) & drumflag)) /* drum note */
249 SEQ_SET_PATCH(synth_dev, i, note + 128);
253 SEQ_SET_PATCH(synth_dev, i, program[channel]);
255 SEQ_START_NOTE(synth_dev, i, note, vel);
260 void stop_note(int channel, int note, int vel)
265 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
266 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
268 SEQ_STOP_NOTE(synth_dev,channel,note,vel);
273 for (i=0; i<card_info.nr_voices;i++)
274 if ((voices[i].note == note) && (voices[i].channel == channel))
276 if (i != card_info.nr_voices)
279 voices[i].channel = -1;
280 SEQ_STOP_NOTE(synth_dev,i,note,vel);
285 void set_control(int channel,int ctrl,int value)
290 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
291 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
293 SEQ_CONTROL(synth_dev,channel,ctrl,value);
298 for (i=0; i<card_info.nr_voices;i++)
299 if (voices[i].channel == channel)
300 if (ctrl == CTL_MAIN_VOLUME)
301 SEQ_MAIN_VOLUME(synth_dev,i,value);
305 void set_pitchbend(int channel, int bend)
310 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
311 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
313 SEQ_BENDER(synth_dev,channel,bend);
318 for (i=0; i<card_info.nr_voices;i++)
319 if (voices[i].channel == channel)
321 /*SEQ_BENDER_RANGE(synth_dev, i, 200);*/
322 SEQ_BENDER(synth_dev, i, bend);
327 void set_key_pressure(int channel, int note, int vel)
332 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
333 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
335 AWE_KEY_PRESSURE(synth_dev,channel,note,vel);
340 for (i=0; i<card_info.nr_voices;i++)
341 if ((voices[i].note == note) && (voices[i].channel == channel))
342 SEQ_KEY_PRESSURE(synth_dev,i,note,vel);
346 void set_chn_pressure(int channel, int vel)
351 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
352 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
354 AWE_CHN_PRESSURE(synth_dev,channel,vel);
359 for (i=0; i<card_info.nr_voices;i++)
360 if (voices[i].channel == channel)
361 SEQ_CHN_PRESSURE(synth_dev,i,vel);
371 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
372 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
376 SEQ_STOP_NOTE(synth_dev,i,j,0);
381 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
385 for (i=0; i<card_info.nr_voices;i++)
386 SEQ_STOP_NOTE(synth_dev,i,voices[i].note,0);
390 int get_dtime(unsigned char *data, int *pos)
398 result = (0x7f & buf);
404 result |=(int) (((int) 0x7f & (int) buf)<<7);
409 result |=(int) (((int) 0x7f & (int) buf)<<14);
414 result |=(int) (((int) 0x7f & (int) buf)<<21);
422 int do_track_event(unsigned char *data, int *pos)
425 unsigned char buf[5];
429 channel = buf[0] & 0xf;
431 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
432 switch((buf[0]&0xf0)) {
438 buf[1]=data[*pos]; *pos+=1;
439 buf[2]=data[*pos]; *pos+=1;
440 MIDI_MESSAGE3(buf[0],buf[1],buf[2]);
444 buf[1]=data[*pos]; *pos+=1;
445 MIDI_MESSAGE3(buf[0],0,buf[1]);
457 switch((buf[0] & 0xf0))
464 stop_note((int) channel, (int) buf[1], (int) buf[2]);
473 stop_note((int) channel, (int) buf[1], (int) buf[2]);
477 start_note((int) channel, (int) buf[1], (int) buf[2]);
485 set_key_pressure((int) channel, (int) buf[1], (int) buf[2]);
492 set_control((int) channel, (int) buf[1], (int) buf[2]);
499 set_pitchbend((int) channel, (int) ((buf[2] << 7) + buf[1]));
504 set_program((int) channel, (int) buf[1] );
509 set_chn_pressure((int) channel, (int) buf[1]);
520 void send_ipc(char *message)
522 printf ("sendipc %s\n", message);//##########3
525 ipc_queue_id=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's',
527 snd=malloc(sizeof(long) + 32);
529 player_thread=SDL_CreateThread(play_hmi, NULL);
530 // player_pid = play_hmi();
532 if (strlen(message) < 16)
534 sprintf(snd->mtext,"%s",message);
535 msgsnd(ipc_queue_id,snd,16,0);
542 // kill(player_pid,SIGTERM);
543 msgctl( ipc_queue_id, IPC_RMID, 0);
549 int do_ipc(int qid, struct msgbuf *buf, int flags)
555 ipc_read = msgrcv(qid,buf,16,0,flags | MSG_NOERROR);
562 perror("IPC trouble");
567 printf ("do_ipc %s\n", buf->mtext);//##########3
568 switch (buf->mtext[0])
571 volume=(double) ((double) buf->mtext[0]/127.0);
574 fptr=cfopen((buf->mtext+1),"rb");
577 l = cfilelength(fptr);
578 data=realloc(data,(size_t) l);
579 cfread(data, l, 1, fptr);
581 printf ("good. fpr=%p l=%i data=%p\n", fptr, l, data);//##########3
589 // SDL_KillThread(player_thread);
597 void play_hmi (void * arg)
614 printf ("play_hmi\n");//#########
631 // signal(SIGTERM, my_quit);
632 rcv=malloc(sizeof(long) + 16);
639 qid=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's', 0660);
647 ipc_read=do_ipc(qid,rcv,0);
649 while(rcv->mtext[0] != 'p');
658 t_info = malloc(sizeof(Track_info)*n_chunks);
663 for(i=0;i<n_chunks;i++)
665 t_info[i].position = pos + 12;
666 t_info[i].status = PLAYING;
667 t_info[i].time = get_dtime(data,&t_info[i].position);
668 pos += (( (0xff & data[pos + 5]) << 8 ) + (0xff & data[pos + 4]));
679 if (t_info[i].status == PLAYING)
683 while((low_chunk <=0) && (i<n_chunks));
688 low_dtime = t_info[low_chunk].time;
690 for(i=1;i<n_chunks;i++)
692 if ((t_info[i].time < low_dtime) &&
693 (t_info[i].status == PLAYING))
695 low_dtime = t_info[i].time;
701 printf("Serious warning: d_time negative!!!!!!\n");
703 csec = 0.86 * low_dtime;
705 //flush sequencer buffer after 20 events
708 ioctl(seqfd, SNDCTL_SEQ_SYNC);
714 t_info[low_chunk].status = do_track_event(data,&t_info[low_chunk].position);
716 if (t_info[low_chunk].status == 3)
718 printf("Error playing data in chunk %d\n",low_chunk);
719 t_info[low_chunk].status = STOPPED;
722 if (t_info[low_chunk].status == PLAYING)
723 t_info[low_chunk].time += get_dtime(data,&t_info[low_chunk].position);
725 //Check if the song has reached the end
726 stop = t_info[0].status;
727 for(i=1;i<n_chunks;i++)
728 stop &= t_info[i].status;
730 if((do_ipc(qid,rcv,IPC_NOWAIT) > 0) && (rcv->mtext[0]=='p'))
733 t_info = realloc(t_info,sizeof(Track_info)*n_chunks);
746 ipc_read=do_ipc(qid,rcv,0);
748 while(rcv->mtext[0] != 'p');
751 t_info = realloc(t_info,sizeof(Track_info)*n_chunks);
762 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {
765 sprintf(buf,"p%s",filename);
768 void digi_set_midi_volume( int mvolume ) {
771 sprintf(buf,"v%i",mvolume);