Add octave offset dropdown, fix waveform sidebar, embed audio in plugin state

- Add octave offset combo (-3 to +3) in title bar for MIDI input transposition
- Fix waveform sidebar base note from C3 to C4
- Fix midiNoteToSliceIndex to compare pitch classes instead of raw MIDI notes
- Add colored slice indicator dots on waveform sidebar keys
- Embed audio data, file path, sample rate, and slices in plugin state for
  DAW project save/restore (falls back to file path if embedded data missing)
This commit is contained in:
Armin 2026-07-21 15:20:49 +02:00
commit 73c4095139
6 changed files with 130 additions and 12 deletions

View file

@ -163,17 +163,18 @@ int WaveformDisplay::sampleToX(int sample) const
int WaveformDisplay::keyRowToMidiNote(int row) const
{
const int numRows = 12;
const int baseMidiNote = 48;
const int baseMidiNote = 60;
return baseMidiNote + (numRows - 1 - row);
}
int WaveformDisplay::midiNoteToSliceIndex(int note) const
{
int pitchClass = note % 12;
const auto& slices = sliceManager.getSlices();
int numSlices = sliceManager.getNumSlices();
for (int i = 0; i < numSlices; ++i)
{
if (slices[static_cast<size_t>(i)].midiNote == note)
if (slices[static_cast<size_t>(i)].midiNote == pitchClass)
return i;
}
return -1;
@ -241,6 +242,13 @@ void WaveformDisplay::drawKeys(juce::Graphics& g, juce::Rectangle<float> bounds)
const int numRows = 12;
float rowHeight = bounds.getHeight() / static_cast<float>(numRows);
juce::Colour markerColours[] = {
juce::Colour(0xffff6b6b), juce::Colour(0xff4ecdc4), juce::Colour(0xffffe66d),
juce::Colour(0xffa8e6cf), juce::Colour(0xff8b94ff), juce::Colour(0xffff8b94),
juce::Colour(0xffdda0dd), juce::Colour(0xff87ceeb), juce::Colour(0xff98fb98),
juce::Colour(0xffffb347), juce::Colour(0xffc39bd3), juce::Colour(0xff76d7c4)
};
for (int row = 0; row < numRows; ++row)
{
float y = bounds.getY() + static_cast<float>(row) * rowHeight;
@ -252,15 +260,10 @@ void WaveformDisplay::drawKeys(juce::Graphics& g, juce::Rectangle<float> bounds)
juce::Colour baseCol = isBlack ? juce::Colour(0xff333344) : juce::Colour(0xff555566);
// Highlight row if it has a slice and that slice is active
int sliceIdx = midiNoteToSliceIndex(midiNote);
if (sliceIdx >= 0 && sliceIdx == activeSliceIndex)
{
juce::Colour markerColours[] = {
juce::Colour(0xffff6b6b), juce::Colour(0xff4ecdc4), juce::Colour(0xffffe66d),
juce::Colour(0xffa8e6cf), juce::Colour(0xffff8b94), juce::Colour(0xffdda0dd)
};
baseCol = markerColours[sliceIdx % 6].withAlpha(0.25f);
baseCol = markerColours[sliceIdx % 12].withAlpha(0.25f);
}
g.setColour(baseCol);
@ -269,6 +272,15 @@ void WaveformDisplay::drawKeys(juce::Graphics& g, juce::Rectangle<float> bounds)
g.setColour(juce::Colour(0xffaaaaaa));
g.drawRect(bounds.getX(), y, bounds.getWidth(), rowHeight, 0.5f);
if (sliceIdx >= 0)
{
float dotR = rowHeight * 0.2f;
float dotX = bounds.getX() + bounds.getWidth() * 0.5f;
float dotY = y + rowHeight * 0.5f;
g.setColour(markerColours[sliceIdx % 12].withAlpha(0.7f));
g.fillEllipse(dotX - dotR, dotY - dotR, dotR * 2.0f, dotR * 2.0f);
}
const char* noteNames[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
int noteIdx = midiNote % 12;
int octave = midiNote / 12 - 1;