mirror of
https://codeberg.org/armin/chromaflock.git
synced 2026-09-01 12:20:47 +02:00
fix pitch bend mapping, add inertia when releasing
This commit is contained in:
parent
0540fb1ce3
commit
6e37f224e1
4 changed files with 46 additions and 23 deletions
|
|
@ -168,8 +168,8 @@ void VuMeter::paint(juce::Graphics& g) {
|
||||||
clipPath.addRoundedRectangle(bounds, 9.0f);
|
clipPath.addRoundedRectangle(bounds, 9.0f);
|
||||||
g.reduceClipRegion(clipPath);
|
g.reduceClipRegion(clipPath);
|
||||||
|
|
||||||
juce::ColourGradient grad(juce::Colour(0xff00cc44).withAlpha(0.4f), 0.0f, bounds.getBottom(),
|
juce::ColourGradient grad(juce::Colour(0xff00cc44).withAlpha(0.7f), 0.0f, bounds.getBottom(),
|
||||||
juce::Colour(0xffcc2200).withAlpha(0.4f), 0.0f, bounds.getY(), false);
|
juce::Colour(0xffcc2200).withAlpha(0.7f), 0.0f, bounds.getY(), false);
|
||||||
g.setGradientFill(grad);
|
g.setGradientFill(grad);
|
||||||
g.fillRoundedRectangle(innerBar, 2.0f);
|
g.fillRoundedRectangle(innerBar, 2.0f);
|
||||||
}
|
}
|
||||||
|
|
@ -230,8 +230,8 @@ void WaveformDisplay::paint(juce::Graphics& g) {
|
||||||
clipPath.addRoundedRectangle(bounds, 9.0f);
|
clipPath.addRoundedRectangle(bounds, 9.0f);
|
||||||
g.reduceClipRegion(clipPath);
|
g.reduceClipRegion(clipPath);
|
||||||
|
|
||||||
juce::ColourGradient waveGrad(juce::Colour(0xff00ff88).withAlpha(0.33f), 0.0f, bounds.getY(),
|
juce::ColourGradient waveGrad(juce::Colour(0xff00ff88).withAlpha(0.5f), 0.0f, bounds.getY(),
|
||||||
juce::Colour(0xff005522).withAlpha(0.12f), 0.0f, bounds.getBottom(), false);
|
juce::Colour(0xff005522).withAlpha(0.4f), 0.0f, bounds.getBottom(), false);
|
||||||
g.setGradientFill(waveGrad);
|
g.setGradientFill(waveGrad);
|
||||||
g.fillPath(filledPath);
|
g.fillPath(filledPath);
|
||||||
|
|
||||||
|
|
@ -309,7 +309,7 @@ void SpectrumAnalyzer::paint(juce::Graphics& g) {
|
||||||
float bx = x + 1.0f;
|
float bx = x + 1.0f;
|
||||||
float by = barBottom - barH;
|
float by = barBottom - barH;
|
||||||
|
|
||||||
g.setColour(juce::Colour(0xff00ff88).withAlpha(0.3f));
|
g.setColour(juce::Colour(0xff00ff88).withAlpha(0.4f));
|
||||||
g.fillRect(bx, by, bw, barH);
|
g.fillRect(bx, by, bw, barH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1126,7 +1126,7 @@ void PianoRollComponent::paint(juce::Graphics& g) {
|
||||||
|
|
||||||
bool pressed = processor.isNoteActive(note);
|
bool pressed = processor.isNoteActive(note);
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
g.setColour(juce::Colour(0xffccaa44).withAlpha(0.8f));
|
g.setColour(juce::Colour(0xffccaa44).withAlpha(0.7f));
|
||||||
} else {
|
} else {
|
||||||
juce::ColourGradient grad(juce::Colour(0xffe4e4e4).withAlpha(0.7f), static_cast<float>(kx), 0.0f,
|
juce::ColourGradient grad(juce::Colour(0xffe4e4e4).withAlpha(0.7f), static_cast<float>(kx), 0.0f,
|
||||||
juce::Colour(0xffc8c8c8).withAlpha(0.7f), static_cast<float>(kx), static_cast<float>(whiteKeyHeight), false);
|
juce::Colour(0xffc8c8c8).withAlpha(0.7f), static_cast<float>(kx), static_cast<float>(whiteKeyHeight), false);
|
||||||
|
|
@ -1179,12 +1179,9 @@ void PianoRollComponent::paint(juce::Graphics& g) {
|
||||||
void PianoRollComponent::mouseDown(const juce::MouseEvent& e) {
|
void PianoRollComponent::mouseDown(const juce::MouseEvent& e) {
|
||||||
auto pos = e.getPosition();
|
auto pos = e.getPosition();
|
||||||
|
|
||||||
// Pitch bend strip
|
// Pitch bend strip: ignore plain clicks — require a vertical drag (see mouseDrag)
|
||||||
if (pos.x < pitchBendWidth) {
|
if (pos.x < pitchBendWidth) {
|
||||||
float pbNorm = 1.0f - static_cast<float>(pos.y) / static_cast<float>(whiteKeyHeight);
|
pitchBendDragging = false;
|
||||||
pbNorm = std::clamp(pbNorm, -1.0f, 1.0f);
|
|
||||||
currentPitchBend = 64 + static_cast<int>(pbNorm * 64.0f);
|
|
||||||
processor.pitchBendValue.store(pbNorm);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1199,14 +1196,13 @@ void PianoRollComponent::mouseDown(const juce::MouseEvent& e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PianoRollComponent::mouseUp(const juce::MouseEvent& e) {
|
void PianoRollComponent::mouseUp(const juce::MouseEvent& e) {
|
||||||
// Reset pitch bend to center on release
|
// Reset pitch bend to center on release (only if it was actually dragged)
|
||||||
if (e.getPosition().x < pitchBendWidth || lastTriggeredNote < 0) {
|
if (pitchBendDragging) {
|
||||||
if (e.getPosition().x < pitchBendWidth) {
|
pitchBendDragging = false;
|
||||||
currentPitchBend = 64;
|
pitchBendGliding = true;
|
||||||
processor.pitchBendValue.store(0.0f);
|
pitchBendGlideStart = static_cast<float>(currentPitchBend - 64) / 64.0f;
|
||||||
repaint();
|
pitchBendGlideStartMs = juce::Time::currentTimeMillis();
|
||||||
}
|
repaint();
|
||||||
if (lastTriggeredNote < 0) return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastTriggeredNote >= 0) {
|
if (lastTriggeredNote >= 0) {
|
||||||
|
|
@ -1216,12 +1212,33 @@ void PianoRollComponent::mouseUp(const juce::MouseEvent& e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PianoRollComponent::timerCallback() {
|
||||||
|
if (pitchBendGliding) {
|
||||||
|
float t = static_cast<float>(juce::Time::currentTimeMillis() - pitchBendGlideStartMs)
|
||||||
|
/ static_cast<float>(pitchBendGlideMs);
|
||||||
|
if (t >= 1.0f) {
|
||||||
|
pitchBendGliding = false;
|
||||||
|
currentPitchBend = 64;
|
||||||
|
processor.pitchBendValue.store(0.0f);
|
||||||
|
} else {
|
||||||
|
float pbNorm = pitchBendGlideStart * (1.0f - t);
|
||||||
|
currentPitchBend = 64 + static_cast<int>(pbNorm * 64.0f);
|
||||||
|
processor.pitchBendValue.store(pbNorm);
|
||||||
|
}
|
||||||
|
repaint();
|
||||||
|
} else {
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PianoRollComponent::mouseDrag(const juce::MouseEvent& e) {
|
void PianoRollComponent::mouseDrag(const juce::MouseEvent& e) {
|
||||||
auto pos = e.getPosition();
|
auto pos = e.getPosition();
|
||||||
|
|
||||||
// Pitch bend drag
|
// Pitch bend drag — only while touching the strip
|
||||||
if (pos.x < pitchBendWidth) {
|
if (pos.x < pitchBendWidth) {
|
||||||
float pbNorm = 1.0f - static_cast<float>(pos.y) / static_cast<float>(whiteKeyHeight);
|
pitchBendDragging = true;
|
||||||
|
pitchBendGliding = false;
|
||||||
|
float pbNorm = 1.0f - 2.0f * static_cast<float>(pos.y) / static_cast<float>(whiteKeyHeight);
|
||||||
pbNorm = std::clamp(pbNorm, -1.0f, 1.0f);
|
pbNorm = std::clamp(pbNorm, -1.0f, 1.0f);
|
||||||
currentPitchBend = 64 + static_cast<int>(pbNorm * 64.0f);
|
currentPitchBend = 64 + static_cast<int>(pbNorm * 64.0f);
|
||||||
processor.pitchBendValue.store(pbNorm);
|
processor.pitchBendValue.store(pbNorm);
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,9 @@ private:
|
||||||
|
|
||||||
class PianoRollComponent : public juce::Component, public juce::Timer {
|
class PianoRollComponent : public juce::Component, public juce::Timer {
|
||||||
public:
|
public:
|
||||||
explicit PianoRollComponent(ChromaFlockProcessor& p) : processor(p) { startTimerHz(30); }
|
explicit PianoRollComponent(ChromaFlockProcessor& p) : processor(p) { startTimerHz(60); }
|
||||||
void paint(juce::Graphics& g) override;
|
void paint(juce::Graphics& g) override;
|
||||||
void timerCallback() override { repaint(); }
|
void timerCallback() override;
|
||||||
void mouseDown(const juce::MouseEvent& e) override;
|
void mouseDown(const juce::MouseEvent& e) override;
|
||||||
void mouseUp(const juce::MouseEvent& e) override;
|
void mouseUp(const juce::MouseEvent& e) override;
|
||||||
void mouseDrag(const juce::MouseEvent& e) override;
|
void mouseDrag(const juce::MouseEvent& e) override;
|
||||||
|
|
@ -91,6 +91,12 @@ private:
|
||||||
|
|
||||||
int lastTriggeredNote = -1;
|
int lastTriggeredNote = -1;
|
||||||
int currentPitchBend = 64; // 0..127, 64 = center
|
int currentPitchBend = 64; // 0..127, 64 = center
|
||||||
|
bool pitchBendDragging = false;
|
||||||
|
|
||||||
|
bool pitchBendGliding = false;
|
||||||
|
float pitchBendGlideStart = 0.0f;
|
||||||
|
juce::int64 pitchBendGlideStartMs = 0;
|
||||||
|
static constexpr int pitchBendGlideMs = 50;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MainContentComponent : public juce::Component {
|
class MainContentComponent : public juce::Component {
|
||||||
|
|
|
||||||
BIN
bg.png
BIN
bg.png
Binary file not shown.
|
Before Width: | Height: | Size: 3 MiB After Width: | Height: | Size: 2.9 MiB |
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue