mirror of
https://codeberg.org/armin/monoslicer.git
synced 2026-10-11 21:11:53 +02:00
Fix GCC build (Clang-only flag), add note mapping + drag/drop overlay, UI tweaks
This commit is contained in:
parent
fd23c92a5d
commit
ca6f1ff0ee
7 changed files with 97 additions and 7 deletions
|
|
@ -91,4 +91,7 @@ target_link_libraries(Monoslicer
|
||||||
)
|
)
|
||||||
|
|
||||||
# Suppress JUCE / VST3 SDK warnings globally for all targets.
|
# Suppress JUCE / VST3 SDK warnings globally for all targets.
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics -Wno-deprecated-declarations -Wno-implicit-int-conversion-on-negation")
|
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
|
||||||
|
endif()
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations -Wno-implicit-int-conversion-on-negation")
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,10 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p)
|
||||||
processorRef.triggerSlice(sliceIdx, 0.8f);
|
processorRef.triggerSlice(sliceIdx, 0.8f);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addChildComponent(dropOverlay);
|
||||||
|
dropOverlay.setInterceptsMouseClicks(false, false);
|
||||||
|
dropOverlay.setVisible(false);
|
||||||
|
|
||||||
startTimerHz(30);
|
startTimerHz(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,6 +290,7 @@ void MonoslicerEditor::resized()
|
||||||
statusBarArea.getWidth() / 2 - 5, statusBarArea.getHeight());
|
statusBarArea.getWidth() / 2 - 5, statusBarArea.getHeight());
|
||||||
buildInfoLabel.setBounds(statusBarArea.getCentreX(), statusBarArea.getY(),
|
buildInfoLabel.setBounds(statusBarArea.getCentreX(), statusBarArea.getY(),
|
||||||
statusBarArea.getWidth() / 2 - 5, statusBarArea.getHeight());
|
statusBarArea.getWidth() / 2 - 5, statusBarArea.getHeight());
|
||||||
|
dropOverlay.setBounds(getLocalBounds());
|
||||||
|
|
||||||
int tx = 120;
|
int tx = 120;
|
||||||
|
|
||||||
|
|
@ -547,17 +552,58 @@ void MonoslicerEditor::comboBoxChanged(juce::ComboBox* comboBoxThatHasChanged)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [EDITOR DIAG] temporary
|
||||||
|
static void ediag(const char* what, const juce::StringArray& files, int accept)
|
||||||
|
{
|
||||||
|
FILE* f = fopen("/tmp/monoslicer_drag.log", "a");
|
||||||
|
if (f == nullptr) return;
|
||||||
|
fprintf(f, "[editor] %s accept=%d files=%d", what, accept, (int)files.size());
|
||||||
|
for (const auto& x : files) fprintf(f, " \"%s\"", x.toUTF8().getAddress());
|
||||||
|
fprintf(f, "\n");
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
bool MonoslicerEditor::isInterestedInFileDrag(const juce::StringArray& files)
|
bool MonoslicerEditor::isInterestedInFileDrag(const juce::StringArray& files)
|
||||||
{
|
{
|
||||||
for (const auto& f : files)
|
for (const auto& f : files)
|
||||||
if (f.endsWithIgnoreCase(".wav") || f.endsWithIgnoreCase(".aiff") ||
|
if (f.endsWithIgnoreCase(".wav") || f.endsWithIgnoreCase(".aiff") ||
|
||||||
f.endsWithIgnoreCase(".flac") || f.endsWithIgnoreCase(".ogg"))
|
f.endsWithIgnoreCase(".flac") || f.endsWithIgnoreCase(".ogg"))
|
||||||
|
{
|
||||||
|
ediag("isInterested", files, 1);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
ediag("isInterested", files, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MonoslicerEditor::fileDragEnter(const juce::StringArray& files, int, int)
|
||||||
|
{
|
||||||
|
ediag("enter", files, isInterestedInFileDrag(files) ? 1 : 0);
|
||||||
|
if (isInterestedInFileDrag(files))
|
||||||
|
{
|
||||||
|
dropOverlay.setVisible(true);
|
||||||
|
dropOverlay.toFront(false);
|
||||||
|
dropOverlay.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MonoslicerEditor::fileDragMove(const juce::StringArray& files, int, int)
|
||||||
|
{
|
||||||
|
if (isInterestedInFileDrag(files))
|
||||||
|
dropOverlay.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MonoslicerEditor::fileDragExit(const juce::StringArray&)
|
||||||
|
{
|
||||||
|
ediag("exit", juce::StringArray(), 0);
|
||||||
|
dropOverlay.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
void MonoslicerEditor::filesDropped(const juce::StringArray& files, int, int)
|
void MonoslicerEditor::filesDropped(const juce::StringArray& files, int, int)
|
||||||
{
|
{
|
||||||
|
ediag("drop", files, 1);
|
||||||
|
dropOverlay.setVisible(false);
|
||||||
|
|
||||||
for (const auto& f : files)
|
for (const auto& f : files)
|
||||||
{
|
{
|
||||||
juce::File file(f);
|
juce::File file(f);
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,8 @@ public:
|
||||||
|
|
||||||
auto drawBar = [&](float y, float level, float peak, const juce::String& legend)
|
auto drawBar = [&](float y, float level, float peak, const juce::String& legend)
|
||||||
{
|
{
|
||||||
float frac = juce::jlimit(0.0f, 1.0f, level);
|
float frac = juce::jlimit(0.0f, 1.0f, level) * 0.95f;
|
||||||
float peakFrac = juce::jlimit(0.0f, 1.0f, peak);
|
float peakFrac = juce::jlimit(0.0f, 1.0f, peak) * 0.95f;
|
||||||
|
|
||||||
// Legend text
|
// Legend text
|
||||||
g.setColour(juce::Colour(0xff888888));
|
g.setColour(juce::Colour(0xff888888));
|
||||||
|
|
@ -114,12 +114,29 @@ public:
|
||||||
void resized() override;
|
void resized() override;
|
||||||
|
|
||||||
bool isInterestedInFileDrag(const juce::StringArray& files) override;
|
bool isInterestedInFileDrag(const juce::StringArray& files) override;
|
||||||
|
void fileDragEnter(const juce::StringArray& files, int x, int y) override;
|
||||||
|
void fileDragMove(const juce::StringArray& files, int x, int y) override;
|
||||||
|
void fileDragExit(const juce::StringArray& files) override;
|
||||||
void filesDropped(const juce::StringArray& files, int x, int y) override;
|
void filesDropped(const juce::StringArray& files, int x, int y) override;
|
||||||
void buttonClicked(juce::Button* button) override;
|
void buttonClicked(juce::Button* button) override;
|
||||||
void comboBoxChanged(juce::ComboBox* comboBoxThatHasChanged) override;
|
void comboBoxChanged(juce::ComboBox* comboBoxThatHasChanged) override;
|
||||||
void timerCallback() override;
|
void timerCallback() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class DropOverlay : public juce::Component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void paint(juce::Graphics& g) override
|
||||||
|
{
|
||||||
|
auto b = getLocalBounds().toFloat();
|
||||||
|
g.setColour(juce::Colour(0x66003a8c));
|
||||||
|
g.fillRoundedRectangle(b.reduced(3.0f), 8.0f);
|
||||||
|
g.setColour(juce::Colour(0xcc88ccff));
|
||||||
|
g.drawRoundedRectangle(b.reduced(3.0f), 8.0f, 2.0f);
|
||||||
|
g.setFont(juce::Font(18.0f, juce::Font::bold));
|
||||||
|
g.drawText(TRANS("Drop audio file to load"), b, juce::Justification::centred, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
MonoslicerLookAndFeel lnf;
|
MonoslicerLookAndFeel lnf;
|
||||||
MonoslicerProcessor& processorRef;
|
MonoslicerProcessor& processorRef;
|
||||||
|
|
||||||
|
|
@ -199,6 +216,7 @@ private:
|
||||||
const juce::String& paramId, std::unique_ptr<SliderAttachment>& attachment);
|
const juce::String& paramId, std::unique_ptr<SliderAttachment>& attachment);
|
||||||
|
|
||||||
int keyClickNote = -1;
|
int keyClickNote = -1;
|
||||||
|
DropOverlay dropOverlay;
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MonoslicerEditor)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MonoslicerEditor)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -470,8 +470,12 @@ void MonoslicerProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::M
|
||||||
|
|
||||||
void MonoslicerProcessor::handleNoteOn(int noteNumber, float velocity)
|
void MonoslicerProcessor::handleNoteOn(int noteNumber, float velocity)
|
||||||
{
|
{
|
||||||
int offset = static_cast<int>(apvts.getRawParameterValue("octaveOffset")->load()) * 12;
|
int offset = 0;
|
||||||
int sliceIdx = noteNumber - 60 + offset;
|
if (auto* p = dynamic_cast<juce::AudioParameterInt*>(apvts.getParameter("octaveOffset")))
|
||||||
|
offset = p->get();
|
||||||
|
|
||||||
|
int note = noteNumber + offset * 12;
|
||||||
|
int sliceIdx = sliceManager.findSliceIndexForNote(note);
|
||||||
sliceIdx = juce::jlimit(0, juce::jmax(0, sliceManager.getNumSlices() - 1), sliceIdx);
|
sliceIdx = juce::jlimit(0, juce::jmax(0, sliceManager.getNumSlices() - 1), sliceIdx);
|
||||||
|
|
||||||
if (apvts.getRawParameterValue("selectViaMidi")->load() > 0.5f)
|
if (apvts.getRawParameterValue("selectViaMidi")->load() > 0.5f)
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,24 @@ int SliceManager::findSliceIndexForSample(int samplePos) const
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SliceManager::findSliceIndexForNote(int midiNote) const
|
||||||
|
{
|
||||||
|
const juce::CriticalSection::ScopedLockType lock(mutex);
|
||||||
|
if (slices.empty())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < slices.size(); ++i)
|
||||||
|
if (slices[i].midiNote == midiNote)
|
||||||
|
return static_cast<int>(i);
|
||||||
|
|
||||||
|
int pitchClass = midiNote % 12;
|
||||||
|
for (size_t i = 0; i < slices.size(); ++i)
|
||||||
|
if (slices[i].midiNote % 12 == pitchClass)
|
||||||
|
return static_cast<int>(i);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void SliceManager::sortSlices()
|
void SliceManager::sortSlices()
|
||||||
{
|
{
|
||||||
std::sort(slices.begin(), slices.end(),
|
std::sort(slices.begin(), slices.end(),
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ public:
|
||||||
void setBeforeChangeCallback(std::function<void()> cb) { beforeChangeCallback = std::move(cb); }
|
void setBeforeChangeCallback(std::function<void()> cb) { beforeChangeCallback = std::move(cb); }
|
||||||
|
|
||||||
int findSliceIndexForSample(int samplePos) const;
|
int findSliceIndexForSample(int samplePos) const;
|
||||||
|
int findSliceIndexForNote(int midiNote) const;
|
||||||
|
|
||||||
juce::AudioBuffer<float>* getMutableBuffer() { return sampleBuffer; }
|
juce::AudioBuffer<float>* getMutableBuffer() { return sampleBuffer; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -403,8 +403,8 @@ void WaveformDisplay::drawWaveform(juce::Graphics& g, juce::Rectangle<float> bou
|
||||||
|
|
||||||
filledPath.closeSubPath();
|
filledPath.closeSubPath();
|
||||||
|
|
||||||
juce::ColourGradient gradient(juce::Colour(0xff4488ff), bounds.getX(), bounds.getY(),
|
juce::ColourGradient gradient(juce::Colour(0xff5599ff), bounds.getX(), bounds.getY(),
|
||||||
juce::Colour(0xff2244aa), bounds.getX(), bounds.getBottom(), false);
|
juce::Colour(0xff002255), bounds.getX(), bounds.getBottom(), false);
|
||||||
g.setGradientFill(gradient);
|
g.setGradientFill(gradient);
|
||||||
g.fillPath(filledPath);
|
g.fillPath(filledPath);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue