Esempio n. 1
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. 2
0
void init() {
  PmError err1;
  PtError err2;
  
  if (isInit) return;
  
  mexPrintf("Initialising PortMidi\n");
  
  MUTEX_LOCK;
  note      = malloc(INPUT_BUFFER_SIZE*sizeof(int32_t));
  channel   = malloc(INPUT_BUFFER_SIZE*sizeof(int32_t));
  velocity  = malloc(INPUT_BUFFER_SIZE*sizeof(int32_t));
  timestamp = malloc(INPUT_BUFFER_SIZE*sizeof(int32_t));
  if (!(channel && note && velocity && timestamp)) {
    FREE(channel);
    FREE(note);
    FREE(velocity);
    FREE(timestamp);
    MUTEX_UNLOCK;
    mexErrMsgTxt("Could not allocate memory");
  }
  else {
    MUTEX_UNLOCK;
  }
  
  err1 = Pm_Initialize();
  reportPmError(err1);
  
  err2 = Pt_Start(1, receive_poll, NULL);
  reportPtError(err2);
  
  /* getting here means that PortMidi and PortTime are both fine */
  mexAtExit(exitFunction);
  isInit = 1;
}
Esempio n. 3
0
void init() {
  PmError err;
  
  if (isInit) return;
  
  printf("Initialising PortMidi\n");
  err = Pm_Initialize();
  reportPmError(err);
  
  if (Pt_Start(1,NULL,NULL) == 0) {
    mexAtExit(exitFunction);
    isInit = 1;
  } else {
    Pm_Terminate();
    mexErrMsgTxt("Could start PortMidi, but not PortTime.");
  }
}
Esempio n. 4
0
void exitFunction() {
  if (isInit) {
    mexPrintf("Terminating PortMidi\n");
    reportPtError(Pt_Stop());
    if (inStream != NULL) {
      reportPmError(Pm_Close(inStream));
      inStream = NULL;
    }
    Pm_Terminate();
    FREE(channel);
    FREE(note);
    FREE(velocity);
    FREE(timestamp);
    isInit = 0;
    deviceOpen = -1;
    numReceived = 0;
  }
}
Esempio n. 5
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. 6
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. 7
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  int code = 'L';
  PmError err1;
  PtError err2;
  
  init(); /* this returns immediately if already done */
  
  if (nrhs > 0) {
    char arg[2];
    if (!mxIsChar(prhs[0]) || mxGetNumberOfElements(prhs[0]) > 1) {
      mexErrMsgTxt("Bad call\n");
    }
    mxGetString(prhs[0], arg, 2);
    code = arg[0];
  }
  
  switch(code) {
    case 'V':
      if (inStream == NULL) {
        mexErrMsgTxt("No MIDI input device is opened");
      } else {
        if (nrhs < 2) mexErrMsgTxt("Usage for 'verbose': midiIn('V', value)");
        verbose = mxGetScalar(prhs[1]);
      }
      break;
    case 'G': /* Return the buffered events as array */
      if (inStream == NULL) {
        mexErrMsgTxt("No MIDI input device is opened");
      } else {
        plhs[0] = getEvent();
      }
      break;
    case 'F': /* Flush all buffered events */
      if (inStream == NULL) {
        mexErrMsgTxt("No MIDI input device is opened");
      } else {
        /* reset the counter to the beginning of the buffer */
        numReceived = 0;
      }
      break;
    case 'C':   /* Close input stream */
      if (inStream == NULL) {
        mexWarnMsgTxt("No MIDI input device is opened - ignoring 'close' command");
      } else {
        err1 = Pm_Close(inStream);
        inStream = NULL;
        if (err1 != pmNoError) reportPmError(err1);
      }
      break;
    case 'O':	/* Open input 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 (inStream != NULL) {
        if (deviceOpen == device) {
          mexWarnMsgTxt("MIDI input device is already open - ignoring request");
          return;
        }
        mexWarnMsgTxt("Another MIDI input device is open - closing that one");
        err1 = Pm_Close(inStream);
        inStream = NULL;
        if (err1 != pmNoError) reportPmError(err1);
      }
      
      err1 = Pm_OpenInput(&inStream, device, NULL, INPUT_BUFFER_SIZE, NULL, NULL);
      if (err1 != pmNoError) {
        inStream = NULL;
        reportPmError(err1);
      }
      
      /* remember which device we just opened */
      deviceOpen = device;
    }
    break;
    case 'L':	/* List devices */
      plhs[0] = getDevices();
      break;
    default:
      mexErrMsgTxt("Bad call\n");
  }
}
Esempio n. 8
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");
  }
}