From 99e8373566820a2c06f9dcb0e933dc3e9c7ecfb7 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Sat, 28 Sep 2013 16:54:05 -0700 Subject: Implementing "record metronome" feature. --- SekaijuRes/SekaijuEnu.rc | 36 +++++++++++++------------- SekaijuRes/SekaijuJpn.rc | Bin 313342 -> 313520 bytes src/MetronomeDlg.cpp | 2 ++ src/MetronomeDlg.h | 1 + src/Resource.h | 1 + src/SekaijuApp.cpp | 65 +++++++++++++++++++++++++++++++++++++---------- src/SekaijuApp.h | 1 + 7 files changed, 75 insertions(+), 31 deletions(-) diff --git a/SekaijuRes/SekaijuEnu.rc b/SekaijuRes/SekaijuEnu.rc index d5d6f74..4b6774d 100755 --- a/SekaijuRes/SekaijuEnu.rc +++ b/SekaijuRes/SekaijuEnu.rc @@ -1816,53 +1816,55 @@ END // Metronome Dialog -IDD_METRONOME DIALOG DISCARDABLE 0, 0, 252, 196 +IDD_METRONOME DIALOG DISCARDABLE 0, 0, 252, 212 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Metronome" FONT 9, "MS Sans Serif" BEGIN AUTOCHECKBOX "Ring metronome while recording", IDC_METRONOME_ON, 4, 8, 244, 12 + AUTOCHECKBOX "When metronome rings, record it", IDC_METRONOME_RECORD, + 4, 24, 244, 12 GROUPBOX "Output", IDC_METRONOME_OUTPUT, - 4, 24, 244, 52, WS_GROUP + 4, 40, 244, 52, WS_GROUP LTEXT "Out Port", IDC_STATIC, - 8, 40, 92, 12, + 8, 56, 92, 12, COMBOBOX IDC_METRONOME_OUTPUTPORT, - 100, 40, 140, 100, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST + 100, 56, 140, 100, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST LTEXT "Out Channel", IDC_STATIC, - 8, 56, 152, 12, + 8, 72, 152, 12, EDITTEXT IDC_METRONOME_OUTPUTCHANNEL, - 200, 56, 40, 12, WS_TABSTOP | ES_AUTOHSCROLL + 200, 72, 40, 12, WS_TABSTOP | ES_AUTOHSCROLL CONTROL "", IDC_METRONOME_OUTPUTCHANNELSP UPDOWN, UDS_DEFAULT, 0, 0, 0, 0 GROUPBOX "Pattern", IDC_METRONOME_PATTERN, - 4, 84, 244, 84, WS_GROUP + 4, 100, 244, 84, WS_GROUP LTEXT "Main Note.Key", IDC_STATIC, - 8, 100, 92, 12, + 8, 116, 92, 12, COMBOBOX IDC_METRONOME_NOTEKEY1, - 100, 100, 140, 100, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST + 100, 116, 140, 100, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST LTEXT "Main Note.Velocity", IDC_STATIC, - 8, 116, 192, 12, + 8, 132, 192, 12, EDITTEXT IDC_METRONOME_NOTEVEL1, - 200, 116, 40, 12, WS_TABSTOP | ES_AUTOHSCROLL + 200, 132, 40, 12, WS_TABSTOP | ES_AUTOHSCROLL CONTROL "", IDC_METRONOME_NOTEVEL1SP UPDOWN, UDS_DEFAULT, 0, 0, 0, 0 LTEXT "Sub Note.Key", IDC_STATIC, - 8, 132, 92, 12, + 8, 148, 92, 12, COMBOBOX IDC_METRONOME_NOTEKEY2, - 100, 132, 140, 100, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST + 100, 148, 140, 100, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST LTEXT "Sub Note.Velocity", IDC_STATIC, - 8, 148, 192, 12, + 8, 164, 192, 12, EDITTEXT IDC_METRONOME_NOTEVEL2, - 200, 148, 40, 12, WS_TABSTOP | ES_AUTOHSCROLL + 200, 164, 40, 12, WS_TABSTOP | ES_AUTOHSCROLL CONTROL "", IDC_METRONOME_NOTEVEL2SP UPDOWN, UDS_DEFAULT, 0, 0, 0, 0 DEFPUSHBUTTON "OK", IDOK, - 148, 176, 48, 14, WS_TABSTOP + 148, 192, 48, 14, WS_TABSTOP PUSHBUTTON "Cancel", IDCANCEL, - 200, 176, 48, 14, WS_TABSTOP + 200, 192, 48, 14, WS_TABSTOP END // Auto Save Dialog diff --git a/SekaijuRes/SekaijuJpn.rc b/SekaijuRes/SekaijuJpn.rc index 0989e13..2cce325 100644 Binary files a/SekaijuRes/SekaijuJpn.rc and b/SekaijuRes/SekaijuJpn.rc differ diff --git a/src/MetronomeDlg.cpp b/src/MetronomeDlg.cpp index 5ffc882..6ad5620 100644 --- a/src/MetronomeDlg.cpp +++ b/src/MetronomeDlg.cpp @@ -44,6 +44,7 @@ // コンストラクタ CMetronomeDlg::CMetronomeDlg () : CDialog (CMetronomeDlg::IDD) { m_nOn = 0; + m_nRecord = 0; m_nOutputPort = 0; m_nOutputChannel = 10; m_nNoteKey1 = 0; @@ -143,6 +144,7 @@ void CMetronomeDlg::DoDataExchange (CDataExchange* pDX) { CDialog::DoDataExchange (pDX); // DDV_MinMaxXXXは各々のDDX_TEXTの直後に配置すること(20090501訂正) DDX_Check (pDX, IDC_METRONOME_ON, m_nOn); + DDX_Check (pDX, IDC_METRONOME_RECORD, m_nRecord); DDX_CBIndex (pDX, IDC_METRONOME_OUTPUTPORT, m_nOutputPort); DDX_Text (pDX, IDC_METRONOME_OUTPUTCHANNEL, m_nOutputChannel); DDV_MinMaxInt (pDX, m_nOutputChannel, 1, 16); diff --git a/src/MetronomeDlg.h b/src/MetronomeDlg.h index efb6792..83280b6 100644 --- a/src/MetronomeDlg.h +++ b/src/MetronomeDlg.h @@ -27,6 +27,7 @@ class CMetronomeDlg : public CDialog { //-------------------------------------------------------------------------- public: int m_nOn; // オン(0=オフ、1=ON) + int m_nRecord; // オンの状態に、メトロノームを録音する int m_nOutputPort; // 出力ポート(0〜15) int m_nOutputChannel; // 出力チャンネル(0〜15) int m_nNoteKey1; // ノートキー強打(0〜127) diff --git a/src/Resource.h b/src/Resource.h index 7ac1e36..cced976 100644 --- a/src/Resource.h +++ b/src/Resource.h @@ -1615,6 +1615,7 @@ #define IDC_METRONOME_NOTEKEY2SP 0x740C #define IDC_METRONOME_NOTEVEL2 0x740D #define IDC_METRONOME_NOTEVEL2SP 0x740E +#define IDC_METRONOME_RECORD 0x740F #define IDC_AUTOSAVE_ON 0x7501 diff --git a/src/SekaijuApp.cpp b/src/SekaijuApp.cpp index c7f92d4..a63ea75 100644 --- a/src/SekaijuApp.cpp +++ b/src/SekaijuApp.cpp @@ -949,6 +949,7 @@ BOOL CSekaijuApp::LoadIniFile () { // [MetronomeDlgStatus] m_theMetronomeDlgStatus.m_nOn = GetProfileInt (_T("MetronomeDlgStatus"), _T("On"), 1); + m_theMetronomeDlgStatus.m_nRecord = GetProfileInt (_T("MetronomeDlgStatus"), _T("Record"), 0); m_theMetronomeDlgStatus.m_nOutputPort = GetProfileInt (_T("MetronomeDlgStatus"), _T("OutputPort"), 0); m_theMetronomeDlgStatus.m_nOutputChannel = GetProfileInt (_T("MetronomeDlgStatus"), _T("OutputChannel"), 9); m_theMetronomeDlgStatus.m_nNoteKey1 = GetProfileInt (_T("MetronomeDlgStatus"), _T("NoteKey1"), 60); @@ -1212,7 +1213,7 @@ BOOL CSekaijuApp::SaveIniFile () { // [MetronomeDlgStatus] WriteProfileInt (_T("MetronomeDlgStatus"), _T("On"), m_theMetronomeDlgStatus.m_nOn); - WriteProfileInt (_T("MetronomeDlgStatus"), _T("OutputPort"), m_theMetronomeDlgStatus.m_nOutputPort); + WriteProfileInt (_T("MetronomeDlgStatus"), _T("Record"), m_theMetronomeDlgStatus.m_nRecord); WriteProfileInt (_T("MetronomeDlgStatus"), _T("OutputChannel"), m_theMetronomeDlgStatus.m_nOutputChannel); WriteProfileInt (_T("MetronomeDlgStatus"), _T("NoteKey1"), m_theMetronomeDlgStatus.m_nNoteKey1); WriteProfileInt (_T("MetronomeDlgStatus"), _T("NoteVel1"), m_theMetronomeDlgStatus.m_nNoteVel1); @@ -1637,6 +1638,9 @@ BOOL CSekaijuApp::PlayRecordProc (LPVOID pInfo) { // メトロノーム出力処理(20080825追加) if (m_bRecording && m_theMetronomeDlgStatus.m_nOn) { if (lTimeMode == MIDIDATA_TPQNBASE) { + bool tick = false; + bool tock = false; + long lOldMeasure, lOldBeat, lOldTick; MIDIData_BreakTime (pMIDIData, pSekaijuDoc->m_lOldTime, &lOldMeasure, &lOldBeat, &lOldTick); @@ -1654,29 +1658,60 @@ BOOL CSekaijuApp::PlayRecordProc (LPVOID pInfo) { for (lMeasure = lOldMeasure; lMeasure < lNewMeasure; lMeasure++) { memset (byMsg, 0, sizeof (byMsg)); byMsg[0] = 0x90 | (BYTE)lOutputChannel; - byMsg[1] = CLIP (0, m_theMetronomeDlgStatus.m_nNoteKey1, 127); - byMsg[2] = CLIP (1, m_theMetronomeDlgStatus.m_nNoteVel1, 127); - if (m_pMIDIOut[lOutputPort]) { - MIDIOut_PutMIDIMessage (m_pMIDIOut[lOutputPort], byMsg, 3); - } - byMsg[2] = 0; + byMsg[10] = 0x80 | (BYTE)lOutputChannel; + byMsg[11] = byMsg[1] = CLIP (0, m_theMetronomeDlgStatus.m_nNoteKey1, 127); + byMsg [2] = CLIP (1, m_theMetronomeDlgStatus.m_nNoteVel1, 127); + byMsg[12] = 0; if (m_pMIDIOut[lOutputPort]) { MIDIOut_PutMIDIMessage (m_pMIDIOut[lOutputPort], byMsg, 3); + MIDIOut_PutMIDIMessage (m_pMIDIOut[lOutputPort], byMsg + 10, 3); } + tick = true; } long lBeat = 0; for (lBeat = lOldBeat; lBeat < lNewBeat; lBeat++) { if (1) { memset (byMsg, 0, sizeof (byMsg)); - byMsg[0] = 0x90 | (BYTE)lOutputChannel; - byMsg[1] = CLIP (0, m_theMetronomeDlgStatus.m_nNoteKey2, 127); - byMsg[2] = CLIP (1, m_theMetronomeDlgStatus.m_nNoteVel2, 127); + byMsg[20] = 0x90 | (BYTE)lOutputChannel; + byMsg[30] = 0x80 | (BYTE)lOutputChannel; + byMsg[31] = byMsg[21] = CLIP (0, m_theMetronomeDlgStatus.m_nNoteKey2, 127); + byMsg[22] = CLIP (1, m_theMetronomeDlgStatus.m_nNoteVel2, 127); + byMsg[32] = 0; if (m_pMIDIOut[lOutputPort]) { - MIDIOut_PutMIDIMessage (m_pMIDIOut[lOutputPort], byMsg, 3); + MIDIOut_PutMIDIMessage (m_pMIDIOut[lOutputPort], byMsg + 20, 3); + MIDIOut_PutMIDIMessage (m_pMIDIOut[lOutputPort], byMsg + 30, 3); } - byMsg[2] = 0; - if (m_pMIDIOut[lOutputPort]) { - MIDIOut_PutMIDIMessage (m_pMIDIOut[lOutputPort], byMsg, 3); + } + tock = true; + } + + if (m_theMetronomeDlgStatus.m_nRecord) { + MIDITrack* pMIDITrack = NULL; + forEachTrack (pSekaijuDoc->m_pMIDIData, pMIDITrack) { + long lInputOn = MIDITrack_GetInputOn (pMIDITrack); + long lInputPort = MIDITrack_GetInputPort (pMIDITrack); + long lInputChannel = MIDITrack_GetInputChannel (pMIDITrack); + if (lInputOn && lInputPort == lOutputPort && lInputChannel == lOutputChannel) { + if (tick) { + MIDIEvent* pMIDIEvent = MIDIEvent_Create + (pSekaijuDoc->m_lNewTime - 1, 0x90, byMsg, 3); + if (pMIDIEvent) + MIDITrack_InsertEvent (pMIDITrack, pMIDIEvent); + pMIDIEvent = MIDIEvent_Create + (pSekaijuDoc->m_lNewTime + 4, 0x80, byMsg + 10, 3); + if (pMIDIEvent) + MIDITrack_InsertEvent (pMIDITrack, pMIDIEvent); + } + if (tock) { + MIDIEvent* pMIDIEvent = MIDIEvent_Create + (pSekaijuDoc->m_lNewTime - 1, 0x90, byMsg + 20, 3); + if (pMIDIEvent) + MIDITrack_InsertEvent (pMIDITrack, pMIDIEvent); + pMIDIEvent = MIDIEvent_Create + (pSekaijuDoc->m_lNewTime + 4, 0x80, byMsg + 30, 3); + if (pMIDIEvent) + MIDITrack_InsertEvent (pMIDITrack, pMIDIEvent); + } } } } @@ -3676,6 +3711,7 @@ void CSekaijuApp::OnSetupInstrument () { void CSekaijuApp::OnSetupMetronome () { CMetronomeDlg theDlg; theDlg.m_nOn = m_theMetronomeDlgStatus.m_nOn; + theDlg.m_nRecord = m_theMetronomeDlgStatus.m_nRecord; theDlg.m_nOutputPort = CLIP (0, m_theMetronomeDlgStatus.m_nOutputPort, 15); theDlg.m_nOutputChannel = CLIP (0, m_theMetronomeDlgStatus.m_nOutputChannel, 15) + 1; theDlg.m_nNoteKey1 = CLIP (0, m_theMetronomeDlgStatus.m_nNoteKey1, 127); @@ -3684,6 +3720,7 @@ void CSekaijuApp::OnSetupMetronome () { theDlg.m_nNoteVel2 = CLIP (0, m_theMetronomeDlgStatus.m_nNoteVel2, 127); if (theDlg.DoModal () == IDOK) { m_theMetronomeDlgStatus.m_nOn =theDlg.m_nOn; + m_theMetronomeDlgStatus.m_nRecord = theDlg.m_nRecord; m_theMetronomeDlgStatus.m_nOutputPort = theDlg.m_nOutputPort; m_theMetronomeDlgStatus.m_nOutputChannel = theDlg.m_nOutputChannel - 1; m_theMetronomeDlgStatus.m_nNoteKey1 = theDlg.m_nNoteKey1; diff --git a/src/SekaijuApp.h b/src/SekaijuApp.h index 22efde9..0b4f212 100644 --- a/src/SekaijuApp.h +++ b/src/SekaijuApp.h @@ -184,6 +184,7 @@ typedef struct { // メトロノームダイアログの状態 typedef struct { int m_nOn; // メトロノームオン + int m_nRecord; // メトロノームを録音する int m_nOutputPort; // 出力ポート(0〜15) int m_nOutputChannel; // 出力チャンネル(0〜15) int m_nNoteKey1; // 強打ノートキー(0〜127) -- cgit v1.2.3