From: <sag...@us...> - 2012-04-13 20:46:47
|
Revision: 1246 http://modplug.svn.sourceforge.net/modplug/?rev=1246&view=rev Author: saga-games Date: 2012-04-13 20:46:38 +0000 (Fri, 13 Apr 2012) Log Message: ----------- [Ref] Cleaned up a lot of MIDI related stuff. Modified Paths: -------------- trunk/OpenMPT/mptrack/MIDIMacroDialog.cpp trunk/OpenMPT/mptrack/MIDIMappingDialog.cpp trunk/OpenMPT/mptrack/MIDIMappingDialog.h trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Mpt_midi.cpp trunk/OpenMPT/mptrack/View_ins.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/Vstplug.h trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/mptrack/test/test.cpp trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/MIDIMacros.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Sndmix.cpp trunk/OpenMPT/soundlib/plugins/PluginEventQueue.h Added Paths: ----------- trunk/OpenMPT/mptrack/MIDIMapping.cpp trunk/OpenMPT/mptrack/MIDIMapping.h trunk/OpenMPT/soundlib/MIDIEvents.cpp trunk/OpenMPT/soundlib/MIDIEvents.h Removed Paths: ------------- trunk/OpenMPT/soundlib/midi.h Modified: trunk/OpenMPT/mptrack/MIDIMacroDialog.cpp =================================================================== --- trunk/OpenMPT/mptrack/MIDIMacroDialog.cpp 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/MIDIMacroDialog.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -16,6 +16,7 @@ #include "Vstplug.h" #include "resource.h" #include "MIDIMacroDialog.h" +#include "../soundlib/MIDIEvents.h" BEGIN_MESSAGE_MAP(CMidiMacroSetup, CDialog) @@ -80,9 +81,9 @@ OnSFxChanged(); // MIDI CC selection box - for (int cc = MIDICC_start; cc <= MIDICC_end; cc++) + for (int cc = MIDIEvents::MIDICC_start; cc <= MIDIEvents::MIDICC_end; cc++) { - wsprintf(s, "CC %02d %s", cc, MidiCCNames[cc]); + wsprintf(s, "CC %02d %s", cc, MIDIEvents::MidiCCNames[cc]); m_CbnMacroCC.SetItemData(m_CbnMacroCC.AddString(s), cc); } Added: trunk/OpenMPT/mptrack/MIDIMapping.cpp =================================================================== --- trunk/OpenMPT/mptrack/MIDIMapping.cpp (rev 0) +++ trunk/OpenMPT/mptrack/MIDIMapping.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -0,0 +1,182 @@ +/* + * MIDIMapping.cpp + * --------------- + * Purpose: MIDI Mapping management classes + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#include "stdafx.h" +#include "MIDIMapping.h" +#include "../soundlib/MIDIEvents.h" +#include "Mainfrm.h" + + +CString CMIDIMappingDirective::ToString() const +//--------------------------------------------- +{ + CString str; str.Preallocate(20); + char flags[4] = "000"; + if(m_Active) flags[0] = '1'; + if(m_CaptureMIDI) flags[1] = '1'; + if(m_AllowPatternEdit) flags[2] = '1'; + str.Format("%s:%d:%x:%d:%d:%d", flags, (int)GetChannel(), (int)GetEvent(), (int)GetController(), (int)m_PluginIndex, m_Parameter); + str.Trim(); + return str; +} + + +size_t CMIDIMapper::GetSerializationSize() const +//---------------------------------------------- +{ + size_t s = 0; + for(const_iterator citer = Begin(); citer != End(); citer++) + { + if(citer->GetParamIndex() <= uint8_max) {s += 5; continue;} + if(citer->GetParamIndex() <= uint16_max) {s += 6; continue;} + s += 8; + } + return s; +} + + +void CMIDIMapper::Serialize(FILE* f) const +//---------------------------------------- +{ + //Bytes: 1 Flags, 2 key, 1 plugindex, 1,2,4,8 plug/etc. + for(const_iterator citer = Begin(); citer != End(); citer++) + { + uint16 temp16 = (citer->GetChnEvent() << 1) + (citer->GetController() << 9); + if(citer->GetAnyChannel()) temp16 |= 1; + uint32 temp32 = citer->GetParamIndex(); + + uint8 temp8 = citer->IsActive(); //bit 0 + if(citer->GetCaptureMIDI()) temp8 |= (1 << 1); //bit 1 + //bits 2-4: Mapping type: 0 for plug param control. + //bit 5: + if(citer->GetAllowPatternEdit()) temp8 |= (1 << 5); + //bits 6-7: Size: 5, 6, 8, 12 + + BYTE parambytes = 4; + if(temp32 <= uint16_max) + { + if(temp32 <= uint8_max) parambytes = 1; + else {parambytes = 2; temp8 |= (1 << 6);} + } + else temp8 |= (2 << 6); + + fwrite(&temp8, 1, sizeof(temp8), f); + fwrite(&temp16, 1, sizeof(temp16), f); + temp8 = citer->GetPlugIndex(); + fwrite(&temp8, 1, sizeof(temp8), f); + fwrite(&temp32, 1, parambytes, f); + } +} + + +bool CMIDIMapper::Deserialize(const BYTE* ptr, const size_t size) +//--------------------------------------------------------------- +{ + m_Directives.clear(); + const BYTE* endptr = ptr + size; + while(ptr + 5 <= endptr) + { + uint8 i8 = 0; + uint16 i16 = 0; + uint32 i32 = 0; + memcpy(&i8, ptr, 1); ptr++; + BYTE psize = 0; + switch(i8 >> 6) + { + case 0: psize = 5; break; + case 1: psize = 6; break; + case 2: psize = 8; break; + case 3: default: psize = 12; break; + } + + if(ptr + psize - 1 > endptr) return true; + if(((i8 >> 2) & 7) != 0) {ptr += psize - 1; continue;} //Skipping unrecognised mapping types. + + CMIDIMappingDirective s; + s.SetActive((i8 & 1) != 0); + s.SetCaptureMIDI((i8 & (1 << 1)) != 0); + s.SetAllowPatternEdit((i8 & (1 << 5)) != 0); + memcpy(&i16, ptr, 2); ptr += 2; //Channel, event, MIDIbyte1. + memcpy(&i8, ptr, 1); ptr++; //Plugindex + const BYTE remainingbytes = psize - 4; + memcpy(&i32, ptr, min(4, remainingbytes)); ptr += remainingbytes; + + s.SetChannel(((i16 & 1) != 0) ? 0 : 1 + ((i16 >> 1) & 0xF)); + s.SetEvent(static_cast<BYTE>((i16 >> 5) & 0xF)); + s.SetController(i16 >> 9); + s.SetPlugIndex(i8); + s.SetParamIndex(i32); + AddDirective(s); + } + + return false; +} + + +bool CMIDIMapper::OnMIDImsg(const DWORD midimsg, BYTE& mappedIndex, uint32& paramindex, BYTE& paramval) +//----------------------------------------------------------------------------------------------------- +{ + bool captured = false; + + if(MIDIEvents::GetTypeFromEvent(midimsg) != MIDIEvents::evControllerChange) return captured; + //For now only controllers can be mapped so if event is not controller change, + //no mapping will be found and thus no search is done. + //NOTE: The event value is not checked in code below. + + const BYTE controller = MIDIEvents::GetDataByte1FromEvent(midimsg); + + const_iterator citer = std::lower_bound(Begin(), End(), controller); + + const BYTE channel = MIDIEvents::GetChannelFromEvent(midimsg); + + for(; citer != End() && citer->GetController() == controller && !captured; citer++) + { + if(!citer->IsActive()) continue; + BYTE plugindex = 0; + uint32 param = 0; + if( citer->GetAnyChannel() || channel+1 == citer->GetChannel()) + { + plugindex = citer->GetPlugIndex(); + param = citer->GetParamIndex(); + if(citer->GetAllowPatternEdit()) + { + mappedIndex = plugindex; + paramindex = param; + paramval = MIDIEvents::GetDataByte2FromEvent(midimsg); + } + if(citer->GetCaptureMIDI()) captured = true; + + if(plugindex > 0 && plugindex <= MAX_MIXPLUGINS) + { + IMixPlugin* pPlug = m_rSndFile.m_MixPlugins[plugindex-1].pMixPlugin; + if(!pPlug) continue; + pPlug->SetZxxParameter(param, (midimsg >> 16) & 0x7F); + CMainFrame::GetMainFrame()->ThreadSafeSetModified(m_rSndFile.GetpModDoc()); + } + } + } + + return captured; +} + + +bool CMIDIMapper::Swap(const size_t a, const size_t b) +//---------------------------------------------------- +{ + if(a < m_Directives.size() && b < m_Directives.size()) + { + CMIDIMappingDirective temp = m_Directives[a]; + m_Directives[a] = m_Directives[b]; + m_Directives[b] = temp; + Sort(); + return false; + } + else return true; +} Added: trunk/OpenMPT/mptrack/MIDIMapping.h =================================================================== --- trunk/OpenMPT/mptrack/MIDIMapping.h (rev 0) +++ trunk/OpenMPT/mptrack/MIDIMapping.h 2012-04-13 20:46:38 UTC (rev 1246) @@ -0,0 +1,125 @@ +/* + * MIDIMapping.h + * ------------- + * Purpose: MIDI Mapping management classes + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + +#include <vector> +#include <algorithm> +using std::vector; + + +//========================= +class CMIDIMappingDirective +//========================= +{ +public: + CMIDIMappingDirective() : + m_Active(true), m_CaptureMIDI(false), m_AllowPatternEdit(true), m_AnyChannel(true), + m_ChnEvent(0xB << 4), m_MIDIByte1(0), m_PluginIndex(1), m_Parameter(0) {} + + void SetActive(const bool b) {m_Active = b;} + bool IsActive() const {return m_Active;} + + void SetCaptureMIDI(const bool b) {m_CaptureMIDI = b;} + bool GetCaptureMIDI() const {return m_CaptureMIDI;} + + void SetAllowPatternEdit(const bool b) {m_AllowPatternEdit = b;} + bool GetAllowPatternEdit() const {return m_AllowPatternEdit;} + + bool GetAnyChannel() const {return m_AnyChannel;} + + //Note: In these functions, channel value is in range [1,16], + //GetChannel() returns 0 on 'any channel'. + void SetChannel(const int c){if(c < 1 || c > 16) m_AnyChannel = true; else {m_ChnEvent &= ~0xF; m_ChnEvent |= c-1; m_AnyChannel = false;}} + BYTE GetChannel() const {return (m_AnyChannel) ? 0 : (m_ChnEvent & 0xF) + 1;} + + void SetEvent(BYTE e) {if(e > 15) e = 15; m_ChnEvent &= ~0xF0; m_ChnEvent |= (e << 4);} + BYTE GetEvent() const {return static_cast<BYTE>((m_ChnEvent >> 4) & 0xF);} + + void SetController(int controller) {if(controller > 127) controller = 127; m_MIDIByte1 = static_cast<BYTE>(controller);} + BYTE GetController() const {return m_MIDIByte1;} + + //Note: Plug index starts from 1. + void SetPlugIndex(const int i) {m_PluginIndex = static_cast<BYTE>(i);} + BYTE GetPlugIndex() const {return m_PluginIndex;} + + void SetParamIndex(const int i) {m_Parameter = i;} + uint32 GetParamIndex() const {return m_Parameter;} + + bool IsDefault() const {return *this == CMIDIMappingDirective();} + + bool operator==(const CMIDIMappingDirective& d) const {return memcmp(this, &d, sizeof(CMIDIMappingDirective)) == 0;} + + CString ToString() const; + + BYTE GetChnEvent() const {return m_ChnEvent;} + +private: + bool m_Active; + bool m_CaptureMIDI; //When true, MIDI data should not be processed beyond this directive + bool m_AllowPatternEdit; //When true, the mapping can be used for modifying pattern. + bool m_AnyChannel; + uint8 m_ChnEvent; //0-3 channel, 4-7 event + BYTE m_MIDIByte1; + BYTE m_PluginIndex; + uint32 m_Parameter; +}; + +class CSoundFile; +inline bool operator<(const CMIDIMappingDirective& a, const CMIDIMappingDirective& b) {return a.GetController() < b.GetController();} +inline bool operator<(const CMIDIMappingDirective& d, const BYTE& ctrlVal) {return d.GetController() < ctrlVal;} +inline bool operator<(const BYTE& ctrlVal, const CMIDIMappingDirective& d) {return ctrlVal < d.GetController();} + +//=============== +class CMIDIMapper +//=============== +{ +public: + typedef vector<CMIDIMappingDirective>::const_iterator const_iterator; + CMIDIMapper(CSoundFile& sndfile) : m_rSndFile(sndfile) {} + + //If mapping found: + // -mappedIndex is set to mapped value(plug index) + // -paramindex to mapped parameter + // -paramvalue to parameter value. + //In case of multiple mappings, these get the values from the last mapping found. + //Returns true if MIDI was 'captured' by some directive, false otherwise. + bool OnMIDImsg(const DWORD midimsg, BYTE& mappedIndex, uint32& paramindex, BYTE& paramvalue); + + //Swaps the positions of two elements. Returns true if swap was not done. + bool Swap(const size_t a, const size_t b); + + //Return the index after sorting for the added element + size_t SetDirective(const size_t i, const CMIDIMappingDirective& d) {m_Directives[i] = d; Sort(); return std::find(m_Directives.begin(), m_Directives.end(), d) - m_Directives.begin();} + + //Return the index after sorting for the added element + size_t AddDirective(const CMIDIMappingDirective& d) {m_Directives.push_back(d); Sort(); return std::find(m_Directives.begin(), m_Directives.end(), d) - m_Directives.begin();} + + void RemoveDirective(const size_t i) {m_Directives.erase(m_Directives.begin()+i);} + + const CMIDIMappingDirective& GetDirective(const size_t i) const {return m_Directives[i];} + + const_iterator Begin() const {return m_Directives.begin();} + const_iterator End() const {return m_Directives.end();} + size_t GetCount() const {return m_Directives.size();} + + size_t GetSerializationSize() const; + void Serialize(FILE* f) const; + bool Deserialize(const BYTE* ptr, const size_t size); //Return false if succesful, true otherwise. + + bool AreOrderEqual(const size_t a, const size_t b) {return !(m_Directives[a] < m_Directives[b] || m_Directives[b] < m_Directives[a]);} + +private: + void Sort() {std::stable_sort(m_Directives.begin(), m_Directives.end());} + +private: + CSoundFile& m_rSndFile; + vector<CMIDIMappingDirective> m_Directives; +}; Modified: trunk/OpenMPT/mptrack/MIDIMappingDialog.cpp =================================================================== --- trunk/OpenMPT/mptrack/MIDIMappingDialog.cpp 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/MIDIMappingDialog.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -11,7 +11,7 @@ #include "stdafx.h" #include "mptrack.h" #include "MIDIMappingDialog.h" -#include "midi.h" +#include "../soundlib/MIDIEvents.h" #include "mainfrm.h" @@ -66,12 +66,12 @@ LRESULT CMIDIMappingDialog::OnMidiMsg(WPARAM dwMidiDataParam, LPARAM) //------------------------------------------------------------------- { - const BYTE event = GetFromMIDIMsg_Event(dwMidiDataParam); + const BYTE event = MIDIEvents::GetTypeFromEvent(dwMidiDataParam); if(event == 0xB && IsDlgButtonChecked(IDC_CHECK_MIDILEARN)) { - m_ChannelCBox.SetCurSel(1+GetFromMIDIMsg_Channel(dwMidiDataParam)); + m_ChannelCBox.SetCurSel(1 + MIDIEvents::GetChannelFromEvent(dwMidiDataParam)); m_EventCBox.SetCurSel(0); - m_ControllerCBox.SetCurSel(GetFromMIDIMsg_DataByte1(dwMidiDataParam)); + m_ControllerCBox.SetCurSel(MIDIEvents::GetDataByte1FromEvent(dwMidiDataParam)); OnCbnSelchangeComboChannel(); OnCbnSelchangeComboEvent(); OnCbnSelchangeComboController(); @@ -89,10 +89,10 @@ m_EventCBox.SetCurSel(0); //Add controller names. - for(size_t i = MIDICC_start; i<=MIDICC_end; i++) + for(size_t i = MIDIEvents::MIDICC_start; i <= MIDIEvents::MIDICC_end; i++) { CString temp; - temp.Format("%3d %s", i, MidiCCNames[i]); + temp.Format("%3d %s", i, MIDIEvents::MidiCCNames[i]); m_ControllerCBox.AddString(temp); } @@ -147,7 +147,7 @@ m_ChannelCBox.SetCurSel(activeSetting.GetChannel()); - if(m_Setting.GetEvent() == MIDIEVENT_CONTROLLERCHANGE) + if(m_Setting.GetEvent() == MIDIEvents::evControllerChange) m_EventCBox.SetCurSel(0); else m_EventCBox.SetCurSel(-1); @@ -328,10 +328,10 @@ str.AppendChar('.'); //Controller name - if(s.GetController() <= MIDICC_end) + if(s.GetController() <= MIDIEvents::MIDICC_end) { CString tstr; - tstr.Format("%d %s", s.GetController(), MidiCCNames[s.GetController()]); + tstr.Format("%d %s", s.GetController(), MIDIEvents::MidiCCNames[s.GetController()]); str.Insert(20, tstr); } Modified: trunk/OpenMPT/mptrack/MIDIMappingDialog.h =================================================================== --- trunk/OpenMPT/mptrack/MIDIMappingDialog.h 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/MIDIMappingDialog.h 2012-04-13 20:46:38 UTC (rev 1246) @@ -10,7 +10,6 @@ #pragma once #include "moddoc.h" -#include "midi.h" #include <vector> #include "afxwin.h" #include "afxcmn.h" Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2012-04-13 20:46:38 UTC (rev 1246) @@ -488,6 +488,8 @@ void SetMidiRecordWnd(HWND hwnd) { m_hWndMidi = hwnd; } HWND GetMidiRecordWnd() const { return m_hWndMidi; } + static int ApplyVolumeRelatedSettings(const DWORD &dwParam1, const BYTE midivolume); + // static functions public: static CMainFrame *GetMainFrame() { return (CMainFrame *)theApp.m_pMainWnd; } Modified: trunk/OpenMPT/mptrack/Mpt_midi.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpt_midi.cpp 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/Mpt_midi.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -10,11 +10,9 @@ #include "stdafx.h" #include <mmsystem.h> -#include "mptrack.h" #include "mainfrm.h" -#include "moddoc.h" #include "dlsbank.h" -#include "midi.h" +#include "../soundlib/MIDIEvents.h" #include "Moptions.h" // for OPTIONS_PAGE_MIDI //#define MPTMIDI_RECORDLOG @@ -24,10 +22,10 @@ //Get Midi message(dwParam1), apply MIDI settings having effect on volume, and return //the volume value [0, 256]. In addition value -1 is used as 'use default value'-indicator. -int ApplyVolumeRelatedMidiSettings(const DWORD &dwParam1, const BYTE midivolume) -//------------------------------------------------------------------------------ +int CMainFrame::ApplyVolumeRelatedSettings(const DWORD &dwParam1, const BYTE midivolume) +//-------------------------------------------------------------------------------------- { - int nVol = GetFromMIDIMsg_DataByte2(dwParam1); + int nVol = MIDIEvents::GetDataByte2FromEvent(dwParam1); if (CMainFrame::GetSettings().m_dwMidiSetup & MIDISETUP_RECORDVELOCITY) { nVol = (CDLSBank::DLSMidiVolumeToLinear(nVol)+255) >> 8; @@ -51,12 +49,12 @@ //----------------------------------------------------------------------- { if ( (CMainFrame::GetSettings().m_dwMidiSetup & MIDISETUP_TRANSPOSEKEYBOARD) - && (GetFromMIDIMsg_Channel(dwParam1) != 9) ) + && (MIDIEvents::GetChannelFromEvent(dwParam1) != 9) ) { int nTranspose = rMainFrm.GetBaseOctave() - 4; if (nTranspose) { - int note = GetFromMIDIMsg_DataByte1(dwParam1); + int note = MIDIEvents::GetDataByte1FromEvent(dwParam1); if (note < 0x80) { note += nTranspose * 12; @@ -94,9 +92,9 @@ hWndMidi = pMainFrm->GetMidiRecordWnd(); if ((hWndMidi) && ((wMsg == MIM_DATA) || (wMsg == MIM_MOREDATA))) { - switch (dwParam1 & 0xF0) + switch(MIDIEvents::GetTypeFromEvent(dwParam1)) { - case 0xF0: // Midi Clock + case MIDIEvents::evSystem: // Midi Clock if (wMsg == MIM_DATA) { DWORD dwTime = timeGetTime(); @@ -107,8 +105,8 @@ } else break; - case 0x80: // Note Off - case 0x90: // Note On + case MIDIEvents::evNoteOff: // Note Off + case MIDIEvents::evNoteOn: // Note On ApplyTransposeKeyboardSetting(*pMainFrm, dwParam1); default: @@ -170,175 +168,3 @@ { if (pCmdUI) pCmdUI->SetCheck((shMidiIn) ? TRUE : FALSE); } - -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- - - -CString CMIDIMappingDirective::ToString() const -//--------------------------------------------- -{ - CString str; str.Preallocate(20); - char flags[4] = "000"; - if(m_Active) flags[0] = '1'; - if(m_CaptureMIDI) flags[1] = '1'; - if(m_AllowPatternEdit) flags[2] = '1'; - str.Format("%s:%d:%x:%d:%d:%d", flags, (int)GetChannel(), (int)GetEvent(), (int)GetController(), (int)m_PluginIndex, m_Parameter); - str.Trim(); - return str; -} - - -size_t CMIDIMapper::GetSerializationSize() const -//---------------------------------------------- -{ - size_t s = 0; - for(const_iterator citer = Begin(); citer != End(); citer++) - { - if(citer->GetParamIndex() <= uint8_max) {s += 5; continue;} - if(citer->GetParamIndex() <= uint16_max) {s += 6; continue;} - s += 8; - } - return s; -} - - -void CMIDIMapper::Serialize(FILE* f) const -//---------------------------------------- -{ - //Bytes: 1 Flags, 2 key, 1 plugindex, 1,2,4,8 plug/etc. - for(const_iterator citer = Begin(); citer != End(); citer++) - { - uint16 temp16 = (citer->GetChnEvent() << 1) + (citer->GetController() << 9); - if(citer->GetAnyChannel()) temp16 |= 1; - uint32 temp32 = citer->GetParamIndex(); - - uint8 temp8 = citer->IsActive(); //bit 0 - if(citer->GetCaptureMIDI()) temp8 |= (1 << 1); //bit 1 - //bits 2-4: Mapping type: 0 for plug param control. - //bit 5: - if(citer->GetAllowPatternEdit()) temp8 |= (1 << 5); - //bits 6-7: Size: 5, 6, 8, 12 - - BYTE parambytes = 4; - if(temp32 <= uint16_max) - { - if(temp32 <= uint8_max) parambytes = 1; - else {parambytes = 2; temp8 |= (1 << 6);} - } - else temp8 |= (2 << 6); - - fwrite(&temp8, 1, sizeof(temp8), f); - fwrite(&temp16, 1, sizeof(temp16), f); - temp8 = citer->GetPlugIndex(); - fwrite(&temp8, 1, sizeof(temp8), f); - fwrite(&temp32, 1, parambytes, f); - } -} - - -bool CMIDIMapper::Deserialize(const BYTE* ptr, const size_t size) -//--------------------------------------------------------------- -{ - m_Directives.clear(); - const BYTE* endptr = ptr + size; - while(ptr + 5 <= endptr) - { - uint8 i8 = 0; - uint16 i16 = 0; - uint32 i32 = 0; - memcpy(&i8, ptr, 1); ptr++; - BYTE psize = 0; - switch(i8 >> 6) - { - case 0: psize = 5; break; - case 1: psize = 6; break; - case 2: psize = 8; break; - case 3: default: psize = 12; break; - } - - if(ptr + psize - 1 > endptr) return true; - if(((i8 >> 2) & 7) != 0) {ptr += psize - 1; continue;} //Skipping unrecognised mapping types. - - CMIDIMappingDirective s; - s.SetActive((i8 & 1) != 0); - s.SetCaptureMIDI((i8 & (1 << 1)) != 0); - s.SetAllowPatternEdit((i8 & (1 << 5)) != 0); - memcpy(&i16, ptr, 2); ptr += 2; //Channel, event, MIDIbyte1. - memcpy(&i8, ptr, 1); ptr++; //Plugindex - const BYTE remainingbytes = psize - 4; - memcpy(&i32, ptr, min(4, remainingbytes)); ptr += remainingbytes; - - s.SetChannel(((i16 & 1) != 0) ? 0 : 1 + ((i16 >> 1) & 0xF)); - s.SetEvent(static_cast<BYTE>((i16 >> 5) & 0xF)); - s.SetController(i16 >> 9); - s.SetPlugIndex(i8); - s.SetParamIndex(i32); - AddDirective(s); - } - - return false; -} - - -bool CMIDIMapper::OnMIDImsg(const DWORD midimsg, BYTE& mappedIndex, uint32& paramindex, BYTE& paramval) -//----------------------------------------------------------------------------------------------------- -{ - bool captured = false; - - if(GetFromMIDIMsg_Event(midimsg) != MIDIEVENT_CONTROLLERCHANGE) return captured; - //For now only controllers can be mapped so if event is not controller change, - //no mapping will be found and thus no search is done. - //NOTE: The event value is not checked in code below. - - const BYTE controller = GetFromMIDIMsg_DataByte1(midimsg); - - const_iterator citer = std::lower_bound(Begin(), End(), controller); - - const BYTE channel = GetFromMIDIMsg_Channel(midimsg); - - for(; citer != End() && citer->GetController() == controller && !captured; citer++) - { - if(!citer->IsActive()) continue; - BYTE plugindex = 0; - uint32 param = 0; - if( citer->GetAnyChannel() || channel+1 == citer->GetChannel()) - { - plugindex = citer->GetPlugIndex(); - param = citer->GetParamIndex(); - if(citer->GetAllowPatternEdit()) - { - mappedIndex = plugindex; - paramindex = param; - paramval = GetFromMIDIMsg_DataByte2(midimsg); - } - if(citer->GetCaptureMIDI()) captured = true; - - if(plugindex > 0 && plugindex <= MAX_MIXPLUGINS) - { - IMixPlugin* pPlug = m_rSndFile.m_MixPlugins[plugindex-1].pMixPlugin; - if(!pPlug) continue; - pPlug->SetZxxParameter(param, (midimsg >> 16) & 0x7F); - CMainFrame::GetMainFrame()->ThreadSafeSetModified(m_rSndFile.GetpModDoc()); - } - } - } - - return captured; -} - - -bool CMIDIMapper::Swap(const size_t a, const size_t b) -//---------------------------------------------------- -{ - if(a < m_Directives.size() && b < m_Directives.size()) - { - CMIDIMappingDirective temp = m_Directives[a]; - m_Directives[a] = m_Directives[b]; - m_Directives[b] = temp; - Sort(); - return false; - } - else return true; -} Modified: trunk/OpenMPT/mptrack/View_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_ins.cpp 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/View_ins.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -20,8 +20,8 @@ #include "dlsbank.h" #include "channelManagerDlg.h" #include "ScaleEnvPointsDlg.h" -#include ".\view_ins.h" -#include "midi.h" +#include "view_ins.h" +#include "../soundlib/MIDIEvents.h" #define ENV_ZOOM 4.0f #define ENV_MIN_ZOOM 2.0f @@ -2152,15 +2152,15 @@ static BYTE midivolume = 127; CModDoc *pModDoc = GetDocument(); - BYTE midiByte1 = GetFromMIDIMsg_DataByte1(dwMidiData); - BYTE midiByte2 = GetFromMIDIMsg_DataByte2(dwMidiData); + BYTE midiByte1 = MIDIEvents::GetDataByte1FromEvent(dwMidiData); + BYTE midiByte2 = MIDIEvents::GetDataByte2FromEvent(dwMidiData); CSoundFile* pSndFile = (pModDoc) ? pModDoc->GetSoundFile() : NULL; if (!pSndFile) return 0; const BYTE nNote = midiByte1 + 1; // +1 is for MPT, where middle C is 61 int nVol = midiByte2; - BYTE event = GetFromMIDIMsg_Event(dwMidiData); + BYTE event = MIDIEvents::GetTypeFromEvent(dwMidiData); if ((event == 0x9) && !nVol) event = 0x8; //Convert event to note-off if req'd BYTE mappedIndex = 0, paramValue = 0; @@ -2170,42 +2170,42 @@ switch(event) { - case MIDIEVENT_NOTEOFF: // Note Off - midiByte2 = 0; + case MIDIEvents::evNoteOff: // Note Off + midiByte2 = 0; - case MIDIEVENT_NOTEON: // Note On - pModDoc->NoteOff(nNote, false, m_nInstrument); - if (midiByte2 & 0x7F) - { - nVol = ApplyVolumeRelatedMidiSettings(dwMidiData, midivolume); - pModDoc->PlayNote(nNote, m_nInstrument, 0, false, nVol); - } + case MIDIEvents::evNoteOn: // Note On + pModDoc->NoteOff(nNote, false, m_nInstrument); + if (midiByte2 & 0x7F) + { + nVol = CMainFrame::ApplyVolumeRelatedSettings(dwMidiData, midivolume); + pModDoc->PlayNote(nNote, m_nInstrument, 0, false, nVol); + } break; - case MIDIEVENT_CONTROLLERCHANGE: //Controller change - switch(midiByte1) - { - case 0x7: //Volume - midivolume = midiByte2; - break; - } + case MIDIEvents::evControllerChange: //Controller change + switch(midiByte1) + { + case MIDIEvents::MIDICC_Volume_Coarse: //Volume + midivolume = midiByte2; + break; + } - default: - if((CMainFrame::GetSettings().m_dwMidiSetup & MIDISETUP_MIDITOPLUG) && CMainFrame::GetMainFrame()->GetModPlaying() == pModDoc) + default: + if((CMainFrame::GetSettings().m_dwMidiSetup & MIDISETUP_MIDITOPLUG) && CMainFrame::GetMainFrame()->GetModPlaying() == pModDoc) + { + const INSTRUMENTINDEX instr = m_nInstrument; + IMixPlugin* plug = pSndFile->GetInstrumentPlugin(instr); + if(plug) { - const INSTRUMENTINDEX instr = m_nInstrument; - IMixPlugin* plug = pSndFile->GetInstrumentPlugin(instr); - if(plug) + plug->MidiSend(dwMidiData); + // Sending midi may modify the plug. For now, if MIDI data + // is not active sensing or aftertouch messages, set modified. + if(dwMidiData != MIDIEvents::BuildSystemEvent(MIDIEvents::sysActiveSense) && event != MIDIEvents::evPolyAftertouch && event != MIDIEvents::evChannelAftertouch) { - plug->MidiSend(dwMidiData); - // Sending midi may modify the plug. For now, if MIDI data - // is not active sensing or aftertouch messages, set modified. - if(dwMidiData != MIDISTATUS_ACTIVESENSING && event != MIDIEVENT_POLYAFTERTOUCH && event != MIDIEVENT_CHANAFTERTOUCH) - { - CMainFrame::GetMainFrame()->ThreadSafeSetModified(pModDoc); - } + CMainFrame::GetMainFrame()->ThreadSafeSetModified(pModDoc); } } + } break; } Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -29,7 +29,7 @@ #include "View_gen.h" #include "MIDIMacros.h" #include "../common/misc_util.h" -#include "midi.h" +#include "../soundlib/MIDIEvents.h" #include <cmath> #define PLUGNAME_HEIGHT 16 //rewbs.patPlugName @@ -3535,7 +3535,7 @@ // +---------------------------+---------------------------+-------------+-------------+ // | Velocity (0-127) | Note (middle C is 60) | Event | Channel | // +---------------------------+---------------------------+-------------+-------------+ -//(http://www.borg.com/~jglatt/tech/midispec.htm) +//(http://home.roadrunner.com/~jgglatt/tech/midispec.htm) //Notes: //. Initial midi data handling is done in MidiInCallBack(). @@ -3546,15 +3546,15 @@ // BYTE event = (dwMidiData>>16) & 0x64; //. Sample- and instrumentview handle midi mesages in their own methods. - const BYTE nByte1 = GetFromMIDIMsg_DataByte1(dwMidiData); - const BYTE nByte2 = GetFromMIDIMsg_DataByte2(dwMidiData); + const BYTE nByte1 = MIDIEvents::GetDataByte1FromEvent(dwMidiData); + const BYTE nByte2 = MIDIEvents::GetDataByte2FromEvent(dwMidiData); const BYTE nNote = nByte1 + 1; // +1 is for MPT, where middle C is 61 int nVol = nByte2; // At this stage nVol is a non linear value in [0;127] // Need to convert to linear in [0;64] - see below - BYTE event = GetFromMIDIMsg_Event(dwMidiData); + BYTE event = MIDIEvents::GetTypeFromEvent(dwMidiData); - if ((event == MIDIEVENT_NOTEON) && !nVol) event = MIDIEVENT_NOTEOFF; //Convert event to note-off if req'd + if ((event == MIDIEvents::evNoteOn) && !nVol) event = MIDIEvents::evNoteOff; //Convert event to note-off if req'd // Handle MIDI mapping. @@ -3581,15 +3581,15 @@ switch(event) { - case MIDIEVENT_NOTEOFF: // Note Off + case MIDIEvents::evNoteOff: // Note Off // The following method takes care of: // . Silencing specific active notes (just setting nNote to 255 as was done before is not acceptible) // . Entering a note off in pattern if required TempStopNote(nNote, ((CMainFrame::GetSettings().m_dwMidiSetup & MIDISETUP_RECORDNOTEOFF) != 0)); break; - case MIDIEVENT_NOTEON: // Note On - nVol = ApplyVolumeRelatedMidiSettings(dwMidiData, midivolume); + case MIDIEvents::evNoteOn: // Note On + nVol = CMainFrame::ApplyVolumeRelatedSettings(dwMidiData, midivolume); if(nVol < 0) nVol = -1; else nVol = (nVol + 3) / 4; //Value from [0,256] to [0,64] TempEnterNote(nNote, true, nVol); @@ -3600,14 +3600,14 @@ break; - case MIDIEVENT_POLYAFTERTOUCH: - case MIDIEVENT_CHANAFTERTOUCH: + case MIDIEvents::evPolyAftertouch: + case MIDIEvents::evChannelAftertouch: break; - case MIDIEVENT_CONTROLLERCHANGE: //Controller change + case MIDIEvents::evControllerChange: //Controller change switch(nByte1) { - case MIDICC_Volume_Coarse: //Volume + case MIDIEvents::MIDICC_Volume_Coarse: //Volume midivolume = nByte2; break; } @@ -3666,7 +3666,7 @@ plug->MidiSend(dwMidiData); // Sending midi may modify the plug. For now, if MIDI data // is not active sensing, set modified. - if(dwMidiData != MIDISTATUS_ACTIVESENSING) + if(dwMidiData != MIDIEvents::BuildSystemEvent(MIDIEvents::sysActiveSense)) pMainFrm->ThreadSafeSetModified(pModDoc); } Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -19,7 +19,7 @@ #include "dlsbank.h" #include "channelManagerDlg.h" #include "view_smp.h" -#include "midi.h" +#include "../soundlib/MIDIEvents.h" #include "SampleEditorDialogs.h" #include "modsmp_ctrl.h" #include "Wav.h" @@ -2568,39 +2568,39 @@ static BYTE midivolume = 127; CModDoc *pModDoc = GetDocument(); - BYTE midibyte1 = GetFromMIDIMsg_DataByte1(dwMidiData); - BYTE midibyte2 = GetFromMIDIMsg_DataByte2(dwMidiData); + BYTE midibyte1 = MIDIEvents::GetDataByte1FromEvent(dwMidiData); + BYTE midibyte2 = MIDIEvents::GetDataByte2FromEvent(dwMidiData); CSoundFile* pSndFile = (pModDoc) ? pModDoc->GetSoundFile() : NULL; if (!pSndFile) return 0; const BYTE nNote = midibyte1 + 1; // +1 is for MPT, where middle C is 61 int nVol = midibyte2; - BYTE event = GetFromMIDIMsg_Event(dwMidiData); - if ((event == 0x9) && !nVol) event = 0x8; //Convert event to note-off if req'd + BYTE event = MIDIEvents::GetTypeFromEvent(dwMidiData); + if ((event == MIDIEvents::evNoteOn) && !nVol) event = MIDIEvents::evNoteOff; //Convert event to note-off if req'd switch(event) { - case 0x8: // Note Off - midibyte2 = 0; + case MIDIEvents::evNoteOff: // Note Off + midibyte2 = 0; - case 0x9: // Note On - pModDoc->NoteOff(nNote, true); - if (midibyte2 & 0x7F) - { - nVol = ApplyVolumeRelatedMidiSettings(dwMidiData, midivolume); - //pModDoc->PlayNote(nNote, 0, m_nSample, FALSE, nVol); - PlayNote(nNote); - } + case MIDIEvents::evNoteOn: // Note On + pModDoc->NoteOff(nNote, true); + if(midibyte2 & 0x7F) + { + nVol = CMainFrame::ApplyVolumeRelatedSettings(dwMidiData, midivolume); + //pModDoc->PlayNote(nNote, 0, m_nSample, FALSE, nVol); + PlayNote(nNote); + } break; - case 0xB: //Controller change - switch(midibyte1) - { - case 0x7: //Volume - midivolume = midibyte2; - break; - } + case MIDIEvents::evControllerChange: //Controller change + switch(midibyte1) + { + case MIDIEvents::MIDICC_Volume_Coarse: //Volume + midivolume = midibyte2; + break; + } break; } Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -22,7 +22,7 @@ #include "AbstractVstEditor.h" //rewbs.defaultPlugGUI #include "VstEditor.h" //rewbs.defaultPlugGUI #include "defaultvsteditor.h" //rewbs.defaultPlugGUI -#include "midi.h" +#include "../soundlib/MIDIEvents.h" #include "version.h" #include "midimappingdialog.h" #include "../common/StringFixer.h" @@ -1321,7 +1321,7 @@ for (int ch=0; ch<16; ch++) { - m_nMidiPitchBendPos[ch]=MIDI_PitchBend_Centre; //centre pitch bend on all channels + m_nMidiPitchBendPos[ch] = MIDIEvents::pitchBendCentre; //centre pitch bend on all channels } } @@ -1949,7 +1949,7 @@ } -// Send events to plugin +// Send events to plugin. Returns true if there are events left to be processed. void CVstPlugin::ProcessVSTEvents() //--------------------------------- { @@ -2244,7 +2244,7 @@ //----------------------------------------- { // Note-Offs go at the start of the queue. - bool insertAtFront = ((dwMidiCode & 0xF0) == 0x80); + bool insertAtFront = (MIDIEvents::GetTypeFromEvent(dwMidiCode) == MIDIEvents::evNoteOff); VstMidiEvent event; event.type = kVstMidiType; @@ -2270,7 +2270,6 @@ void CVstPlugin::HardAllNotesOff() //-------------------------------- { - bool overflow; float in[2][SCRATCH_BUFFER_SIZE], out[2][SCRATCH_BUFFER_SIZE]; // scratch buffers // The JUCE framework doesn't like processing while being suspended. @@ -2280,40 +2279,33 @@ Resume(); } - do + for(int mc = 0; mc < 16; mc++) //all midi chans { - overflow=false; - for (int mc=0; mc<16; mc++) //all midi chans - { - DWORD dwMidiCode = 0x80 | (mc & 0x0f); //command|channel|velocity - VSTInstrChannel &channel = m_MidiCh[mc]; + VSTInstrChannel &channel = m_MidiCh[mc]; - MidiPitchBend(mc, MIDI_PitchBend_Centre); // centre pitch bend - MidiSend(0xB0|mc|(0x79<<8)); // reset all controllers - MidiSend(0xB0|mc|(0x7b<<8)); // all notes off - MidiSend(0xB0|mc|(0x78<<8)); // all sounds off + MidiPitchBend(mc, MIDIEvents::pitchBendCentre); // centre pitch bend + MidiSend(MIDIEvents::BuildCCEvent(MIDIEvents::MIDICC_AllControllersOff, mc, 0)); // reset all controllers + MidiSend(MIDIEvents::BuildCCEvent(MIDIEvents::MIDICC_AllNotesOff, mc, 0)); // all notes off + MidiSend(MIDIEvents::BuildCCEvent(MIDIEvents::MIDICC_AllSoundOff, mc, 0)); // all sounds off - for (size_t i = 0; i < CountOf(channel.uNoteOnMap); i++) //all notes + for (size_t i = 0; i < CountOf(channel.uNoteOnMap); i++) //all notes + { + for (CHANNELINDEX c = 0; c < CountOf(channel.uNoteOnMap[i]); c++) { - for (CHANNELINDEX c = 0; c < CountOf(channel.uNoteOnMap[i]); c++) + while(channel.uNoteOnMap[i][c]) { - while (channel.uNoteOnMap[i][c] && !overflow) - { - overflow=!(MidiSend(dwMidiCode | (i << 8))); - channel.uNoteOnMap[i][c]--; - } - if (overflow) break; //yuck + MidiSend(MIDIEvents::BuildNoteOffEvent(mc, i, 0)); + channel.uNoteOnMap[i][c]--; } - if (overflow) break; //yuck } - if (overflow) break; //yuck } - // let plug process events + } + // let plug process events + while(vstEvents.GetNumQueuedEvents() > 0) + { Process((float*)in, (float*)out, SCRATCH_BUFFER_SIZE); + } - // If we had hit an overflow, we need to loop around and start again. - } while (overflow); - if(wasSuspended) { Suspend(); @@ -2330,38 +2322,19 @@ LimitMax(nParam, 127u); if(m_pSndFile && m_pSndFile->GetModFlag(MSF_MIDICC_BUGEMULATION)) - MidiSend((nController << 16) | (nParam << 8) | (0xB0 | nMidiCh)); + MidiSend(MIDIEvents::BuildEvent(MIDIEvents::evControllerChange, nMidiCh, nParam, nController)); // param and controller are swapped (old broken implementation) else - MidiSend((nParam << 16) | (nController << 8) | (0xB0 | nMidiCh)); + MidiSend(MIDIEvents::BuildCCEvent(static_cast<MIDIEvents::MidiCC>(nController), nMidiCh, nParam)); } -short CVstPlugin::getMIDI14bitValueFromShort(short value) -//------------------------------------------------------- -{ - //http://www.srm.com/qtma/davidsmidispec.html: - // The two bytes of the pitch bend message form a 14 bit number, 0 to 16383. - // The value 8192 (sent, LSB first, as 0x00 0x40), is centered, or "no pitch bend." - // The value 0 (0x00 0x00) means, "bend as low as possible," and, - // similarly, 16383 (0x7F 0x7F) is to "bend as high as possible." - // The exact range of the pitch bend is specific to the synthesizer. - ASSERT(0 <= value && value <= 16383); - - BYTE byte1 = static_cast<BYTE>(value >> 7); // get last 7 bits only - BYTE byte2 = static_cast<BYTE>(value & 0x7F); // get first 7 bits only - short converted = (byte1 << 8) | byte2; // merge - - return converted; - -} - // Bend midi pitch for given midi channel using tracker param (0x00-0xFF) void CVstPlugin::MidiPitchBend(UINT nMidiCh, int nParam, UINT /*trackChannel*/) //----------------------------------------------------------------------------- { const int16 increment = static_cast<int16>(nParam * 0x2000 / 0xFF); int16 newPitchBendPos = m_nMidiPitchBendPos[nMidiCh] + increment; - Limit(newPitchBendPos, int16(MIDI_PitchBend_Min), int16(MIDI_PitchBend_Max)); + Limit(newPitchBendPos, int16(MIDIEvents::pitchBendMin), int16(MIDIEvents::pitchBendMax)); MidiPitchBend(nMidiCh, newPitchBendPos); } @@ -2370,9 +2343,9 @@ void CVstPlugin::MidiPitchBend(UINT nMidiCh, short newPitchBendPos) //----------------------------------------------------------------- { - m_nMidiPitchBendPos[nMidiCh] = newPitchBendPos; //store pitch bend position - short converted = getMIDI14bitValueFromShort(newPitchBendPos); - MidiSend(converted << 8 | MIDI_PitchBend_Command | nMidiCh); + ASSERT(MIDIEvents::pitchBendMin <= newPitchBendPos && newPitchBendPos <= MIDIEvents::pitchBendMax); + m_nMidiPitchBendPos[nMidiCh] = newPitchBendPos; + MidiSend(MIDIEvents::BuildPitchBendEvent(nMidiCh, newPitchBendPos)); } @@ -2381,7 +2354,7 @@ //---------------------------------------------------------------------------------------------------------------- { VSTInstrChannel &channel = m_MidiCh[nMidiCh]; - DWORD dwMidiCode = 0; + bool bankChanged = (channel.wMidiBank != --wMidiBank) && (wMidiBank < 0x4000); bool progChanged = (channel.nProgram != --nMidiProg) && (nMidiProg < 0x80); //get vol in [0,128[ @@ -2396,11 +2369,11 @@ if((channel.wMidiBank >> 7) != high) { // High byte changed - MidiSend(((high << 16) | (MIDICC_BankSelect_Coarse << 8)) | ((MIDIEVENT_CONTROLLERCHANGE << 4) | nMidiCh)); + MidiSend(MIDIEvents::BuildCCEvent(MIDIEvents::MIDICC_BankSelect_Coarse, nMidiCh, high)); } // Low byte //GetSoundFile()->ProcessMIDIMacro(trackChannel, false, GetSoundFile()->m_MidiCfg.szMidiGlb[MIDIOUT_BANKSEL], 0); - MidiSend((low << 16) | (MIDICC_BankSelect_Fine << 8) | ((MIDIEVENT_CONTROLLERCHANGE << 4) | nMidiCh)); + MidiSend(MIDIEvents::BuildCCEvent(MIDIEvents::MIDICC_BankSelect_Fine, nMidiCh, low)); channel.wMidiBank = wMidiBank; } @@ -2412,21 +2385,19 @@ { channel.nProgram = nMidiProg; //GetSoundFile()->ProcessMIDIMacro(trackChannel, false, GetSoundFile()->m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM], 0); - MidiSend((nMidiProg << 8) | ((MIDIEVENT_PROGRAMCHANGE << 4) | nMidiCh)); + MidiSend(MIDIEvents::BuildProgramChangeEvent(nMidiCh, nMidiProg)); } // Specific Note Off if (note > NOTE_KEYOFF) //rewbs.vstiLive { - dwMidiCode = (MIDIEVENT_NOTEOFF << 4) | nMidiCh; //note off, on chan nCh - note--; UINT i = note - NOTE_KEYOFF; - if (channel.uNoteOnMap[i][trackChannel]) + if(channel.uNoteOnMap[i][trackChannel]) { channel.uNoteOnMap[i][trackChannel]--; - MidiSend(dwMidiCode | (i << 8)); + MidiSend(MIDIEvents::BuildNoteOffEvent(nMidiCh, i, 0)); } } @@ -2435,14 +2406,14 @@ // Also less likely to cause a VST event buffer overflow. else if (note == NOTE_NOTECUT) // ^^ { - MidiSend((MIDIEVENT_CONTROLLERCHANGE << 4) | nMidiCh | (MIDICC_AllNotesOff << 8)); // all notes off - MidiSend((MIDIEVENT_CONTROLLERCHANGE << 4) | nMidiCh | (MIDICC_AllSoundOff << 8)); // all sounds off + MidiSend(MIDIEvents::BuildCCEvent(MIDIEvents::MIDICC_AllNotesOff, nMidiCh, 0)); + MidiSend(MIDIEvents::BuildCCEvent(MIDIEvents::MIDICC_AllSoundOff, nMidiCh, 0)); - dwMidiCode = (MIDIEVENT_NOTEOFF << 4) | nMidiCh | (vol << 16); //note off, on chan nCh; vol is note off velocity. - for (UINT i=0; i<128; i++) //all notes + // Turn off all notes + for(uint8 i = 0; i < 128; i++) { - channel.uNoteOnMap[i][trackChannel]=0; - MidiSend(dwMidiCode|(i<<8)); + channel.uNoteOnMap[i][trackChannel] = 0; + MidiSend(MIDIEvents::BuildNoteOffEvent(nMidiCh, i, vol)); } } @@ -2451,15 +2422,12 @@ // using note mask. else if(note == NOTE_KEYOFF || note == NOTE_FADE) // ==, ~~ { - dwMidiCode = (MIDIEVENT_NOTEOFF << 4) | nMidiCh | (vol << 16); //note off, on chan nCh; vol is note off velocity. - - for(UINT i = 0; i < 128; i++) + for(uint8 i = 0; i < 128; i++) { // Some VSTis need a note off for each instance of a note on, e.g. fabfilter. - // But this can cause a VST event overflow if we have many active notes... while(channel.uNoteOnMap[i][trackChannel]) { - if(MidiSend(dwMidiCode | (i << 8))) + if(MidiSend(MIDIEvents::BuildNoteOffEvent(nMidiCh, i, vol))) { channel.uNoteOnMap[i][trackChannel]--; } else @@ -2475,14 +2443,12 @@ // Note On else if(ModCommand::IsNote(note)) { - dwMidiCode = (MIDIEVENT_NOTEON << 4) | nMidiCh; //note on, on chan nCh + note -= NOTE_MIN; - note--; - //reset pitch bend on each new note, tracker style. - if(m_nMidiPitchBendPos[nMidiCh] != MIDI_PitchBend_Centre) + if(m_nMidiPitchBendPos[nMidiCh] != MIDIEvents::pitchBendCentre) { - MidiPitchBend(nMidiCh, MIDI_PitchBend_Centre); + MidiPitchBend(nMidiCh, MIDIEvents::pitchBendCentre); } // count instances of active notes. @@ -2490,12 +2456,10 @@ // Problem: if a note dies out naturally and we never send a note off, this counter // will block at max until note off. Is this a problem? // Safe to assume we won't need more than 16 note offs max on a given note? - if (channel.uNoteOnMap[note][trackChannel] < 17) + if(channel.uNoteOnMap[note][trackChannel] < 17) channel.uNoteOnMap[note][trackChannel]++; - - - MidiSend(dwMidiCode | (note << 8) | (vol << 16)); + MidiSend(MIDIEvents::BuildNoteOnEvent(nMidiCh, note, vol)); } m_nPreviousMidiChan = nMidiCh; Modified: trunk/OpenMPT/mptrack/Vstplug.h =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.h 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/Vstplug.h 2012-04-13 20:46:38 UTC (rev 1246) @@ -217,7 +217,6 @@ VstSpeakerArrangement speakerArrangement; //rewbs.VSTcompliance private: - short getMIDI14bitValueFromShort(short value); void MidiPitchBend(UINT nMidiCh, short pitchBendPos); bool GetProgramNameIndexed(VstInt32 index, VstIntPtr category, char *text); //rewbs.VSTpresets Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -17,7 +17,6 @@ #include "ChildFrm.h" #include "vstplug.h" #include "ChannelManagerDlg.h" -#include "midi.h" #include "version.h" #include "../common/StringFixer.h" Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2012-04-13 20:46:38 UTC (rev 1246) @@ -381,6 +381,10 @@ > </File> <File + RelativePath="..\soundlib\MIDIEvents.cpp" + > + </File> + <File RelativePath=".\MIDIMacroDialog.cpp" > </File> @@ -393,6 +397,10 @@ > </File> <File + RelativePath=".\MIDIMapping.cpp" + > + </File> + <File RelativePath="..\common\misc_util.cpp" > </File> @@ -1031,7 +1039,7 @@ > </File> <File - RelativePath="..\soundlib\midi.h" + RelativePath="..\soundlib\MIDIEvents.h" > </File> <File @@ -1047,6 +1055,10 @@ > </File> <File + RelativePath=".\MIDIMapping.h" + > + </File> + <File RelativePath="..\common\misc_util.h" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2012-04-13 20:46:38 UTC (rev 1246) @@ -170,6 +170,7 @@ <ClCompile Include="..\common\misc_util.cpp" /> <ClCompile Include="..\common\Reporting.cpp" /> <ClCompile Include="..\soundlib\ITTools.cpp" /> + <ClCompile Include="..\soundlib\MIDIEvents.cpp" /> <ClCompile Include="..\soundlib\MIDIMacros.cpp" /> <ClCompile Include="..\soundlib\ModChannel.cpp" /> <ClCompile Include="..\soundlib\ModInstrument.cpp" /> @@ -214,6 +215,7 @@ <ClCompile Include="MainFrm.cpp" /> <ClCompile Include="..\soundlib\Message.cpp" /> <ClCompile Include="MIDIMacroDialog.cpp" /> + <ClCompile Include="MIDIMapping.cpp" /> <ClCompile Include="MIDIMappingDialog.cpp" /> <ClCompile Include="..\soundlib\mmcmp.cpp" /> <ClCompile Include="..\soundlib\Mmx_mix.cpp" /> @@ -333,6 +335,7 @@ <ClInclude Include="..\common\StringFixer.h" /> <ClInclude Include="..\common\typedefs.h" /> <ClInclude Include="..\soundlib\ITTools.h" /> + <ClInclude Include="..\soundlib\MIDIEvents.h" /> <ClInclude Include="..\soundlib\MIDIMacros.h" /> <ClInclude Include="..\soundlib\ModChannel.h" /> <ClInclude Include="..\soundlib\ModInstrument.h" /> @@ -348,6 +351,7 @@ <ClInclude Include="EffectInfo.h" /> <ClInclude Include="ExceptionHandler.h" /> <ClInclude Include="MIDIMacroDialog.h" /> + <ClInclude Include="MIDIMapping.h" /> <ClInclude Include="PatternClipboard.h" /> <ClInclude Include="PatternCursor.h" /> <ClInclude Include="PatternRandomizer.h" /> @@ -392,7 +396,6 @@ <ClInclude Include="KeyConfigDlg.h" /> <ClInclude Include="mainbar.h" /> <ClInclude Include="MainFrm.h" /> - <ClInclude Include="..\soundlib\midi.h" /> <ClInclude Include="MIDIMappingDialog.h" /> <ClInclude Include="mod2midi.h" /> <ClInclude Include="mod2wave.h" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2012-04-13 20:46:38 UTC (rev 1246) @@ -454,6 +454,12 @@ <ClCompile Include="..\soundlib\plugins\JBridge.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="MIDIMapping.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\soundlib\MIDIEvents.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="AbstractVstEditor.h"> @@ -537,9 +543,6 @@ <ClInclude Include="MainFrm.h"> <Filter>Header Files</Filter> </ClInclude> - <ClInclude Include="..\soundlib\midi.h"> - <Filter>Header Files</Filter> - </ClInclude> <ClInclude Include="mod2midi.h"> <Filter>Header Files</Filter> </ClInclude> @@ -807,6 +810,12 @@ <ClInclude Include="..\soundlib\plugins\JBridge.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="MIDIMapping.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\MIDIEvents.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="res\bitmap1.bmp"> Modified: trunk/OpenMPT/mptrack/test/test.cpp =================================================================== --- trunk/OpenMPT/mptrack/test/test.cpp 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/mptrack/test/test.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -15,6 +15,7 @@ #include "../moddoc.h" #include "../MainFrm.h" #include "../version.h" +#include "../../soundlib/MIDIEvents.h" #include "../../soundlib/MIDIMacros.h" #include "../../common/misc_util.h" #include "../../common/StringFixer.h" @@ -75,6 +76,7 @@ void TestLoadSaveFile(); void TestPCnoteSerialization(); void TestMisc(); +void TestMIDIEvents(); void TestStringIO(); @@ -87,6 +89,7 @@ DO_TEST(TestTypes); DO_TEST(TestPCnoteSerialization); DO_TEST(TestMisc); + DO_TEST(TestMIDIEvents); DO_TEST(TestLoadSaveFile); DO_TEST(TestStringIO); @@ -266,6 +269,50 @@ } +// Test MIDI Event generating / reading +void TestMIDIEvents() +//------------------- +{ + uint32 midiEvent; + + midiEvent = MIDIEvents::BuildCCEvent(MIDIEvents::MIDICC_Balance_Coarse, 13, 40); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetTypeFromEvent(midiEvent), MIDIEvents::evControllerChange); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetChannelFromEvent(midiEvent), 13); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte1FromEvent(midiEvent), MIDIEvents::MIDICC_Balance_Coarse); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte2FromEvent(midiEvent), 40); + + midiEvent = MIDIEvents::BuildNoteOnEvent(10, 50, 120); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetTypeFromEvent(midiEvent), MIDIEvents::evNoteOn); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetChannelFromEvent(midiEvent), 10); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte1FromEvent(midiEvent), 50); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte2FromEvent(midiEvent), 120); + + midiEvent = MIDIEvents::BuildNoteOffEvent(15, 127, 42); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetTypeFromEvent(midiEvent), MIDIEvents::evNoteOff); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetChannelFromEvent(midiEvent), 15); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte1FromEvent(midiEvent), 127); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte2FromEvent(midiEvent), 42); + + midiEvent = MIDIEvents::BuildProgramChangeEvent(1, 127); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetTypeFromEvent(midiEvent), MIDIEvents::evProgramChange); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetChannelFromEvent(midiEvent), 1); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte1FromEvent(midiEvent), 127); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte2FromEvent(midiEvent), 0); + + midiEvent = MIDIEvents::BuildPitchBendEvent(2, MIDIEvents::pitchBendCentre); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetTypeFromEvent(midiEvent), MIDIEvents::evPitchBend); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetChannelFromEvent(midiEvent), 2); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte1FromEvent(midiEvent), 0x00); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte2FromEvent(midiEvent), 0x40); + + midiEvent = MIDIEvents::BuildSystemEvent(MIDIEvents::sysStart); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetTypeFromEvent(midiEvent), MIDIEvents::evSystem); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetChannelFromEvent(midiEvent), MIDIEvents::sysStart); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte1FromEvent(midiEvent), 0); + VERIFY_EQUAL_NONCONT(MIDIEvents::GetDataByte2FromEvent(midiEvent), 0); +} + + // Check if our test file was loaded correctly. void TestLoadXMFile(const CModDoc *pModDoc) //--------------------------------------- @@ -699,8 +746,8 @@ VERIFY_EQUAL_NONCONT(mapping.GetChannel(), 5); VERIFY_EQUAL_NONCONT(mapping.GetPlugIndex(), 1); VERIFY_EQUAL_NONCONT(mapping.GetParamIndex(), 0); - VERIFY_EQUAL_NONCONT(mapping.GetEvent(), MIDIEVENT_CONTROLLERCHANGE); - VERIFY_EQUAL_NONCONT(mapping.GetController(), MIDICC_ModulationWheel_Coarse); + VERIFY_EQUAL_NONCONT(mapping.GetEvent(), MIDIEvents::evControllerChange); + VERIFY_EQUAL_NONCONT(mapping.GetController(), MIDIEvents::MIDICC_ModulationWheel_Coarse); } Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2012-04-13 16:57:10 UTC (rev 1245) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -1804,6 +1804,7 @@ #ifndef MODPLUG_NO_FILESAVE + UINT CSoundFile::SaveMixPlugins(FILE *f, BOOL bUpdate) //---------------------------------------------------- { @@ -1910,9 +1911,10 @@ } return nTotalSize; } -#endif +#endif // MODPLUG_NO_FILESAVE + UINT CSoundFile::LoadMixPlugins(const void *pData, UINT nLen) //----------------------------------------------------------- { @@ -1998,7 +2000,7 @@ } } //end rewbs.plugDefaultProgram - //else if.. (add extra attempts to recognize chunks here) + //else if.. (add extra attempts to recognize chunks here) else // otherwise move forward a byte. { currPos++; @@ -2017,6 +2019,8 @@ } +#ifndef MODPLUG_NO_FILESAVE + // Used only when saving IT, XM and MPTM. // ITI, ITP saves using Ericus' macros etc... // The reason is that ITs and XMs save [code][size][ins1.Value][ins2.Value]... @@ -2207,7 +2211,7 @@ //Additional flags for XM/IT/MPTM if(m_ModFlags) { - code = 'MSF.'; + code = 'MSF.'; fwrite(&code, 1, sizeof(__int32), f); size = sizeof(m_ModFlags); fwrite(&size, 1, sizeof(__int16), f); @@ -2239,6 +2243,9 @@ return; } +#endif // MODPLUG_NO_FILESAVE + + LPCBYTE CSoundFile::LoadExtendedInstrumentProperties(const LPCBYTE pStart, const LPCBYTE pEnd, bool* pInterpretMptMade) @@ -2399,6 +2406,8 @@ } +#ifndef MODPLUG_NO_FILESAVE + size_t CSoundFile::SaveModularInstrumentData(FILE *f, const ModInstrument *pIns) const //------------------------------------------------------------------------------------ { @@ -2444,7 +2453,9 @@ return sizeof(ModInstID) + sizeof(modularInstSize) + modularInstSize; } +#endif // MODPLUG_NO_FILESAVE + size_t CSoundFile::LoadModularInstrumentData(const LPCBYTE lpStream, const DWORD dwMemLength, ModInstrument *pIns) const //---------------------------------------------------------------------------------------------------------------------- { Added: trunk/OpenMPT/soundlib/MIDIEvents.cpp =================================================================== --- trunk/OpenMPT/soundlib/MIDIEvents.cpp (rev 0) +++ trunk/OpenMPT/soundlib/MIDIEvents.cpp 2012-04-13 20:46:38 UTC (rev 1246) @@ -0,0 +1,104 @@ +/* + * MIDI.cpp + * -------- + * Purpose: MIDI event handling, event lists, ... + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#include "stdafx.h" +#include "MIDIEvents.h" + +namespace MIDIEvents +{ + +// Build a generic MIDI event +uint32 BuildEvent(EventType eventType, uint8 midiChannel, uint8 dataByte1, uint8 dataByte2) +//----------------------------------------------------------------------------------------- +{ + return (eventType << 4) | (midiChannel & 0x0F) | (dataByte1 << 8) | (dataByte2 << 16); +} + + +// Build a MIDI CC event +uint32 BuildCCEvent(MidiCC midiCC, uint8 midiChannel, uint8 param) +//---------------------------------------------------------------- +{ + return BuildEvent(evControllerChange, midiChannel, midiCC, param); +} + + +// Build a MIDI Pitchbend event +uint32 BuildPitchBendEvent(uint8 midiChannel, uint16 bendAmount) +//-------------------------------------------------------------- +{ + return BuildEvent(evPitchBend, midiChannel, (bendAmount & 0x7F), (bendAmount >> 7)); +} + + +// Build a MIDI Program Change event +uint32 BuildProgramChangeEvent(uint8 midiChannel, uint8 program) +//-------------------------------------------------------------- +{ + return BuildEvent(evProgramChange, midiChannel, program, 0); +} + + +// Build a MIDI Note Off event +uint32 BuildNoteOffEvent(uint8 midiChannel, uint8 note, uint8 velocity) +//--------------------------------------------------------------------- +{ + return BuildEvent(evNoteOff, midiChannel, note, velocity); +} + + +// Build a MIDI Note On event +uint32 BuildNoteOnEvent(uint8 midiChannel, uint8 note, uint8 velocity) +//-------------------------------------------------------------------- +{ + return BuildEvent(evNoteOn, midiChannel, note, velocity); +} + + +// Build a MIDI System Event +uint8 BuildSystemEvent(SystemEvent eventType) +//------------------------------------------- +{ + return (evSystem << 4) | eventType; +} + + +// Get MIDI channel from a MIDI event +uint8 GetChannelFromEvent(uint32 midiMsg) +//--------------------------------------- +{ + return static_cast<uint8>((midiMsg & 0xF)); +} + + +// Get MIDI Event type from a MIDI event +EventType GetTypeFromEvent(uint32 midiMsg) +//---------------------------------------- +{ + return static_cast<EventType>(((midiMsg >> 4) & 0xF)); +} + + +// Get first data byte from a MIDI event +uint8 GetDataByte1FromEvent(uint32 midiMsg) +//----------------------------------------- +{ + return static_cast<uint8>(((midiMsg >> 8) & 0xFF)); +} + + +// Get second data byte from a MIDI event +uint8 GetDataByte2FromEvent(uint32 midiMsg) +//----------------------------------------- +{ + return static_cast<uint8>(((midiMsg >> 16) & 0xFF)); +} + +} // End namespace Copied: trunk/OpenMPT/soundlib/MIDIEvents.h (from rev 1224, trunk/OpenMPT/soundlib/midi.h) =================================================================== --- trunk/OpenMPT/soundlib/MIDIEvents.h (rev 0) +++ trunk/OpenMPT/soundlib/MIDIEvents.h 2012-04-13 20:46:38 UTC (rev 1246) @@ -0,0 +1,289 @@ +/* + * MIDI.h + * ------ + * Purpose: MIDI event handling, event lists, ... + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + + +// MIDI related enums and helper functions +namespace MIDIEvents +{ + + // MIDI Event Types + enum EventType + { + evNoteOff = 0x8, // Note Off event + evNoteOn = 0x9, // Note On event + evPolyAftertouch = 0xA, // Poly Aftertouch / Poly Pressure event + evControllerChange = 0xB, // Controller Change (see MidiCC enum) + evProgramChange = 0xC, // Program Change + evChannelAftertouch = 0xD, // Channel Aftertouch + evPitchBend = 0xE, // Pitchbend event (see PitchBend enum) + evSystem = 0xF, // System event (see SystemEvent enum) + }; + + // System Events (Fx ...) + enum SystemEvent + { + sysExStart = 0x0, // Begin of System Exclusive message + sysQuarterFrame = 0x1, // Quarter Frame Message + sysPositionPointer ... [truncated message content] |