49a50,61
> # use ALSA Sequencer MIDI interface
> CFLAGS+= -DHAVE_ASEQ
> LIBS+= -lasound
> 
> # JACKify
> CFLAGS+= -DHAVE_JACK
> LIBS+= -ljack
> 
> # Do not use libsamplerate (experimental).
> #CFLAGS+= -DHAVE_SRC
> #LIBS+= -lsamplerate
> 
1060a1061,1194
> 
> 
> #ifdef HAVE_ASEQ
> #include <alsa/asoundlib.h>
> // getpid()
> #include <sys/types.h>
> #include <unistd.h>
> 
> snd_seq_t *seq= NULL;
> int aseq_stop=0; // only modify in main thread.
> 
> void aseq_close(void) {
>   if(!seq) return;
>   printf("closing alsa midi...");
>   snd_seq_close(seq);
>   seq=NULL;
> }
> 
> #if 0
> inline void midi_close(void) {
>   if(!seq) return;
>   aseq_stop=1;
>   sleep(1);
>   //pthread_join(t_midi,NULL);
>   aseq_close();
> }
> #endif
> 
> int aseq_open(char *port_name) {
>   int err=0;
>   snd_seq_addr_t port;
>   char seq_name[32];
>   snprintf(seq_name,32,"beatrix-%i",(int) getpid());
> 
>   if (seq) return (-1);
> 
>   if ((err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_INPUT, 0)) <0 ) {
>     fprintf(stderr,"cannot open alsa sequencer: %s\n", snd_strerror(err));
>     seq=NULL;
>     return(-1);
>   }
> 
>   if ((err = snd_seq_set_client_name(seq, seq_name)) <0 ) {
>     fprintf(stderr,"cannot set client name: %s\n", snd_strerror(err));
>     aseq_close();
>     return(-1);
>   }
> 
>   if ((err = snd_seq_create_simple_port(seq, "MTC in", 
>     	SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, 
>     	SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {
>     fprintf(stderr,"cannot create port: %s\n", snd_strerror(err));
>     aseq_close();
>     return(-1);
>   }
> 
>   if (port_name) {
>     err = snd_seq_parse_address(seq, &port, port_name);
>     if (err < 0) {
>       fprintf(stderr,"Cannot find port %s - %s\n", port_name, snd_strerror(err));
>     }
>     err = snd_seq_connect_from(seq, 0, port.client, port.port);
>     if (err < 0) {
>       fprintf(stderr,"Cannot connect from port %d:%d - %s\n", port.client, port.port, snd_strerror(err));
>     }
>   }
> 
>   snd_seq_nonblock(seq, 1);
> 
>   /* Load the tables */
> 
>   loadControllerTable ();
>   loadKeyTableA ();
>   loadKeyTableB ();
>   loadKeyTableC ();
>   loadStatusTable ();
> 
>   return(0);
> }
> 
> void process_seq_event(const snd_seq_event_t *ev) {
>   // see "snd_seq_event_type" file:///usr/share/doc/libasound2-doc/html/group___seq_events.html
>   switch(ev->type) {
>     case SND_SEQ_EVENT_NOTEON:
>       //printf("DEBUG KEY on %i %i\n",ev->data.note.channel, ev->data.note.note);
>       keyTable = (unsigned char *) statusTable[MIDI_NOTEON|ev->data.note.channel].handback;
>       oscKeyOn (keyTable[ev->data.note.note]);
>       break;
>     case SND_SEQ_EVENT_NOTEOFF:
>       //printf("DEBUG KEY off %i %i\n",ev->data.note.channel, ev->data.note.note);
>       keyTable = (unsigned char *) statusTable[MIDI_NOTEOFF|ev->data.note.channel].handback;
>       oscKeyOff (keyTable[ev->data.note.note]);
>       break;
>     case SND_SEQ_EVENT_PGMCHANGE:
>       printf("DEBUG Programchange %i\n",ev->data.control.value);
>       installProgram(ev->data.control.value);	
>       break;
>     case SND_SEQ_EVENT_CONTROLLER:
>       printf("DEBUG Controller [%i] %i -> %i\n",ev->data.control.channel, ev->data.control.param, ev->data.control.value);
>       ctrlvec = (void (**) (unsigned char)) statusTable[MIDI_CTL_CHANGE|ev->data.control.channel].handback;
>       (ctrlvec[ev->data.control.param])(ev->data.control.value);
>       break;
>     default:
>       printf("unhandled midi event: %i\n", ev->type);
>       assert(1);
>       break;
>   }
> }
> 
> void *aseq_run(void *arg) {
>   int err;
>   int npfds = 0;
>   struct pollfd *pfds;
> 
>   npfds = snd_seq_poll_descriptors_count(seq, POLLIN);
>   pfds = alloca(sizeof(*pfds) * npfds);
>   for (;;) {
>     snd_seq_poll_descriptors(seq, pfds, npfds, POLLIN);
>     if (poll(pfds, npfds, 1) < 0) break;
>     do {
>       snd_seq_event_t *event;
>       err = snd_seq_event_input(seq, &event);
>       if (err < 0) break;
>       if (event) process_seq_event(event);
>     } while (err > 0);
>     if (aseq_stop) break;
>   }
>   pthread_exit(NULL);
>   return (NULL);
> }
> 
> #endif
> 
> /* vi:set ts=8 sts=2 sw=2: */
44a45,49
> #ifdef HAVE_ASEQ
> extern void *aseq_run(void *arg);
> extern int aseq_open(char *port_name);
> #endif
> 
122a123,289
> #ifdef HAVE_JACK
> #include <jack/jack.h>
> 
> jack_client_t *j_client = NULL;
> jack_port_t **j_output_port; 
> jack_default_audio_sample_t **j_output_bufferptrs; // 
> jack_default_audio_sample_t bufJ [2][BUFFER_SIZE_SAMPLES];
> 
> jack_nframes_t jack_splrate=44100;
> jack_nframes_t jack_fragsize=128;
> 
> 
> /* when jack shuts down... */
> void jack_shutdown_callback(void *arg) {
>   fprintf(stderr,"jack server shut us down.\n");
>   jack_deactivate(j_client);
>   j_client=NULL;
> }
> 
> int jack_srate_callback(jack_nframes_t nframes, void *arg) {
>   jack_splrate= nframes;
>   return(0); 
> }
> 
> int jack_bufsiz_callback(jack_nframes_t nframes, void *arg) {
>   jack_fragsize= nframes;
>   return(0); 
> }
> #ifdef HAVE_SRC
> #include<samplerate.h>
> #include<math.h>
> #endif
> 
> int jack_audio_callback (jack_nframes_t nframes, void *arg) {
>   jack_default_audio_sample_t **out = j_output_bufferptrs; 
>   int i,s;
>   jack_nframes_t my_tot_latency = 0;
> 
>   for (i=0;i<audio_channels;i++) {
>   	jack_nframes_t my_latency = jack_port_get_total_latency(j_client,j_output_port[i]);
>   	if (my_latency > my_tot_latency) my_tot_latency = my_latency;
>   	//printf("DEBUG: c=%i pl=%i tl=%i\n",i,jack_port_get_latency(j_output_port[i]) ,jack_port_get_total_latency(j_client,j_output_port[i]));
>   	out[i] = jack_port_get_buffer (j_output_port[i], nframes);
>   	//memset(out[i],0, sizeof (jack_default_audio_sample_t) * nframes);
>   }
> 
>   static unsigned char * obuf;
>   static int boffset = BUFFER_SIZE_SAMPLES;
> 
>   float m_fResampleRatio = (float) jack_splrate / (float)SampleRateD;
> #ifndef HAVE_SRC
>   static int info =0;
> #if 1 
>   if (!info) { 
>     info=1;
>     printf ("JACK: integer resampling factor: %f\nJACK: suggest: osc.tuning=%f\n",
>       floorf(m_fResampleRatio+.5),
>       440.0/m_fResampleRatio*floorf(m_fResampleRatio+.5));
>   }
>   m_fResampleRatio = floorf(m_fResampleRatio+.5);
> # endif
> #endif
> 
>   jack_nframes_t out_off = 0; 
> 
>   while (out_off < nframes) {
>     int remain_src = BUFFER_SIZE_SAMPLES - boffset;
>     int remain_dst = nframes - out_off;
>     if (remain_src <= 0)  {
>       boffset = 0; remain_src+=BUFFER_SIZE_SAMPLES;
>       // generate sound
>       oscGenerateFragment (bufA, BUFFER_SIZE_SAMPLES);
>       obuf = preamp (bufA, bufB, BUFFER_SIZE_SAMPLES);
>       obuf = reverb (obuf, bufB, BUFFER_SIZE_SAMPLES);
>       whirlProc (obuf, bufC, BUFFER_SIZE_SAMPLES);
> 
>       // convert interlaced channels
>       float nfactor =  1.0 / ((float) 0x8000);
>       for (s=0;s<BUFFER_SIZE_SAMPLES;s++)
> 	for (i=0;i<audio_channels;i++) 
> 	//bufJ[i][s]= (((jack_default_audio_sample_t)(((signed short*)bufA)[s]))/32768.0);
> 	//bufJ[i][s]= ((((signed short*)obuf)[s]))/32768.0;
> 	  bufJ[i][s]= ((jack_default_audio_sample_t)(((signed short*)bufC)[audio_channels*s+i]))*nfactor;
>     }
> 
>     jack_nframes_t nread = (jack_nframes_t) ceilf((float)remain_dst / m_fResampleRatio);
>     if (nread > remain_src) nread = remain_src;
>     jack_nframes_t nwrite = (jack_nframes_t) floorf((float)nread * m_fResampleRatio);
>     //printf("DEBUG %i %i %f\n", nread, nwrite, m_fResampleRatio);
> #ifdef HAVE_SRC 
>     SRC_DATA src_data;
>     src_data.input_frames  = nread;
>     src_data.output_frames = nwrite;
>     src_data.end_of_input  = 0;
>     src_data.src_ratio     = m_fResampleRatio;
>     src_data.input_frames_used = 0;
>     src_data.output_frames_gen = 0;
> 
>     for (i=0;i< audio_channels; i++ ) {
>       src_data.data_in       = &(bufJ[i][boffset]);
>       src_data.data_out      = &(out[i][out_off]);
>       src_simple (&src_data, SRC_SINC_FASTEST, 1) ;
>       //src_simple (&src_data, SRC_SINC_MEDIUM_QUALITY, 1) ;
>       //src_simple (&src_data, SRC_ZERO_ORDER_HOLD, 1) ;
>       //src_simple (&src_data, SRC_LINEAR, 1) ;
>       //src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1) ;
>     }
>     out_off+=src_data.output_frames_gen;
>     boffset+=src_data.input_frames_used;
> #else
>     assert (m_fResampleRatio == 2.0 || m_fResampleRatio==1.0 || m_fResampleRatio==4.0 || m_fResampleRatio==3.0);
>     int r,stride = (int) rintf(m_fResampleRatio);
> 
>     for (i=0;i< audio_channels; i++ ) {
>       for (s=0;s<nread;s++) {
> 	for (r=0;r<stride;r++)
> 	  out[i][out_off+r+stride*s] = bufJ[i][boffset+s];
>       }
>     }
>     out_off+=stride*nread;
>     boffset+=nread;
> #endif
>   }
>   return(0);
> }
> 
> int open_jack(void) {
>   int i;
>   i = 0;
>   do {
>     char jackid[16];
>     snprintf(jackid,16,"beatrix-%i",i);
>     j_client = jack_client_new (jackid);
>   } while (j_client == 0 && i++<16);
> 
>   if (!j_client) {
>     fprintf(stderr, "could not connect to jack.\n");
>     return(1);
>   }	
>   audio_channels=audio_channels_requested;
>   audio_format = audio_format_requested;
> 
>   jack_on_shutdown (j_client, jack_shutdown_callback, NULL);
>   jack_set_process_callback(j_client,jack_audio_callback,NULL);
>   jack_set_sample_rate_callback (j_client, jack_srate_callback, NULL);
>   jack_set_buffer_size_callback (j_client, jack_bufsiz_callback, NULL);
> 
>   j_output_port= calloc(audio_channels,sizeof(jack_port_t*));
>   j_output_bufferptrs = calloc(audio_channels,sizeof(jack_default_audio_sample_t*));
> 
>   for (i=0;i<audio_channels;i++) {
>     char channelid[16];
>     snprintf(channelid,16,"output-%i",i);
>     j_output_port[i] = jack_port_register (j_client, channelid, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
>     if (!j_output_port[i]) {
>       fprintf(stderr, "no more jack ports available.\n");
>       jack_client_close (j_client);
>       return(1);
>     }
>   }
>   jack_srate_callback(jack_get_sample_rate(j_client),NULL); // init j_srate
>   jack_bufsiz_callback(jack_get_buffer_size(j_client),NULL); // init j_bufsiz & alloc
> 
>   return(0);
> }
> #endif
> 
129a297,303
> #ifdef HAVE_JACK
>   if (open_jack()) {
>     perror ("could not connect to JACK.");
>     exit(1);
>   }
> #else /* NO JACK - OSS */
> 
211a386
> #endif /* NO JACK = OSS */
408a584,585
>   printf ("-R <rate>  set samplerate for synth. default 22050.\n");
>   printf ("           jack-sr must be a multiple of this.\n");
455a633,635
>       else if (!strcmp (av, "-R")) {
> 	state = 2;
>       }
479a660,665
>     else if (state == 2) {
>       SampleRateI = atoi (av);
>       SampleRateD = (double) SampleRateI;
>       printf(" beatrix internal samplerate: %.1f SPS\n",SampleRateD);
>       state = 0;
>     }
541a728,731
> # ifdef HAVE_ASEQ
>   if (!aseq_open(NULL))
>     k= pthread_create(&t_midi, NULL, aseq_run, NULL); 
> # else
542a733
> # endif
595a787,792
> #ifdef HAVE_JACK
>       jack_activate(j_client);
>       while (j_client)
> 	sleep (1); // jack callback is doing this:
>       return(0);
> #else
629a827
> #endif
636a835,836
> 
> /* vi:set ts=8 sts=2 sw=2: */
