#include #include #include #include #include #include #include "defines.h" #include "globals.h" #include "jack.h" #include "communication.h" #include "lfos.h" using namespace std; //#define DO_DEBUGGING_EVENTS jack_port_t *midi_in; jack_port_t *out_port[N_CHANNELS]; #ifdef STEREO jack_port_t *out_port2[N_CHANNELS]; #endif jack_client_t *jack_client = NULL; void manage_program_lock(int prog, bool lock) //TODO woandershinschieben? { program_lock[prog]=lock; if (lock) for (int i=0;ikill_program(prog); } void process_request(request_t request) { switch (request.type) { case request_t::NONE: break; case request_t::SUSPEND_PROGRAM: case request_t::RESUME_PROGRAM: if (request.prog_or_chan==-1) for (int i=0;i<128;++i) manage_program_lock(i,request.type==request_t::SUSPEND_PROGRAM); else manage_program_lock(request.prog_or_chan,request.type==request_t::SUSPEND_PROGRAM); break; case request_t::PANIC: if (request.prog_or_chan==-1) for (int i=0;ipanic(); else channel[request.prog_or_chan]->panic(); break; case request_t::RELEASE_ALL: if (request.prog_or_chan==-1) for (int i=0;irelease_all(); else channel[request.prog_or_chan]->release_all(); break; default: cout << "ERROR: bad request, ignoring it." << endl; } request_finished(0); } //connect to jack, init some stuff and get information void init_jack() { jack_client = jack_client_open("flosoftsynth", JackNullOption, NULL); if (jack_client == NULL) throw string("Registering client failed"); if (jack_set_process_callback(jack_client, process_callback, 0)) throw string("Registering callback failed"); if (jack_set_xrun_callback(jack_client, xrun_callback, 0)) throw string("Registering xrun-callback failed"); midi_in = jack_port_register(jack_client, MIDI_IN_NAME, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); if (midi_in == NULL) throw string ("Registering MIDI IN failed"); for (int i=0;i history; list::iterator it; float now=float(jack_get_time())/1000000; cout << "got an XRUN! if this happens too often, consider reducing CPU usage, for\n example by setting a voice limit or by quitting other programs"<= xrun_n) { cout << "PANIC -- TOO MANY XRUNs! killing all voices" << flush; do_request(request_t(request_t::PANIC, -1)); cout << " (done)" << endl << endl; history.clear(); } return 0; } #define IGNORE_MIDI_OFFSET int process_callback(jack_nframes_t nframes, void *notused) { #ifdef DO_DEBUGGING_EVENTS static jack_nframes_t tmp=0, tmp2=0; #endif static jack_nframes_t next_cleanup=0; size_t curr_event=0, n_events, i, chan; void *inport; jack_default_audio_sample_t *outbuf[N_CHANNELS]; #ifdef STEREO jack_default_audio_sample_t *outbuf2[N_CHANNELS]; #endif jack_midi_event_t event; jack_nframes_t lastframe; lastframe=jack_last_frame_time(jack_client); if (nframes <= 0) { output_note ("NOTE: Process callback called with nframes = 0; bug in JACK?"); return 0; } if (request_available()) process_request(get_request()); for (i=0;i=next_cleanup) { next_cleanup=lastframe+cleanup_interval; for (i=0;icleanup(); } #ifdef DO_DEBUGGING_EVENTS if (tmp==0) //DEBUG !!! { tmp=lastframe; channel[0]->set_controller(5,10); channel[0]->set_controller(65,127); channel[0]->event(0x90,80,64); // channel[0]->event(0x90,84,64); } else if (tmp2==0) { if (lastframe>tmp+44100*1) { tmp2=1; cout << "BÄÄM" << endl; channel[0]->event(0x90,84,64); } } else if (tmp2==1) { if (lastframe>tmp+44100*2) { tmp2=2; channel[0]->event(0x90,87,5); channel[0]->set_controller(58, 0); cout << "BÄÄM2" << endl; } } else if (tmp2==2) { if (lastframe>tmp+44100*3) { tmp2=3; channel[0]->event(0x90,90,127); cout << "BÄÄM2" << endl; } } else if (tmp2==3) { if (lastframe>tmp+44100*4) { tmp2=4; channel[0]->event(0x90,60,96); cout << "BÄÄM2" << endl; } } else if (tmp2==4) { if (lastframe>tmp+44100*5) { tmp2=5; channel[0]->event(0x90,63,32); cout << "BÄÄM2" << endl; } } else if (tmp2==5) { if (lastframe>tmp+44100*6) { tmp2=6; channel[0]->event(0x90,66,60); cout << "BÄÄM2" << endl; } } else { if (lastframe>tmp+44100*8) { cout << "finished" << endl; exit(0); } } #endif #ifdef FRAMESKIP if (outtemp_nframes_left) { jack_nframes_t real_nframes; if (outtemp_nframes_left > nframes) { real_nframes=nframes; outtemp_nframes_left-=nframes; } else { real_nframes=outtemp_nframes_left; outtemp_nframes_left=0; } for (i=0;i=event.time)) { output_verbose("processing event #"+IntToStr(curr_event)+" of "+IntToStr(n_events)+" events"); if (event.size > 3) { output_verbose(" Ignoring MIDI message longer than three bytes, probably a SysEx."); } else { chan=event.buffer[0] & 0x0F; output_verbose(" channel="+IntToStr(chan)+", data is "+IntToStrHex(event.buffer[0])+" "+IntToStrHex(event.buffer[1])+" "+IntToStrHex(event.buffer[2])); channel[chan]->event(event.buffer[0], event.buffer[1], event.buffer[2]); } --n_events; ++curr_event; //as long as there are some events left and getting one fails, get the next while ((n_events) && (jack_midi_event_get(&event, inport, curr_event /*, nframes */))) { output_note("NOTE2: lost a note :("); --n_events; ++curr_event; } } maybe_calc_lfos(); for (int j=0;jget_sample())/ONE*VOL_FACTOR; #else jack_default_audio_sample_t sample=jack_default_audio_sample_t(channel[j]->get_sample())/ONE*VOL_FACTOR; outbuf[j][i]=channel[j]->balL*sample; outbuf2[j][i]=channel[j]->balR*sample; #endif // if the above changes, (1) must also change #ifdef FRAMESKIP for (size_t k=i+frameskip-1;k>i;--k) { outbuf[j][k]=outbuf[j][i]; #ifdef STEREO outbuf2[j][k]=outbuf2[j][i]; #endif } #endif } } #ifdef FRAMESKIP if (i!=nframes) // nicht aufgegangen? { for (int j=0;jget_sample())/ONE*VOL_FACTOR; #else jack_default_audio_sample_t sample=jack_default_audio_sample_t(channel[j]->get_sample())/ONE*VOL_FACTOR; outtemp[j]=channel[j]->balL*sample; outtemp2[j]=channel[j]->balR*sample; #endif } outtemp_nframes_left=frameskip-nframes+i; for (i=i; i