Skip to content

Commit

Permalink
Add waveform zoom
Browse files Browse the repository at this point in the history
  • Loading branch information
tobiashienzsch committed Jun 12, 2022
1 parent d713f9f commit b1d887c
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 13 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ target_compile_definitions(StiggiDJ
PRIVATE
JUCE_APPLICATION_NAME_STRING="$<TARGET_PROPERTY:StiggiDJ,JUCE_PRODUCT_NAME>"
JUCE_APPLICATION_VERSION_STRING="$<TARGET_PROPERTY:StiggiDJ,JUCE_VERSION>"
JUCE_USE_MP3AUDIOFORMAT=1
JUCE_DISPLAY_SPLASH_SCREEN=0
JUCE_MODAL_LOOPS_PERMITTED=1
JUCE_REPORT_APP_USAGE=0
Expand Down
9 changes: 5 additions & 4 deletions src/MainComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ MainComponent::MainComponent() : _djPlayer{_threadPool, _formatManager}
else { _djPlayer.startPlayback(); }
};

_sideBarLeft.onCueClicked = [this]() { _djPlayer.positionRelative(0.0); };
_sideBarRight.onTempoDeltaChanged = [this](double delta) { _djPlayer.speed((100.0 + delta) / 100.0); };
_sideBarRight.onTimeStretchToggled = [this](bool isEnabled) { _djPlayer.timeStretch(isEnabled); };
_sideBarLeft.onCueClicked = [this]() { _djPlayer.positionRelative(0.0); };
_sideBarRight.onTempoDeltaChanged = [this](double delta) { _djPlayer.speed((100.0 + delta) / 100.0); };
_sideBarRight.onWaveformZoomChanged = [this](double zoom) { _display.waveformZoom(zoom); };
_sideBarRight.onTimeStretchToggled = [this](bool isEnabled) { _djPlayer.timeStretch(isEnabled); };

setSize(640, 800);
}
Expand Down Expand Up @@ -66,6 +67,6 @@ auto MainComponent::setAudioDevices() -> void
_deviceManager.addAudioCallback(&_audioPlayer);
_audioPlayer.setSource(&_djPlayer);

auto file = juce::File{"/home/tobante/Music/Loops/Bass.wav"};
auto file = juce::File{"/home/tobante/Downloads/Lars_Huismann_Echo.mp3"};
_djPlayer.loadFile(file);
}
20 changes: 15 additions & 5 deletions src/UI/Component/WaveformDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,24 @@ void WaveformDisplay::paint(juce::Graphics& g)
g.setColour(juce::Colours::white);
if (!_fileLoaded) { return; }

auto const length = _audioThumb.getTotalLength();
_audioThumb.drawChannel(g, area, 0, length, 0, 1.0f);
auto const totalLength = _audioThumb.getTotalLength();
auto const lengthToShow = totalLength * _proportionToShow;
auto const posInSeconds = totalLength * _playHeadPosition;

_audioThumb.drawChannel(g, area, posInSeconds, posInSeconds + lengthToShow, 0, 0.5f);

auto const x = area.getX();
auto const top = area.getY();
auto const bottom = area.getBottom();
auto const width = area.getWidth();

g.fillRect(juce::Rectangle<double>(x + (width * _playHeadPosition), top, 2.0, bottom - top).toFloat());
// g.setColour(juce::Colours::black);
// g.fillRect(juce::Rectangle<double>(x + (width * _playHeadPosition), top, 2.0, bottom - top).toFloat());

g.setColour(juce::Colours::white.withAlpha(0.5f));
g.setColour(juce::Colours::black.withAlpha(0.5f));
for (auto beat : _beatPositions)
{
auto normalized = beat / length;
auto normalized = beat / totalLength;
g.fillRect(juce::Rectangle<double>(x + (width * normalized), top, 2.0, bottom - top).toFloat());
}
}
Expand Down Expand Up @@ -57,4 +61,10 @@ auto WaveformDisplay::beatPositions(std::vector<double> positionsInSeconds) -> v
repaint();
}

auto WaveformDisplay::lengthToShow(double proportionToShow) -> void
{
_proportionToShow = proportionToShow;
repaint();
}

} // namespace ta
3 changes: 2 additions & 1 deletion src/UI/Component/WaveformDisplay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct WaveformDisplay final

/// \brief Set the relative position of the playhead
void setPositionRelative(double pos);

auto lengthToShow(double proportionToShow) -> void;
auto beatPositions(std::vector<double> positionsInSeconds) -> void;

void paint(juce::Graphics& g) override;
Expand All @@ -26,6 +26,7 @@ struct WaveformDisplay final
juce::AudioThumbnail _audioThumb;
bool _fileLoaded{false};
double _playHeadPosition{0};
double _proportionToShow{1.0};
std::vector<double> _beatPositions{};

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WaveformDisplay) // NOLINT
Expand Down
2 changes: 2 additions & 0 deletions src/UI/Section/Display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ auto Display::timerCallback() -> void { _waveformDisplay.setPositionRelative(_dj

auto Display::loadURL(juce::URL const& url) -> void { _waveformDisplay.loadURL(url); }

auto Display::waveformZoom(double zoom) -> void { _waveformDisplay.lengthToShow(zoom); }

auto Display::djPlayerFileChanged(juce::File const& file) -> void
{
_waveformDisplay.loadURL(juce::URL{file});
Expand Down
1 change: 1 addition & 0 deletions src/UI/Section/Display.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct Display final
~Display() override;

auto loadURL(juce::URL const& url) -> void;
auto waveformZoom(double zoom) -> void;

auto resized() -> void override;
auto timerCallback() -> void override;
Expand Down
16 changes: 14 additions & 2 deletions src/UI/Section/SideBarRight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@ namespace ta
{
SideBarRight::SideBarRight()
{
addAndMakeVisible(_placeholder);
addAndMakeVisible(_placeholderTop);
addAndMakeVisible(_placeholderBottom);
addAndMakeVisible(_waveformZoom);
addAndMakeVisible(_vinylButton);
addAndMakeVisible(_warpButton);
addAndMakeVisible(_tempoRange);
addAndMakeVisible(_tempo);

_waveformZoom.setRange({0.01, 1.0}, 0.001);
_waveformZoom.setSkewFactorFromMidPoint(0.1);
_waveformZoom.setValue(1.0);
_waveformZoom.onValueChange = [this]()
{
if (onWaveformZoomChanged) { onWaveformZoomChanged(_waveformZoom.getValue()); }
};

_warpButton.setClickingTogglesState(true);
_warpButton.onClick = [this]()
{
Expand Down Expand Up @@ -44,8 +54,10 @@ auto SideBarRight::resized() -> void
grid.templateRows = fillArray(Track(1_fr), 12);
grid.templateColumns = fillArray(Track(1_fr), 1);
grid.items.addArray({
GridItem(_placeholder).withArea(GridItem::Span(5), {}),
GridItem(_placeholderTop).withArea(GridItem::Span(2), {}),
GridItem(_waveformZoom).withArea(GridItem::Span(1), {}),
GridItem(_vinylButton).withArea(GridItem::Span(1), {}),
GridItem(_placeholderBottom).withArea(GridItem::Span(2), {}),
GridItem(_warpButton).withArea(GridItem::Span(1), {}),
GridItem(_tempoRange).withArea(GridItem::Span(1), {}),
GridItem(_tempo).withArea(GridItem::Span(4), {}),
Expand Down
5 changes: 4 additions & 1 deletion src/UI/Section/SideBarRight.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ struct SideBarRight final : juce::Component
auto resized() -> void override;

std::function<void(double)> onTempoDeltaChanged{};
std::function<void(double)> onWaveformZoomChanged{};
std::function<void(bool)> onTimeStretchToggled{};

private:
auto updateSpeedRange() -> void;

Placeholder _placeholder{"", juce::Colours::transparentBlack};
Placeholder _placeholderTop{"", juce::Colours::transparentBlack};
Placeholder _placeholderBottom{"", juce::Colours::transparentBlack};
juce::Slider _waveformZoom{juce::Slider::RotaryHorizontalVerticalDrag, juce::Slider::NoTextBox};
juce::TextButton _vinylButton{"Vinyl"};
juce::TextButton _warpButton{"Warp"};
juce::ComboBox _tempoRange;
Expand Down

0 comments on commit b1d887c

Please sign in to comment.