示例#1
0
文件: midibus.cpp 项目: vext01/seq24
void
midibus::continue_from( long a_tick )
{
    /* tell the device that we are going to start at a certain position */
    long pp16th = (c_ppqn / 4);

    long leftover = ( a_tick % pp16th );
    long beats = ( a_tick / pp16th );

    long starting_tick = a_tick - leftover;

    /* was there anything left?, then wait for next beat (16th note) to start clocking */
    if ( leftover > 0)
    {
        starting_tick += pp16th;
    }
    //printf ( "continue_from leftover[%ld] starting_tick[%ld]\n", leftover, starting_tick );

    m_lasttick = starting_tick - 1;    

    if ( m_clock_type != e_clock_off )
    {
        //printf( "control value %ld\n",  beats);

        snd_seq_event_t evc;
        snd_seq_event_t ev;

        ev.type = SND_SEQ_EVENT_CONTINUE;
        evc.type = SND_SEQ_EVENT_SONGPOS;
        evc.data.control.value = beats;
        snd_seq_ev_set_fixed( &ev );    
        snd_seq_ev_set_fixed( &evc );

        snd_seq_ev_set_priority( &ev, 1 );
        snd_seq_ev_set_priority( &evc, 1 );

        /* set source */
        snd_seq_ev_set_source(&evc, m_local_addr_port );
        snd_seq_ev_set_subs(&evc);
        snd_seq_ev_set_source(&ev, m_local_addr_port );
        snd_seq_ev_set_subs(&ev);

        // its immediate 
        snd_seq_ev_set_direct( &ev );
        snd_seq_ev_set_direct( &evc );

        /* pump it into the queue */
        snd_seq_event_output(m_seq, &evc);
        flush();
        snd_seq_event_output(m_seq, &ev);
    }
}
示例#2
0
文件: midibus.cpp 项目: vext01/seq24
void 
midibus::stop()
{

    m_lasttick = -1;

    if ( m_clock_type != e_clock_off ){   
	
	snd_seq_event_t ev;
	
	ev.type = SND_SEQ_EVENT_STOP;
	snd_seq_ev_set_fixed( &ev );
	
	snd_seq_ev_set_priority( &ev, 1 );
	
	/* set source */
	snd_seq_ev_set_source(&ev, m_local_addr_port );
	snd_seq_ev_set_subs(&ev);
	
	// its immediate 
	snd_seq_ev_set_direct( &ev );
	
	/* pump it into the queue */
	snd_seq_event_output(m_seq, &ev);
	
    }
}
示例#3
0
void
midibus::clock (midipulse tick)
{
#ifdef SEQ64_HAVE_LIBASOUND
    automutex locker(m_mutex);
    if (m_clock_type != e_clock_off)
    {
        bool done = m_lasttick >= tick;
        int ct = clock_ticks_from_ppqn(m_ppqn);         /* ppqn / 24    */
        while (! done)
        {
            ++m_lasttick;
            done = m_lasttick >= tick;
            if ((m_lasttick % ct) == 0)                 /* tick time?           */
            {
                /*
                 * Set the event tag to 127 so the sequences won't remove it.
                 */

                snd_seq_event_t ev;
                ev.type = SND_SEQ_EVENT_CLOCK;
                ev.tag = 127;
                snd_seq_ev_set_fixed(&ev);
                snd_seq_ev_set_priority(&ev, 1);
                snd_seq_ev_set_source(&ev, m_local_addr_port); /* set source    */
                snd_seq_ev_set_subs(&ev);
                snd_seq_ev_set_direct(&ev);             /* it's immediate       */
                snd_seq_event_output(m_seq, &ev);       /* pump it into queue   */
            }
        }
        flush();            /* and send out */
    }
#endif  // SEQ64_HAVE_LIBASOUND
}
示例#4
0
	// Decoder.
	bool dequeue ( snd_seq_event_t *ev )
	{
		qxgeditMidiRpn::Event event;

		if (!qxgeditMidiRpn::dequeue(event))
			return false;

		snd_seq_ev_clear(ev);
		snd_seq_ev_schedule_tick(ev, 0, 0, event.time);
		snd_seq_ev_set_dest(ev, 0, event.port);
		snd_seq_ev_set_fixed(ev);

		switch (qxgeditMidiRpn::Type(event.status & 0x70)) {
		case qxgeditMidiRpn::CC:	// 0x10
			ev->type = SND_SEQ_EVENT_CONTROLLER;
			break;
		case qxgeditMidiRpn::RPN:	// 0x20
			ev->type = SND_SEQ_EVENT_REGPARAM;
			break;
		case qxgeditMidiRpn::NRPN:	// 0x30
			ev->type = SND_SEQ_EVENT_NONREGPARAM;
			break;
		case qxgeditMidiRpn::CC14:	// 0x40
			ev->type = SND_SEQ_EVENT_CONTROL14;
			break;
		default:
			return false;
		}

		ev->data.control.channel = event.status & 0x0f;
		ev->data.control.param   = event.param;
		ev->data.control.value   = event.value;

		return true;
	}
示例#5
0
void
midibus::continue_from (midipulse tick)
{
#ifdef SEQ64_HAVE_LIBASOUND

    /*
     * Tell the device that we are going to start at a certain position.
     */

    midipulse pp16th = m_ppqn / 4;
    midipulse leftover = tick % pp16th;
    long beats = tick / pp16th;
    midipulse starting_tick = tick - leftover;

    /*
     * Was there anything left? Then wait for next beat (16th note) to
     * start clocking.
     */

    if (leftover > 0)
        starting_tick += pp16th;

    m_lasttick = starting_tick - 1;
    if (m_clock_type != e_clock_off)
    {
        snd_seq_event_t ev;
        ev.type = SND_SEQ_EVENT_CONTINUE;

        snd_seq_event_t evc;
        evc.type = SND_SEQ_EVENT_SONGPOS;
        evc.data.control.value = beats;
        snd_seq_ev_set_fixed(&ev);
        snd_seq_ev_set_fixed(&evc);
        snd_seq_ev_set_priority(&ev, 1);
        snd_seq_ev_set_priority(&evc, 1);
        snd_seq_ev_set_source(&evc, m_local_addr_port); /* set the source   */
        snd_seq_ev_set_subs(&evc);
        snd_seq_ev_set_source(&ev, m_local_addr_port);
        snd_seq_ev_set_subs(&ev);
        snd_seq_ev_set_direct(&ev);                     /* it's immediate   */
        snd_seq_ev_set_direct(&evc);
        snd_seq_event_output(m_seq, &evc);              /* pump into queue  */
        flush();
        snd_seq_event_output(m_seq, &ev);
    }
#endif  // SEQ64_HAVE_LIBASOUND
}
示例#6
0
文件: midibus.cpp 项目: vext01/seq24
// generates midi clock
void
midibus::clock( long a_tick )
{

    lock();

    if ( m_clock_type != e_clock_off ){

	bool done = false;
	
	long uptotick = a_tick;
	
	if ( m_lasttick >= uptotick )
	    done = true;
	
	while ( !done ){
	    
	    m_lasttick++;
	    
	    if ( m_lasttick >= uptotick )
		done = true;
	    
	    /* tick time? */
	    if ( m_lasttick % ( c_ppqn / 24 ) == 0 ){
		
		snd_seq_event_t ev;
		
		ev.type = SND_SEQ_EVENT_CLOCK;
		
		/* set tag to 127 so the sequences
		   wont remove it */
		ev.tag = 127;
		
		snd_seq_ev_set_fixed( &ev );
		
		snd_seq_ev_set_priority( &ev, 1 );
		
		/* set source */
		snd_seq_ev_set_source(&ev, m_local_addr_port );
		snd_seq_ev_set_subs(&ev);
		
		// its immediate 
		snd_seq_ev_set_direct( &ev );
		
		/* pump it into the queue */
		snd_seq_event_output(m_seq, &ev);

	    }
	}
	/* and send out */
	flush();
    }

    unlock();
}
示例#7
0
//  FUNCTIONS
void JVlibForm::send_data(char * buf,int data_size) {
    snd_seq_event_t ev;
    snd_seq_ev_clear(&ev);
    snd_seq_ev_set_direct(&ev);
    ev.queue = SND_SEQ_QUEUE_DIRECT;
    ev.type = SND_SEQ_EVENT_CONTROLLER;
    ev.dest = ports[0];
    ev.data.control.channel = buf[0];
    if (data_size>1)
      ev.data.control.param = buf[1];
    if (data_size==3)
      ev.data.control.value = buf[2];
    snd_seq_ev_set_fixed(&ev);
    snd_seq_ev_set_direct(&ev);
    snd_seq_event_output_direct(seq, &ev);
    snd_seq_drain_output(seq);
}   // end send_data
示例#8
0
void
midibus::stop ()
{
#ifdef SEQ64_HAVE_LIBASOUND
    m_lasttick = -1;
    if (m_clock_type != e_clock_off)
    {
        snd_seq_event_t ev;
        ev.type = SND_SEQ_EVENT_STOP;
        snd_seq_ev_set_fixed(&ev);
        snd_seq_ev_set_priority(&ev, 1);
        snd_seq_ev_set_source(&ev, m_local_addr_port);  /* set the source   */
        snd_seq_ev_set_subs(&ev);
        snd_seq_ev_set_direct(&ev);                     /* it's immediate   */
        snd_seq_event_output(m_seq, &ev);               /* pump into queue  */
    }
#endif  // SEQ64_HAVE_LIBASOUND
}
示例#9
0
int send_note(int port, int on, int ch, int note, int vel)
{
	snd_seq_event_t ev;
	snd_seq_ev_clear(&ev);
	ev.dest.client = SND_SEQ_ADDRESS_SUBSCRIBERS;
	ev.source.client = snd_seq_client_id(handle);
	ev.source.port = port;
	snd_seq_ev_set_direct(&ev);

	ev.type = on ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF;
	snd_seq_ev_set_fixed(&ev);
	ev.data.note.channel  = ch;
	ev.data.note.note     = note;
	ev.data.note.velocity = vel;

	snd_seq_event_output(handle, &ev);
	snd_seq_drain_output(handle);
	return 1;
}
示例#10
0
void
midibus::clock (long a_tick)
{
#ifdef HAVE_LIBASOUND
    automutex locker(m_mutex);
    if (m_clock_type != e_clock_off)
    {
        bool done = false;
        if (m_lasttick >= a_tick)
            done = true;

        while (!done)
        {
            m_lasttick++;
            if (m_lasttick >= a_tick)
                done = true;

            if (m_lasttick % (c_ppqn / 24) == 0)        /* tick time? */
            {
                /*
                 * Set the event tag to 127 so the sequences won't remove it.
                 */

                snd_seq_event_t ev;
                ev.type = SND_SEQ_EVENT_CLOCK;
                ev.tag = 127;
                snd_seq_ev_set_fixed(&ev);
                snd_seq_ev_set_priority(&ev, 1);
                snd_seq_ev_set_source(&ev, m_local_addr_port); /* set source */
                snd_seq_ev_set_subs(&ev);
                snd_seq_ev_set_direct(&ev);                 /* it's immediate */
                snd_seq_event_output(m_seq, &ev);       /* pump it into queue */
            }
        }
        flush();            /* and send out */
    }
#endif  // HAVE_LIBASOUND
}
示例#11
0
文件: midi.c 项目: kazutomi/xiphqt
int midi_eventout(midi_info_t *mi, snd_seq_event_t *ev)
{
	int64_t stamp, length;
	int status, data;
	int tempo;
	int err;
	void *buf;

	if (_data_left(mi) == 0) return EDATA;

	snd_seq_ev_clear(ev);
	snd_seq_ev_set_fixed(ev);
	// We know at this point that the entire event
	// is within the packet, since it's illegal
	// to span packet boundries for events.
	// this makes our lives _so_ much easier.

	stamp = _read_var_value(mi);
	if (stamp < 0) return EEVENT;
	mi->time += stamp;
	snd_seq_ev_schedule_tick(ev, mi->q, 0, mi->time);

	status = _read_byte(mi);
	if (status < 0) return EEVENT;

	switch (status & 0xF0) {
	case 0x80:
		ev->type = SND_SEQ_EVENT_NOTEOFF;
		ev->data.note.channel = status & 0x0F;
		data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.note.note = data & 0x7F;
		data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.note.velocity = data & 0x7F;
		break;
	case 0x90:
		ev->type = SND_SEQ_EVENT_NOTEON;
		ev->data.note.channel = status & 0x0F;
		data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.note.note = data & 0x7F;
		data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.note.velocity = data & 0x7F;
		break;
	case 0xA0:
		ev->type = SND_SEQ_EVENT_KEYPRESS;
		ev->data.note.channel = status & 0x0F;
		data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.note.note = data & 0x7F;
		data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.note.velocity = data & 0x7F;
		break;
	case 0xB0:
		ev->type = SND_SEQ_EVENT_CONTROLLER;
		ev->data.control.channel = status & 0x0F;
		data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.control.param = data & 0x7F;
	        data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.control.value = data & 0x7F;
		break;
	case 0xC0:
		ev->type = SND_SEQ_EVENT_PGMCHANGE;
		ev->data.control.channel = status & 0x0F;
		data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.control.value = data & 0x7F;
		break;
	case 0xD0:
		ev->type = SND_SEQ_EVENT_CHANPRESS;
		ev->data.control.channel = status & 0x0F;
		data = _read_byte(mi);
		if (data < 0 ) return EEVENT;
		ev->data.control.value = data & 0x7F;
		break;
	case 0xE0:
		ev->type = SND_SEQ_EVENT_PITCHBEND;
		ev->data.control.channel = status & 0x0F;
		data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.control.param = data & 0x7F;
		data = _read_byte(mi);
		if (data < 0) return EEVENT;
		ev->data.control.value = data & 0x7F;
		break;
	case 0xF0:
		// these events are special
		// we should not send only the tempo changes
		// and sysex events
		switch (status & 0xFF) {
		case 0xF0:
			ev->type = SND_SEQ_EVENT_SYSEX;
			length = _read_var_value(mi);
			if (length < 1) return EEVENT;
			if (_data_left(mi) < length) return EEVENT;
			ev->data.ext.len = length;
		        buf = (void *)malloc(length);
			if (buf == NULL) return EMALLOC;
			memcpy(buf, &mi->data[mi->pos], length);
			snd_seq_ev_set_variable(ev, length, buf);
			mi->pos += length;
			break;
		case 0xFF:
			data = _read_byte(mi);
			if (data < 0) return EEVENT;

			if (data == 0x51) {
				length = _read_var_value(mi);
				if (length != 3) return EEVENT;
				if (_data_left(mi) < length) return EEVENT;
				ev->type = SND_SEQ_EVENT_TEMPO;
				ev->data.queue.queue = mi->q;
				ev->data.queue.param.value = (mi->data[mi->pos] << 16) | (mi->data[mi->pos+1] << 8) | (mi->data[mi->pos+2]);
				mi->pos += length;
			} else {
				snd_seq_ev_clear(ev);
				// skip this event
				length = _read_var_value(mi);
				if (length < 0) return EEVENT;
				if (_data_left(mi) < length) return EEVENT;
				mi->pos += length;
			}
			break;
		default:
			return EEVENT;
		}
		break;
	default:
		return EEVENT;
	}


	return 0;
}
示例#12
0
void sys_alsa_putmidimess(int portno, int a, int b, int c)
{
    if (portno >= 0 && portno < alsa_nmidiout)
    {
        snd_seq_event_t ev;
        snd_seq_ev_clear(&ev);
        int status = a & 0xf0;
        int channel = a & 0x0f;
        status = (status >= MIDI_SYSEX) ? status : (status & 0xf0);
        switch (status)
        {
            case MIDI_NOTEON:
                snd_seq_ev_set_noteon(&ev, channel, b, c);
                break;
            case MIDI_NOTEOFF:
                snd_seq_ev_set_noteoff(&ev, channel, b, c);
                break;
            case MIDI_POLYAFTERTOUCH:
                snd_seq_ev_set_chanpress(&ev, channel, b);
                break;
            case MIDI_CONTROLCHANGE:
                snd_seq_ev_set_controller(&ev, channel, b, c);
                break;
            case MIDI_PROGRAMCHANGE:
                snd_seq_ev_set_pgmchange(&ev, channel, b);
                break;
            case MIDI_AFTERTOUCH:
                snd_seq_ev_set_chanpress(&ev, channel, b);
                break;
            case MIDI_PITCHBEND:
                /* b and c are already correct but alsa needs to recalculate them */
                snd_seq_ev_set_pitchbend(&ev, channel, (((c<<7)|b)-8192));
                break;
            case MIDI_TIMECODE:
                ev.type = SND_SEQ_EVENT_QFRAME;
                snd_seq_ev_set_fixed(&ev);
                ev.data.raw8.d[0] = a & 0xff; /* status */
                ev.data.raw8.d[1] = b & 0x7f; /* data */
                break;
            case MIDI_SONGPOS:
                ev.type = SND_SEQ_EVENT_SONGPOS;
                snd_seq_ev_set_fixed(&ev);
                ev.data.raw8.d[0] = a & 0xff; /* status */
                ev.data.raw8.d[1] = b & 0x7f; /* data */
                ev.data.raw8.d[2] = c & 0x7f; /* data */
                break;
            case MIDI_SONGSELECT:
                ev.type = SND_SEQ_EVENT_SONGSEL;
                snd_seq_ev_set_fixed(&ev);
                ev.data.raw8.d[0] = a & 0xff; /* status */
                ev.data.raw8.d[1] = b & 0x7f; /* data */
                break;
            default:
                bug("couldn't put alsa midi message");
                break;
        }
        snd_seq_ev_set_direct(&ev);
        snd_seq_ev_set_subs(&ev);
        snd_seq_ev_set_source(&ev, alsa_midioutfd[portno]);
        snd_seq_event_output_direct(midi_handle, &ev);
    }
    //post("%d %d %d\n", a, b, c);
}
示例#13
0
void MIDI_PLAYER::play_midi(unsigned int startTick) {
    int end_delay = 2;
    int err;
    // set data in (snd_seq_event_t ev) and output the event
    // common settings for all events
    snd_seq_event_t ev;
    snd_seq_ev_clear(&ev);
    ev.queue = queue;
    ev.source.port = 0;
    ev.flags = SND_SEQ_TIME_STAMP_TICK;
    // parse each event, already in sort order by 'tick' from parse_file
    for (std::vector<event>::iterator Event=all_events.begin(); Event!=all_events.end(); ++Event)  {
        // skip over everything except TEMPO, CONTROLLER, PROGRAM, ChannelPressure and SysEx changes until startTick is reached.
        if (Event->tick<startTick &&
            (Event->type!=SND_SEQ_EVENT_TEMPO ||
             Event->type!=SND_SEQ_EVENT_CONTROLLER ||
             Event->type!=SND_SEQ_EVENT_PGMCHANGE ||
             Event->type!=SND_SEQ_EVENT_CHANPRESS ||
             Event->type!=SND_SEQ_EVENT_SYSEX))
	{
            continue;
	}
        ev.time.tick = Event->tick;
        ev.type = Event->type;
//        ev.dest = ports[Event->port];
        ev.dest = ports[0];
        switch (ev.type) {
        case SND_SEQ_EVENT_NOTEON:
        case SND_SEQ_EVENT_NOTEOFF:
        case SND_SEQ_EVENT_KEYPRESS:
            snd_seq_ev_set_fixed(&ev);
            ev.data.note.channel = Event->data.d[0];
            ev.data.note.note = Event->data.d[1];
            ev.data.note.velocity = Event->data.d[2];
            break;
        case SND_SEQ_EVENT_CONTROLLER:
            snd_seq_ev_set_fixed(&ev);
            ev.data.control.channel = Event->data.d[0];
            ev.data.control.param = Event->data.d[1];
            ev.data.control.value = Event->data.d[2];
            break;
        case SND_SEQ_EVENT_PGMCHANGE:
        case SND_SEQ_EVENT_CHANPRESS:
            snd_seq_ev_set_fixed(&ev);
            ev.data.control.channel = Event->data.d[0];
            ev.data.control.value = Event->data.d[1];
            break;
        case SND_SEQ_EVENT_PITCHBEND:
            snd_seq_ev_set_fixed(&ev);
            ev.data.control.channel = Event->data.d[0];
            ev.data.control.value =
                ((Event->data.d[1]) |
                 ((Event->data.d[2]) << 7)) - 0x2000;
            break;
        case SND_SEQ_EVENT_SYSEX:
            snd_seq_ev_set_variable(&ev, Event->data.length, &Event->sysex);
            break;
        case SND_SEQ_EVENT_TEMPO:
            snd_seq_ev_set_fixed(&ev);
            ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
            ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
            ev.data.queue.queue = queue;
            ev.data.queue.param.value = Event->data.tempo;
            break;
        default:
            QMessageBox::critical(this, "MIDI Player", QString("Invalid event type %1") .arg(ev.type));
        }   // end SWITCH ev.type
        // do the actual output of the event to the MIDI queue
        // this blocks when the output pool has been filled
        err = snd_seq_event_output(seq, &ev);
        check_snd("output event", err);
    }	// end for all_events iterator

    // schedule queue stop at end of song
    snd_seq_ev_set_fixed(&ev);
    ev.type = SND_SEQ_EVENT_STOP;
    ev.time.tick = all_events.back().tick;
    ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
    ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
    ev.data.queue.queue = queue;
    err = snd_seq_event_output(seq, &ev);
    check_snd("output event", err);
    // make sure that the sequencer sees all our events
    err = snd_seq_drain_output(seq);
    check_snd("drain output", err);

    // There are three possibilities for how to wait until all events have been played:
    // 1) send an event back to us (like pmidi does), and wait for it;
    // 2) wait for the EVENT_STOP notification for our queue which is sent
    //    by the system timer port (this would require a subscription);
    // 3) wait until the output pool is empty.
    // The last is the simplest.
    err = snd_seq_sync_output_queue(seq);
    check_snd("sync output", err);
    // give the last notes time to die away
    if (end_delay > 0)
        sleep(end_delay);
}   // end play_midi