int MD_MFTrack::load(uint8_t trackId, MD_MIDIFile *mf) { uint32_t dat32; uint16_t dat16; // save the trackid for use later _trackId = _mev.track = trackId; // Read the Track header // track_chunk = "MTrk" + <length:4> + <track_event> [+ <track_event> ...] { char h[MTRK_HDR_SIZE+1]; // Header characters + nul mf->_fd.fgets(h, MTRK_HDR_SIZE+1); h[MTRK_HDR_SIZE] = '\0'; if (strcmp(h, MTRK_HDR) != 0) return(0); } // Row read track chunk size and in bytes. This is not really necessary // since the track MUST end with an end of track meta event. dat32 = readMultiByte(&mf->_fd, MB_LONG); _length = dat32; // save where we are in the file as this is the start of offset for this track _startOffset = mf->_fd.curPosition(); _currOffset = 0; // Advance the file pointer to the start of the next track; if (mf->_fd.seekSet(_startOffset+_length) == -1) return(1); return(-1); }
void ADXL345::readAxisValue(AxisValue_s& AxisVal){ uint8_t valueBuffer[6]; readMultiByte(DATAX0_REG, valueBuffer, 6); AxisVal.X = valueBuffer[1] << 8 | valueBuffer[0]; AxisVal.Y = valueBuffer[3] << 8 | valueBuffer[2]; AxisVal.Z = valueBuffer[5] << 8 | valueBuffer[4]; // add gravity factor //AxisVal.X = AxisVal.X * 0.004 * 9.806; //AxisVal.Y = AxisVal.Y * 0.004 * 9.806; //AxisVal.Z = AxisVal.Z * 0.004 * 9.806; }
int MD_MIDIFile::load() // Load the MIDI file into memory ready for processing { uint32_t dat32; uint16_t dat16; if (_fileName[0] == '\0') return(0); // open the file for reading: if (!_fd.open(_fileName, O_READ)) return(2); // Read the MIDI header // header chunk = "MThd" + <header_length:4> + <format:2> + <num_tracks:2> + <time_division:2> { char h[MTHD_HDR_SIZE+1]; // Header characters + nul _fd.fgets(h, MTHD_HDR_SIZE+1); h[MTHD_HDR_SIZE] = '\0'; if (strcmp(h, MTHD_HDR) != 0) { _fd.close(); return(3); } } // read header size dat32 = readMultiByte(&_fd, MB_LONG); if (dat32 != 6) // must be 6 for this header { _fd.close(); return(4); } // read file type dat16 = readMultiByte(&_fd, MB_WORD); if ((dat16 != 0) && (dat16 != 1)) { _fd.close(); return(5); } _format = dat16; // read number of tracks dat16 = readMultiByte(&_fd, MB_WORD); if ((_format == 0) && (dat16 != 1)) { _fd.close(); return(6); } if (dat16 > MIDI_MAX_TRACKS) { _fd.close(); return(7); } _trackCount = dat16; // read ticks per quarter note dat16 = readMultiByte(&_fd, MB_WORD); if (dat16 & 0x8000) // top bit set is SMTE format { int framespersecond = (dat16 >> 8) & 0x00ff; int resolution = dat16 & 0x00ff; switch (framespersecond) { case 232: framespersecond = 24; break; case 231: framespersecond = 25; break; case 227: framespersecond = 29; break; case 226: framespersecond = 30; break; default: _fd.close(); return(7); } dat16 = framespersecond * resolution; }
void MD_MFTrack::parseEvent(MD_MIDIFile *mf) // process the event from the physical file { uint8_t eType; uint32_t eLen, mLen; sysex_event sev; // used for sysex callback function // now we have to process this event eType = mf->_fd.read(); switch (eType) { // ---------------------------- MIDI // midi_event = any MIDI channel message, including running status // Midi events (status bytes 0x8n - 0xEn) The standard Channel MIDI messages, where 'n' is the MIDI channel (0 - 15). // This status byte will be followed by 1 or 2 data bytes, as is usual for the particular MIDI message. // Any valid Channel MIDI message can be included in a MIDI file. case 0x80 ... 0xBf: // MIDI message with 2 parameters case 0xe0 ... 0xef: _mev.size = 3; _mev.data[0] = eType; _mev.channel = _mev.data[0] & 0xf; // mask off the channel _mev.data[0] = _mev.data[0] & 0xf0; // just the command byte _mev.data[1] = mf->_fd.read(); _mev.data[2] = mf->_fd.read(); DUMP("[MID2] Ch: ", _mev.channel); DUMPX(" Data: ", _mev.data[0]); DUMPX(" ", _mev.data[1]); DUMPX(" ", _mev.data[2]); #if !DUMP_DATA if (mf->_midiHandler != NULL) (mf->_midiHandler)(&_mev); #endif // !DUMP_DATA break; case 0xc0 ... 0xdf: // MIDI message with 1 parameter _mev.size = 2; _mev.data[0] = eType; _mev.channel = _mev.data[0] & 0xf; // mask off the channel _mev.data[0] = _mev.data[0] & 0xf0; // just the command byte _mev.data[1] = mf->_fd.read(); DUMP("[MID1] Ch: ", _mev.channel); DUMPX(" Data: ", _mev.data[0]); DUMPX(" ", _mev.data[1]); #if !DUMP_DATA if (mf->_midiHandler != NULL) (mf->_midiHandler)(&_mev); #endif break; case 0x00 ... 0x7f: // MIDI run on message { // If the first (status) byte is less than 128 (0x80), this implies that MIDI // running status is in effect, and that this byte is actually the first data byte // (the status carrying over from the previous MIDI event). // This can only be the case if the immediately previous event was also a MIDI event, // ie SysEx and Meta events clear running status. This means that the _mev structure // should contain the info from the previous message in the structure's channel member // and data[0] (for the MIDI command). // Hence start saving the data at byte data[1] with the byte we have just read (eType) // and use the size member to determine how large the message is (ie, same as before). _mev.data[1] = eType; for (uint8_t i = 2; i < _mev.size; i++) { _mev.data[i] = mf->_fd.read(); // next byte } DUMP("[MID+] Ch: ", _mev.channel); DUMPS(" Data:"); for (uint8_t i = 0; i<_mev.size; i++) { DUMPX(" ", _mev.data[i]); } #if !DUMP_DATA if (mf->_midiHandler != NULL) (mf->_midiHandler)(&_mev); #endif } break; // ---------------------------- SYSEX case 0xf0: // sysex_event = 0xF0 + <len:1> + <data_bytes> + 0xF7 case 0xf7: // sysex_event = 0xF7 + <len:1> + <data_bytes> + 0xF7 { uint8_t c, i; sysex_event sev; // collect all the bytes until the 0xf7 - boundaries are included in the message sev.track = _trackId; sev.data[0] = eType; sev.size = mf->_fd.read(); // The length parameter includes the 0xF7 but not the start boundary. // However, it may be bigger than our buffer will allow us to store. sev.size = (sev.size > BUF_SIZE(sev.data) - 2 ? BUF_SIZE(sev.data) - 2 : sev.size + 1); for (i = 1; (i < sev.size) && (c != 0xf7); i++) { c = mf->_fd.read(); // next char sev.data[i] = c; } // check if we had an overflow if (c != 0xf7) { while ((c = mf->_fd.read()) != 0xf7) ; // skip read all data sev.data[sev.size] = 0xf7; // terminate properly - data is probably nuked anyway } DUMPS("[SYSX] Data:"); for (uint8_t i = 0; i<sev.size; i++) { DUMPX(" ", sev.data[i]); } #if !DUMP_DATA if (mf->_sysexHandler != NULL) (mf->_sysexHandler)(&sev); #endif } break; // ---------------------------- META case 0xff: // meta_event = 0xFF + <meta_type:1> + <length:v> + <event_data_bytes> eType = mf->_fd.read(); mLen = readVarLen(&mf->_fd); DUMPX("[META] Type: 0x", eType); DUMP("\tLen: ", mLen); DUMPS("\t"); switch (eType) { case 0x2f: // End of track _endOfTrack = true; DUMPS("END OF TRACK"); break; case 0x51: // set Tempo - really the microseconds per tick mf->setMicrosecondPerQuarterNote(readMultiByte(&mf->_fd, MB_TRYTE)); DUMP("SET TEMPO to ", mf->getTickTime()); DUMP(" us/tick or ", mf->getTempo()); DUMPS(" beats/min"); break; case 0x58: // time signature mf->setTimeSignature(mf->_fd.read(), (1 << mf->_fd.read())); // denominator is 2^n mf->_fd.seekCur(mLen-2); DUMP("SET TIME SIGNATURE to ", mf->getTimeSignature()>>8); DUMP("/", mf->getTimeSignature()&0xf); break; #if SHOW_UNUSED_META case 0x0: // Sequence Number DUMP("SEQUENCE NUMBER ", readMultiByte(&mf->_fd, MB_WORD)); break; case 0x1: // Text DUMPS("TEXT "); for (int i=0; i<mLen; i++) DUMP("", (char)mf->_fd.read()); break; case 0x2: // Copyright Notice DUMPS("COPYRIGHT "); for (uint8_t i=0; i<mLen; i++) DUMP("", (char)mf->_fd.read()); break; case 0x3: // Sequence or Track Name DUMPS("SEQ/TRK NAME "); for (uint8_t i=0; i<mLen; i++) DUMP("", (char)mf->_fd.read()); break; case 0x4: // Instrument Name DUMPS("INSTRUMENT "); for (uint8_t i=0; i<mLen; i++) DUMP("", (char)mf->_fd.read()); break; case 0x5: // Lyric DUMPS("LYRIC "); for (uint8_t i=0; i<mLen; i++) DUMP("", (char)mf->_fd.read()); break; case 0x6: // Marker DUMPS("MARKER "); for (uint8_t i=0; i<mLen; i++) DUMP("", (char)mf->_fd.read()); break; case 0x7: // Cue Point DUMPS("CUE POINT "); for (uint8_t i=0; i<mLen; i++) DUMP("", (char)mf->_fd.read()); break; case 0x20:// Channel Prefix DUMP("CHANNEL PREFIX ", readMultiByte(&mf->_fd, MB_BYTE)); break; case 0x21:// Port Prefix DUMP("PORT PREFIX ", readMultiByte(&mf->_fd, MB_BYTE)); break; case 0x54:// SMPTE Offset DUMPS("SMPTE OFFSET"); for (uint8_t i=0; i<mLen; i++) { DUMP(" ", mf->_fd.read()); } break; case 0x59:// Key Signature DUMPS("KEY SIGNATURE"); for (uint8_t i=0; i<mLen; i++) { DUMP(" ", mf->_fd.read()); } break; case 0x7F: // Sequencer Specific Metadata DUMPS("SEQ SPECIFIC"); for (uint8_t i=0; i<mLen; i++) { DUMPX(" ", mf->_fd.read()); } break; #endif // SHOW_UNUSED_META default: mf->_fd.seekCur(mLen); DUMPS("IGNORED"); } break; // ---------------------------- UNKNOWN default: // stop playing this track as we cannot identify the eType _endOfTrack = true; DUMPX("[UKNOWN 0x", eType); DUMPS("] Track aborted"); } }