Logo Search packages:      
Sourcecode: aubio version File versions  Download package

int aubio_midi_file_read_event ( aubio_midi_file_t mf,
aubio_track_t track 
)

aubio_midi_file_read_event

Bug:
Sysex messages are not handled yet

Definition at line 303 of file midi_file.c.

References _aubio_midi_file_t::eot, _aubio_midi_file_t::running_status, and _aubio_midi_file_t::varlen.

{
  int dtime;
  int status;
  int type;
  int tempo;
  unsigned char* metadata = NULL;
  unsigned char* dyn_buf = NULL;
  unsigned char static_buf[256];
  int nominator, denominator, clocks, notes, sf, mi;
  aubio_midi_event_t* evt;
  int channel = 0;
  int param1 = 0;
  int param2 = 0;


  /* read the delta-time of the event */
  if (aubio_midi_file_read_varlen(mf) != AUBIO_OK) {
    return AUBIO_FAIL;
  }
  dtime = mf->varlen;

  /* read the status byte */
  status = aubio_midi_file_getc(mf);
  if (status < 0) {
    AUBIO_ERR( "Unexpected end of file");
    return AUBIO_FAIL;
  }

  /* not a valid status byte: use the running status instead */
  if ((status & 0x80) == 0) {
    if ((mf->running_status & 0x80) == 0) {
      AUBIO_ERR( "Undefined status and invalid running status");
      return AUBIO_FAIL;
    }
    aubio_midi_file_push(mf, status);
    status = mf->running_status;
  } 

  /* check what message we have */
  if (status & 0x80) {
    mf->running_status = status;

    if ((status == MIDI_SYSEX) || (status == MIDI_EOX)) {     /* system exclusif */
      /** \bug Sysex messages are not handled yet */
      /* read the length of the message */
      if (aubio_midi_file_read_varlen(mf) != AUBIO_OK) {
        return AUBIO_FAIL;
      }

      if (mf->varlen < 255) {
        metadata = &static_buf[0];
      } else {
        AUBIO_DBG( "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen);
        dyn_buf = AUBIO_MALLOC(mf->varlen + 1);
        if (dyn_buf == NULL) {
          //AUBIO_LOG(AUBIO_PANIC, "Out of memory");
          AUBIO_ERR("Out of memory");
          return AUBIO_FAIL;
        }
        metadata = dyn_buf;
      }

      /* read the data of the message */
      if (mf->varlen) {

        if (aubio_midi_file_read(mf, metadata, mf->varlen) != AUBIO_OK) {
          if (dyn_buf) {
            AUBIO_FREE(dyn_buf);
          }
          return AUBIO_FAIL;
        }

        if (dyn_buf) {
          AUBIO_DBG( "%s: %d: free metadata", __FILE__, __LINE__);
          AUBIO_FREE(dyn_buf);
        }
      }

      return AUBIO_OK;

    } else if (status == MIDI_META_EVENT) {             /* meta events */

      int result = AUBIO_OK;

      /* get the type of the meta message */
      type = aubio_midi_file_getc(mf);
      if (type < 0) {
        AUBIO_ERR( "Unexpected end of file");
        return AUBIO_FAIL;
      }

      /* get the length of the data part */
      if (aubio_midi_file_read_varlen(mf) != AUBIO_OK) {
        return AUBIO_FAIL;
      }

      if (mf->varlen) {

        if (mf->varlen < 255) {
          metadata = &static_buf[0];
        } else {
          AUBIO_DBG( "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen);
          dyn_buf = AUBIO_MALLOC(mf->varlen + 1);
          if (dyn_buf == NULL) {
            AUBIO_ERR("Out of memory");
            return AUBIO_FAIL;
          }
          metadata = dyn_buf;
        }

        /* read the data */
        if (aubio_midi_file_read(mf, metadata, mf->varlen) != AUBIO_OK) {
          if (dyn_buf) {
            AUBIO_FREE(dyn_buf);
          }
          return AUBIO_FAIL;
        }
      }

      /* handle meta data */
      switch (type) {

        case MIDI_COPYRIGHT:
          metadata[mf->varlen] = 0;
          break;

        case MIDI_TRACK_NAME:
          if (metadata != NULL) /* avoids crashes on empty tracks */
            metadata[mf->varlen] = 0;
          aubio_track_set_name(track, (char*) metadata);
          break;

        case MIDI_INST_NAME:
          metadata[mf->varlen] = 0;
          break;

        case MIDI_LYRIC:
          break;

        case MIDI_MARKER:
          break;

        case MIDI_CUE_POINT:
          break; /* don't care much for text events */

        case MIDI_EOT:
          if (mf->varlen != 0) {
            AUBIO_ERR("Invalid length for EndOfTrack event");
            result = AUBIO_FAIL;
            break;
          }
          mf->eot = 1;
          break; 

        case MIDI_SET_TEMPO:
          if (mf->varlen != 3) {
            AUBIO_ERR("Invalid length for SetTempo meta event");
            result = AUBIO_FAIL;
            break;
          }
          tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2];
          evt = new_aubio_midi_event();
          if (evt == NULL) {
            AUBIO_ERR( "Out of memory");
            result = AUBIO_FAIL;
            break;
          }
          evt->dtime = dtime;
          evt->type = MIDI_SET_TEMPO;
          evt->channel = 0;
          evt->param1 = tempo;
          evt->param2 = 0;
          aubio_track_add_event(track, evt);
          break; 

        case MIDI_SMPTE_OFFSET:
          if (mf->varlen != 5) {
            AUBIO_ERR("Invalid length for SMPTE Offset meta event");
            result = AUBIO_FAIL;
            break;
          }
          break; /* we don't use smtp */  

        case MIDI_TIME_SIGNATURE:
          if (mf->varlen != 4) {
            AUBIO_ERR("Invalid length for TimeSignature meta event");
            result = AUBIO_FAIL;
            break;
          }
          nominator = metadata[0];
          denominator = pow(2.0, (double) metadata[1]);
          clocks = metadata[2];
          notes = metadata[3];

          AUBIO_DBG("signature=%d/%d, metronome=%d, 32nd-notes=%d\n", 
              nominator, denominator, clocks, notes);

          break;

        case MIDI_KEY_SIGNATURE:
          if (mf->varlen != 2) {
            AUBIO_ERR( "Invalid length for KeySignature meta event");
            result = AUBIO_FAIL;
            break;
          }
          sf = metadata[0];
          mi = metadata[1];
          break;

        case MIDI_SEQUENCER_EVENT:
          AUBIO_DBG("Sequencer event ignored\n");
          break;

        default:
          break;
      }

      if (dyn_buf) {
        AUBIO_DBG( "%s: %d: free metadata", __FILE__, __LINE__);
        AUBIO_FREE(dyn_buf);
      }

      return result;

    } else {                /* channel messages */

      type = status & 0xf0;
      channel = status & 0x0f;

      /* all channel message have at least 1 byte of associated data */
      if ((param1 = aubio_midi_file_getc(mf)) < 0) {
        AUBIO_ERR( "Unexpected end of file");
        return AUBIO_FAIL;
      }

      switch (type) {

        case NOTE_ON:
          if ((param2 = aubio_midi_file_getc(mf)) < 0) {
            AUBIO_ERR( "Unexpected end of file");
            return AUBIO_FAIL;
          }
          break;

        case NOTE_OFF:  
          if ((param2 = aubio_midi_file_getc(mf)) < 0) {
            AUBIO_ERR( "Unexpected end of file");
            return AUBIO_FAIL;
          }
          break;

        case KEY_PRESSURE:
          if ((param2 = aubio_midi_file_getc(mf)) < 0) {
            AUBIO_ERR( "Unexpected end of file");
            return AUBIO_FAIL;
          }
          break;

        case CONTROL_CHANGE:
          if ((param2 = aubio_midi_file_getc(mf)) < 0) {
            AUBIO_ERR( "Unexpected end of file");
            return AUBIO_FAIL;
          }
          break;

        case PROGRAM_CHANGE:
          break;

        case CHANNEL_PRESSURE:
          break;

        case PITCH_BEND:
          if ((param2 = aubio_midi_file_getc(mf)) < 0) {
            AUBIO_ERR( "Unexpected end of file");
            return AUBIO_FAIL;
          }

          param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f);
          param2 = 0;
          break;

        default:
          /* Can't possibly happen !? */
          AUBIO_ERR( "Unrecognized MIDI event");
          return AUBIO_FAIL;      
      }
      evt = new_aubio_midi_event();
      if (evt == NULL) {
        AUBIO_ERR( "Out of memory");
        return AUBIO_FAIL;
      }
      evt->dtime = dtime;
      evt->type = type;
      evt->channel = channel;
      evt->param1 = param1;
      evt->param2 = param2;
      aubio_track_add_event(track, evt);
    }
  }
  return AUBIO_OK;
}


Generated by  Doxygen 1.6.0   Back to index