コード例 #1
0
ファイル: MIDIController.cpp プロジェクト: cslr/resonanz
void MIDIController::poll_loop()
{
	int update_freq = 5; // 5 Hz (200ms)

	std::vector<float> x;

	while(keep_polling){
		microsleep(1000/update_freq);

		if(source.data(x) == false) continue;

		unsigned int d = 8;
		if(x.size() < d) d = x.size();
		unsigned int m = 0;

		for(unsigned int i=0;i<d;i++){
			if(mute[i]) continue; // don't send this controller's value

			int v = (int)(127*x[i]);
			if(v > 127) v = 127;
			else if(v < 0) v = 0;

			if(i < 4){
				// controller values [0x10-0x13]: 0-127
				unsigned int cc = (0x10 + i);
				event[m].message = Pm_Message((0xB0+channel), cc, ((unsigned int)v));
				event[m].timestamp = 0;
				m++;
			}
			else{
				// controller values [0x50-0x53]: 0-127
				unsigned int cc = (0x50+(i-4));
				event[m].message = Pm_Message((0xB0+channel), cc, ((unsigned int)v));
				event[m].timestamp = 0;
				m++;
			}
		}


		if(m > 0){
			pthread_mutex_lock(&portmidi_lock);

			if(Pm_Write(midi, event, m) == pmNoError){
				sending_data = true;
			}
			else{
				sending_data = false;
			}

			pthread_mutex_unlock(&portmidi_lock);
		}
		else{
			sending_data = false;
		}

	}
}
コード例 #2
0
ファイル: latency.c プロジェクト: gillspice/mios32
/* callback function for PortTime -- computes histogram */
void pt_callback(PtTimestamp timestamp, void *userData)
{
    PtTimestamp difference = timestamp - previous_callback_time - period;
    previous_callback_time = timestamp;

    /* allow 5 seconds for the system to settle down */
    if (timestamp < 5000) return;

    iteration++;
    /* send a note on/off if user requested it */
    if (test_out && (iteration % output_period == 0)) {
        PmEvent buffer[1];
        buffer[0].timestamp = Pt_Time(NULL);
        if (note_on) {
            /* note off */
            buffer[0].message = Pm_Message(0x90, 60, 0);
            note_on = 0;
        } else {
            /* note on */
            buffer[0].message = Pm_Message(0x90, 60, 100);
            note_on = 1;
        }
        Pm_Write(out, buffer, 1);
        iteration = 0;
    }

    /* read all waiting events (if user requested) */
    if (test_in) {
       PmError status;
       PmEvent buffer[1];
       do {
          status = Pm_Poll(in);
          if (status == TRUE) {
              Pm_Read(in,buffer,1);
          }
       } while (status == TRUE);
    }

    if (difference < 0) return; /* ignore when system is "catching up" */

    /* update the histogram */
    if (difference < HIST_LEN) {
        histogram[difference]++;
    } else {
        out_of_range++;
    }

    if (max_latency < difference) max_latency = difference;
}
コード例 #3
0
ファイル: pmidi.c プロジェクト: hlolli/csound
static int WriteMidiData_(CSOUND *csound, void *userData,
                          const unsigned char *mbuf, int nbytes)
{
    int             n, st;
    PmEvent         mev;
    PortMidiStream  *midistream;
    /*
     * Writes to user-defined MIDI output.
     */
    midistream = (PortMidiStream*) userData;
    if (UNLIKELY(nbytes < 1))
      return 0;
    n = 0;
    do {
      //int time = csound->GetCurrentTimeSamples(csound)/csound->GetSr(csound);
      //printf("jitter: %d \n",
      //       Pt_Time(NULL) - (int)(1000*time/csound->GetSr(csound)));
      st = (int)*(mbuf++);
      if (UNLIKELY(st < 0x80)) {
        portMidiErrMsg(csound, Str("invalid MIDI out data"));
        break;
      }
      if (UNLIKELY(st >= 0xF0 && st < 0xF8)) {
        portMidiErrMsg(csound,
                       Str("MIDI out: system message 0x%02X is not supported"),
                       (unsigned int) st);
        break;
      }
      nbytes -= (datbyts[(st - 0x80) >> 4] + 1);
      if (UNLIKELY(nbytes < 0)) {
        portMidiErrMsg(csound, Str("MIDI out: truncated message"));
        break;
      }
      mev.message = (PmMessage) 0;
      mev.timestamp = (PmTimestamp) 0;
      mev.message |= (PmMessage) Pm_Message(st, 0, 0);
      if (datbyts[(st - 0x80) >> 4] > 0)
        mev.message |= (PmMessage) Pm_Message(0, (int)*(mbuf++), 0);
      if (datbyts[(st - 0x80) >> 4] > 1)
        mev.message |= (PmMessage) Pm_Message(0, 0, (int)*(mbuf++));
      if (UNLIKELY(Pm_Write(midistream, &mev, 1L) != pmNoError))
        portMidiErrMsg(csound, Str("MIDI out: error writing message"));
      else {
        n += (datbyts[(st - 0x80) >> 4] + 1);
      }
    } while (nbytes > 0);
    /* return the number of bytes written */
    return n;
}
コード例 #4
0
ファイル: NoteTrack.cpp プロジェクト: dannyflax/audacity
void SonifyNoteOnOff(int p, int v)
{
   if (!sonificationStarted)
      SonifyBeginSonification();
   if (sonMidiStream)
      Pm_WriteShort(sonMidiStream, 0, Pm_Message(0x90, p, v));
}
コード例 #5
0
ファイル: midiOut.c プロジェクト: JmauLeonetti/eegsynth
void sendNoteOnOff(int status, const mxArray *prhs[]) {
  int n,N;
  const double *note, *vel;
  int channel = (int) mxGetScalar(prhs[1]);
  
  if (channel < 1 || channel > 16) mexErrMsgTxt("Channel (2nd arg.) must be 1..16");
  --channel;
  
  if (!mxIsDouble(prhs[2]) || !mxIsDouble(prhs[3])) {
    mexErrMsgTxt("3rd and 4th arguments (note number and velocity) must be 'double' arrays");
  }
  N = mxGetNumberOfElements(prhs[2]);
  if (N != mxGetNumberOfElements(prhs[3])) {
    mexErrMsgTxt("3rd and 4th arguments (note number and velocity) must have same number of elements");
  }
  note = mxGetPr(prhs[2]);
  vel = mxGetPr(prhs[3]);
  
  status = (status & 0xF0) | channel;
  
  for (n=0;n<N;n++) {
    PmMessage msg;
    PmError err;
    
    msg = Pm_Message(status, (int) note[n], (int) vel[n]);
    /* latency=0 => send asap */
    err = Pm_WriteShort(outStream, 0, msg);
    if (err!=pmNoError) reportPmError(err);
  }
}
コード例 #6
0
ファイル: midibus_portmidi.cpp プロジェクト: EQ4/seq42
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 )
    {

        PmEvent event;
        event.timestamp = 0;
        event.message = Pm_Message( EVENT_MIDI_CONTINUE, 0,0 );
        Pm_Write( m_pms, &event, 1 );
        event.message = Pm_Message( EVENT_MIDI_SONG_POS, (beats & 0x3F80 >> 7), (beats & 0x7F) );
        Pm_Write( m_pms, &event, 1 );
    }
コード例 #7
0
void TestPmEventParser::programChange()
{
  uint8_t input[] = {
    0xc0, 0x7f, /* Program Change */
    0xc1, 0x01, /* Program Change */
  };
  PmEventParser parser;
  PmEvent event;

  parser.feed(input, sizeof(input));

  QVERIFY(parser.next(&event));
  QVERIFY(event.message == Pm_Message(0xc0, 0x7f, 0x00));
  QVERIFY(parser.next(&event));
  QVERIFY(event.message == Pm_Message(0xc1, 0x01, 0x00));
  QVERIFY(!parser.next(&event));
}
コード例 #8
0
ファイル: md_portmidi.c プロジェクト: Rotbaeckchen/pyo
void
pm_pressout(Server *self, int value, int chan, long timestamp)
{
    int i, curtime;
    PmEvent buffer[1];

    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;

    curtime = Pt_Time();
    buffer[0].timestamp = curtime + timestamp;
    if (chan == 0)
        buffer[0].message = Pm_Message(0xD0, value, 0);
    else
        buffer[0].message = Pm_Message(0xD0 | (chan - 1), value, 0);
    for (i=0; i<self->midiout_count; i++) {
        Pm_Write(be_data->midiout[i], buffer, 1);
    }
}
コード例 #9
0
/*!
 @function midi_note
 @abstract
 @discussion
 @param
 @result
 */
void midi_note(int pitch, int channel, int velocity)
{
    int channel1,  velocity1;

    channel1 = 1 + (channel % 16);
    velocity1 = velocity % 128;

    Pm_WriteShort(mstream, 0, Pm_Message(SBYTE(MD_NOTEON,channel1), pitch, velocity1));
}
コード例 #10
0
ファイル: NoteTrack.cpp プロジェクト: dannyflax/audacity
void SonifyBeginSonification()
{
   PmError err = Pm_OpenOutput(&sonMidiStream, Pm_GetDefaultOutputDeviceID(),
                               NULL, 0, NULL, NULL, 0);
   if (err) sonMidiStream = NULL;
   if (sonMidiStream)
      Pm_WriteShort(sonMidiStream, 0, Pm_Message(0xC0, SON_PROGRAM, 0));
   sonificationStarted = true;
}
コード例 #11
0
/*!
 @function program_change
 @abstract
 @discussion
 @param
 @result
 */
void program_change(int channel, int instrument)
{
    int channel1, instrument1;

    instrument1 = 1+ (instrument % 128);
    channel1 = 1 + (channel % 16);

    Pm_WriteShort(mstream, 0, Pm_Message(SBYTE(MD_PRG,channel1), instrument1, 0));
}
コード例 #12
0
ファイル: md_portmidi.c プロジェクト: Rotbaeckchen/pyo
void
pm_bendout(Server *self, int value, int chan, long timestamp)
{
    int i, lsb, msb, curtime;
    PmEvent buffer[1];

    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;

    curtime = Pt_Time();
    buffer[0].timestamp = curtime + timestamp;
    lsb = value & 0x007F;
    msb = (value & (0x007F << 7)) >> 7;
    if (chan == 0)
        buffer[0].message = Pm_Message(0xE0, lsb, msb);
    else
        buffer[0].message = Pm_Message(0xE0 | (chan - 1), lsb, msb);
    for (i=0; i<self->midiout_count; i++) {
        Pm_Write(be_data->midiout[i], buffer, 1);
    }
}
コード例 #13
0
ファイル: portmidi_out.c プロジェクト: lucidstack/ex-portmidi
static ERL_NIF_TERM do_write(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
  static PortMidiStream ** stream;

  ErlNifResourceType* streamType = (ErlNifResourceType*)enif_priv_data(env);
  if(!enif_get_resource(env, argv[0], streamType, (PortMidiStream **) &stream)) {
    return enif_make_badarg(env);
  }

  ERL_NIF_TERM erlMessages = argv[1];
  const ERL_NIF_TERM * erlEvent;
  const ERL_NIF_TERM * erlMessage;
  ERL_NIF_TERM erlTuple;

  unsigned int numOfMessages;
  int tupleSize;
  enif_get_list_length(env, erlMessages, &numOfMessages);

  PmEvent events[numOfMessages];
  long int status, note, velocity, timestamp;

  for(unsigned int i = 0; i < numOfMessages; i++) {
    enif_get_list_cell(env, erlMessages, &erlTuple, &erlMessages);
    enif_get_tuple(env, erlTuple, &tupleSize, &erlEvent);

    enif_get_tuple(env, erlEvent[0], &tupleSize, &erlMessage);
    enif_get_long(env, erlMessage[0], &status);
    enif_get_long(env, erlMessage[1], &note);
    enif_get_long(env, erlMessage[2], &velocity);

    enif_get_long(env, erlEvent[1], &timestamp);

    PmEvent event;
    event.message = Pm_Message(status, note, velocity);
    event.timestamp = timestamp;

    events[i] = event;
  }

  PmError writeError;
  writeError = Pm_Write(*stream, events, numOfMessages);

  if (writeError == pmNoError) {
    return enif_make_atom(env, "ok");
  }

  const char * writeErrorMsg;
  writeErrorMsg = Pm_GetErrorText(writeError);

  return enif_make_tuple2(
    env,
    enif_make_atom(env, "error"),
    enif_make_string(env, writeErrorMsg, ERL_NIF_LATIN1)
  );
}
コード例 #14
0
ファイル: s_midi_pm.c プロジェクト: umnum/pd-extended
void sys_putmidimess(int portno, int a, int b, int c)
{
    PmEvent buffer;
    /* fprintf(stderr, "put 1 msg %d %d\n", portno, mac_nmidioutdev); */
    if (portno >= 0 && portno < mac_nmidioutdev)
    {
        buffer.message = Pm_Message(a, b, c);
        buffer.timestamp = 0;
        /* fprintf(stderr, "put msg\n"); */
        Pm_Write(mac_midioutdevlist[portno], &buffer, 1);
    }
}
コード例 #15
0
int main (void)
{
    midi_init();

    // Play a chord
    midi_write(Pm_Message(0x90, 60, 100));
    midi_write(Pm_Message(0x90, 64, 100));
    midi_write(Pm_Message(0x90, 67, 100));
    midi_flush();
    
    printf("num_devices: %i\n",Pm_CountDevices());
    PmDeviceID id = Pm_GetDefaultOutputDeviceID();
    const PmDeviceInfo* device = Pm_GetDeviceInfo(id);
    printf("%s\n", device->name);
    
    
    char setchar = '.';
	int channel = 0;
	while (setchar!='\e'){
		scanf(" %c", &setchar);
		//printf("%c\n", setchar);
		switch (setchar){
			case 'z': channel = 0xB0; break;
			case 'x': channel = 0xB1; break;
			case 'c': channel = 0xB2; break;
			case 'v': channel = 0xB3; break;
                // 'q': Pm_WriteShort(midi, 0, Pm_Message(channel, 10, 0)); //button1
                // 'w': Pm_WriteShort(midi, 0, Pm_Message(channel, 11, 0)); //button2
                // 'e': Pm_WriteShort(midi, 0, Pm_Message(channel, 12, 0)); //button3
                // 'r': Pm_WriteShort(midi, 0, Pm_Message(channel, 13, 0)); //button4
			case '1': midi_write(Pm_Message(channel, 0, 0)); midi_flush(); break;
			case '2': midi_write(Pm_Message(channel, 1, 0)); midi_flush(); break;//hand angle
                // '7': Pm_WriteShort(midi, 0, Pm_Message(channel, 7, 0));
                // '8': Pm_WriteShort(midi, 0, Pm_Message(channel, 8, 0));
                // '9': Pm_WriteShort(midi, 0, Pm_Message(channel, 9, 0));
                // '0': Pm_WriteShort(midi, 0, Pm_Message(channel, 10, 0));
			default:
                break;
		}
	}
コード例 #16
0
ファイル: keyboard.c プロジェクト: glocklueng/midiDmxCtrlv2
int keyboard_send(MidiObj* m,uint8_t a,uint8_t b , uint8_t c) {

	if(!m->midi_stream_out) return 0;

	static PmEvent events[KEYBOARD_MAX_EVENTS];

	events[0].timestamp =  0;
	events[0].message = Pm_Message( a,b,c );

	int i = Pm_Write(m->midi_stream_out, events, 1);

	return i;
}
コード例 #17
0
void TestPmEventParser::noteOnOff()
{
  uint8_t input[] = {
    0x90, 0x40, 0x7f, /* Note On */
    0x90, 0x41, 0x32, /* Note On */
    0x80, 0x40, 0x7f, /* Note Off */
    0x80, 0x41, 0x32, /* Note Off */
  };
  PmEventParser parser;
  PmEvent event;

  parser.feed(input, sizeof(input));

  QVERIFY(parser.next(&event));
  QVERIFY(event.message == Pm_Message(0x90, 0x40, 0x7f));
  QVERIFY(parser.next(&event));
  QVERIFY(event.message == Pm_Message(0x90, 0x41, 0x32));
  QVERIFY(parser.next(&event));
  QVERIFY(event.message == Pm_Message(0x80, 0x40, 0x7f));
  QVERIFY(parser.next(&event));
  QVERIFY(event.message == Pm_Message(0x80, 0x41, 0x32));
  QVERIFY(!parser.next(&event));
}
コード例 #18
0
ファイル: hreducevel.c プロジェクト: GregorR/humidity
int main(int argc, char **argv)
{
    FILE *f;
    PmError perr;
    MfFile *pf;
    int ti;
    MfTrack *track;
    MfEvent *cur;
    int redux;

    if (argc < 4) {
        fprintf(stderr, "Use: hreducevel <file> <output file> <range reduction>\n");
        return 1;
    }
    redux = atoi(argv[3]);

    PSF(perr, Mf_Initialize, ());

    /* open it for input */
    SF(f, fopen, NULL, (argv[1], "rb"));

    /* and read it */
    PSF(perr, Mf_ReadMidiFile, (&pf, f));
    fclose(f);

    /* redux it */
    for (ti = 0; ti < pf->trackCt; ti++) {
        track = pf->tracks[ti];
        cur = track->head;
        while (cur) {
            if (Pm_MessageType(cur->e.message) == MIDI_NOTE_ON) {
                uint8_t vel = Pm_MessageData2(cur->e.message);
                vel = 127 - (127-vel)/redux;
                cur->e.message = Pm_Message(
                    Pm_MessageStatus(cur->e.message),
                    Pm_MessageData1(cur->e.message),
                    vel);
            }
            cur = cur->next;
        }
    }

    /* write it out */
    SF(f, fopen, NULL, (argv[2], "wb"));
    PSF(perr, Mf_WriteMidiFile, (f, pf));
    fclose(f);

    return 0;
}
コード例 #19
0
ファイル: midibus_portmidi.cpp プロジェクト: EQ4/sequencer64
void
midibus::play (event * a_e24, unsigned char a_channel)
{
    automutex locker(m_mutex);
    PmEvent event;
    event.timestamp = 0;

    /* fill buffer and set midi channel */

    unsigned char buffer[3];                /* temp for midi data */
    buffer[0] = a_e24->get_status();
    buffer[0] += (a_channel & 0x0F);
    a_e24->get_data(&buffer[1], &buffer[2]);
    event.message = Pm_Message(buffer[0], buffer[1], buffer[2]);
    /*PmError err = */ Pm_Write(m_pms, &event, 1);
}
コード例 #20
0
static Scheme_Object *note_off(int argc, Scheme_Object **argv)
{
intptr_t channel,note,velocity;
PmEvent event;

  scheme_get_int_val(argv[0],&channel);
  scheme_get_int_val(argv[1],&note);
  scheme_get_int_val(argv[2],&velocity);

  event.message=Pm_Message(0x80+(unsigned char)channel,
                    (unsigned char)note,
                    (unsigned char)velocity);
  event.timestamp=0;
  midi_io.write_event(&event);

  return scheme_void;
} // note_off()
コード例 #21
0
ファイル: midiOut.c プロジェクト: JmauLeonetti/eegsynth
void playRaw(const mxArray *A) {
  int N = mxGetNumberOfElements(A);
  unsigned char * data = mxGetData(A);
  int n;
  
  PmMessage msg;
  PmError err;
  
  if (N % 3 != 0) mexErrMsgTxt("Raw arguments must be a multiple of 3 elements long.");
  
  N/=3;
  
  for (n=0;n<N;n++) {
    msg = Pm_Message(data[0], data[1], data[2]);
    err = Pm_WriteShort(outStream, 0, msg);
    if (err!=pmNoError) reportPmError(err);
    data+=3;
  }
}
コード例 #22
0
ファイル: SC_PortMIDI.cpp プロジェクト: 2mc/supercollider
/*
-------------------------------------------------------------
*/
int prSendMIDIOut(struct VMGlobals *g, int numArgsPushed)
{
	ScopeMutexLock mulo(&gPmStreamMutex);
	//port, uid, len, hiStatus, loStatus, a, b, latency
	//PyrSlot *m = g->sp - 8;
	PyrSlot *p = g->sp - 7;

	PyrSlot *u = g->sp - 6;
	PyrSlot *l = g->sp - 5;

	PyrSlot *his = g->sp - 4;
	PyrSlot *los = g->sp - 3;

	PyrSlot *a = g->sp - 2;
	PyrSlot *b = g->sp - 1;
	PyrSlot *plat = g->sp;

	int err, outputIndex, uid, length, hiStatus, loStatus, aval, bval;
	float late;
	err = slotIntVal(p, &outputIndex);
	if (err) return err;
	if (outputIndex < 0 || outputIndex >= gNumMIDIOutPorts) return errIndexOutOfRange;

	err = slotIntVal(u, &uid);
	if (err) return err;
	err = slotIntVal(l, &length);
	if (err) return err;
	err = slotIntVal(his, &hiStatus);
	if (err) return err;
	err = slotIntVal(los, &loStatus);
	if (err) return err;
	err = slotIntVal(a, &aval);
	if (err) return err;
	err = slotIntVal(b, &bval);
	if (err) return err;
	err = slotFloatVal(plat, &late);
	if (err) return err;

	Pm_WriteShort(gMIDIOutStreams[uid], 0, 
	Pm_Message((hiStatus & 0xF0) | (loStatus & 0x0F) , aval, bval));

	return errNone;
}
コード例 #23
0
ファイル: MIDIOutput.cpp プロジェクト: EQ4/JamomaCore
TTErr MIDIOutput::sendMessage(TTAddress& address, const TTValue& value)
{
    if (mRunning) {
        
        MIDIParserTo    parser;
        TTBoolean       done;
        
        // until the parsing ends
        do {
            done = parser.parse(address, value);
            int message = Pm_Message(parser.statusByte, parser.dataByte1, parser.dataByte2);
            Pm_WriteShort(mStream, 0, message);
        }
        while (!done);
        
        return kTTErrNone;
    }
    
    return kTTErrGeneric;
}
コード例 #24
0
static Scheme_Object *note_on(int argc, Scheme_Object **argv)
{
intptr_t channel,note,velocity;
PmEvent event;

  scheme_get_int_val(argv[0],&channel);
  scheme_get_int_val(argv[1],&note);
  scheme_get_int_val(argv[2],&velocity);

  /*
    #define Pm_Message(status, data1, data2) \
              ((((data2) << 16) & 0xFF0000) | \
               (((data1) << 8) & 0xFF00) | \
               ((status) & 0xFF))
  */
  event.message=Pm_Message(0x90+(int)channel,(int)note,(int)velocity);
  event.timestamp=0;
  midi_io.write_event(&event);

  return scheme_void;
} // note_on()
コード例 #25
0
ファイル: midiOut.c プロジェクト: JmauLeonetti/eegsynth
void sendProgChange(const mxArray *prhs[]) {
  int channel = (int) mxGetScalar(prhs[1]);
  int prog = (int) mxGetScalar(prhs[2]);
  int status;
  PmMessage msg;
  PmError err;
  
  if (channel < 1 || channel > 16) mexErrMsgTxt("Channel (2nd arg.) must be 1..16");
  --channel;
  
  if (!mxIsDouble(prhs[2])) {
    mexErrMsgTxt("3rd argument (program number) must be a 'double'");
  }
  
  status = 0xC0 | channel;
  
  msg = Pm_Message(status, prog-1, 0);
  /* latency=0 => send asap */
  err = Pm_WriteShort(outStream, 0, msg);
  if (err!=pmNoError) reportPmError(err);
}
コード例 #26
0
ファイル: midifstream.c プロジェクト: GregorR/midifile
static void Mf_FinalizeTrack(MfTrack *track)
{
    MfEvent *event;
    int mustFinalize = 0;

    if (track->tail) {
        event = track->tail;
        if (!(event->meta) || event->meta->type != 0x2F) { /* last isn't end-of-stream */
            mustFinalize = 1;
        }
    } else {
        mustFinalize = 1;
    }

    if (mustFinalize) {
        /* OK, we have to finalize */
        event = Mf_NewEvent();
        event->e.message = Pm_Message(0xFF, 0, 0);
        event->meta = Mf_NewMeta(0);
        event->meta->type = 0x2F;
        Mf_PushEvent(track, event);
    }
}
コード例 #27
0
ファイル: midithread.c プロジェクト: RTcmix/RTcmix
/* timer interrupt for processing midi data */
void process_midi(PtTimestamp timestamp, void *userData)
{
    PmError result;
    PmEvent buffer; /* just one message at a time */
    long msg;

    /* do nothing until initialization completes */
    if (!active) 
        return;

    /* check for messages */
    do { 
        result = Pm_Dequeue(main_to_midi, &msg); 
        if (result) {
            if (msg >= -127 && msg <= 127) 
                transpose = msg;
            else if (msg == QUIT_MSG) {
                /* acknowledge receipt of quit message */
                Pm_Enqueue(midi_to_main, &msg);
                active = FALSE;
                return;
            } else if (msg == MONITOR_MSG) {
                /* main has requested a pitch. monitor is a flag that
                 * records the request:
                 */
                monitor = TRUE;
            } else if (msg == THRU_MSG) {
                /* toggle Thru on or off */
                midi_thru = !midi_thru;
            }
        }
    } while (result);         
    
    /* see if there is any midi input to process */
    do {
		result = Pm_Poll(midi_in);
        if (result) {
            long status, data1, data2;
            if (Pm_Read(midi_in, &buffer, 1) == pmBufferOverflow) 
                continue;
            if (midi_thru) 
                Pm_Write(midi_out, &buffer, 1);
            /* unless there was overflow, we should have a message now */
            status = Pm_MessageStatus(buffer.message);
            data1 = Pm_MessageData1(buffer.message);
            data2 = Pm_MessageData2(buffer.message);
            if ((status & 0xF0) == 0x90 ||
                (status & 0xF0) == 0x80) {
                
                /* this is a note-on or note-off, so transpose and send */
                data1 += transpose;
                
                /* keep within midi pitch range, keep proper pitch class */
                while (data1 > 127) 
                    data1 -= 12;
                while (data1 < 0) 
                    data1 += 12;
                
                /* send the message */
                buffer.message = Pm_Message(status, data1, data2);
                Pm_Write(midi_out, &buffer, 1);
                
                /* if monitor is set, send the pitch to the main thread */
                if (monitor) {
                    Pm_Enqueue(midi_to_main, &data1);
                    monitor = FALSE; /* only send one pitch per request */
                }
            }
        }
    } while (result);
}
コード例 #28
0
ファイル: pa.cpp プロジェクト: Jojo-Schmitz/MuseScore
// TODO: this was copied from Jack version...I'd like to eventually unify these two, so that they handle midi event types in the same manner
void Portaudio::putEvent(const NPlayEvent& e, unsigned framePos)
      {
      PortMidiDriver* portMidiDriver = static_cast<PortMidiDriver*>(midiDriver);
      if (!portMidiDriver || !portMidiDriver->getOutputStream() || !portMidiDriver->canOutput())
            return;

      int portIdx = seq->score()->midiPort(e.channel());
      int chan    = seq->score()->midiChannel(e.channel());

      if (portIdx < 0 ) {
            qDebug("Portaudio::putEvent: invalid port %d", portIdx);
            return;
            }

      if (midiOutputTrace) {
            int a     = e.dataA();
            int b     = e.dataB();
            qDebug("MidiOut<%d>: Portaudio: %02x %02x %02x, chan: %i", portIdx, e.type(), a, b, chan);
            }

      switch(e.type()) {
            case ME_NOTEON:
            case ME_NOTEOFF:
            case ME_POLYAFTER:
            case ME_CONTROLLER:
                  // Catch CTRL_PROGRAM and let other ME_CONTROLLER events to go
                  if (e.dataA() == CTRL_PROGRAM) {
                        // Convert CTRL_PROGRAM event to ME_PROGRAM
                        long msg = Pm_Message(ME_PROGRAM | chan, less128(e.dataB()), 0);
                        PmError error = Pm_WriteShort(portMidiDriver->getOutputStream(), seq->getCurrentMillisecondTimestampWithLatency(framePos), msg);
                        if (error != pmNoError) {
                              qDebug("Portaudio: error %d", error);
                              return;
                              }
                        break;
                        }
                  // fall through
            case ME_PITCHBEND:
                  {
                  long msg = Pm_Message(e.type() | chan, less128(e.dataA()), less128(e.dataB()));
                  PmError error = Pm_WriteShort(portMidiDriver->getOutputStream(), seq->getCurrentMillisecondTimestampWithLatency(framePos), msg);
                  if (error != pmNoError) {
                        qDebug("Portaudio: error %d", error);
                        return;
                        }
                  }
                  break;

            case ME_PROGRAM:
            case ME_AFTERTOUCH:
                  {
                  long msg = Pm_Message(e.type() | chan, less128(e.dataA()), 0);
                  PmError error = Pm_WriteShort(portMidiDriver->getOutputStream(), seq->getCurrentMillisecondTimestampWithLatency(framePos), msg);
                  if (error != pmNoError) {
                        qDebug("Portaudio: error %d", error);
                        return;
                        }
                  }
                  break;
            case ME_SONGPOS:
            case ME_CLOCK:
            case ME_START:
            case ME_CONTINUE:
            case ME_STOP:
                  qDebug("Portaudio: event type %x not supported", e.type());
                  break;
            }
      }
コード例 #29
0
ファイル: test.c プロジェクト: AkiraShirase/audacity
void main_test_output() {
    PmStream * midi;
	char line[80];
    int32_t off_time;
    int chord[] = { 60, 67, 76, 83, 90 };
    #define chord_size 5 
    PmEvent buffer[chord_size];
    PmTimestamp timestamp;

    /* determine which output device to use */
    int i = get_number("Type output number: ");

    /* It is recommended to start timer before PortMidi */
    TIME_START;

    /* open output device -- since PortMidi avoids opening a timer
       when latency is zero, we will pass in a NULL timer pointer
       for that case. If PortMidi tries to access the time_proc,
       we will crash, so this test will tell us something. */
    Pm_OpenOutput(&midi, 
                  i, 
                  DRIVER_INFO,
                  OUTPUT_BUFFER_SIZE, 
                  (latency == 0 ? NULL : TIME_PROC),
                  (latency == 0 ? NULL : TIME_INFO), 
                  latency);
    printf("Midi Output opened with %ld ms latency.\n", (long) latency);

    /* output note on/off w/latency offset; hold until user prompts */
    printf("ready to send program 1 change... (type RETURN):");
    fgets(line, STRING_MAX, stdin);
    /* if we were writing midi for immediate output, we could always use
       timestamps of zero, but since we may be writing with latency, we
       will explicitly set the timestamp to "now" by getting the time.
       The source of timestamps should always correspond to the TIME_PROC
       and TIME_INFO parameters used in Pm_OpenOutput(). */
    buffer[0].timestamp = TIME_PROC(TIME_INFO);
    /* Send a program change to increase the chances we will hear notes */
    /* Program 0 is usually a piano, but you can change it here: */
#define PROGRAM 0
    buffer[0].message = Pm_Message(0xC0, PROGRAM, 0);
    Pm_Write(midi, buffer, 1);

    printf("ready to note-on... (type RETURN):");
    fgets(line, STRING_MAX, stdin);
    buffer[0].timestamp = TIME_PROC(TIME_INFO);
    buffer[0].message = Pm_Message(0x90, 60, 100);
    Pm_Write(midi, buffer, 1);
    printf("ready to note-off... (type RETURN):");
    fgets(line, STRING_MAX, stdin);
    buffer[0].timestamp = TIME_PROC(TIME_INFO);
    buffer[0].message = Pm_Message(0x90, 60, 0);
    Pm_Write(midi, buffer, 1);

    /* output short note on/off w/latency offset; hold until user prompts */
    printf("ready to note-on (short form)... (type RETURN):");
    fgets(line, STRING_MAX, stdin);
    Pm_WriteShort(midi, TIME_PROC(TIME_INFO),
                  Pm_Message(0x90, 60, 100));
    printf("ready to note-off (short form)... (type RETURN):");
    fgets(line, STRING_MAX, stdin);
    Pm_WriteShort(midi, TIME_PROC(TIME_INFO),
                  Pm_Message(0x90, 60, 0));

    /* output several note on/offs to test timing. 
       Should be 1s between notes */
    printf("chord will arpeggiate if latency > 0\n");
    printf("ready to chord-on/chord-off... (type RETURN):");
    fgets(line, STRING_MAX, stdin);
    timestamp = TIME_PROC(TIME_INFO);
    for (i = 0; i < chord_size; i++) {
        buffer[i].timestamp = timestamp + 1000 * i;
        buffer[i].message = Pm_Message(0x90, chord[i], 100);
    }
    Pm_Write(midi, buffer, chord_size);

    off_time = timestamp + 1000 + chord_size * 1000; 
    while (TIME_PROC(TIME_INFO) < off_time) 
		/* busy wait */;
    for (i = 0; i < chord_size; i++) {
        buffer[i].timestamp = timestamp + 1000 * i;
        buffer[i].message = Pm_Message(0x90, chord[i], 0);
    }
    Pm_Write(midi, buffer, chord_size);    

    /* close device (this not explicitly needed in most implementations) */
    printf("ready to close and terminate... (type RETURN):");
    fgets(line, STRING_MAX, stdin);
	
    Pm_Close(midi);
    Pm_Terminate();
    printf("done closing and terminating...\n");
}
コード例 #30
0
ファイル: test.c プロジェクト: AkiraShirase/audacity
/*    The winmm stream mode is used for latency>0, and sends
   timestamped messages. The timestamps are relative (delta) 
   times, whereas PortMidi times are absolute. Since peculiar
   things happen when messages are not always sent in advance,
   this function allows us to exercise the system and test it.
 */
void main_test_stream() {
    PmStream * midi;
	char line[80];
    PmEvent buffer[16];

	/* determine which output device to use */
    int i = get_number("Type output number: ");

	latency = 500; /* ignore LATENCY for this test and
				      fix the latency at 500ms */

    /* It is recommended to start timer before PortMidi */
    TIME_START;

	/* open output device */
    Pm_OpenOutput(&midi, 
                  i, 
                  DRIVER_INFO,
                  OUTPUT_BUFFER_SIZE, 
                  TIME_PROC,
                  TIME_INFO, 
                  latency);
    printf("Midi Output opened with %ld ms latency.\n", (long) latency);

    /* output note on/off w/latency offset; hold until user prompts */
    printf("ready to send output... (type RETURN):");
    fgets(line, STRING_MAX, stdin);

    /* if we were writing midi for immediate output, we could always use
       timestamps of zero, but since we may be writing with latency, we
       will explicitly set the timestamp to "now" by getting the time.
       The source of timestamps should always correspond to the TIME_PROC
       and TIME_INFO parameters used in Pm_OpenOutput(). */
    buffer[0].timestamp = TIME_PROC(TIME_INFO);
    buffer[0].message = Pm_Message(0xC0, 0, 0);
	buffer[1].timestamp = buffer[0].timestamp;
	buffer[1].message = Pm_Message(0x90, 60, 100);
	buffer[2].timestamp = buffer[0].timestamp + 1000;
	buffer[2].message = Pm_Message(0x90, 62, 100);
	buffer[3].timestamp = buffer[0].timestamp + 2000;
	buffer[3].message = Pm_Message(0x90, 64, 100);
	buffer[4].timestamp = buffer[0].timestamp + 3000;
	buffer[4].message = Pm_Message(0x90, 66, 100);
	buffer[5].timestamp = buffer[0].timestamp + 4000;
	buffer[5].message = Pm_Message(0x90, 60, 0);
	buffer[6].timestamp = buffer[0].timestamp + 4000;
	buffer[6].message = Pm_Message(0x90, 62, 0);
	buffer[7].timestamp = buffer[0].timestamp + 4000;
	buffer[7].message = Pm_Message(0x90, 64, 0);
	buffer[8].timestamp = buffer[0].timestamp + 4000;
	buffer[8].message = Pm_Message(0x90, 66, 0);

    Pm_Write(midi, buffer, 9);
#ifdef SEND8
	/* Now, we're ready for the real test.
	   Play 4 notes at now, now+500, now+1000, and now+1500
	   Then wait until now+2000.
	   Play 4 more notes as before.
	   We should hear 8 evenly spaced notes. */
	now = TIME_PROC(TIME_INFO);
	for (i = 0; i < 4; i++) {
		buffer[i * 2].timestamp = now + (i * 500);
		buffer[i * 2].message = Pm_Message(0x90, 60, 100);
		buffer[i * 2 + 1].timestamp = now + 250 + (i * 500);
		buffer[i * 2 + 1].message = Pm_Message(0x90, 60, 0);
	}
    Pm_Write(midi, buffer, 8);

    while (Pt_Time() < now + 2500) 
		/* busy wait */;
	/* now we are 500 ms behind schedule, but since the latency
	   is 500, the delay should not be audible */
	now += 2000;
	for (i = 0; i < 4; i++) {
		buffer[i * 2].timestamp = now + (i * 500);
		buffer[i * 2].message = Pm_Message(0x90, 60, 100);
		buffer[i * 2 + 1].timestamp = now + 250 + (i * 500);
		buffer[i * 2 + 1].message = Pm_Message(0x90, 60, 0);
	}
    Pm_Write(midi, buffer, 8);
#endif
    /* close device (this not explicitly needed in most implementations) */
    printf("ready to close and terminate... (type RETURN):");
    fgets(line, STRING_MAX, stdin);
	
    Pm_Close(midi);
    Pm_Terminate();
    printf("done closing and terminating...\n");
}