Pattern XP mod
Re: Pattern XP mod
very nice additions!
minor annoyance: when "use toolbar" is off, clicking a button (chord for example) switches the focus away from the pattern. So you have to click on the pattern again and only then can you enter notes and move around again etc.
This doesn't happen with "use toolbar" on.
minor annoyance: when "use toolbar" is off, clicking a button (chord for example) switches the focus away from the pattern. So you have to click on the pattern again and only then can you enter notes and move around again etc.
This doesn't happen with "use toolbar" on.
Re: Pattern XP mod
Great update!
I wanted to suggest simple solution for new curves, but you were faster ;d
This is the idea:
Anyway, possibility to invert/mirror selected notes or values would be pretty nice addition for patterns editing.
In built-in pattern editor is very cool feature. Timeline doesn't disappear, if you stop sequence. This is very helpful during editing long patterns. Is it possible, to reintroduce this functionality? What do you think?
If you select just one value, humanize option is inactive in toolbar mode, but you can use it via shortcut.
I just found that, new interpolation works very well on values from min to max, but not vice versa.
I wanted to suggest simple solution for new curves, but you were faster ;d
This is the idea:
Anyway, possibility to invert/mirror selected notes or values would be pretty nice addition for patterns editing.
In built-in pattern editor is very cool feature. Timeline doesn't disappear, if you stop sequence. This is very helpful during editing long patterns. Is it possible, to reintroduce this functionality? What do you think?
If you select just one value, humanize option is inactive in toolbar mode, but you can use it via shortcut.
I just found that, new interpolation works very well on values from min to max, but not vice versa.
Re: Pattern XP mod
Thanks for this new update, what is the limit for the list? (just because i don't want to crash buzz again if I have the stupid idea to merge all the lists i' m doing).
3 new lists
Intervals, very short, but useful for two voices harmonization.
3 notes chords in 7 different positions for the 3 states:fundamental, first and second inversions
just major minor and dim, maybe some adds, but maybe not, the most useful list, for clean sound.
4 notes chords in different positions, clear sound, larger intervals.
3 new lists
Intervals, very short, but useful for two voices harmonization.
3 notes chords in 7 different positions for the 3 states:fundamental, first and second inversions
just major minor and dim, maybe some adds, but maybe not, the most useful list, for clean sound.
4 notes chords in different positions, clear sound, larger intervals.
Re: Pattern XP mod
The limit is 200, but it's dirty worktinga wrote:Thanks for this new update, what is the limit for the list? (just because i don't want to crash buzz again if I have the stupid idea to merge all the lists i' m doing).
I'll rewrite that one day with no limitation (I don't have time ...)
Installation files updated.tinga wrote:3 new lists
Re: Pattern XP mod
This is the way "Buttons" act. They have focus when you click on it.UNZ wrote:very nice additions!
minor annoyance: when "use toolbar" is off, clicking a button (chord for example) switches the focus away from the pattern. So you have to click on the pattern again and only then can you enter notes and move around again etc.
This doesn't happen with "use toolbar" on.
The "ToolButtons" don't have focus, so the pattern don't loose it when you click.
I only use the toolbar version. I kept the button version because someone asked for it, but I don't plan to improve it.
Re: Pattern XP mod
I keep the idea.rav wrote: Anyway, possibility to invert/mirror selected notes or values would be pretty nice addition for patterns editing.
I'll have a look at that.rav wrote: In built-in pattern editor is very cool feature. Timeline doesn't disappear, if you stop sequence. This is very helpful during editing long patterns. Is it possible, to reintroduce this functionality? What do you think?
I'll have a look at that.rav wrote: If you select just one value, humanize option is inactive in toolbar mode, but you can use it via shortcut.
I just found that, new interpolation works very well on values from min to max, but not vice versa.
Re: Pattern XP mod
New version available to correct this bug.rav wrote: I just found that, new interpolation works very well on values from min to max, but not vice versa.
Pattern XP mod - pitch bend problem
I had a look at the "record pitch bend commands from the midi keyboard" problem.
To try to find what happens, I restarted from the sources of the original patternXP.
Then, when I compile this sources, I already have the same problem.
So, it seems that it doesn't come from what I have added : the problem is there from the start.
But obviously, it works fine in the dll Oskari provides in Buzz install.
I know that I don't use the same version of the MFC, maybe the problem is here ...
I know also that Oskari don't use Visual C++ 2010 Express.
So if someone have a suggestion.
To try to find what happens, I restarted from the sources of the original patternXP.
Then, when I compile this sources, I already have the same problem.
So, it seems that it doesn't come from what I have added : the problem is there from the start.
But obviously, it works fine in the dll Oskari provides in Buzz install.
I know that I don't use the same version of the MFC, maybe the problem is here ...
I know also that Oskari don't use Visual C++ 2010 Express.
So if someone have a suggestion.
Re: Pattern XP mod
Maybe it is related to this problem with compiling peer adsr machine. Oskari mentioned about pxp in this thread too:
viewtopic.php?f=3&t=1383
viewtopic.php?f=3&t=1383
Re: Pattern XP mod
It looks like the code on jeskola.net was old so it didn't have the latest features like pitch bend record. It's updated now and I think you might be able to automatically merge it with your new code. There are some other important changes like UpdateWaveReferences (template paste). Here's the whole diff:
Code: Select all
diff old/ActionStack.cpp new/ActionStack.cpp
21c21
< int oldsize = pdata->size();
---
> int oldsize = (int)pdata->size();
83a84
> s.scrollpos = pew->pe.GetScrollPos();
101a103
> pew->pe.ScrollTo(ps->scrollpos);
diff old/ActionStack.h new/ActionStack.h
13a14
> CPoint scrollpos;
diff old/App.cpp new/App.cpp
62a63,64
> //afxAmbientActCtx = FALSE;
>
diff old/EditorWnd.cpp new/EditorWnd.cpp
318,320c318
< MACHINE_LOCK;
< pPattern->EnableColumns(dlg.enabledColumns, pCB);
< pPattern->SetRowsPerBeat(dlg.m_RPBValue);
---
> pPattern->EnableColumns(dlg.enabledColumns, pCB, 1, dlg.m_RPBValue);
diff old/MachinePattern.h new/MachinePattern.h
2a3
> #include <functional>
172c173
< modulators = shared_ptr<CModulators>(new CModulators());
---
> modulators = make_shared<CModulators>();
201c202
< enum State { note_on_pending, playing, note_off_pending, recording };
---
> enum State { note_on_pending, playing, note_off_pending, recording, pw_or_cc };
208a210,211
> int pw;
> int cc;
381a385,393
> int GetValueClamp(int row, int mini, int maxi) const
> {
> MapIntToValue::const_iterator i = events.find(row);
> if (i == events.end())
> return GetNoValue();
> else
> return min(max((*i).second, mini), maxi);
> }
>
597a610
> MapIntToValue::const_iterator EventsBeginAt(int offset) const { return events.lower_bound(offset); }
630a644,645
> bool IsMidiPW() const { return paramIndex == MidiPitchWheel; }
> bool IsMidiCC() const { return paramIndex == MidiCC; }
633c648
< int GetDigitCount()
---
> int GetDigitCount() const
639c654
< case pt_byte: return 2;
---
> case pt_byte: return IsAscii() ? 1 : 2;
646c661
< int GetWidth()
---
> int GetWidth() const
651c666
< return GetDigitCount() + 1;
---
> return GetDigitCount() + (IsTiedToNext() ? 0 : 1);
654c669
< bool IsNormalValue(int value)
---
> bool IsNormalValue(int value) const
677a693,694
> int GetIndex() const { return paramIndex; }
>
742,743c759,761
< if (GetParamType() == pt_note)
< value = EncodeNote(modulators->DiatonicTransposition(DecodeNote(value)));
---
> if (GetParamType() == pt_note && IsNormalValue(value))
> value = EncodeNote(min(max(modulators->DiatonicTransposition(DecodeNote(value)), 0), 9 * 12 + 11));
>
770a789
> if (modulators) n.note = min(max(modulators->DiatonicTransposition(n.note), 0), 9 * 12 + 11);
773a793
> n.pw = n.cc = -1;
796a817,850
> else if (ip == MidiPitchWheel)
> {
> auto n = gdata.activeMidiNotes.find(MacIntPair(pMachine, paramTrack));
> if (n == gdata.activeMidiNotes.end())
> {
> gdata.activeMidiNotes[MacIntPair(pMachine, paramTrack)] = ActiveMidiNote();
> n = gdata.activeMidiNotes.find(MacIntPair(pMachine, paramTrack));
> (*n).second.state = ActiveMidiNote::pw_or_cc;
> (*n).second.cc = -1;
> (*n).second.delaytime = 0;
> (*n).second.cuttime = 0x7fffffff;
> }
>
> (*n).second.rowInBeat = gdata.currentRowInBeat;
> (*n).second.RPB = gdata.currentRPB;
> (*n).second.pw = (*i).second;
> }
> else if (ip == MidiCC)
> {
> auto n = gdata.activeMidiNotes.find(MacIntPair(pMachine, paramTrack));
> if (n == gdata.activeMidiNotes.end())
> {
> gdata.activeMidiNotes[MacIntPair(pMachine, paramTrack)] = ActiveMidiNote();
> n = gdata.activeMidiNotes.find(MacIntPair(pMachine, paramTrack));
> (*n).second.state = ActiveMidiNote::pw_or_cc;
> (*n).second.pw = -1;
> (*n).second.delaytime = 0;
> (*n).second.cuttime = 0x7fffffff;
> }
>
> (*n).second.rowInBeat = gdata.currentRowInBeat;
> (*n).second.RPB = gdata.currentRPB;
> (*n).second.cc = (*i).second;
> }
802c856
< if ((*n).second.state == ActiveMidiNote::note_on_pending)
---
> if ((*n).second.state == ActiveMidiNote::note_on_pending || (*n).second.pw >= 0 || (*n).second.cc >= 0)
823c877
< (*sptv)[tid] = shared_ptr<CSubPatternControl>(new CSubPatternControl((*i).second, paramTrack));
---
> (*sptv)[tid] = make_shared<CSubPatternControl>((*i).second, paramTrack);
887a942,971
> bool IsTiedToNext() const
> {
> assert(pParam != NULL);
> return (pParam->Flags & MPF_TIE_TO_NEXT) != 0;
> }
>
> bool IsAscii() const
> {
> assert(pParam != NULL);
> return (pParam->Flags & MPF_ASCII) != 0;
> }
>
> char const *GetName() const
> {
> assert(pParam != NULL);
> return pParam->Name;
> }
>
> bool NameEqualsIgnoreCase(char const *str) const
> {
> assert(pParam != NULL);
> return ::_stricmp(pParam->Name, str) == 0;
> }
>
> bool NameStartsWithIgnoreCase(char const *str) const
> {
> assert(pParam != NULL);
> return ::_strnicmp(pParam->Name, str, strlen(str)) == 0;
> }
>
893a978
>
922a1008,1020
> void UpdateWaveReferences(byte const *remap)
> {
> if (!IsWaveParameter()) return;
>
> for (MapIntToValue::iterator i = events.begin(); i != events.end(); i++)
> {
> int wr = (*i).second;
> if (wr >= WAVE_MIN && wr <= WAVE_MAX && remap[wr] >= WAVE_MIN && remap[wr] <= WAVE_MAX)
> (*i).second = remap[wr];
> }
>
> }
>
982c1080
< columns.push_back(shared_ptr<CColumn>(new CColumn((*i).get(), copydata)));
---
> columns.push_back(make_shared<CColumn>((*i).get(), copydata));
1030c1128
< CColumn *pc = new CColumn();
---
> auto pc = make_shared<CColumn>();
1032c1130
< columns.push_back(shared_ptr<CColumn>(pc));
---
> columns.push_back(pc);
1180c1278
< shared_ptr<CColumn> pc = shared_ptr<CColumn>(new CColumn(columns[lastcoli+i].get(), false, true));
---
> shared_ptr<CColumn> pc = make_shared<CColumn>(columns[lastcoli+i].get(), false, true);
1184,1185c1282,1283
< // int nmt = pcb->GetNumTracks(pmac);
< // if (nmt < tc + 1)
---
> int nmt = pcb->GetNumTracks(pmac);
> if (nmt < tc + 1)
1218a1317,1325
> shared_ptr<CColumn> GetColumn(function<bool (shared_ptr<CColumn> const &)> match) const
> {
> for (auto i = columns.begin(); i != columns.end(); i++)
> if (match(*i))
> return (*i);
>
> return shared_ptr<CColumn>();
> }
>
1241c1348
< return shared_ptr<CColumn>(new CColumn(pcb, mpp, track));
---
> return make_shared<CColumn>(pcb, mpp, track);
1244c1351
< void EnableColumns(MacParamPairVector const &_ec, CMICallbacks *pcb, int mintracks = 1)
---
> void EnableColumns(MacParamPairVector const &_ec, CMICallbacks *pCB, int mintracks = 1, int rpb = -1)
1253c1360
< if (IsGlobalParameter(*i, pcb))
---
> if (IsGlobalParameter(*i, pCB))
1262c1369
< if (!c) c = CreateColumn(*i, 0, pcb);
---
> if (!c) c = CreateColumn(*i, 0, pCB);
1266d1372
<
1271a1378
> maxtracks = max(maxtracks, GetTrackCount((*i).first));
1289c1396
< cv.push_back(shared_ptr<CColumn>(CreateColumn(MacIntPair(*(i + c)), t, pcb)));
---
> cv.push_back(shared_ptr<CColumn>(CreateColumn(MacIntPair(*(i + c)), t, pCB)));
1295a1403
> MACHINE_LOCK;
1296a1405,1408
>
> if (rpb > 0)
> SetRowsPerBeat(rpb);
>
1404a1517,1525
> void UpdateWaveReferences(byte const *remap)
> {
> for (ColumnVector::iterator i = columns.begin(); i != columns.end(); i++)
> (*i)->UpdateWaveReferences(remap);
>
> for (ColumnVector::iterator i = deletedColumns.begin(); i != deletedColumns.end(); i++)
> (*i)->UpdateWaveReferences(remap);
> }
>
1415a1537,1541
> auto pwcol = GetColumn(MacIntPair(pmac, MidiPitchWheel), t).get();
> if (pwcol != NULL && pwcol->HasValue(row)) continue;
> auto cccol = GetColumn(MacIntPair(pmac, MidiCC), t).get();
> if (cccol != NULL && cccol->HasValue(row)) continue;
>
1533a1660,1732
> int AllocateMidiCCTrack(CMachine *pmac, int row, int delay, MapMacAndTrackToActiveMidiNote ¬es, int tc)
> {
> for (int t = 0; t < tc; t++)
> {
> MapMacAndTrackToActiveMidiNote::iterator i;
>
> for (i = notes.begin(); i != notes.end(); i++)
> if ((*i).first.second == t) break;
>
> if (i == notes.end())
> {
> auto notecol = GetColumn(MacIntPair(pmac, MidiNote), t).get();
> auto pwcol = GetColumn(MacIntPair(pmac, MidiPitchWheel), t).get();
> auto cccol = GetColumn(MacIntPair(pmac, MidiCC), t).get();
> auto delaycol = GetColumn(MacIntPair(pmac, MidiNoteDelay), t).get();
> auto cutcol = GetColumn(MacIntPair(pmac, MidiNoteCut), t).get();
>
> bool gotstuff = notecol != NULL && notecol->HasValue(row);
> gotstuff |= pwcol != NULL && pwcol->HasValue(row);
> gotstuff |= cccol != NULL && cccol->HasValue(row);
> gotstuff |= cutcol != NULL && cutcol->HasValue(row);
>
> if (!gotstuff) return t;
> }
> }
>
> return tc > 0 ? 0 : -1;
> }
>
> void RecordMidiCCs(int row, CRecQueue::Event const &e, CGlobalData &gdata)
> {
> int tc = GetTrackCount(e.pmac);
> if (tc < 1) return;
>
> if (e.param == 255)
> {
> if (!HasMidiPWColumn()) return;
> }
> else if (e.param >= 0 && e.param <= 127)
> {
> if (!HasMidiCCColumn()) return;
> }
> else
> {
> return;
> }
>
>
> auto range = GetRowSubtickRange(row % gdata.currentRPB, gdata.currentRPB, gdata.subticksPerTick);
> int delay = min(max((gdata.currentSubtick - range.first) * 96 / (range.second - range.first), 0), 95);
>
> int rectrack = AllocateMidiCCTrack(e.pmac, row, delay, gdata.recordingMidiNotes, tc);
> if (rectrack < 0) return;
>
> if (e.param == 255)
> {
> auto pwcol = GetColumn(MacIntPair(e.pmac, MidiPitchWheel), rectrack).get();
> if (pwcol == NULL) return;
> pwcol->SetValue(row, e.value);
> }
> else
> {
> auto cccol = GetColumn(MacIntPair(e.pmac, MidiCC), rectrack).get();
> if (cccol == NULL) return;
> cccol->SetValue(row, (e.param << 8) | e.value);
> }
>
> auto delaycol = GetColumn(MacIntPair(e.pmac, MidiNoteDelay), rectrack).get();
> if (delaycol != NULL && delay != 0) delaycol->SetValue(row, delay);
>
>
> }
>
1546c1745,1751
< if (e.group < 0 && e.value > 0) RecordMidiNoteOns(row, e, gdata);
---
> if (e.group == -1 && e.value > 0) RecordMidiNoteOns(row, e, gdata);
> }
>
> for (int ei = 0; ei < (int)ev.size(); ei++)
> {
> CRecQueue::Event const &e = ev[ei];
> if (e.group == -1 && e.value == 0) RecordMidiNoteOffs(row, e, gdata);
1552c1757
< if (e.group < 0 && e.value == 0) RecordMidiNoteOffs(row, e, gdata);
---
> if (e.group == -2) RecordMidiCCs(row, e, gdata);
1588a1794,1816
> bool HasMidiPWColumn() const
> {
> for (auto i = columns.begin(); i != columns.end(); i++)
> if ((*i)->IsMidiPW())
> return true;
>
> return false;
> }
>
> bool HasMidiCCColumn() const
> {
> for (auto i = columns.begin(); i != columns.end(); i++)
> if ((*i)->IsMidiCC())
> return true;
>
> return false;
> }
>
> int ScaleToMidiTime(int row, int delay, int range) const
> {
> return (range * row + delay) * 960 * BUZZ_TICKS_PER_BEAT / (range * rowsPerBeat);
> }
>
1591d1818
< if (!HasMidiNoteColumn()) return false;
1604a1832,1840
> if (notecol[i] == NULL)
> {
> notecol[i] = GetColumn([=] (shared_ptr<CColumn> const &c)
> {
> return c->GetParamType() == pt_note && c->IsTrackParam() && c->GetTrack() == i && c->NameEqualsIgnoreCase("note");
> }).get();
> if (notecol[i] == NULL) return false;
> }
>
1605a1842,1849
> if (velcol[i] == NULL)
> {
> velcol[i] = GetColumn([=] (shared_ptr<CColumn> const &c)
> {
> return c->GetParamType() == pt_byte && c->IsTrackParam() && c->GetTrack() == i && (c->NameEqualsIgnoreCase("note velocity") || c->NameEqualsIgnoreCase("velocity"));
> }).get();
> }
>
1606a1851,1858
> if (delaycol[i] == NULL)
> {
> delaycol[i] = GetColumn([=] (shared_ptr<CColumn> const &c)
> {
> return c->GetParamType() == pt_byte && c->IsTrackParam() && c->GetTrack() == i && c->NameEqualsIgnoreCase("note delay");
> }).get();
> }
>
1607a1860,1866
> if (cutcol[i] == NULL)
> {
> cutcol[i] = GetColumn([=] (shared_ptr<CColumn> const &c)
> {
> return c->GetParamType() == pt_byte && c->IsTrackParam() && c->GetTrack() == i && c->NameEqualsIgnoreCase("note cut");
> }).get();
> }
1615a1875,1877
> int const delayrange = (delaycol[t] != NULL) ? (delaycol[t]->GetMaxValue() + 1) : 96;
> int const cutrange = (cutcol[t] != NULL) ? (cutcol[t]->GetMaxValue() + 1) : 96;
>
1619c1881
< int cut = 96;
---
> int cut = cutrange;
1622c1884
< if (velcol[t] != NULL && velcol[t]->HasValue(row)) velocity = velcol[t]->GetValue(row);
---
> if (velcol[t] != NULL && velcol[t]->HasValue(row)) velocity = velcol[t]->GetValueClamp(row, 1, 127);
1634c1896
< (96 * row + delay) * 10 * BUZZ_TICKS_PER_BEAT / rowsPerBeat,
---
> ScaleToMidiTime(row, delay, delayrange),
1641c1903
< (96 * row + delay) * 10 * BUZZ_TICKS_PER_BEAT / rowsPerBeat,
---
> ScaleToMidiTime(row, delay, delayrange),
1646c1908
< if (cut < 96)
---
> if (cut < cutrange)
1650c1912
< (96 * row + cut) * 10 * BUZZ_TICKS_PER_BEAT / rowsPerBeat,
---
> ScaleToMidiTime(row, cut, cutrange),
1658c1920
< (96 * row + min(delay, cut)) * 10 * BUZZ_TICKS_PER_BEAT / rowsPerBeat,
---
> ScaleToMidiTime(row, min(delay, cut), delayrange),
1952c2214
< shared_ptr<CPlayingPattern> p = shared_ptr<CPlayingPattern>(new CPlayingPattern(gdata.patternList[spi], NULL, -1, tofs, (*i).second->modulators));
---
> auto p = make_shared<CPlayingPattern>(gdata.patternList[spi], nullptr, -1, tofs, (*i).second->modulators);
diff old/PatEd.cpp new/PatEd.cpp
42a43
> ON_WM_CHAR()
217,218d217
< MapIntToValue::const_iterator ei = pc->EventsBegin();
<
219a219
> MapIntToValue::const_iterator ei = pc->EventsBeginAt(firstrow);
222,223d221
< while(ei != pc->EventsEnd() && (*ei).first < firstrow) ei++;
<
246c244
< static void FieldToText(char *txt, CMPType type, bool hasval, void *fdata)
---
> static void FieldToText(char *txt, CMPType type, bool ascii, bool hasval, void *fdata)
282c280
< if (!hasval)
---
> if (ascii)
284,285c282,287
< txt[0] = '.';
< txt[1] = '.';
---
> if (!hasval)
> txt[0] = '.';
> else
> txt[0] = b;
>
> txt[1] = 0;
289,290c291,301
< txt[0] = NibbleToHexText[b >> 4];
< txt[1] = NibbleToHexText[b & 15];
---
> if (!hasval)
> {
> txt[0] = '.';
> txt[1] = '.';
> }
> else
> {
> txt[0] = NibbleToHexText[b >> 4];
> txt[1] = NibbleToHexText[b & 15];
> }
> txt[2] = 0;
292d302
< txt[2] = 0;
336a347,389
> static CString FieldToLongText(CMPType type, bool hasval, int v)
> {
> CString s;
>
> switch(type)
> {
> case pt_note:
> {
> if (!hasval)
> {
> }
> else if (v == NOTE_OFF)
> {
> s = "note off";
> }
> else
> {
> int octave = v >> 4;
> int note = (v & 15) -1;
>
> s = NoteToText[note*2+0];
> s += NoteToText[note*2+1];
> s += (char)(octave + '0');
> }
> }
> break;
> default:
> if (v != -1)
> {
> if (v > 255)
> s.Format("%04X (%d)", v, v);
> else
> s.Format("%02X (%d)", v, v);
> }
>
> break;
>
>
> }
>
> return s;
> }
>
340a394,402
> int bar = 4;
>
> if (ppat->numBeats % 13 == 0) bar = 13;
> else if (ppat->numBeats % 11 == 0) bar = 11;
> else if (ppat->numBeats % 9 == 0) bar = 9;
> else if (ppat->numBeats % 7 == 0) bar = 7;
> else if (ppat->numBeats % 5 == 0) bar = 5;
> else if (ppat->numBeats % 3 == 0) bar = 3;
>
345c407
< else if ((row % (4 * ppat->rowsPerBeat)) == 0)
---
> else if ((row % (bar * ppat->rowsPerBeat)) == 0)
377c439
< FieldToText(txt, pc->GetParamType(), hasvalue, (void *)&data);
---
> FieldToText(txt, pc->GetParamType(), pc->IsAscii(), hasvalue, (void *)&data);
379c441
< int len = strlen(txt);
---
> int len = (int)strlen(txt);
479c541
< if (x < colx - pew->fontSize.cx)
---
> if (x < colx - (ppat->columns[col]->IsTiedToNext() ? 0 : pew->fontSize.cx))
561c623
< r.right = r.left + GetColumnWidth(column) - pew->fontSize.cx;
---
> r.right = r.left + GetColumnWidth(column); // - pew->fontSize.cx;
882a945,959
> void CPatEd::EditAscii(char val)
> {
> CMachinePattern *ppat = pew->pPattern;
> CColumn *pc = ppat->columns[cursor.column].get();
>
> ppat->actions.BeginAction(pew, "Edit ASCII");
> {
> MACHINE_LOCK;
> pc->SetValue(cursor.row, val);
> }
>
> InvalidateField(cursor.row, cursor.column);
> MoveCursorDelta(0, cursorStep);
> }
>
1088,1095c1165,1175
< if (nChar >= '0' && nChar <= '9')
< EditByte(nChar - '0');
< else if (nChar == 'A') EditByte(0xA);
< else if (nChar == 'B') EditByte(0xB);
< else if (nChar == 'C') EditByte(0xC);
< else if (nChar == 'D') EditByte(0xD);
< else if (nChar == 'E') EditByte(0xE);
< else if (nChar == 'F') EditByte(0xF);
---
> if (!pc->IsAscii())
> {
> if (nChar >= '0' && nChar <= '9')
> EditByte(nChar - '0');
> else if (nChar == 'A') EditByte(0xA);
> else if (nChar == 'B') EditByte(0xB);
> else if (nChar == 'C') EditByte(0xC);
> else if (nChar == 'D') EditByte(0xD);
> else if (nChar == 'E') EditByte(0xE);
> else if (nChar == 'F') EditByte(0xF);
> }
1121a1202,1239
> void CPatEd::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
> {
> CMachinePattern *ppat = pew->pPattern;
> if (ppat == NULL || ppat->columns.size() == 0)
> return;
>
> CColumn *pc = ppat->columns[cursor.column].get();
>
> if (pc->GetParamType() == pt_byte && pc->IsAscii())
> {
> if (nChar != '.')
> {
> char ch = (char)nChar;
> bool valid = pCB->IsValidAsciiChar(pc->GetMachine(), pc->GetIndex(), ch);
>
> if (!valid && nChar >= 'a' && nChar <= 'z')
> {
> ch += 'A' - 'a';
> valid = pCB->IsValidAsciiChar(pc->GetMachine(), pc->GetIndex(), ch);
> }
> else if (!valid && nChar >= 'A' && nChar <= 'Z')
> {
> ch += 'a' - 'A';
> valid = pCB->IsValidAsciiChar(pc->GetMachine(), pc->GetIndex(), ch);
> }
>
> if (ch < pc->GetMinValue() || ch > pc->GetMaxValue())
> valid = false;
>
> if (valid)
> EditAscii(ch);
> }
> }
>
> CWnd::OnChar(nChar, nRepCnt, nFlags);
> }
>
>
1279,1280d1396
< char txt[6];
< FieldToText(txt, pc->GetParamType(), pc->HasValue(cursor.row), (void *)&value);
1284c1400
< char const *desc = pc->DescribeValue(value, pCB);
---
> s = FieldToLongText(pc->GetParamType(), pc->HasValue(cursor.row), value);
1286c1402,1403
< s = txt;
---
> char const *desc = pc->DescribeValue(value, pCB);
>
1288c1405
< s += (CString)" (" + desc + ")";
---
> s += (CString)" " + desc;
1372a1490,1491
> CColumn *pc = ppat->columns[cursor.column].get();
>
1379a1499,1500
> CCursorPos oldpos = cursor;
>
1388a1510,1540
> if (cursor == oldpos)
> {
> switch(selMode)
> {
> case column: selMode = track; break;
> case track: if (pc->IsTrackParam()) selMode = group; else selMode = all; break;
> case group: selMode = all; break;
> case all: selMode = column; break;
> }
>
> switch(selMode)
> {
> case column:
> selStart.x = selEnd.x = cursor.column;
> break;
> case track:
> selStart.x = ppat->GetFirstColumnOfTrackByColumn(cursor.column);
> selEnd.x = selStart.x + ppat->GetGroupColumnCount(cursor.column) - 1;
> break;
> case group:
> selStart.x = ppat->GetFirstColumnOfTrackByColumn(cursor.column) - pc->GetTrack() * ppat->GetGroupColumnCount(cursor.column);
> selEnd.x = selStart.x + ppat->GetGroupColumnCount(cursor.column) * ppat->GetTrackCount(pc->GetMachine()) - 1;
> break;
> case all:
> selStart.x = 0;
> selEnd.x = (int)ppat->columns.size() - 1;
> break;
> }
>
> }
>
1763,1764c1915,1916
< int vel = lParam;
< int n = wParam - pew->pCB->GetBaseOctave() * 12;
---
> int vel = (int)lParam;
> int n = (int)wParam - pew->pCB->GetBaseOctave() * 12;
diff old/PatEd.h new/PatEd.h
69a70
> void EditAscii(char n);
131a133
> afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
diff old/PatternXP.cpp new/PatternXP.cpp
92a93
> virtual void UpdateWaveReferences(CPattern *p, byte const *remap);
448a450,453
> void miex::UpdateWaveReferences(CPattern *p, byte const *remap)
> {
> pmi->patterns[p]->UpdateWaveReferences(remap);
> }
508a514,519
> if (pmi->pCB->GetStateFlags() & SF_RECORDING)
> {
> pmi->recQueue.Push(CRecQueue::Event(pmac, -2, channel, ctrl, value));
> pmi->patEd->pe.InvalidateInTimer();
> }
>
696a708,719
> if ((*i).second.pw >= 0 && cst >= dtime)
> {
> pCB->SendMidiControlChange((*i).first.first, 255, 0, (*i).second.pw);
> (*i).second.pw = -1;
> }
>
> if ((*i).second.cc >= 0 && cst >= dtime)
> {
> pCB->SendMidiControlChange((*i).first.first, ((*i).second.cc >> 8) & 0x7f, 0, (*i).second.cc & 0x7f);
> (*i).second.cc = -1;
> }
>
701a725,729
> else if ((*i).second.state == ActiveMidiNote::pw_or_cc && (*i).second.pw < 0 && (*i).second.cc < 0)
> {
> globalData.activeMidiNotes.erase(i);
> }
>
diff old/ScrollWnd.cpp new/ScrollWnd.cpp
44,45c44,48
< canvasSize = s;
< ScrollTo(CPoint(0, 0));
---
> if (canvasSize != s)
> {
> canvasSize = s;
> ScrollTo(GetScrollPos());
> }
diff old/ScrollWnd.h new/ScrollWnd.h
50a51
> void ScrollTo(CPoint pos);
58d58
< void ScrollTo(CPoint pos);
diff old/stdafx.h new/stdafx.h
14a15,24
> #define NOMINMAX
>
> #ifndef max
> #define max(a,b) (((a) > (b)) ? (a) : (b))
> #endif
>
> #ifndef min
> #define min(a,b) (((a) < (b)) ? (a) : (b))
> #endif
>
53a64,65
>
> //#define MI_DEBUG_LOCKS
68a81
>
Re: Pattern XP mod
Thanks.oskari wrote:It looks like the code on jeskola.net was old so it didn't have the latest features like pitch bend record. It's updated now and I think you might be able to automatically merge it with your new code. There are some other important changes like UpdateWaveReferences (template paste).
That's what I was thinking.
I use Beyond Compare to merge the code, that's not a problem.
Re: Pattern XP mod
New version
- Upgraded to last official PatternXP sources (add pitch bend record ...)
- New chords files added. Thanks to Tinga as usual
- Import pattern can be undone.
- Upgraded to last official PatternXP sources (add pitch bend record ...)
- New chords files added. Thanks to Tinga as usual
- Import pattern can be undone.
Re: Pattern XP mod
Added :
- Reverse selection (shortcut Ctrl+D)
- Humanize Toolbutton enabled when selection is empty
- Reverse selection (shortcut Ctrl+D)
- Humanize Toolbutton enabled when selection is empty
Re: Pattern XP mod
YAY!!!!
Thanks guys!
Thanks guys!
Re: Pattern XP mod
Added
- Mirror selection (ctrl+shift+D).
- Mirror selection (ctrl+shift+D).
Re: Pattern XP mod
Chahur, thanks for this, you're doing a great job.
In Pattern XP editor I'd like to be able to trigger the machine help display by double clicking (or by choosing it via left mouse button menu).
Main reason would be to more directly/intuitively get info of effects command parameters values while editing patterns.
In Pattern XP editor I'd like to be able to trigger the machine help display by double clicking (or by choosing it via left mouse button menu).
Main reason would be to more directly/intuitively get info of effects command parameters values while editing patterns.
Re: Pattern XP mod
chahur wrote:This is the way "Buttons" act. They have focus when you click on it.UNZ wrote:very nice additions!
minor annoyance: when "use toolbar" is off, clicking a button (chord for example) switches the focus away from the pattern. So you have to click on the pattern again and only then can you enter notes and move around again etc.
This doesn't happen with "use toolbar" on.
The "ToolButtons" don't have focus, so the pattern don't loose it when you click.
I only use the toolbar version. I kept the button version because someone asked for it, but I don't plan to improve it.
they don't have to work like this, its configurable. look at the "columns.." button. there, even dialog comes up and when you close it focus switches back to the pattern editor. it shouldn't be a big thing to switch back focus or disable focus stealing imho. please ?
the "midi edit" checkbox has the same issue btw.
Re: Pattern XP mod
Added :
- Remove Chords limit
- Add "Parameters" dialog"
- Keep "Draw play position" persistent (parameter)
- Put focus back to editor when clicking on a button
- Remove Chords limit
- Add "Parameters" dialog"
- Keep "Draw play position" persistent (parameter)
- Put focus back to editor when clicking on a button
Re: Pattern XP mod
THANK YOUchahur wrote:Added :
- Remove Chords limit
- Add "Parameters" dialog"
- Keep "Draw play position" persistent (parameter)
- Put focus back to editor when clicking on a button
Re: Pattern XP mod
Loving the new features, thanks!! Mirror selection is changing all notes, not just the selected ones, is that intentional?