mirror of
https://codeberg.org/armin/monoslicer.git
synced 2026-10-11 13:01:54 +02:00
Match Length button toggles with red highlight, moved controls to right side
This commit is contained in:
parent
7630bb93fc
commit
16322a2bb6
3 changed files with 73 additions and 31 deletions
|
|
@ -156,8 +156,11 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
|
|||
|
||||
addAndMakeVisible(stretchButton);
|
||||
stretchButton.addListener(this);
|
||||
stretchButton.setClickingTogglesState(true);
|
||||
stretchButton.setColour(juce::TextButton::buttonColourId, juce::Colour(0xff2a2a4a));
|
||||
stretchButton.setColour(juce::TextButton::textColourOffId, juce::Colours::white);
|
||||
stretchButton.setColour(juce::TextButton::buttonOnColourId, juce::Colour(0xffcc3333));
|
||||
stretchButton.setColour(juce::TextButton::textColourOnId, juce::Colours::white);
|
||||
|
||||
// Key shift combo
|
||||
addAndMakeVisible(keyShiftComboBox);
|
||||
|
|
@ -328,35 +331,36 @@ void MonoslicerEditor::resized()
|
|||
int comboGap = 4;
|
||||
int contentW = bw - 2 * sectionGap - comboGap;
|
||||
|
||||
int leftW = static_cast<int>(contentW * 0.21);
|
||||
int sideW = static_cast<int>(contentW * 0.21);
|
||||
int comboW = static_cast<int>(contentW * 0.12);
|
||||
int kw = (contentW - leftW - comboW) / 7;
|
||||
int kw = (contentW - sideW - sideW - comboW - sectionGap * 2 - comboGap) / 7;
|
||||
int adsrW = 4 * kw;
|
||||
int filterW = 3 * kw + comboW + comboGap;
|
||||
|
||||
// Bottom panel: buttons + stretch | amp ADSR | filter ADSR | filter knobs
|
||||
auto leftArea = bottomRow.removeFromLeft(leftW);
|
||||
// Place auto-slice controls and stretch controls on the right side
|
||||
int rightW = sideW;
|
||||
auto rightArea = bottomRow.removeFromRight(rightW);
|
||||
{
|
||||
auto btnArea = leftArea.removeFromTop(28);
|
||||
auto btnArea = rightArea.removeFromTop(28);
|
||||
autoSliceButton.setBounds(btnArea.getX(), btnArea.getY(), btnArea.getWidth() / 2 - 2, 24);
|
||||
clearSlicesButton.setBounds(btnArea.getX() + btnArea.getWidth() / 2 + 2, btnArea.getY(), btnArea.getWidth() / 2 - 2, 24);
|
||||
leftArea.removeFromTop(4);
|
||||
rightArea.removeFromTop(4);
|
||||
// Stretch controls
|
||||
int stretchW = leftArea.getWidth();
|
||||
int stretchW = rightArea.getWidth();
|
||||
int col1W = stretchW / 2 - 2;
|
||||
int col2W = stretchW / 2 - 2;
|
||||
bpmSlider.setBounds(leftArea.getX(), leftArea.getY(), col1W, 20);
|
||||
stretchBeatsComboBox.setBounds(leftArea.getX() + col1W + 4, leftArea.getY(), col2W, 20);
|
||||
leftArea.removeFromTop(24);
|
||||
stretchButton.setBounds(leftArea.getX(), leftArea.getY(), stretchW, 22);
|
||||
leftArea.removeFromTop(26);
|
||||
leftArea.removeFromTop(20);
|
||||
keyShiftComboBox.setBounds(leftArea.getX(), leftArea.getY(), stretchW, 20);
|
||||
leftArea.removeFromTop(24);
|
||||
vuMeter.setBounds(leftArea.getX(), leftArea.getY(), stretchW, 40);
|
||||
bpmSlider.setBounds(rightArea.getX(), rightArea.getY(), col1W, 20);
|
||||
stretchBeatsComboBox.setBounds(rightArea.getX() + col1W + 4, rightArea.getY(), col2W, 20);
|
||||
rightArea.removeFromTop(24);
|
||||
stretchButton.setBounds(rightArea.getX(), rightArea.getY(), stretchW, 22);
|
||||
rightArea.removeFromTop(26);
|
||||
rightArea.removeFromTop(20);
|
||||
keyShiftComboBox.setBounds(rightArea.getX(), rightArea.getY(), stretchW, 20);
|
||||
rightArea.removeFromTop(24);
|
||||
vuMeter.setBounds(rightArea.getX(), rightArea.getY(), stretchW, 40);
|
||||
}
|
||||
|
||||
bottomRow.removeFromLeft(sectionGap);
|
||||
bottomRow.removeFromRight(sectionGap);
|
||||
|
||||
auto adsrSection = bottomRow.removeFromLeft(adsrW);
|
||||
{
|
||||
|
|
@ -430,6 +434,25 @@ void MonoslicerEditor::timerCallback()
|
|||
waveformDisplay.setActiveSliceIndex(processorRef.currentActiveSlice.load());
|
||||
waveformDisplay.setSelectedSlice(processorRef.selectedSlice.load());
|
||||
|
||||
// Update stretch button state
|
||||
{
|
||||
int beatsId = stretchBeatsComboBox.getSelectedId();
|
||||
int numBeats = 4;
|
||||
switch (beatsId)
|
||||
{
|
||||
case 1: numBeats = 1; break;
|
||||
case 2: numBeats = 2; break;
|
||||
case 3: numBeats = 4; break;
|
||||
case 4: numBeats = 8; break;
|
||||
case 5: numBeats = 16; break;
|
||||
case 6: numBeats = 32; break;
|
||||
default: numBeats = 4; break;
|
||||
}
|
||||
float bpm = static_cast<float>(bpmSlider.getValue());
|
||||
bool matched = processorRef.isLengthMatchedToBeats(numBeats, bpm);
|
||||
stretchButton.setToggleState(matched, juce::dontSendNotification);
|
||||
}
|
||||
|
||||
// Release key click note when mouse is released
|
||||
if (keyClickNote >= 0)
|
||||
{
|
||||
|
|
@ -494,22 +517,29 @@ void MonoslicerEditor::buttonClicked(juce::Button* button)
|
|||
}
|
||||
else if (button == &stretchButton)
|
||||
{
|
||||
int beatsId = stretchBeatsComboBox.getSelectedId();
|
||||
int numBeats = 4;
|
||||
switch (beatsId)
|
||||
if (stretchButton.getToggleState())
|
||||
{
|
||||
case 1: numBeats = 1; break;
|
||||
case 2: numBeats = 2; break;
|
||||
case 3: numBeats = 4; break;
|
||||
case 4: numBeats = 8; break;
|
||||
case 5: numBeats = 16; break;
|
||||
case 6: numBeats = 32; break;
|
||||
default: numBeats = 4; break;
|
||||
int beatsId = stretchBeatsComboBox.getSelectedId();
|
||||
int numBeats = 4;
|
||||
switch (beatsId)
|
||||
{
|
||||
case 1: numBeats = 1; break;
|
||||
case 2: numBeats = 2; break;
|
||||
case 3: numBeats = 4; break;
|
||||
case 4: numBeats = 8; break;
|
||||
case 5: numBeats = 16; break;
|
||||
case 6: numBeats = 32; break;
|
||||
default: numBeats = 4; break;
|
||||
}
|
||||
float bpm = static_cast<float>(bpmSlider.getValue());
|
||||
processorRef.stretchToBeats(numBeats, bpm);
|
||||
waveformDisplay.setSampleBuffer(&processorRef.getSampleBuffer(), processorRef.getSampleRateLoaded());
|
||||
}
|
||||
else
|
||||
{
|
||||
processorRef.undo();
|
||||
waveformDisplay.setSampleBuffer(&processorRef.getSampleBuffer(), processorRef.getSampleRateLoaded());
|
||||
}
|
||||
float bpm = static_cast<float>(bpmSlider.getValue());
|
||||
processorRef.stretchToBeats(numBeats, bpm);
|
||||
waveformDisplay.setSampleBuffer(&processorRef.getSampleBuffer(), processorRef.getSampleRateLoaded());
|
||||
|
||||
}
|
||||
else if (button == &zoomInButton)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -768,6 +768,17 @@ juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter()
|
|||
return new MonoslicerProcessor();
|
||||
}
|
||||
|
||||
bool MonoslicerProcessor::isLengthMatchedToBeats(int numBeats, float bpm) const
|
||||
{
|
||||
if (sampleBuffer.getNumSamples() == 0 || bpm <= 0.0f || numBeats <= 0)
|
||||
return false;
|
||||
double sr = loadedSampleRate;
|
||||
if (sr <= 0.0) return false;
|
||||
double currentDuration = static_cast<double>(sampleBuffer.getNumSamples()) / sr;
|
||||
double targetDuration = static_cast<double>(numBeats) * 60.0 / static_cast<double>(bpm);
|
||||
return std::abs(currentDuration - targetDuration) < 0.005;
|
||||
}
|
||||
|
||||
void MonoslicerProcessor::stretchToBeats(int numBeats, float bpm)
|
||||
{
|
||||
if (sampleBuffer.getNumSamples() == 0 || bpm <= 0.0f || numBeats <= 0) return;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public:
|
|||
void stretchToBeats(int numBeats, float bpm);
|
||||
void psolaStretch(int targetLength);
|
||||
float getHostBpm() const;
|
||||
bool isLengthMatchedToBeats(int numBeats, float bpm) const;
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue