void run()
    {
        const int maxEventSize = 16 * 1024;
        snd_midi_event_t* midiParser;

        if (snd_midi_event_new (maxEventSize, &midiParser) >= 0)
        {
            HeapBlock <uint8> buffer (maxEventSize);

            const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN);
            struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd));

            snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN);

            while (! threadShouldExit())
            {
                if (poll (pfd, numPfds, 500) > 0)
                {
                    snd_seq_event_t* inputEvent = nullptr;

                    snd_seq_nonblock (seqHandle, 1);

                    do
                    {
                        if (snd_seq_event_input (seqHandle, &inputEvent) >= 0)
                        {
                            // xxx what about SYSEXes that are too big for the buffer?
                            const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent);

                            snd_midi_event_reset_decode (midiParser);

                            if (numBytes > 0)
                            {
                                const MidiMessage message ((const uint8*) buffer,
                                                           numBytes,
                                                           Time::getMillisecondCounter() * 0.001);


                                callback->handleIncomingMidiMessage (midiInput, message);
                            }

                            snd_seq_free_event (inputEvent);
                        }
                    }
                    while (snd_seq_event_input_pending (seqHandle, 0) > 0);

                    snd_seq_free_event (inputEvent);
                }
            }

            snd_midi_event_free (midiParser);
        }
    };
Ejemplo n.º 2
0
// This splits the Midi events from one channel to another two channels
void Spliter::midievents(){
    snd_seq_event_t *midievent;
    midievent=NULL;
    snd_seq_event_input(midi_in,&midievent);
    
    if (midievent==NULL) return;
    if  ((midievent->type==SND_SEQ_EVENT_NOTEON)||(midievent->type==SND_SEQ_EVENT_NOTEOFF)){
	int cmdchan=midievent->data.note.channel;
	if (cmdchan==Pchin){
	snd_seq_ev_set_subs(midievent);  
	snd_seq_ev_set_direct(midievent);
	if (midievent->data.note.note<Psplitpoint) {
	    midievent->data.note.channel=Pchout1;
	    int tmp=midievent->data.note.note;
	    tmp+=Poct1*12;if (tmp>127) tmp=127;if (tmp<0) tmp=0;
	    midievent->data.note.note=tmp;
	    } else {
	    midievent->data.note.channel=Pchout2;
	    int tmp=midievent->data.note.note;
	    tmp+=Poct2*12;if (tmp>127) tmp=127;if (tmp<0) tmp=0;
	    midievent->data.note.note=tmp;
	    };
	snd_seq_event_output_direct(midi_out,midievent);
	} else {
	snd_seq_ev_set_subs(midievent);  
	snd_seq_ev_set_direct(midievent);
	snd_seq_event_output_direct(midi_out,midievent);
	};
				    
    };
    snd_seq_free_event(midievent);
};
Ejemplo n.º 3
0
/* handles all the midi calls */
void midi_action(snd_seq_t *seq_handle) {
	snd_seq_event_t *ev;
	do {
	snd_seq_event_input(seq_handle, &ev);
		printf( "%i \n", ev->data.control.channel, ev->data.control.value);
		switch (ev->type) {
			
			case SND_SEQ_EVENT_CONTROLLER: 
				printf("Control event on Channel %2d: %5d       \n",
			        ev->data.control.channel, ev->data.control.value);
				midi_set(ev, 2);
				pedal_set(ev);
			break;
			case SND_SEQ_EVENT_PITCHBEND:
				printf("Pitchbender event on Channel %2d: %5d   \n", 
			        ev->data.control.channel, ev->data.control.value);
			break;
			case SND_SEQ_EVENT_NOTEON:
				printf("Note On event on Channel %2d: %5d       \n",
			        ev->data.control.channel, ev->data.note.note);
			break;        
			case SND_SEQ_EVENT_NOTEOFF: 
				printf("Note Off event on Channel %2d: %5d      \n",         
			        ev->data.control.channel, ev->data.note.note);           
			break;        
			case SND_SEQ_EVENT_PGMCHANGE: 
				printf("PGM event on Channel %2d: %5d      \n",         
			        ev->data.control.channel, ev->data.control.value);   
				midi_set(ev, 1);
			break; 
		}
	   	snd_seq_free_event(ev);
	  } while (snd_seq_event_input_pending(seq_handle, 0) > 0);
}
Ejemplo n.º 4
0
void* midi2lp(void* nothing)
{
    printf("waiting for midi events\n");
    snd_seq_event_t *ev;
    while (1) {
	
	// get a new event. if there aren't any, wait for one
	snd_seq_event_input(midi_client, &ev);

	// copy the data to send
	switch (ev->type) {
	    
	case SND_SEQ_EVENT_NOTEON:
	    lp_send3(lp, NOTE_ON, ev->data.note.note, ev->data.note.velocity);
	    break;
	    
	case SND_SEQ_EVENT_NOTEOFF:
	    lp_send3(lp, NOTE_OFF, ev->data.note.note, ev->data.note.velocity);
	    break;
	    
	case SND_SEQ_EVENT_CONTROLLER:
	    lp_send3(lp, CTRL, ev->data.control.param, ev->data.control.value);
	    break;
	}
	
	// free the midi event
	snd_seq_free_event(ev);
    }
}
/* TODO: ADD MIDI PANIC/ALL NOTES OFF */
int midi_callback() {

    snd_seq_event_t *ev;
    int l1;

    do {
        snd_seq_event_input(seq_handle, &ev);
        switch (ev->type) {
            case SND_SEQ_EVENT_NOTEON:
                for (l1 = 0; l1 < POLY; l1++) {
                    if (!note_active[l1]) {
                        note[l1] = ev->data.note.note;
			printf("Note ON  %d FREQ %d\n", note[l1] ,(note[l1])*FREQ_CHANNEL_WIDTH+FREQ_START);
                        velocity[l1] = ev->data.note.velocity / 127.0;
                        env_time[l1] = 0;
                        gate[l1] = 1;
                        note_active[l1] = 1;
                        break;
                    }
                }
                break;
            case SND_SEQ_EVENT_NOTEOFF:
                for (l1 = 0; l1 < POLY; l1++) {
                    if (gate[l1] && note_active[l1] && (note[l1] == ev->data.note.note)) {
			printf("Note OFF %d \n", note[l1]);
                        env_time[l1] = 0;
                        gate[l1] = 0;
                    }
                }
                break;
        }
        snd_seq_free_event(ev);
    } while (snd_seq_event_input_pending(seq_handle, 0) > 0);
    return (0);
}
    int MidiInputDeviceAlsa::Main() {
        int npfd;
        struct pollfd* pfd;
        snd_seq_event_t* ev;

        npfd = snd_seq_poll_descriptors_count(hAlsaSeq, POLLIN);
        pfd = (struct pollfd*) alloca(npfd * sizeof(struct pollfd));
        snd_seq_poll_descriptors(hAlsaSeq, pfd, npfd, POLLIN);
        while (true) {
            if (poll(pfd, npfd, 100000) > 0) {
                do {
                    snd_seq_event_input(hAlsaSeq, &ev);
                    int port = (int) ev->dest.port;
                    MidiInputPort* pMidiInputPort = Ports[port];

                    switch (ev->type) {
                        case SND_SEQ_EVENT_CONTROLLER:
                            if (ev->data.control.param == 0)
                                pMidiInputPort->DispatchBankSelectMsb(ev->data.control.value, ev->data.control.channel);
                            else if (ev->data.control.param == 32)
                                pMidiInputPort->DispatchBankSelectLsb(ev->data.control.value, ev->data.control.channel);
                            pMidiInputPort->DispatchControlChange(ev->data.control.param, ev->data.control.value, ev->data.control.channel);
                            break;

                        case SND_SEQ_EVENT_CHANPRESS:
                            pMidiInputPort->DispatchControlChange(128, ev->data.control.value, ev->data.control.channel);
                            break;

                        case SND_SEQ_EVENT_PITCHBEND:
                            pMidiInputPort->DispatchPitchbend(ev->data.control.value, ev->data.control.channel);
                            break;

                        case SND_SEQ_EVENT_NOTEON:
                            if (ev->data.note.velocity != 0) {
                                pMidiInputPort->DispatchNoteOn(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel);
                            }
                            else {
                                pMidiInputPort->DispatchNoteOff(ev->data.note.note, 0, ev->data.control.channel);
                            }
                            break;

                        case SND_SEQ_EVENT_NOTEOFF:
                            pMidiInputPort->DispatchNoteOff(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel);
                            break;

                        case SND_SEQ_EVENT_SYSEX:
                            pMidiInputPort->DispatchSysex(ev->data.ext.ptr, ev->data.ext.len);
                            break;

                        case SND_SEQ_EVENT_PGMCHANGE:
                            pMidiInputPort->DispatchProgramChange(ev->data.control.value, ev->data.control.channel);
                            break;
                    }
                    snd_seq_free_event(ev);
                } while (snd_seq_event_input_pending(hAlsaSeq, 0) > 0);
            }
        }
        // just to avoid a compiler warning
        return EXIT_FAILURE;
    }
Ejemplo n.º 7
0
void* alsa_input_thread(void * arg)
{
	struct a2j * self = arg;
	int npfd;
	struct pollfd * pfd;
	snd_seq_addr_t addr;
	snd_seq_client_info_t * client_info;
	snd_seq_port_info_t * port_info;
	bool initial;
	snd_seq_event_t * event;
	int ret;

	npfd = snd_seq_poll_descriptors_count(self->seq, POLLIN);
	pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
	snd_seq_poll_descriptors(self->seq, pfd, npfd, POLLIN);

	initial = true;
	while (g_keep_alsa_walking) {
		if ((ret = poll(pfd, npfd, 1000)) > 0) {

			while (snd_seq_event_input (self->seq, &event) > 0) {
				if (initial) {
					snd_seq_client_info_alloca(&client_info);
					snd_seq_port_info_alloca(&port_info);
					snd_seq_client_info_set_client(client_info, -1);
					while (snd_seq_query_next_client(self->seq, client_info) >= 0) {
						addr.client = snd_seq_client_info_get_client(client_info);
						if (addr.client == SND_SEQ_CLIENT_SYSTEM || addr.client == self->client_id) {
							continue;
						}
						snd_seq_port_info_set_client(port_info, addr.client);
						snd_seq_port_info_set_port(port_info, -1);
						while (snd_seq_query_next_port(self->seq, port_info) >= 0) {
							addr.port = snd_seq_port_info_get_port(port_info);
							a2j_update_port(self, addr, port_info);
						}
					}

					initial = false;
				}

				if (event->source.client == SND_SEQ_CLIENT_SYSTEM) {
					a2j_port_event(self, event);
				} else {
					a2j_input_event(self, event);
				}

				snd_seq_free_event (event);
			}
		}
	}

	return (void*) 0;
}
Ejemplo n.º 8
0
void midi_process(snd_seq_event_t *ev)
{

    // If this event is a PGMCHANGE type, it's a request to map a channel to an instrument
    if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
        //printf("PGMCHANGE: channel %2d, %5d, %5d\n", ev->data.control.channel, ev->data.control.param,  ev->data.control.value);

        // Clear pins state, this is probably the beginning of a new song
        allOff();
    }

    // If the event is SND_SEQ_EVENT_BOUNCE, then maybe this is an interrupt?
    if (ev->type == SND_SEQ_EVENT_BOUNCE) {
        allOff();
    }

    if (channelActive == ev->data.control.channel) {
        // Note on/off event
        if (ev->type == SND_SEQ_EVENT_NOTEON) {

            // When pinActive is -1, we're playing the first note
            if (-1 == pinActive) {
                pinActive = 0;
            } else {
                // First turn off the current pin
                printf("Turning off pin %d\n", pinActive);
                pinOff(pinActive);

                // Increment pinActive
                printf("Incrementing pinActive\n");
                pinActive++;

                // Reset to zero if we're above the number of pins
                if (pinActive >= TOTAL_PINS) {
                    printf("Resetting pinActive to zero\n");
                    pinActive = 0;
                }
            }

            // Turn on the next pin
            printf("Turning on pin %d\n", pinActive);
            pinOn(pinActive);
        }
    }

    snd_seq_free_event(ev);
}
Ejemplo n.º 9
0
void midi_process(snd_seq_event_t *ev)
{
    //If this event is a PGMCHANGE type, it's a request to map a channel to an instrument
    if( ev->type == SND_SEQ_EVENT_PGMCHANGE )  {
       //Clear pins state, this is probably the beginning of a new song
       clearPinsState();
       setPlayChannel(ev->data.control.channel, 1);
    }
    else if ( ((ev->type == SND_SEQ_EVENT_NOTEON)||(ev->type == SND_SEQ_EVENT_NOTEOFF)) ) { //Note on/off event

        int isOn = 1;
        //Note velocity == 0 means the same thing as a NOTEOFF type event
        if( ev->data.note.velocity == 0 || ev->type == SND_SEQ_EVENT_NOTEOFF) {
           isOn = 0;
        }

        //There are 12 different kinds of notes.  (I will only use the first 8 for my rig but I need to the modulus.  will be 0-11.)
        int pinIdx = ev->data.note.note % 12;
        
        //If pin is set to be turned on
        if( isOn ) {
           //If pin is currently available to play a note, or if currently playing channel can be overriden due to higher priority channel
           if( pinNotes[pinIdx] == -1 || pinChannels[pinIdx] > ev->data.note.channel )  {
              //Write to the pin, save the note to pinNotes
              digitalWrite(pinIdx, 1); 
              pinNotes[pinIdx] = ev->data.note.note;
              pinChannels[pinIdx] =  ev->data.note.channel;
           }
        }
        else {  //Pin is to be turned off
           //If this is the note that turned the pin on..
           if( pinNotes[pinIdx] == ev->data.note.note && pinChannels[pinIdx] == ev->data.note.channel ) {
              //Write to the pin, indicate that pin is available
              digitalWrite(pinIdx, 0); 
              pinNotes[pinIdx] = -1;
              pinChannels[pinIdx] = INT_MAX;
           }
        }
    }
    
    else {
       printf("Unhandled event %2d\n", ev->type);
    }
    snd_seq_free_event(ev);
}  // end of midi_process
Ejemplo n.º 10
0
void Midi2UdpThread::run()
{
	QUdpSocket *udpSocket;
	udpSocket = new QUdpSocket(0);
	 
	forever {
		
		if (abort) {
			delete udpSocket;
			
			return;
		}
		
		if (poll(pfd, npfd, 250) > 0) {
			
			// Get MIDI event
			snd_seq_event_input(seq_handle, &midi_event);
			
			long len = snd_midi_event_decode(eventparser, midimsg, MAX_MIDI_MESSAGE_LENGTH, midi_event);
			
			if( len < 0 ) {
				printf("midi2udp: Error decoding midi event!\n");
			} else {
				printf("midi2udp: got midi event: ");
				for(int i=0; i<len; ++i) {
					printf("0x%x ", midimsg[i]);
				}
				printf("\n");
			
				// Send it over UDP
				for(set<string>::iterator ip_it = ds_ips.begin(); ip_it != ds_ips.end(); ++ip_it)
				{
					QString to_((*ip_it).c_str());
					printf("sending to %s\n", (*ip_it).c_str());
					QHostAddress to(to_);
					udpSocket->writeDatagram((char*)midimsg, len, to, DS_PORT);
				}
			}
			
			snd_seq_free_event(midi_event);
			
			snd_midi_event_reset_decode(eventparser);
		}
	}
}
/* TODO: ADD MIDI PANIC/ALL NOTES OFF */
int midi_callback() {

    snd_seq_event_t *ev;
    int l1;

    do {
        snd_seq_event_input(seq_handle, &ev);
        switch (ev->type) {
            case SND_SEQ_EVENT_NOTEON:
                for (l1 = 0; l1 < POLY; l1++) {
                    if (!note_active[l1]) {
                        note[l1] = ev->data.note.note;
			midichannel[l1] = ev->data.note.channel;
			velocity[l1] = ev->data.note.velocity / 127;
			attron(COLOR_PAIR(1));			
			printw("CH %2.0f ", midichannel[l1]+1);
			printw("Note %3d ", note[l1]);
			printw("Velocity %3.0f ", velocity[l1] * 127);
			printw("Frequency %3.1f \n", ((note[l1]*FREQ_CHANNEL_WIDTH)+((128*FREQ_CHANNEL_WIDTH*midichannel[l1])+FREQ_START)) );
			refresh();
			attroff(COLOR_PAIR(1));
                        env_time[l1] = 0;
                        gate[l1] = 1;
                        note_active[l1] = 1;
                        break;
                    }
                }
                break;
            case SND_SEQ_EVENT_NOTEOFF:
                for (l1 = 0; l1 < POLY; l1++) {
                    if (gate[l1] && note_active[l1] && (note[l1] == ev->data.note.note)) {
			printw("Note OFF %3d \n", note[l1]);
                        env_time[l1] = 0;
                        gate[l1] = 0;
                    }
                }
                break;
        }
        snd_seq_free_event(ev);
    } while (snd_seq_event_input_pending(seq_handle, 0) > 0);
    return (0);
}
Ejemplo n.º 12
0
int midi_action(snd_seq_t *seq_handle) {

	snd_seq_event_t *ev;
	int cnt = 0;

	do {
		snd_seq_event_input(seq_handle, &ev);
		switch (ev->type) {
			case SND_SEQ_EVENT_NOTEON:
				if (channels && !(channels & (1<<ev->data.note.channel)))
					break;
				if (ev->data.note.velocity != 0) {
					note_on(ev->data.note.note, ev->data.note.velocity);
					cnt++;
				}
			}
		snd_seq_free_event(ev);
	} while (snd_seq_event_input_pending(seq_handle, 0) > 0);
	return cnt;
}
Ejemplo n.º 13
0
int midi_callback() {

    snd_seq_event_t *ev;
    int l1;
  
    do {
        snd_seq_event_input(seq_handle, &ev);
        switch (ev->type) {
            case SND_SEQ_EVENT_PITCHBEND:
                pitch = (double)ev->data.control.value / 8192.0;
                break;
            case SND_SEQ_EVENT_CONTROLLER:
                if (ev->data.control.param == 1) {
                    modulation = (double)ev->data.control.value / 10.0;
                } 
                break;
            case SND_SEQ_EVENT_NOTEON:
                for (l1 = 0; l1 < POLY; l1++) {
                    if (!note_active[l1]) {
                        note[l1] = ev->data.note.note;
                        velocity[l1] = ev->data.note.velocity / 127.0;
                        env_time[l1] = 0;
                        gate[l1] = 1;
                        note_active[l1] = 1;
                        break;
                    }
                }
                break;        
            case SND_SEQ_EVENT_NOTEOFF:
                for (l1 = 0; l1 < POLY; l1++) {
                    if (gate[l1] && note_active[l1] && (note[l1] == ev->data.note.note)) {
                        env_time[l1] = 0;
                        gate[l1] = 0;
                    }
                }
                break;        
        }
        snd_seq_free_event(ev);
    } while (snd_seq_event_input_pending(seq_handle, 0) > 0);
    return (0);
}
Ejemplo n.º 14
0
int midi_read() {

    snd_seq_event_t *ev;
    int channel,value,note,velocity,param;

    do {
        snd_seq_event_input(seq_handle, &ev);
        switch (ev->type) {
            case SND_SEQ_EVENT_NOTEON:
		channel = ev->data.note.channel;
		note = ev->data.note.note & 0x7f;
		velocity = ev->data.note.velocity;
		note_on_action(channel,note,velocity);
		break;
            case SND_SEQ_EVENT_NOTEOFF:
		channel = ev->data.note.channel;
		note = ev->data.note.note;
		velocity = ev->data.note.velocity;
		note_off_action(channel,note,velocity);
		break;
            case SND_SEQ_EVENT_PGMCHANGE:
		channel = ev->data.control.channel;
		value = ev->data.control.value;
		program_change_action(channel,value);	
		break;
            case SND_SEQ_EVENT_CONTROLLER:
		channel = ev->data.control.channel;
		param = ev->data.control.param;
		value = ev->data.control.value;
		control_change_action(channel,param,value);	
		break;	    
	 
        }
        snd_seq_free_event(ev);
    } while (snd_seq_event_input_pending(seq_handle, 0) > 0);
    return (0);
}
Ejemplo n.º 15
0
void midi_action(snd_seq_t *seq_handle) {

  snd_seq_event_t *ev;

  do {
    snd_seq_event_input(seq_handle, &ev);
    switch (ev->type) {
      case SND_SEQ_EVENT_CONTROLLER:
        printf(MIDI_FORMAT, MIDI_CONTROL, ev->data.control.channel, ev->data.control.value);
        break;
      case SND_SEQ_EVENT_PITCHBEND:
        printf(MIDI_FORMAT, MIDI_PITCH_BEND, ev->data.control.channel, ev->data.control.value);
        break;
      case SND_SEQ_EVENT_NOTEON:
        printf(MIDI_FORMAT, MIDI_NOTE_ON, ev->data.control.channel, ev->data.note.note);
        break;
      case SND_SEQ_EVENT_NOTEOFF:
        printf(MIDI_FORMAT, MIDI_NOTE_OFF, ev->data.control.channel, ev->data.note.note);
        break;
    }
		fflush(stdout); fflush(stderr);
    snd_seq_free_event(ev);
  } while (snd_seq_event_input_pending(seq_handle, 0) > 0);
}
Ejemplo n.º 16
0
int main( int argc, char *argv[] )
{
	jack_client_t *jackClient;

	snd_seq_t *seqport;
	struct pollfd *pfd;
	int npfd;
	snd_seq_event_t *midievent;
	int channel, midiport;
	
	int note, length, i, j, minpos;
	double freq, avg, vol, scale, min;
	double *tempstring;

	puts( "SO-KL5 v.1.2 by 50m30n3 2009-2011" );

	if( argc > 1 )
		channel = atoi( argv[1] );
	else
		channel = 0;

	signal( SIGINT, sig_exit );
	signal( SIGTERM, sig_exit );


	puts( "Connecting to Jack Audio Server" );
	
	jackClient = jack_client_open( "SO-KL5", JackNoStartServer, NULL );
	if( jackClient == NULL )
	{
		fputs( "Cannot connect to Jack Server\n", stderr );
		return 1;
	}

	jack_on_shutdown( jackClient, jack_shutdown, 0 );

	outport = jack_port_register( jackClient, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 );

	jack_set_process_callback( jackClient, process, 0 );

	samplerate = jack_get_sample_rate( jackClient );


	puts( "Initializing synth parameters" );

	sustain = 0;
	cutoff = 64;
	resonance = 100;
	attack = 64;
	volume = 100;

	fcutoff = (cutoff+5.0)/400.0;
	sattack = (attack+5.0)/800.0;
	freso = (resonance/160.0)*(1.0-fcutoff);
	ssustain = 0.6+pow( sustain/127.0, 0.4)*0.4;

	for( note=0; note<NUMNOTES; note++ )
	{
		freq = 440.0*pow( 2.0, (note+BASENOTE-69) / 12.0 );
		stringcutoff[note] = 0.5 + pow( (double)note / (double)NUMNOTES, 0.5 ) * 0.45;
		length = round( (double)samplerate / freq );
		stringlength[note] = length;
		strings[note] = malloc( length * sizeof( double ) );
		if( strings[note] == NULL )
		{
			fputs( "Error allocating memory\n", stderr );
			return 1;
		}
		
		for( i=0; i<length; i++ )
		{
			strings[note][i] = 0.0;
		}
		stringpos[note] = 0;
		status[note] = 0;
	}

	freq = 440.0*pow( 2.0, (BASENOTE-69) / 12.0 );
	length = (double)samplerate / freq;
	tempstring = malloc( length * sizeof( double ) );
	if( tempstring == NULL )
	{
		fputs( "Error allocating memory\n", stderr );
		return 1;
	}

	lpval = lplast = 0.0;

	jack_activate( jackClient );


	printf( "Listening on MIDI channel %i\n", channel );

	if( snd_seq_open( &seqport, "default", SND_SEQ_OPEN_INPUT, 0 ) < 0 )
	{
		fputs( "Cannot connect to ALSA sequencer\n", stderr );
		return 1;
	}

	snd_seq_set_client_name( seqport, "SO-KL5" );

	midiport = snd_seq_create_simple_port( seqport, "input",
		SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
		SND_SEQ_PORT_TYPE_APPLICATION );

	if( midiport < 0 )
	{
		fputs( "Cannot create ALSA sequencer port\n", stderr );
		return 1;
	}

	npfd = snd_seq_poll_descriptors_count( seqport, POLLIN );
	pfd = (struct pollfd *)malloc( npfd * sizeof( struct pollfd ) );
	snd_seq_poll_descriptors( seqport, pfd, npfd, POLLIN );


	done = 0;

	while( ! done )
	{
		if( poll( pfd, npfd, 100000 ) > 0 )
		{
			do
			{
				snd_seq_event_input( seqport, &midievent );
				
				if( ( midievent->type == SND_SEQ_EVENT_NOTEON ) && ( midievent->data.note.channel == channel ) )
				{
					note = midievent->data.note.note;
					if( ( note >= BASENOTE ) && ( note < BASENOTE+NUMNOTES ) )
					{
						note -= BASENOTE;

						status[note] = 1;

						for( i=0; i<stringlength[note]; i++ )
						{
							tempstring[i] = ((double)rand()/(double)RAND_MAX)*2.0-1.0;
						}

						freq = stringcutoff[note] * 0.25 + midievent->data.note.velocity/127.0 * 0.2 + sattack + 0.1;

						for( j=0; j<30; j++ )
						{
							tempstring[0] = tempstring[0]*freq + tempstring[stringlength[note]-1]*(1.0-freq);
							for( i=1; i<stringlength[note]; i++ )
							{
								tempstring[i] = tempstring[i]*freq + tempstring[(i-1)%stringlength[note]]*(1.0-freq);
							}
						}

						avg = 0.0;

						for( i=0; i<stringlength[note]; i++ )
						{
							avg += tempstring[i];
						}

						avg /= stringlength[note];

						scale = 0.0;

						for( i=0; i<stringlength[note]; i++ )
						{
							tempstring[i] -= avg;
							if( fabs( tempstring[i] ) > scale )
								scale = fabs( tempstring[i] );
						}

						min = 10.0;
						minpos = 0;

						for( i=0; i<stringlength[note]; i++ )
						{
							tempstring[i] /= scale;
							if( fabs( tempstring[i] ) + fabs( tempstring[i] - tempstring[i-1] ) * 5.0 < min )
							{
								min = fabs( tempstring[i] ) + fabs( tempstring[i] - tempstring[i-1] ) * 5.0;
								minpos = i;
							}
						}

						vol = midievent->data.note.velocity/256.0;

						for( i=0; i<stringlength[note]; i++ )
						{
							strings[note][(stringpos[note]+i)%stringlength[note]] += tempstring[(i+minpos)%stringlength[note]]*vol;
						}
					}
				}
				else if( ( midievent->type == SND_SEQ_EVENT_NOTEOFF ) && ( midievent->data.note.channel == channel ) )
				{
					note = midievent->data.note.note;
					if( ( note >= BASENOTE ) && ( note < BASENOTE+NUMNOTES ) )
					{
						note -= BASENOTE;
						status[note] = 0;
					}
				}
				else if( ( midievent->type == SND_SEQ_EVENT_CONTROLLER ) && ( midievent->data.control.channel == channel ) )
				{
					if( midievent->data.control.param == 74 )
					{
						cutoff = midievent->data.control.value;
						fcutoff = (cutoff+5.0)/400.0;
						printf( "Cutoff: %i     \r", cutoff );
						fflush( stdout );
					}
					else if( midievent->data.control.param == 71 )
					{
						resonance = midievent->data.control.value;
						freso = (resonance/140.0)*(1.0-fcutoff);
						printf( "Resonance: %i     \r", resonance );
						fflush( stdout );
					}
					else if( midievent->data.control.param == 73 )
					{
						attack = midievent->data.control.value;
						sattack = (attack+5.0)/800.0;
						printf( "Attack: %i     \r", attack );
						fflush( stdout );
					}
					else if( midievent->data.control.param == 7 )
					{
						volume = midievent->data.control.value;
						printf( "Volume: %i     \r", volume );
						fflush( stdout );
					}
					else if( ( midievent->data.control.param == 64 ) || ( midievent->data.control.param == 1 ) )
					{
						sustain = midievent->data.control.value;
						ssustain = 0.6+pow( sustain/127.0, 0.4)*0.4;
						printf( "Sustain: %i    \r", sustain );
						fflush( stdout );
					}
				}
				
				snd_seq_free_event( midievent );
			}
			while( snd_seq_event_input_pending( seqport, 0 ) > 0 );
		}
	}

	free( pfd );
	snd_seq_delete_port( seqport, midiport );
	snd_seq_close( seqport );
	
	jack_deactivate( jackClient );

	puts( "Freeing data" );
	for( note=0; note<NUMNOTES; note++ )
	{
		free( strings[note] );
	}
	free( tempstring );

	jack_port_unregister( jackClient, outport );
	jack_client_close( jackClient );

	return 0;
}
Ejemplo n.º 17
0
void midi_process(snd_seq_event_t *ev)
{
    
    //If this event is a PGMCHANGE type, it's a request to map a channel to an instrument
    if( ev->type == SND_SEQ_EVENT_PGMCHANGE )  {
        //printf("PGMCHANGE: channel %2d, %5d, %5d\n", ev->data.control.channel, ev->data.control.param,  ev->data.control.value);
        
        //Clear pins state, this is probably the beginning of a new song
        clearPinsState();
        
        setChannelInstrument(ev->data.control.channel, ev->data.control.value);
    }
    
    //Note on/off event
    else if ( ((ev->type == SND_SEQ_EVENT_NOTEON)||(ev->type == SND_SEQ_EVENT_NOTEOFF)) ) {
        
        
        //choose the output pin based on the pitch of the note
        int pinIdx = choosePinIdx(ev->data.note.note, ev->data.note.channel);
        
        
        if(!isPercussionChannel(ev->data.note.channel) ) {
            int isOn = 1;
            //Note velocity == 0 means the same thing as a NOTEOFF type event
            if( ev->data.note.velocity == 0 || ev->type == SND_SEQ_EVENT_NOTEOFF) {
                isOn = 0;
            }
            
            
            //If pin is set to be turned on
            if( isOn ) {
                //If pin is currently available to play a note, or if currently playing channel can be overriden due to higher priority channel
                if( pinNotes[pinIdx] == -1 || pinChannels[pinIdx] > ev->data.note.channel )  {
                    
                    if( (pinChannels[pinIdx] > ev->data.note.channel ) && pinNotes[pinIdx] != -1)  {
                        //printf("OVERRIDING CHANNEL %i for %i\n", pinChannels[pinIdx], ev->data.note.channel);
                    }
                    //Write to the pin, save the note to pinNotes
                    //printf("Pin %i - %s %i %i \n", pinIdx, isOn ? "on" : "off", ev->data.note.note, ev->data.note.channel);
                    digitalWrite(pinIdx, 1);
                    pinNotes[pinIdx] = ev->data.note.note;
                    pinChannels[pinIdx] =  ev->data.note.channel;
                }
            }
            
            //Pin is to be turned off
            else {
                //If this is the note that turned the pin on..
                if( pinNotes[pinIdx] == ev->data.note.note && pinChannels[pinIdx] == ev->data.note.channel ) {
                    //Write to the pin, indicate that pin is available
                    //printf("Pin %i - %s %i %i \n", pinIdx, isOn ? "on" : "off", ev->data.note.note, ev->data.note.channel);
                    digitalWrite(pinIdx, 0);
                    pinNotes[pinIdx] = -1;
                    pinChannels[pinIdx] = INT_MAX;
                }
            }
        }
        else {
            //This is the percussion channel, flip the value
            static int percussionOn = 0;
            if( PERCUSSION_PIN_IDX != -1 ) {
                if( percussionOn) {
                    digitalWrite(pinIdx, 0);
                    percussionOn = 0;
                }
                else {
                    digitalWrite(pinIdx, 1);
                    percussionOn = 1;
                }
            }
            
        }
        
    }
    
    else {
        printf("Unhandled event %2d\n", ev->type);
        
    }
    
    snd_seq_free_event(ev);
}
Ejemplo n.º 18
0
bool
mastermidibus::get_midi_event( event *a_in )
{
    lock();
    
    snd_seq_event_t *ev; 
    
    bool sysex = false;
    
    /* temp for midi data */
    unsigned char buffer[0x1000];
    
    snd_seq_event_input(m_alsa_seq, &ev);
    
    
    
    bool ret = false;

    if (! global_manual_alsa_ports )
    {
        switch( ev->type ){ 

            case SND_SEQ_EVENT_PORT_START:
                {   
                    //printf("SND_SEQ_EVENT_PORT_START:    addr[%d:%d]\n", 
                    //	   ev->data.addr.client, ev->data.addr.port );
                    port_start( ev->data.addr.client, ev->data.addr.port );
                    ret = true; 
                    break;
                }

            case SND_SEQ_EVENT_PORT_EXIT:     
                {
                    //printf("SND_SEQ_EVENT_PORT_EXIT:     addr[%d:%d]\n", 
                    //	   ev->data.addr.client, ev->data.addr.port ); 
                    port_exit( ev->data.addr.client, ev->data.addr.port );
                    ret = true; 
                    break;
                }

            case SND_SEQ_EVENT_PORT_CHANGE:
                {   
                    //printf("SND_SEQ_EVENT_PORT_CHANGE:   addr[%d:%d]\n", 
                    //	   ev->data.addr.client, 
                    //	   ev->data.addr.port ); 
                    ret = true; 
                    break;
                }

            default: break;

        }
    }

    if( ret ){
        unlock();
        return false;
    }
    
    /* alsa midi parser */
    snd_midi_event_t *midi_ev;
    snd_midi_event_new( 0x1000, &midi_ev );
    
    long bytes =
        snd_midi_event_decode( midi_ev,
                               buffer,
                               0x1000,
                               ev ); 
    
    a_in->set_timestamp( ev->time.tick );
    a_in->set_status( buffer[0] );
    a_in->set_size( bytes );
    
    /* we will only get EVENT_SYSEX on the first 
       packet of midi data, the rest we have
       to poll for */
    //if ( buffer[0] == EVENT_SYSEX ){
    if ( 0 ){
    
        /* set up for sysex if needed */
        a_in->start_sysex( );
        sysex = a_in->append_sysex( buffer, bytes );
    }
    else {
        
        a_in->set_data( buffer[1], buffer[2] );
        
        // some keyboards send on's with vel 0 for off
        if ( a_in->get_status() == EVENT_NOTE_ON &&
             a_in->get_note_velocity() == 0x00 ){
            a_in->set_status( EVENT_NOTE_OFF );
        }
        
        sysex = false;
    }
    
    /* sysex messages might be more than one message */
    while ( sysex ){
        
        snd_seq_event_input(m_alsa_seq, &ev);
        
        bytes =
            snd_midi_event_decode( midi_ev,
                                   buffer,
                                   0x1000,
                                   ev ); 
        
        sysex = a_in->append_sysex( buffer, bytes );
        
    }
    
    snd_seq_free_event( ev );
    snd_midi_event_free( midi_ev );
    
    unlock();
    
    return true;
}
Ejemplo n.º 19
0
void AlsaMidiInputThread::readEvent()
{
    m_mutex.lock();

    /* Wait for input data */
    do
    {
        AlsaMidiInputDevice* device = NULL;
        snd_seq_event_t* ev = NULL;

        /* Receive an event */
        snd_seq_event_input(m_alsa, &ev);

        // Find a device matching the event's address. If one isn't
        // found, skip this event, since we're not interested in it.
        uint uid = AlsaMidiUtil::addressToVariant(&ev->source).toUInt();
        if (m_devices.contains(uid) == true)
            device = m_devices[uid];
        else
            continue;
        Q_ASSERT(device != NULL);

        uchar cmd = 0;
        uchar data1 = 0;
        uchar data2 = 0;

        //qDebug() << "ALSA MIDI event received !" << ev->type;

        if (snd_seq_ev_is_control_type(ev))
        {
            switch (ev->type)
            {
            case SND_SEQ_EVENT_PGMCHANGE:
                cmd = MIDI_PROGRAM_CHANGE;
                data1 = ev->data.control.value;
                data2 = 127;
                break;

            case SND_SEQ_EVENT_CONTROLLER:
                cmd = MIDI_CONTROL_CHANGE | ev->data.control.channel;
                data1 = ev->data.control.param;
                data2 = ev->data.control.value;
                break;

            case SND_SEQ_EVENT_PITCHBEND:
                cmd = MIDI_PITCH_WHEEL | ev->data.control.channel;
                data1 = (ev->data.control.value + 8192) & 0x7f;
                data2 = (ev->data.control.value + 8192) >> 7;
                break;

            case SND_SEQ_EVENT_KEYPRESS:
                cmd = MIDI_NOTE_AFTERTOUCH | ev->data.note.channel;
                data1 = ev->data.note.note;
                data2 = ev->data.note.velocity;
                break;

            case SND_SEQ_EVENT_CHANPRESS:
                cmd = MIDI_CHANNEL_AFTERTOUCH | ev->data.control.channel;
                data1 = ev->data.control.value;
                break;
 
            default:
                break;
            }
        }
        else if (snd_seq_ev_is_note_type(ev))
        {
            if (ev->type == SND_SEQ_EVENT_NOTEOFF)
                cmd = MIDI_NOTE_OFF | ev->data.note.channel;
            else if (ev->data.note.velocity == 0 && ev->data.note.off_velocity == 0)
                cmd = MIDI_NOTE_OFF | ev->data.note.channel;
            else
                cmd = MIDI_NOTE_ON | ev->data.note.channel;
            data1 = ev->data.note.note;
            data2 = ev->data.note.velocity;
        }
        else if (snd_seq_ev_is_queue_type(ev))
        {
            if (device->processMBC(ev->type) == false)
                continue;
            if (ev->type == SND_SEQ_EVENT_START)
                cmd = MIDI_BEAT_START;
            else if(ev->type == SND_SEQ_EVENT_STOP)
                cmd = MIDI_BEAT_STOP;
            else if(ev->type == SND_SEQ_EVENT_CONTINUE)
                cmd = MIDI_BEAT_CONTINUE;
            else if(ev->type == SND_SEQ_EVENT_CLOCK)
                cmd = MIDI_BEAT_CLOCK;

            qDebug()  << "MIDI clock: " << cmd;
        }

        // ALSA API is a bit controversial on this. snd_seq_event_input() says
        // it ALLOCATES the event but snd_seq_free_event() says this is not
        // needed because the event IS NOT allocated. No crashes observed
        // either way, so I guess freeing nevertheless is a bit safer.
        snd_seq_free_event(ev);

        uint channel = 0;
        uchar value = 0;
        if (QLCMIDIProtocol::midiToInput(cmd, data1, data2, device->midiChannel(),
                                         &channel, &value) == true)
        {
            device->emitValueChanged(channel, value);
            // for MIDI beat clock signals,
            // generate a synthetic release event
            if (cmd >= MIDI_BEAT_CLOCK && cmd <= MIDI_BEAT_STOP)
                device->emitValueChanged(channel, 0);
        }
    } while (snd_seq_event_input_pending(m_alsa, 0) > 0);
Ejemplo n.º 20
0
static void midi_in_cb (gpointer data, int fd, GdkInputCondition condition)
{
    snd_seq_t *handle = (snd_seq_t *)data;
    snd_seq_event_t *pev;
    int rc;

    /* Perform sanity checks. */

    if ((int)condition != GDK_INPUT_READ) {
	g_print( "wrong condition (%d). %d was expected\n",
		 condition, GDK_INPUT_READ);
	return;
    }

    if (handle == NULL) {
	g_print( "NULL handle detected\n");
	return;
    }

    /* Process MIDI event.  Don't forget to free the event after usage. */

    rc = snd_seq_event_input( handle, &pev);
    if (rc < 0) {
	g_print("unable to get event");
	return;
    }

    switch (pev->type) {
    case SND_SEQ_EVENT_NOTEOFF:
	/* Simulate a note on event. */
	pev->data.note.velocity = 0;
	/* no break here. Go to next case...*/
    case SND_SEQ_EVENT_NOTE:
    case SND_SEQ_EVENT_NOTEON:
      if (IS_MIDI_DEBUG_ON) {
	  midi_print_event(pev);
	}
	midi_process_note_on( &(pev->data.note));
	break;

    case SND_SEQ_EVENT_CONTROLLER:
      if (IS_MIDI_DEBUG_ON) {
	  midi_print_event(pev);
	}
	midi_process_controller( &(pev->data.control));
	break;

    case SND_SEQ_EVENT_PGMCHANGE:
      if (IS_MIDI_DEBUG_ON) {
	  midi_print_event(pev);
	}
	midi_process_program_change( &(pev->data.control));
	break;

    default:
      if (IS_MIDI_DEBUG_ON) {
	  /* Some events (like SND_SEQ_EVENT_SENSING) are not printed
	     by the print_event routine. */
	  midi_print_event(pev);
	}
	break;
    }

    rc = snd_seq_free_event( pev);
    if (rc < 0) {
	g_print("unable to free event");
	return;
    }

    return;

} /* midi_in_cb() */
Ejemplo n.º 21
0
void Udp2MidiThread::run()
{
	QUdpSocket *udpSocket = new QUdpSocket();
	bool bres = udpSocket->bind(PC_PORT);
	if( bres == false ) {
                printf("Could not bind to port %d!\n", PC_PORT);
		return;
	}
	
	forever {
		
		if (abort) {
			delete udpSocket;
			
			return;
		}
		
		if( udpSocket->waitForReadyRead(250) == true ) {
			
			// Receive from UDP
			
			QHostAddress from_address;
                        int len = udpSocket->readDatagram((char*)midimsg, MAX_MIDI_MESSAGE_LENGTH, &from_address);
		
                        if( len == -1 ) {
				printf("udp2midi: Error receiving data!\n");
			}
			
                        if( (len == 3) && (midimsg[0] == 0) && (midimsg[1] == 0) && (midimsg[2] == 0) ) {

				string from_ip = from_address.toString().toStdString();
			
				printf("Keepalive from: %s\n", from_ip.c_str());

				midi2udp->add_ip(from_ip);
			
			} else {

				// Send to MIDI
                                printf("udp2midi: Sending event: ");
                                for(int i=0; i<len; ++i) {
                                    printf("0x%x ", midimsg[i]);
                                }
                                printf("\n");
		
                                long res = snd_midi_event_encode(eventparser, midimsg, len, midi_event);
				
				if( res < 0) {
					printf("Error encoding midi event!\n");
				}
				
				snd_midi_event_reset_encode(eventparser);
				
				if(midi_event->type == SND_SEQ_EVENT_NOTEON) {
					printf("udp2midi: Note on: %d, channel %d\n", midi_event->data.note.note, midi_event->data.control.channel);
				} else if(midi_event->type == SND_SEQ_EVENT_NOTEOFF){
					printf("udp2midi: Note off: %d, channel %d\n", midi_event->data.note.note, midi_event->data.control.channel);
				}
				
				snd_seq_ev_set_subs(midi_event);
				snd_seq_ev_set_direct(midi_event);
				snd_seq_ev_set_source(midi_event, midi_out_port);
				
				snd_seq_event_output_direct(seq_handle, midi_event);
				
				snd_seq_free_event(midi_event);
			}
		}
	}
}
Ejemplo n.º 22
0
void midi_process(snd_seq_event_t *ev)
{
    //If this event is a PGMCHANGE type, it's a request to map a channel to an instrument
    if( ev->type == SND_SEQ_EVENT_PGMCHANGE )  {
       printf("PGMCHANGE: channel %2d, %5d, %5d\n", ev->data.control.channel, ev->data.control.param,  ev->data.control.value);

       //Clear pins state, this is probably the beginning of a new song
       clearPinsState();
       

       //Filter out this channel if it's a base, percussion, or synth instrument
       if(
           (ev->data.control.value >= 8 && ev->data.control.value <= 15) ||  //Percussion
           (ev->data.control.value >= 32 && ev->data.control.value <= 39) || //Base
           (ev->data.control.value >= 88 && ev->data.control.value <= 103)   //Synth
        
       ) {
          setPlayChannel(ev->data.control.channel, 0);
       }
       else {
          setPlayChannel(ev->data.control.channel, 1);
       }
    }

    //Note on/off event
    else if ( ((ev->type == SND_SEQ_EVENT_NOTEON)||(ev->type == SND_SEQ_EVENT_NOTEOFF)) ) {
        
       //If it's on a channel I care about
       if( isPlayChannel(ev->data.note.channel) ) {
       
          int isOn = 1;
          //Note velocity == 0 means the same thing as a NOTEOFF type event
          if( ev->data.note.velocity == 0 || ev->type == SND_SEQ_EVENT_NOTEOFF) {
             isOn = 0;
          }
  

          //There are 12 different kinds of notes.
          int noteMod = ev->data.note.note % 12;

          //Cast to double
          double noteModDouble = noteMod;

          //The pin to use is determined by:
          // ( pitch  /  ( Total number of notes / Total Number of Pins) )
          double noteBin = noteModDouble / (12.0 / MY_NUM_PINS); 
         
          //Cast back to int
          int pinIdx = (int)noteBin;

          //If pin is set to be turned on
          if( isOn ) {
             //If pin is currently available to play a note, or if currently playing channel can be overriden due to higher priority channel
             if( pinNotes[pinIdx] == -1 || pinChannels[pinIdx] > ev->data.note.channel )  {
                    
                if( (pinChannels[pinIdx] > ev->data.note.channel ) && pinNotes[pinIdx] != -1)  {
                   printf("OVERRIDING CHANNEL %i for %i\n", pinChannels[pinIdx], ev->data.note.channel);
                }
                //Write to the pin, save the note to pinNotes
                //printf("Pin %i - %s %i %i \n", pinIdx, isOn ? "on" : "off", ev->data.note.note, ev->data.note.channel);       
                digitalWrite(pinIdx, 1); 
                pinNotes[pinIdx] = ev->data.note.note;
                pinChannels[pinIdx] =  ev->data.note.channel;
             }
          }
        
          //Pin is to be turned off
          else {
             //If this is the note that turned the pin on..
             if( pinNotes[pinIdx] == ev->data.note.note && pinChannels[pinIdx] == ev->data.note.channel ) {
                //Write to the pin, indicate that pin is available
                //printf("Pin %i - %s %i %i \n", pinIdx, isOn ? "on" : "off", ev->data.note.note, ev->data.note.channel);       
                digitalWrite(pinIdx, 0); 
                pinNotes[pinIdx] = -1;
                pinChannels[pinIdx] = INT_MAX;
             }
          }
       }
    }
    
    else {
       printf("Unhandled event %2d\n", ev->type);
   
    }

    snd_seq_free_event(ev);
}
Ejemplo n.º 23
0
int main( int argc, char *argv[] )
{
	jack_client_t *jackClient;

	snd_seq_t *seqport;
	struct pollfd *pfd;
	int npfd;
	snd_seq_event_t *midievent;
	int channel, midiport;
	
	int note, length, i;
	double freq;

	puts( "SO-666 v.1.01 by 50m30n3 2009-2010" );

	if( argc > 1 )
		channel = atoi( argv[1] );
	else
		channel = 0;

	signal( SIGINT, sig_exit );
	signal( SIGTERM, sig_exit );


	puts( "Connecting to Jack Audio Server" );
	
	jackClient = jack_client_open( "SO-666", JackNoStartServer, NULL );
	if( jackClient == NULL )
	{
		fputs( "Cannot connect to Jack Server\n", stderr );
		return 1;
	}

	jack_on_shutdown( jackClient, jack_shutdown, 0 );

	outport = jack_port_register( jackClient, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 );

	jack_set_process_callback( jackClient, process, 0 );

	samplerate = jack_get_sample_rate( jackClient );


	puts( "Initializing synth parameters" );

	feedback = 32;
	cutoff = 64;
	resonance = 64;
	volume = 100;

	fcutoff = pow( (cutoff+50.0)/200.0, 5.0 );
	freso = resonance/127.0;
	ffeedback = 0.01+pow( feedback/127.0, 4.0)*0.9;

	for( note=0; note<NUMNOTES; note++ )
	{
		freq = 440.0*pow( 2.0, (note+BASENOTE-69) / 12.0 );
		//stringcutoff[note] = ( freq * 16.0 ) / (double)samplerate;
		stringcutoff[note] = 0.9;
		length = (double)samplerate / freq;
		stringlength[note] = length;
		strings[note] = malloc( length * sizeof( double ) );
		if( strings[note] == NULL )
		{
			fputs( "Error allocating memory\n", stderr );
			return 1;
		}
		
		for( i=0; i<length; i++ )
		{
			strings[note][i] = 0.0;
		}
		stringpos[note] = 0;
		status[note] = 0;
	}

	lpval = lplast = 0.0;
	hpval = hplast = 0.0;

	jack_activate( jackClient );


	printf( "Listening on MIDI channel %i\n", channel );

	if( snd_seq_open( &seqport, "default", SND_SEQ_OPEN_INPUT, 0 ) < 0 )
	{
		fputs( "Cannot connect to ALSA sequencer\n", stderr );
		return 1;
	}

	snd_seq_set_client_name( seqport, "SO-666" );

	midiport = snd_seq_create_simple_port( seqport, "input",
		SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
		SND_SEQ_PORT_TYPE_APPLICATION );

	if( midiport < 0 )
	{
		fputs( "Cannot create ALSA sequencer port\n", stderr );
		return 1;
	}

	npfd = snd_seq_poll_descriptors_count( seqport, POLLIN );
	pfd = (struct pollfd *)malloc( npfd * sizeof( struct pollfd ) );
	snd_seq_poll_descriptors( seqport, pfd, npfd, POLLIN );


	done = 0;

	while( ! done )
	{
		if( poll( pfd, npfd, 100000 ) > 0 )
		{
			do
			{
				snd_seq_event_input( seqport, &midievent );
				
				if( ( midievent->type == SND_SEQ_EVENT_NOTEON ) && ( midievent->data.note.channel == channel ) )
				{
					note = midievent->data.note.note;
					if( ( note >= BASENOTE ) && ( note < BASENOTE+NUMNOTES ) )
					{
						note -= BASENOTE;

						status[note] = 1;
					}
				}
				else if( ( midievent->type == SND_SEQ_EVENT_NOTEOFF ) && ( midievent->data.note.channel == channel ) )
				{
					note = midievent->data.note.note;
					if( ( note >= BASENOTE ) && ( note < BASENOTE+NUMNOTES ) )
					{
						note -= BASENOTE;
						status[note] = 0;
					}
				}
				else if( ( midievent->type == SND_SEQ_EVENT_CONTROLLER ) && ( midievent->data.control.channel == channel ) )
				{
					if( midievent->data.control.param == 74 )
					{
						cutoff = midievent->data.control.value;
						fcutoff = pow( (cutoff+50.0)/200.0, 5.0 );
						printf( "Cutoff: %i     \r", cutoff );
						fflush( stdout );
					}
					else if( midievent->data.control.param == 71 )
					{
						resonance = midievent->data.control.value;
						freso = resonance/127.0;
						printf( "Resonance: %i     \r", resonance );
						fflush( stdout );
					}
					else if( midievent->data.control.param == 7 )
					{
						volume = midievent->data.control.value;
						printf( "Volume: %i     \r", volume );
						fflush( stdout );
					}
					else if( midievent->data.control.param == 1 )
					{
						feedback = midievent->data.control.value;
						ffeedback = 0.01+pow( feedback/127.0, 4.0)*0.9;
						printf( "Feedback: %i    \r", feedback );
						fflush( stdout );
					}
				}
				
				snd_seq_free_event( midievent );
			}
			while( snd_seq_event_input_pending( seqport, 0 ) > 0 );
		}
	}

	free( pfd );
	snd_seq_delete_port( seqport, midiport );
	snd_seq_close( seqport );
	
	jack_deactivate( jackClient );

	puts( "Freeing data" );
	for( note=0; note<NUMNOTES; note++ )
	{
		free( strings[note] );
	}

	jack_port_unregister( jackClient, outport );
	jack_client_close( jackClient );

	return 0;
}
Ejemplo n.º 24
0
static DWORD WINAPI midRecThread(LPVOID arg)
{
    int npfd;
    struct pollfd *pfd;

    TRACE("Thread startup\n");

    while(!end_thread) {
	TRACE("Thread loop\n");
	npfd = snd_seq_poll_descriptors_count(midiSeq, POLLIN);
	pfd = HeapAlloc(GetProcessHeap(), 0, npfd * sizeof(struct pollfd));
	snd_seq_poll_descriptors(midiSeq, pfd, npfd, POLLIN);

	/* Check if an event is present */
	if (poll(pfd, npfd, 250) < 0) {
	    HeapFree(GetProcessHeap(), 0, pfd);
	    continue;
	}

	/* Note: This definitely does not work.  
	 * while(snd_seq_event_input_pending(midiSeq, 0) > 0) {
	       snd_seq_event_t* ev;
	       snd_seq_event_input(midiSeq, &ev);
	       ....................
	       snd_seq_free_event(ev);
	   }*/

	do {
	    WORD wDevID;
	    snd_seq_event_t* ev;
	    snd_seq_event_input(midiSeq, &ev);
	    /* Find the target device */
	    for (wDevID = 0; wDevID < MIDM_NumDevs; wDevID++)
		if ( (ev->source.client == MidiInDev[wDevID].addr.client) && (ev->source.port == MidiInDev[wDevID].addr.port) )
		    break;
	    if ((wDevID == MIDM_NumDevs) || (MidiInDev[wDevID].state != 1))
		FIXME("Unexpected event received, type = %x from %d:%d\n", ev->type, ev->source.client, ev->source.port);
	    else {
		DWORD dwTime, toSend = 0;
		/* FIXME: Should use ev->time instead for better accuracy */
		dwTime = GetTickCount() - MidiInDev[wDevID].startTime;
		TRACE("Event received, type = %x, device = %d\n", ev->type, wDevID);
		switch(ev->type)
		{
		case SND_SEQ_EVENT_NOTEOFF:
		    toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_OFF | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_NOTEON:
		    toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_ON | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_KEYPRESS:
		    toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_PRESSURE | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_CONTROLLER: 
		    toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CONTROL | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_PITCHBEND:
		    toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_BENDER | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_PGMCHANGE:
		    toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_PGM_CHANGE | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_CHANPRESS:
		    toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CHANNEL_PRESSURE | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_SYSEX:
		    {
			int len = ev->data.ext.len;
			LPBYTE ptr = (BYTE*) ev->data.ext.ptr;
			LPMIDIHDR lpMidiHdr;

			/* FIXME: Should handle sysex greater that a single buffer */
			EnterCriticalSection(&crit_sect);
			if ((lpMidiHdr = MidiInDev[wDevID].lpQueueHdr) != NULL) {
			    if (len <= lpMidiHdr->dwBufferLength) {
				lpMidiHdr->dwBytesRecorded = len;
				memcpy(lpMidiHdr->lpData, ptr, len);
				lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
				lpMidiHdr->dwFlags |= MHDR_DONE;
				MidiInDev[wDevID].lpQueueHdr = (LPMIDIHDR)lpMidiHdr->lpNext;
				if (MIDI_NotifyClient(wDevID, MIM_LONGDATA, (DWORD)lpMidiHdr, dwTime) != MMSYSERR_NOERROR)
				    WARN("Couldn't notify client\n");
			    } else
				FIXME("No enough space in the buffer to store sysex!\n");
			} else
			    FIXME("Sysex received but no buffer to store it!\n");
			LeaveCriticalSection(&crit_sect);
		    }
		    break;
		case SND_SEQ_EVENT_SENSING:
		    /* Noting to do */
		    break;
		default:
		    FIXME("Unhandled event received, type = %x\n", ev->type);
		    break;
		}
		if (toSend != 0) {
		    TRACE("Sending event %08lx (from %d %d)\n", toSend, ev->source.client, ev->source.port);
		    if (MIDI_NotifyClient(wDevID, MIM_DATA, toSend, dwTime) != MMSYSERR_NOERROR) {
			WARN("Couldn't notify client\n");
		    }
		}
	    }
	    snd_seq_free_event(ev);
	} while(snd_seq_event_input_pending(midiSeq, 0) > 0);
	
	HeapFree(GetProcessHeap(), 0, pfd);
    }
    return 0;
}
Ejemplo n.º 25
0
void event_decoder(snd_seq_t *handle, int argc, char *argv[])
{
	snd_seq_event_t *ev;
	snd_seq_port_info_t *pinfo;
	snd_seq_port_subscribe_t *sub;
	snd_seq_addr_t addr;
	int client, port, queue, max, err, v1, v2;
	char *ptr;
	struct pollfd *pfds;

	if ((client = snd_seq_client_id(handle))<0) {
		fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client));
		return;
	}
	printf("Client ID = %i\n", client);
	if ((queue = snd_seq_alloc_queue(handle))<0) {
		fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue));
		return;
	}
	printf("Queue ID = %i\n", queue);
	if ((err = snd_seq_nonblock(handle, 1))<0)
		fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err));
	snd_seq_port_info_alloca(&pinfo);
	snd_seq_port_info_set_name(pinfo, "Input");
	snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC);
	snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_WRITE);

	/* Enable timestamping for events sent by external subscribers. */
	snd_seq_port_info_set_timestamping(pinfo, 1);
	snd_seq_port_info_set_timestamp_real(pinfo, 1);
	snd_seq_port_info_set_timestamp_queue(pinfo, queue);

	if ((err = snd_seq_create_port(handle, pinfo)) < 0) {
		fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err));
		return;
	}
	port = snd_seq_port_info_get_port(pinfo);
	event_decoder_start_timer(handle, queue, client, port);

	snd_seq_port_subscribe_alloca(&sub);
	addr.client = SND_SEQ_CLIENT_SYSTEM;
	addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
	snd_seq_port_subscribe_set_sender(sub, &addr);
	addr.client = client;
	addr.port = port;
	snd_seq_port_subscribe_set_dest(sub, &addr);
	snd_seq_port_subscribe_set_queue(sub, queue);
	snd_seq_port_subscribe_set_time_update(sub, 1);
	snd_seq_port_subscribe_set_time_real(sub, 1);
	if ((err = snd_seq_subscribe_port(handle, sub))<0) {
		fprintf(stderr, "Cannot subscribe announce port: %s\n", snd_strerror(err));
		return;
	}

	addr.client = SND_SEQ_CLIENT_SYSTEM;
	addr.port = SND_SEQ_PORT_SYSTEM_TIMER;
	snd_seq_port_subscribe_set_sender(sub, &addr);
	if ((err = snd_seq_subscribe_port(handle, sub))<0) {
		fprintf(stderr, "Cannot subscribe timer port: %s\n", snd_strerror(err));
		return;
	}

	for (max = 0; max < argc; max++) {
		ptr = argv[max];
		if (!ptr)
			continue;
		snd_seq_port_subscribe_set_time_real(sub, 0);
		if (tolower(*ptr) == 'r') {
			snd_seq_port_subscribe_set_time_real(sub, 1);
			ptr++;
		}
		if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) {
			fprintf(stderr, "Wrong argument '%s'...\n", argv[max]);
			return;
		}
		addr.client = v1;
		addr.port = v2;
		snd_seq_port_subscribe_set_sender(sub, &addr);
		if ((err = snd_seq_subscribe_port(handle, sub))<0) {
			fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err));
			return;
		}
	}
	
	max = snd_seq_poll_descriptors_count(handle, POLLIN);
	pfds = alloca(sizeof(*pfds) * max);
	while (1) {
		snd_seq_poll_descriptors(handle, pfds, max, POLLIN);
		if (poll(pfds, max, -1) < 0)
			break;
		do {
			if ((err = snd_seq_event_input(handle, &ev))<0)
				break;
			if (!ev)
				continue;
			decode_event(ev);
			snd_seq_free_event(ev);
		} while (err > 0);
	}
}
Ejemplo n.º 26
0
static	int		vj_dequeue_midi_event( vmidi_t *v )
{
	int ret = 0;
	int err = 0;
	while( snd_seq_event_input_pending( v->sequencer, 1 ) > 0 ) {
		int data[4] = { 0,0,0,0};
		int isvalid = 1;
		snd_seq_event_t *ev = NULL;

		err = snd_seq_event_input( v->sequencer, &ev );
		if( err == -ENOSPC || err == -EAGAIN )
			return ret;

		data[0] = ev->type;
		switch( ev->type )
		{
			/* controller: channel <0-N>, <modwheel 0-127> */
			case SND_SEQ_EVENT_CONTROLLER:
				data[1] = ev->data.control.channel*256+ev->data.control.param; // OB: added chan+param as identifier
				data[2] = ev->data.control.value;
				break;
			case SND_SEQ_EVENT_PITCHBEND:
				data[1] = ev->data.control.channel;
				data[2] = ev->data.control.value;
				break;
			case SND_SEQ_EVENT_NOTE:
				data[1] = ev->data.control.channel;
				data[2] = ev->data.note.note;
				break;
			case SND_SEQ_EVENT_NOTEON:
				data[2] = ev->data.control.channel;
				data[1] = ev->data.note.note;
				break;
			case SND_SEQ_EVENT_NOTEOFF:
				data[2] = ev->data.control.channel;
				data[1] = ev->data.note.note;
				break;
			case SND_SEQ_EVENT_KEYPRESS:
				data[1] = ev->data.control.channel;
				data[2] = ev->data.note.velocity;
				break;
			case SND_SEQ_EVENT_PGMCHANGE:
				data[1] = ev->data.control.param;
				data[2] = ev->data.control.value;
				break;
			default:
				data[1] = -1;
				data[2] = -1;
				isvalid = 0;
				veejay_msg(VEEJAY_MSG_WARNING, "unknown midi event received: %d %x %x",ev->type,data[1],data[2],data[2]);
				break;
		}

		if( isvalid == 1 ) {
			vj_midi_send_vims_now( v, data );
		}

		if( ev ) {
			snd_seq_free_event( ev );
			ret ++;
		}
	}

	return ret; 
}
Ejemplo n.º 27
0
void PrintMidiIn() 
{
	snd_seq_event_t* t_event;
	char bytes[] = {0x00, 0x00, 0xFF}; 

	do 
	{
		snd_seq_event_input(t_seq, &t_event);

		//printf("t_event->source.port: %u\n", t_event->source.port); 
		//printf("t_event->source.client: %u\n", t_event->source.client); 
		if     (t_event->data.addr.port == nIdPortInA) printf("PORTA AA\n");
		else if(t_event->data.addr.port == nIdPortInB) printf("PORTA BB\n");
		else if(t_event->data.addr.port == nIdPortInC) printf("PORTA CC\n");
		else printf("ev->data.addr.port: %u\n", t_event->data.addr.port); 
		//printf("ev->data.addr.client: %u\n", t_event->data.addr.client); 
		if     (t_event->dest.port == nIdPortInA) printf("PORTA A\n");
		else if(t_event->dest.port == nIdPortInB) printf("PORTA B\n");
		else if(t_event->dest.port == nIdPortInC) printf("PORTA C\n");
		else printf("t_event->dest.port: %u\n", t_event->data.addr.port); 

		switch (t_event->type) 
		{

			case SND_SEQ_EVENT_NOTEOFF: 
				bytes[0] = 0x80 + t_event->data.control.channel;
				bytes[1] = t_event->data.note.note;
				bytes[2] = t_event->data.note.velocity; 
				printf("IN     ==> 0x%x Note off           0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); 
				break; 

			case SND_SEQ_EVENT_NOTEON:
				bytes[0] = 0x90 + t_event->data.control.channel;
				bytes[1] = t_event->data.note.note;
				bytes[2] = t_event->data.note.velocity;        
				printf("IN     ==> 0x%x Note on            0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); 
				break;        

			case SND_SEQ_EVENT_KEYPRESS: 
				bytes[0] = 0x90 + t_event->data.control.channel;
				bytes[1] = t_event->data.note.note;
				bytes[2] = t_event->data.note.velocity;        
				printf("IN     ==> 0x%x Pressure change    0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); 
				break;       

			case SND_SEQ_EVENT_CONTROLLER: 
				bytes[0] = 0xB0 + t_event->data.control.channel;
				bytes[1] = t_event->data.control.param;
				bytes[2] = t_event->data.control.value;
				printf("IN     ==> 0x%x Controller change  0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); 
				break;   

			case SND_SEQ_EVENT_PGMCHANGE: 
				bytes[0] = 0xC0 + t_event->data.control.channel;
				bytes[1] = t_event->data.control.value;
				printf("IN     ==> 0x%x Program change     0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); 
				break;  

			case SND_SEQ_EVENT_CHANPRESS: 
				bytes[0] = 0xD0 + t_event->data.control.channel;
				bytes[1] = t_event->data.control.value;
				printf("IN     ==> 0x%x Channel change     0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); 
				break;  

			case SND_SEQ_EVENT_PITCHBEND:
				bytes[0] = 0xE0 + t_event->data.control.channel;
				t_event->data.control.value += 8192;
				bytes[1] = (int)t_event->data.control.value & 0x7F;
				bytes[2] = (int)t_event->data.control.value >> 7;
				printf("IN     ==> 0x%x Pitch bend         %03u %5d\n", bytes[0]&0xF0, bytes[0]&0xF, t_event->data.control.value);
				break;

			default:
				break;
		}

		snd_seq_free_event(t_event);

	} while (snd_seq_event_input_pending(t_seq, 0) > 0);
}
Ejemplo n.º 28
0
int main(int argc, char *argv[]){
	int note = -1; /* MIDI note we are currently playing. */
	int note_update = 1; /* If 1, the note has changed;
	                      * re-send the output voltage. */
	int pitchbend = 8192; /* Current pitchbend value. 8192 = no bend. */
	snd_seq_t *seqhandle; /* ALSA Sequencer handle */
	snd_seq_event_t *ev; /* Sequencer event for handling MIDI messages. */
	int npfd; /* Number of pollfds */
	struct pollfd *pfd; /* Storage for array of struct pollfd, used for
	                     * polling for MIDI messages. */
	if(argc != 2){
		fputs(usage, stderr);
		return -1;
	}
	if(serialcv_init(argv[1], VREF)){
		fputs("monotron: could not open serial port\n", stderr);
		return -2;
	}
	if(alsa_init(&seqhandle)){
		fputs("monotron: coudle not open ALSA sequencer\n", stderr);
		serialcv_shutdown();
		return -3;
	}
	npfd = snd_seq_poll_descriptors_count(seqhandle, POLLIN);
	pfd = malloc(npfd * sizeof(struct pollfd));
	if(NULL == pfd){
		fputs("monotron: malloc failure\n", stderr);
		serialcv_shutdown();
		alsa_shutdown(seqhandle);
	}
	snd_seq_poll_descriptors(seqhandle, pfd, npfd, POLLIN);
	signal(SIGINT, terminate_loop);
	signal(SIGTERM, terminate_loop);
	while(!gotsignal){
		if(note_update){
			if(note >= 0){
				serialcv_voltage(note_voltage(note) +
				    pitchbend_voltage(pitchbend));
			} else {
				serialcv_voltage(note_voltage(-1));
			}
			note_update = 0;
		}
		if(poll(pfd, npfd, 1000) > 0){ /* MIDI Message received */
			do{
				snd_seq_event_input(seqhandle, &ev);
				if(MIDI_CH == ev->data.control.channel){
					switch(ev->type){
						case SND_SEQ_EVENT_PITCHBEND:
							pitchbend = ev->data.control.value;
							note_update = 1;
							break;
						case SND_SEQ_EVENT_NOTEON:
							if(0 == ev->data.note.velocity){
								if(ev->data.note.note == note){
									note = -1;
									note_update = 1;
								}
							} else {
								note = ev->data.note.note;
							/* Briefly output the idle voltage to
							 * re-trigger the synth's EG */
								serialcv_voltage(IDLE_VOLTS);
								note_update = 1;
							}
							break;
						case SND_SEQ_EVENT_NOTEOFF:
							if(ev->data.note.note == note){
								note = -1;
								note_update = 1;
							}
							break;
					}
				}
				snd_seq_free_event(ev);
			}while(snd_seq_event_input_pending(seqhandle, 0));
		}
	}
	serialcv_shutdown();
	alsa_shutdown(seqhandle);
	free(pfd);
	return 0;
}