Esempio n. 1
0
void SonifyNoteOnOff(int p, int v)
{
   if (!sonificationStarted)
      SonifyBeginSonification();
   if (sonMidiStream)
      Pm_WriteShort(sonMidiStream, 0, Pm_Message(0x90, p, v));
}
Esempio n. 2
0
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);
  }
}
Esempio n. 3
0
/*
 * Method:    Pm_WriteShort
 */
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1WriteShort
  (JNIEnv *env, jclass cl, jobject jstream, jint when, jint msg)
{
    CLASS(c, jstream);
    ADDRESS_FID(fid, c);
    return Pm_WriteShort(PMSTREAM(jstream, fid), when, msg);
}
Esempio n. 4
0
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;
}
/*!
 @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));
}
/*!
 @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));
}
Esempio n. 7
0
/*
 * Method:    Pm_Write
 */
JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Write
        (JNIEnv *env, jclass cl, jobject jstream, jobject jpmevent)
{
    CLASS(jstream_class, jstream);
    ADDRESS_FID(address_fid, jstream_class);
    jclass jpmevent_class = (*env)->GetObjectClass(env, jpmevent);
    jfieldID message_fid = 
            (*env)->GetFieldID(env, jpmevent_class, "message", "I");
    jfieldID timestamp_fid = 
            (*env)->GetFieldID(env, jpmevent_class, "timestamp", "I");
    // note that we call WriteShort because it's simpler than constructing
    // a buffer and passing it to Pm_Write
    return Pm_WriteShort(PMSTREAM(jstream, address_fid),
            (*env)->GetIntField(env, jpmevent, timestamp_fid),
            (*env)->GetIntField(env, jpmevent, message_fid));
}
Esempio n. 8
0
/*
-------------------------------------------------------------
*/
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;
}
Esempio n. 9
0
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;
  }
}
Esempio n. 10
0
void play(PtTimestamp timestamp, void *ignore)
{
    MfEvent *event;
    int track;
    PmEvent ev;

    if (!ready) return;

    while (Mf_StreamReadNormal(stream, &event, &track, 1) == 1) {
        ev = event->e;
        Pm_WriteShort(ostream, 0, ev.message);
        Mf_FreeEvent(event);
    }

    if (Mf_StreamEmpty(stream) == TRUE) {
        Mf_FreeFile(Mf_CloseStream(stream));
        Pm_Terminate();
        exit(0);
    }
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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);
}
Esempio n. 13
0
// 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;
            }
      }
Esempio n. 14
0
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");
}
Esempio n. 15
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  int code = 'L';
  PmError err;
  
  init(); /* returns immediately if already done */
  
  if (nrhs > 0) {
    char arg[2];
    
    if (mxIsUint8(prhs[0])) {
      if (outStream == NULL) {
        mexErrMsgTxt("No MIDI output device is opened");
      } else {
        playRaw(prhs[0]);
      }
      return;
    }
    
    if (!mxIsChar(prhs[0]) || mxGetNumberOfElements(prhs[0]) > 1) {
      mexErrMsgTxt("Bad call\n");
    }
    mxGetString(prhs[0], arg, 2);
    code = arg[0];
  }
  
  switch(code) {
    case 'P':
      if (outStream == NULL) {
        mexErrMsgTxt("No MIDI output device is opened");
      } else {
        if (nrhs < 3) mexErrMsgTxt("Usage for 'program change': midiOut('P', channel, program)");
        sendProgChange(prhs);
      }
      break;
    case '+':	/* Note on */
      if (outStream == NULL) {
        mexErrMsgTxt("No MIDI output device is opened");
      } else {
        if (nrhs < 4) mexErrMsgTxt("Usage for 'note on': midiOut('+', channel, notes, velocities)");
        sendNoteOnOff(0x90, prhs);
      }
      break;
    case '-': 	/* Note off */
      if (outStream == NULL) {
        mexErrMsgTxt("No MIDI output device is opened");
      } else {
        if (nrhs < 4) mexErrMsgTxt("Usage for 'note on': midiOut('+', channel, notes, velocities)");
        sendNoteOnOff(0x80, prhs);
      }
      break;
    case '.':	/* All notes off */
      if (outStream == NULL) {
        mexErrMsgTxt("No MIDI output device is opened");
      } else {
        int channel;
        
        if (nrhs < 2) mexErrMsgTxt("Usage for 'all notes off': midiOut('.', channel)");
        channel = (int) mxGetScalar(prhs[1]);
        if (channel < 1 || channel > 16) mexErrMsgTxt("Channel (2nd arg.) must be 1..16");
        --channel;
        err = Pm_WriteShort(outStream, 0, Pm_Message(0xB0 | channel, 123, 0));
        if (err!=pmNoError) reportPmError(err);
      }
      break;
    case 'C':   /* Close output stream */
      if (outStream == NULL) {
        mexWarnMsgTxt("No MIDI output device is opened - ignoring 'close' command");
      } else {
        err = Pm_Close(outStream);
        outStream = NULL;
      }
      break;
    case 'O':	/* Open output stream */
    {
      int device = 0;
      
      
      if (nrhs<2 || !mxIsNumeric(prhs[1])) mexErrMsgTxt("Bad call\n");
      device = (int) mxGetScalar(prhs[1]);
      if (device < 1 || device > Pm_CountDevices()) mexErrMsgTxt("Device index out of range");
      --device;
      
      if (outStream != NULL) {
        if (openID == device) {
          mexWarnMsgTxt("MIDI output device is already open - ignoring request");
          return;
        }
        mexWarnMsgTxt("Another MIDI output device is open - closing that one");
        err = Pm_Close(outStream);
        outStream = NULL;
        if (err != pmNoError) reportPmError(err);
      }
      
      /* last parameter = latency = 0 means that timestamps are ignored */
      err = Pm_OpenOutput(&outStream, device, NULL, OUTPUT_BUFFER_SIZE, NULL, NULL, 0);
      if (err != pmNoError) {
        outStream = NULL;
        reportPmError(err);
      }
      openID = device;
    }
    break;
    case 'L':	/* List devices */
      plhs[0] = getDevices();
      break;
    default:
      mexErrMsgTxt("Bad call\n");
  }
}
Esempio n. 16
0
/*
 * All MIDI sends take place here
 */
void timer_poll(PtTimestamp timestamp, void *userData)
{
    static int callback_owns_portmidi = false;
    static long clock_start_time = 0;
    static double next_clock_time = 0;
    /* SMPTE time */
    static int frames = 0;
    static int seconds = 0;
    static int minutes = 0;
    static int hours = 0;
    static int mtc_count = 0; /* where are we in quarter frame sequence? */
    static int smpte_start_time = 0;
    static double next_smpte_time = 0;
    #define QUARTER_FRAME_PERIOD (1.0 / 120.0) /* 30fps, 1/4 frame */

    if (callback_owns_portmidi && !active) {
        /* main is requesting (by setting active to false) that we shut down */
        callback_owns_portmidi = false;
        return;
    }
    if (!active) return; /* main still getting ready or it's closing down */
    callback_owns_portmidi = true; /* main is ready, we have portmidi */
    if (send_start_stop) {
        if (clock_running) {
            Pm_WriteShort(midi, 0, MIDI_STOP);
        } else {
            Pm_WriteShort(midi, 0, MIDI_START);
            clock_start_time = timestamp;
            next_clock_time = TEMPO_TO_CLOCK / tempo;
        }
        clock_running = !clock_running;
        send_start_stop = false; /* until main sets it again */
        /* note that there's a slight race condition here: main could
           set send_start_stop asynchronously, but we assume user is 
           typing slower than the clock rate */
    }
    if (clock_running) {
        if ((timestamp - clock_start_time) > next_clock_time) {
            Pm_WriteShort(midi, 0, MIDI_TIME_CLOCK);
            next_clock_time += TEMPO_TO_CLOCK / tempo;
        }
    }
    if (time_code_running) {
        int data;
        if ((timestamp - smpte_start_time) < next_smpte_time) 
            return;
        switch (mtc_count) {
        case 0: /* frames low nibble */
            data = frames;
            break;
        case 1: /* frames high nibble */
            data = frames >> 4;
            break;
        case 2: /* frames seconds low nibble */
            data = seconds;
            break;
        case 3: /* frames seconds high nibble */
            data = seconds >> 4;
            break;
        case 4: /* frames minutes low nibble */
            data = minutes;
            break;
        case 5: /* frames minutes high nibble */
            data = minutes >> 4;
            break;
        case 6: /* hours low nibble */
            data = hours;
            break;
        case 7: /* hours high nibble */
            data = hours >> 4;
            break;
        }
        data &= 0xF; /* take only 4 bits */
        Pm_WriteShort(midi, 0, 
                      Pm_Message(MIDI_Q_FRAME, (mtc_count << 4) + data, 0));
        mtc_count = (mtc_count + 1) & 7; /* wrap around */
        if (mtc_count == 0) { /* update time by two frames */
            frames += 2;
            if (frames >= 30) {
                frames = 0;
                seconds++;
                if (seconds >= 60) {
                    seconds = 0;
                    minutes++;
                    if (minutes >= 60) {
                        minutes = 0;
                        hours++;
                        /* just let hours wrap if it gets that far */
                    }
                }
            }
        }
        next_smpte_time += QUARTER_FRAME_PERIOD;
    } else { /* time_code_running is false */