Index: mptrack/PatternEditorDialogs.cpp =================================================================== --- mptrack/PatternEditorDialogs.cpp (revision 12048) +++ mptrack/PatternEditorDialogs.cpp (working copy) @@ -880,7 +880,7 @@ CMainFrame *pMainFrm; CDialog::OnInitDialog(); - m_Keyboard.Init(m_hWnd, 2); + m_Keyboard.Init(m_hWnd, 4); pMainFrm = CMainFrame::GetMainFrame(); if (!pMainFrm) return TRUE; // Fills the shortcut key combo box @@ -891,22 +891,25 @@ m_CbnBaseNote.SetItemData(m_CbnBaseNote.AddString(_T("Relative")), MPTChord::relativeMode); AppendNotesToControl(m_CbnBaseNote, NOTE_MIN, NOTE_MIN + 3 * 12 - 1); - // Minor notes + // Chord Factor combo boxes CString s; - for (int inotes=-1; inotes<24; inotes++) + for (int inotes = -25; inotes < 24; inotes++) { - if(inotes < 0) + if(inotes == -25) { s = _T("--"); + } else if(inotes >= 0) + { + s = mpt::ToCString(CSoundFile::GetDefaultNoteName(inotes % 12)); + if(inotes >= 12) s.AppendFormat(_T(" (+%d)"), inotes / 12); } else { - s = mpt::ToCString(CSoundFile::GetDefaultNoteName(inotes % 12)); - if(inotes >= 12) - s.AppendFormat(_T(" (+%d)"), inotes / 12); + s = mpt::ToCString(CSoundFile::GetDefaultNoteName((24 + inotes) % 12)); + s.AppendFormat(_T(" (-%d)"), (11 - inotes) / 12); } - m_CbnNote1.AddString(s); - m_CbnNote2.AddString(s); - m_CbnNote3.AddString(s); + m_CbnNote1.SetItemData(m_CbnNote1.AddString(s), inotes); + m_CbnNote2.SetItemData(m_CbnNote2.AddString(s), inotes); + m_CbnNote3.SetItemData(m_CbnNote3.AddString(s), inotes); } // Update Dialog OnChordChanged(); @@ -928,47 +931,67 @@ { if (wParam != KBDNOTIFY_LBUTTONDOWN) return 0; MPTChord &chord = GetChord(); - UINT cnote = NOTE_NONE; - chord.notes[0] = NOTE_NONE; - chord.notes[1] = NOTE_NONE; - chord.notes[2] = NOTE_NONE; - for(UINT i = 0; i < 2 * 12; i++) + int8 newKey = 1 + -2 * 12 + (int8)nKey; + //NOTE_NONE is zero, so "C-" or "root note" uses ZERO_SURROGATE. + newKey = (newKey == NOTE_NONE) ? ZERO_SURROGATE : newKey; + + //Clear note. + for(UINT i = 0; i + 1 < MPTChord::notesPerChord; i++) { - if(chord.key == MPTChord::relativeMode) + if(chord.notes[i] == newKey) { - if(!i) continue; - } else - { - if(i == chord.key % 12u) continue; + for(UINT j = i; j + 1 < MPTChord::notesPerChord; j++) + { + chord.notes[j] = (j + 2 < MPTChord::notesPerChord) ? chord.notes[j + 1] : NOTE_NONE; + } + OnChordChanged(); + return 0; } + } - UINT n = m_Keyboard.GetFlags(i); - if (i == (UINT)nKey) n = (n) ? 0 : 1; - if (n) + //Add note. + for(UINT i = 0; i + 1 < MPTChord::notesPerChord; i++) + { + if(chord.notes[i] == NOTE_NONE || i + 2 >= MPTChord::notesPerChord) { - if ((cnote < 3) || (i == (UINT)nKey)) - { - UINT k = (cnote < 3) ? cnote : 2; - chord.notes[k] = static_cast(i+1); - if (cnote < 3) cnote++; - } + chord.notes[i] = newKey; + OnChordChanged(); + return 0; } } - OnChordChanged(); - return 0; + + //Do nothing. + return 1; } void CChordEditor::OnChordChanged() { + int8 tempChord[3]; //scratch copy of chord.notes MPTChord &chord = GetChord(); if(chord.key != MPTChord::relativeMode) m_CbnBaseNote.SetCurSel(chord.key + 1); else m_CbnBaseNote.SetCurSel(0); - m_CbnNote1.SetCurSel(chord.notes[0]); - m_CbnNote2.SetCurSel(chord.notes[1]); - m_CbnNote3.SetCurSel(chord.notes[2]); + for (UINT i = 0; i + 1 < MPTChord::notesPerChord; i++) + { + tempChord[i] = chord.notes[i]; + if(tempChord[i] == ZERO_SURROGATE) + { + tempChord[i] = 2 * 12; + } + else if (tempChord[i] == 0) + { + tempChord[i] = 0; + } + else + { + tempChord[i] += 2 * 12; + } + } + m_CbnNote1.SetCurSel(tempChord[0]); + m_CbnNote2.SetCurSel(tempChord[1]); + m_CbnNote3.SetCurSel(tempChord[2]); UpdateKeyboard(); } @@ -981,15 +1004,26 @@ { note = 0; } - for(UINT i = 0; i < 2 * 12; i++) + for(INT i = -2 * 12; i < 2 * 12; i++) { uint8 b = CKeyboardControl::KEYFLAG_NORMAL; - if(i == note) b = CKeyboardControl::KEYFLAG_REDDOT; - else if(chord.notes[0] && i + 1 == chord.notes[0]) b = CKeyboardControl::KEYFLAG_REDDOT; - else if(chord.notes[1] && i + 1 == chord.notes[1]) b = CKeyboardControl::KEYFLAG_REDDOT; - else if(chord.notes[2] && i + 1 == chord.notes[2]) b = CKeyboardControl::KEYFLAG_REDDOT; - m_Keyboard.SetFlags(i, b); + if(i + 1 && i + 1 == chord.notes[0]) + b = CKeyboardControl::KEYFLAG_REDDOT; + else if(i + 1 && i + 1 == chord.notes[1]) + b = CKeyboardControl::KEYFLAG_REDDOT; + else if(i + 1 && i + 1 == chord.notes[2]) + b = CKeyboardControl::KEYFLAG_REDDOT; + else if(i == (INT)note) + b = CKeyboardControl::KEYFLAG_BRIGHTDOT; + m_Keyboard.SetFlags(i + 2 * 12, b); } + for(UINT i = 0; i + 1 < MPTChord::notesPerChord; i++) + { + if(chord.notes[i] == ZERO_SURROGATE) + { + m_Keyboard.SetFlags(2 * 12 - 1, CKeyboardControl::KEYFLAG_REDDOT); + } + } m_Keyboard.InvalidateRect(NULL, FALSE); } @@ -1009,11 +1043,18 @@ { MPTChord &chord = GetChord(); int note = m_CbnNote1.GetCurSel(); - if(note >= 0) + if(note < 0) + return; + if(note == 2 * 12) { - chord.notes[0] = (uint8)note; - UpdateKeyboard(); + note = ZERO_SURROGATE; } + else if (note) + { + note -= 2 * 12; + } + chord.notes[0] = (int8)note; + UpdateKeyboard(); } @@ -1021,11 +1062,17 @@ { MPTChord &chord = GetChord(); int note = m_CbnNote2.GetCurSel(); - if(note >= 0) + if(note < 0) + return; + if(note == 2 * 12) { - chord.notes[1] = (uint8)note; - UpdateKeyboard(); + note = ZERO_SURROGATE; + } else if(note) + { + note -= 2 * 12; } + chord.notes[1] = (int8)note; + UpdateKeyboard(); } @@ -1033,11 +1080,17 @@ { MPTChord &chord = GetChord(); int note = m_CbnNote3.GetCurSel(); - if(note >= 0) + if(note < 0) + return; + if(note == 2 * 12) { - chord.notes[2] = (uint8)note; - UpdateKeyboard(); + note = ZERO_SURROGATE; + } else if(note) + { + note -= 2 * 12; } + chord.notes[2] = (int8)note; + UpdateKeyboard(); } Index: mptrack/PatternEditorDialogs.h =================================================================== --- mptrack/PatternEditorDialogs.h (revision 12048) +++ mptrack/PatternEditorDialogs.h (working copy) @@ -108,6 +108,13 @@ class CChordEditor: public CDialog { + +public: + enum + { + ZERO_SURROGATE = 0x3E + }; + protected: CKeyboardControl m_Keyboard; CComboBox m_CbnShortcut, m_CbnBaseNote, m_CbnNote1, m_CbnNote2, m_CbnNote3; Index: mptrack/TrackerSettings.cpp =================================================================== --- mptrack/TrackerSettings.cpp (revision 12048) +++ mptrack/TrackerSettings.cpp (working copy) @@ -393,15 +393,15 @@ if(ichord < 12) { // Major Chords - Chords[ichord].notes[0] = (uint8)(ichord+5); - Chords[ichord].notes[1] = (uint8)(ichord+8); - Chords[ichord].notes[2] = (uint8)(ichord+11); + Chords[ichord].notes[0] = (int8)(ichord+5); + Chords[ichord].notes[1] = (int8)(ichord+8); + Chords[ichord].notes[2] = (int8)(ichord+11); } else if(ichord < 24) { // Minor Chords - Chords[ichord].notes[0] = (uint8)(ichord-8); - Chords[ichord].notes[1] = (uint8)(ichord-4); - Chords[ichord].notes[2] = (uint8)(ichord-1); + Chords[ichord].notes[0] = (int8)(ichord-8); + Chords[ichord].notes[1] = (int8)(ichord-4); + Chords[ichord].notes[2] = (int8)(ichord-1); } } @@ -1238,9 +1238,9 @@ if((chord & 0xFFFFFFC0) || (!chords[i].notes[0])) { chords[i].key = (uint8)(chord & 0x3F); - chords[i].notes[0] = (uint8)((chord >> 6) & 0x3F); - chords[i].notes[1] = (uint8)((chord >> 12) & 0x3F); - chords[i].notes[2] = (uint8)((chord >> 18) & 0x3F); + chords[i].notes[0] = static_cast(((chord >> 6) & 0x3F) | (0xC0 * ((chord >> 11) & 1))); + chords[i].notes[1] = static_cast(((chord >> 12) & 0x3F) | (0xC0 * ((chord >> 17) & 1))); + chords[i].notes[2] = static_cast(((chord >> 18) & 0x3F) | (0xC0 * ((chord >> 23) & 1))); } } } @@ -1251,7 +1251,7 @@ { for(std::size_t i = 0; i < std::size(chords); i++) { - int32 s = (chords[i].key) | (chords[i].notes[0] << 6) | (chords[i].notes[1] << 12) | (chords[i].notes[2] << 18); + int32 s = (chords[i].key) | ((chords[i].notes[0] & 0x3F) << 6) | ((chords[i].notes[1] & 0x3F) << 12) | ((chords[i].notes[2] & 0x3F) << 18); mpt::ustring note = mpt::format(U_("%1%2"))(mpt::ustring(NoteNamesSharp[i % 12]), i / 12); conf.Write(U_("Chords"), note, s); } Index: mptrack/TrackerSettings.h =================================================================== --- mptrack/TrackerSettings.h (revision 12048) +++ mptrack/TrackerSettings.h (working copy) @@ -193,7 +193,7 @@ }; uint8 key; // Base note - uint8 notes[3]; // Additional chord notes + int8 notes[3]; // Additional chord notes }; using MPTChords = std::array; // 3 octaves Index: mptrack/View_pat.cpp =================================================================== --- mptrack/View_pat.cpp (revision 12048) +++ mptrack/View_pat.cpp (working copy) @@ -5193,18 +5193,18 @@ for(auto cnote : chord.notes) { - if(cnote) + if(cnote) //Check for NOTE_NONE { - ModCommand::NOTE chordNote = key - NOTE_MIN; + int32 chordNote = key - NOTE_MIN; if(!relativeMode) { // Only use octave information from the base key chordNote = (chordNote / 12) * 12; } - chordNote += cnote; - if(specs.HasNote(chordNote)) + chordNote += (cnote == CChordEditor::ZERO_SURROGATE) ? 0 : (int32)cnote; + if(chordNote >= NOTE_MIN && chordNote <= NOTE_MAX && specs.HasNote(static_cast(chordNote))) { - outNotes[numNotes++] = chordNote; + outNotes[numNotes++] = static_cast(chordNote); } } }