1 /* $Id: hmiplay.c,v 1.4 2004-05-19 02:02:42 btb Exp $ */
3 * HMI midi playing routines by Jani Frilander
5 * External device support by Patrick McCarthy
7 * Ported to d1x/sdl_threads by Matthew Mueller
17 #include <linux/soundcard.h>
18 #include <sys/ioctl.h>
20 #include <sys/types.h>
22 #define __USE_GNU //in recent glibc versions msgbuf is only defined if you have __USE_GNU defined
27 #include <SDL/SDL_thread.h>
29 //#define WANT_AWE32 1
32 #include <linux/awe_voice.h>
35 //#define WANT_MPU401 1
38 #define MIDI_MESSAGE2(a,b) { \
39 SEQ_MIDIOUT(synth_dev,a); \
40 SEQ_MIDIOUT(synth_dev,b); \
43 #define MIDI_MESSAGE3(a,b,c) { \
44 SEQ_MIDIOUT(synth_dev,a); \
45 SEQ_MIDIOUT(synth_dev,b); \
46 SEQ_MIDIOUT(synth_dev,c); \
59 int ipc_queue_id = -1;
62 SDL_Thread *player_thread=NULL;
65 unsigned char *data=NULL;
67 struct synth_info card_info;
73 if (write(seqfd, _seqbuf, _seqbufptr) == -1)
75 perror ("Error writing sequencer device");
76 SDL_KillThread(player_thread);
84 // printf("goodbye\n");//#####
90 int nrmidis,nrsynths,i;
92 if ((seqfd = open(SEQ_DEV, O_WRONLY, 0)) < 0)
94 perror ("Error opening sequencer device");
98 if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrsynths) == -1)
100 perror ("There is no soundcard");
104 if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &nrmidis) == -1)
106 perror ("There is no soundcard");
111 if(nrsynths < 1 && nrmidis < 1)
113 printf("No synth or midi device!\n");
119 //Check if we have wavetable synth device
120 for (i=0; i < nrsynths; i++)
122 card_info.device = i;
123 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
125 perror("cannot get info on soundcard");
129 if (card_info.synth_type == SYNTH_TYPE_SAMPLE)
137 for (i=0; i < nrsynths; i++)
139 card_info.device = i;
140 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
142 perror("cannot get info on soundcard");
146 if (card_info.synth_type==SYNTH_TYPE_SAMPLE
147 &&card_info.synth_subtype==SAMPLE_TYPE_AWE32) {
155 for (i=0; i < nrmidis; i++)
157 struct midi_info cinfo;
159 if (ioctl(seqfd, SNDCTL_MIDI_INFO, &cinfo) == -1)
161 perror("cannot get info on soundcard");
165 // Just take first available for now.
166 card_info.synth_type=SYNTH_TYPE_MIDI;
172 if (card_info.synth_type!=SYNTH_TYPE_MIDI) {
175 card_info.device = synth_dev;
176 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
178 perror("cannot get info on soundcard");
185 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
186 // Insert some sort of midi reset here later.
190 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
191 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
193 AWE_SET_CHANNEL_MODE(synth_dev,1);
194 AWE_DRUM_CHANNELS(synth_dev,drumflag);
199 voices = malloc(sizeof(Voice_info)*card_info.nr_voices);
200 for (i=0;i<card_info.nr_voices;i++)
203 voices[i].channel = -1;
213 ioctl(seqfd,SNDCTL_SEQ_SYNC);
218 void set_program(int channel, int pgm)
221 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
222 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
224 SEQ_SET_PATCH(synth_dev,channel,pgm);
228 program[channel]=pgm;
231 void start_note(int channel, int note, int vel)
236 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
237 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
239 SEQ_START_NOTE(synth_dev,channel,note,vel);
244 for (i=0; i<card_info.nr_voices;i++)
245 if ((voices[i].note == -1) && (voices[i].channel == -1))
247 if (i != card_info.nr_voices)
249 voices[i].note = note;
250 voices[i].channel = channel;
251 if (((1<<channel) & drumflag)) /* drum note */
253 SEQ_SET_PATCH(synth_dev, i, note + 128);
257 SEQ_SET_PATCH(synth_dev, i, program[channel]);
259 SEQ_START_NOTE(synth_dev, i, note, vel);
264 void stop_note(int channel, int note, int vel)
269 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
270 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
272 SEQ_STOP_NOTE(synth_dev,channel,note,vel);
277 for (i=0; i<card_info.nr_voices;i++)
278 if ((voices[i].note == note) && (voices[i].channel == channel))
280 if (i != card_info.nr_voices)
283 voices[i].channel = -1;
284 SEQ_STOP_NOTE(synth_dev,i,note,vel);
289 void set_control(int channel,int ctrl,int value)
294 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
295 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
297 SEQ_CONTROL(synth_dev,channel,ctrl,value);
302 for (i=0; i<card_info.nr_voices;i++)
303 if (voices[i].channel == channel)
304 if (ctrl == CTL_MAIN_VOLUME)
305 SEQ_MAIN_VOLUME(synth_dev,i,value);
309 void set_pitchbend(int channel, int bend)
314 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
315 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
317 SEQ_BENDER(synth_dev,channel,bend);
322 for (i=0; i<card_info.nr_voices;i++)
323 if (voices[i].channel == channel)
325 /*SEQ_BENDER_RANGE(synth_dev, i, 200);*/
326 SEQ_BENDER(synth_dev, i, bend);
331 void set_key_pressure(int channel, int note, int vel)
336 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
337 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
339 AWE_KEY_PRESSURE(synth_dev,channel,note,vel);
344 for (i=0; i<card_info.nr_voices;i++)
345 if ((voices[i].note == note) && (voices[i].channel == channel))
346 SEQ_KEY_PRESSURE(synth_dev,i,note,vel);
350 void set_chn_pressure(int channel, int vel)
355 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
356 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
358 AWE_CHN_PRESSURE(synth_dev,channel,vel);
363 for (i=0; i<card_info.nr_voices;i++)
364 if (voices[i].channel == channel)
365 SEQ_CHN_PRESSURE(synth_dev,i,vel);
375 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
376 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
380 SEQ_STOP_NOTE(synth_dev,i,j,0);
385 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
389 for (i=0; i<card_info.nr_voices;i++)
390 SEQ_STOP_NOTE(synth_dev,i,voices[i].note,0);
394 int get_dtime(unsigned char *data, int *pos)
402 result = (0x7f & buf);
408 result |=(int) (((int) 0x7f & (int) buf)<<7);
413 result |=(int) (((int) 0x7f & (int) buf)<<14);
418 result |=(int) (((int) 0x7f & (int) buf)<<21);
426 int do_track_event(unsigned char *data, int *pos)
429 unsigned char buf[5];
433 channel = buf[0] & 0xf;
435 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
436 switch((buf[0]&0xf0)) {
442 buf[1]=data[*pos]; *pos+=1;
443 buf[2]=data[*pos]; *pos+=1;
444 MIDI_MESSAGE3(buf[0],buf[1],buf[2]);
448 buf[1]=data[*pos]; *pos+=1;
449 MIDI_MESSAGE3(buf[0],0,buf[1]);
461 switch((buf[0] & 0xf0))
468 stop_note((int) channel, (int) buf[1], (int) buf[2]);
477 stop_note((int) channel, (int) buf[1], (int) buf[2]);
481 start_note((int) channel, (int) buf[1], (int) buf[2]);
489 set_key_pressure((int) channel, (int) buf[1], (int) buf[2]);
496 set_control((int) channel, (int) buf[1], (int) buf[2]);
503 set_pitchbend((int) channel, (int) ((buf[2] << 7) + buf[1]));
508 set_program((int) channel, (int) buf[1] );
513 set_chn_pressure((int) channel, (int) buf[1]);
524 void send_ipc(char *message)
526 printf ("sendipc %s\n", message);//##########3
529 ipc_queue_id=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's',
531 snd=malloc(sizeof(long) + 32);
533 player_thread=SDL_CreateThread(play_hmi, NULL);
534 // player_pid = play_hmi();
536 if (strlen(message) < 16)
538 sprintf(snd->mtext,"%s",message);
539 msgsnd(ipc_queue_id,snd,16,0);
546 // kill(player_pid,SIGTERM);
547 msgctl( ipc_queue_id, IPC_RMID, 0);
553 int do_ipc(int qid, struct msgbuf *buf, int flags)
559 ipc_read = msgrcv(qid,buf,16,0,flags | MSG_NOERROR);
566 perror("IPC trouble");
571 printf ("do_ipc %s\n", buf->mtext);//##########3
572 switch (buf->mtext[0])
575 volume=(double) ((double) buf->mtext[0]/127.0);
578 fptr=cfopen((buf->mtext+1),"rb");
581 l = cfilelength(fptr);
582 data=realloc(data,(size_t) l);
583 cfread(data, l, 1, fptr);
585 printf ("good. fpr=%p l=%i data=%p\n", fptr, l, data);//##########3
593 // SDL_KillThread(player_thread);
601 void play_hmi (void * arg)
618 printf ("play_hmi\n");//#########
635 // signal(SIGTERM, my_quit);
636 rcv=malloc(sizeof(long) + 16);
643 qid=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's', 0660);
651 ipc_read=do_ipc(qid,rcv,0);
653 while(rcv->mtext[0] != 'p');
662 t_info = malloc(sizeof(Track_info)*n_chunks);
667 for(i=0;i<n_chunks;i++)
669 t_info[i].position = pos + 12;
670 t_info[i].status = PLAYING;
671 t_info[i].time = get_dtime(data,&t_info[i].position);
672 pos += (( (0xff & data[pos + 5]) << 8 ) + (0xff & data[pos + 4]));
683 if (t_info[i].status == PLAYING)
687 while((low_chunk <=0) && (i<n_chunks));
692 low_dtime = t_info[low_chunk].time;
694 for(i=1;i<n_chunks;i++)
696 if ((t_info[i].time < low_dtime) &&
697 (t_info[i].status == PLAYING))
699 low_dtime = t_info[i].time;
705 printf("Serious warning: d_time negative!!!!!!\n");
707 csec = 0.86 * low_dtime;
709 //flush sequencer buffer after 20 events
712 ioctl(seqfd, SNDCTL_SEQ_SYNC);
718 t_info[low_chunk].status = do_track_event(data,&t_info[low_chunk].position);
720 if (t_info[low_chunk].status == 3)
722 printf("Error playing data in chunk %d\n",low_chunk);
723 t_info[low_chunk].status = STOPPED;
726 if (t_info[low_chunk].status == PLAYING)
727 t_info[low_chunk].time += get_dtime(data,&t_info[low_chunk].position);
729 //Check if the song has reached the end
730 stop = t_info[0].status;
731 for(i=1;i<n_chunks;i++)
732 stop &= t_info[i].status;
734 if((do_ipc(qid,rcv,IPC_NOWAIT) > 0) && (rcv->mtext[0]=='p'))
737 t_info = realloc(t_info,sizeof(Track_info)*n_chunks);
750 ipc_read=do_ipc(qid,rcv,0);
752 while(rcv->mtext[0] != 'p');
755 t_info = realloc(t_info,sizeof(Track_info)*n_chunks);
766 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {
769 sprintf(buf,"p%s",filename);
772 void digi_set_midi_volume( int mvolume ) {
775 sprintf(buf,"v%i",mvolume);