void align_midi_events(midi & m, const tracktempo & newtempo) { for (unsigned int i = 0; i < m.trackCount(); i++) { tracktempo oldtempo = m.tracks(i).getTrackTempo(); for (unsigned int j = 0; j < m.tracks(i).eventCount(); j++) { align_midi_event(m.tracks(i), j, newtempo); m.tracks(i).setTrackTempo(newtempo); } } }
bool midi_file_write(const midi & m, const char * fn) { ofstream out(fn, ios_base::out | ios_base::binary); if (out.fail()) return false; printHeader(m, out); int lengths[m.trackCount()]; uint16_t ff = getFileFormat(m); if (m.trackCount()) { lengths[0] = writeTrack(m.tracks(0), out, m.getTicksPerQuaterNote(), true); for (unsigned i = 1; i < m.trackCount(); ++i) { if (ff < 2) lengths[i] = writeTrack(m.tracks(i), out); else lengths[i] = writeTrack(m.tracks(i), out, m.getTicksPerQuaterNote(), true); } } out.seekp(14, ios_base::beg); for (unsigned i = 0; i < m.trackCount(); ++i) { out.seekp(4, ios_base::cur); printUint32_t(lengths[i] - 8, out); out.seekp(lengths[i] - 8, ios_base::cur); } out.close(); return out.fail(); }
void printHeader(const midi& m, ostream &out) { out.write("MThd\0\0\0\6", 8); if (m.trackCount() == 0) throw "No tracks! Cannot save a file."; else if (m.trackCount() == 1) printUint16_t(1, out); else { printUint16_t(getFileFormat(m), out); } printUint16_t(m.trackCount(), out); printUint16_t((uint16_t) m.getTicksPerQuaterNote(), out); }
uint16_t getFileFormat(const midi& m) { if (m.trackCount() <= 1) return 0; uint16_t ff = 1; for (unsigned i = 1; i < m.trackCount(); ++i) { if (m.tracks(i).getTrackTempo() != m.tracks(0).getTrackTempo()) { ff = 2; break; } } return ff; }
// Closes the MIDI input device void CMIDIInDevice::Close() { // If the device is recording, stop recording before closing the // device if(m_State == RECORDING) { StopRecording(); } // If the device is opened... if(m_State == OPENED) { // Close the device MMRESULT Result = ::midiInClose(m_DevHandle); // If a failure occurred, throw exception if(Result != MMSYSERR_NOERROR) { throw CMIDIInException(Result); } // Change state m_State = CLOSED; } }
// Add system exclusive buffer to queue void CMIDIInDevice::CMIDIInHeader::AddSysExBuffer() { MMRESULT Result = ::midiInAddBuffer(m_DevHandle, &m_MIDIHdr, sizeof m_MIDIHdr); // If an error occurred, throw exception if(Result != MMSYSERR_NOERROR) { throw CMIDIInException(Result); } }
// Gets the capabilities of a particular MIDI input device void CMIDIInDevice::GetDevCaps(UINT DeviceId, MIDIINCAPS &Caps) { MMRESULT Result = ::midiInGetDevCaps(DeviceId, &Caps, sizeof Caps); // If we are not able to retrieve device capabilities, throw // exception if(Result != MMSYSERR_NOERROR) { throw CMIDIInException(Result); } }
// Gets Id for this device UINT CMIDIInDevice::GetDevID() const { UINT DeviceID; MMRESULT Result = ::midiInGetID(m_DevHandle, &DeviceID); if(Result != MMSYSERR_NOERROR) { throw CMIDIInException(Result); } return DeviceID; }
// Starts the recording process void CMIDIInDevice::StartRecording(ThreadPriority RecordingThreadPriority/* = MIDI_THREAD_PRIORITY_NORMAL*/) { static const int WinThreadPriorities[5] = { THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST }; // Only begin recording if the MIDI input device has been opened if(m_State == OPENED) { // Change state m_State = RECORDING; //m_Thread = ::AfxBeginThread((AFX_THREADPROC)HeaderProc, this); if (!m_hThread) { m_hThread = CreateThread(NULL, 0, &HeaderProc, (void*)this, 0, &m_threadID); if (RecordingThreadPriority >= 0 && RecordingThreadPriority < (signed)sizeof(WinThreadPriorities) / (signed)sizeof(int)) SetThreadPriority(m_hThread, WinThreadPriorities[RecordingThreadPriority]); } // Start recording MMRESULT Result = ::midiInStart(m_DevHandle); // If recording attempt failed... if(Result != MMSYSERR_NOERROR) { // Revert back to opened state m_State = OPENED; // Signal the worker thread to finish ::SetEvent(m_Event); ::WaitForSingleObject(m_hThread, INFINITE); // Throw exception throw CMIDIInException(Result); } } }
// Constructor CMIDIInDevice::CMIDIInHeader::CMIDIInHeader(HMIDIIN DevHandle, LPSTR Buffer, DWORD BufferLength) : m_DevHandle(DevHandle) { // Initialize header m_MIDIHdr.lpData = Buffer; m_MIDIHdr.dwBufferLength = BufferLength; m_MIDIHdr.dwFlags = 0; // Prepare header MMRESULT Result = ::midiInPrepareHeader(DevHandle, &m_MIDIHdr, sizeof m_MIDIHdr); // If an error occurred, throw exception if(Result != MMSYSERR_NOERROR) { throw CMIDIInException(Result); } }
// Opens the MIDI input device void CMIDIInDevice::Open(UINT DeviceId) { // Makes sure the previous device, if any, is closed before // opening another one Close(); // Open MIDI input device MMRESULT Result = ::midiInOpen(&m_DevHandle, DeviceId, reinterpret_cast<DWORD>(MidiInProc), reinterpret_cast<DWORD>(this), CALLBACK_FUNCTION); // If we are able to open the device, change state if(Result == MMSYSERR_NOERROR) { m_State = OPENED; } // Else opening failed, throw exception else { throw CMIDIInException(Result); } }