diff --git a/Userland/Libraries/LibDSP/Music.h b/Userland/Libraries/LibDSP/Music.h index f495cf7a3b..30059f22b1 100644 --- a/Userland/Libraries/LibDSP/Music.h +++ b/Userland/Libraries/LibDSP/Music.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -33,12 +34,14 @@ enum class SignalType : u8 { Note }; -struct Signal : public Variant> { +using RollNotes = OrderedHashMap; + +struct Signal : public Variant { using Variant::Variant; ALWAYS_INLINE SignalType type() const { - return has() ? SignalType::Sample : has>() ? SignalType::Note - : SignalType::Invalid; + return has() ? SignalType::Sample : has() ? SignalType::Note + : SignalType::Invalid; } }; diff --git a/Userland/Libraries/LibDSP/Track.cpp b/Userland/Libraries/LibDSP/Track.cpp index 5369201d07..dd049c66c4 100644 --- a/Userland/Libraries/LibDSP/Track.cpp +++ b/Userland/Libraries/LibDSP/Track.cpp @@ -4,9 +4,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include "Track.h" -#include "Processor.h" +#include #include +#include +#include using namespace std; @@ -49,15 +50,17 @@ bool NoteTrack::check_processor_chain_valid() const Sample Track::current_signal() { - Signal the_signal = current_clips_signal(); + compute_current_clips_signal(); + Optional the_signal; + for (auto& processor : m_processor_chain) { - the_signal = processor.process(the_signal); + the_signal = processor.process(the_signal.value_or(m_current_signal)); } - VERIFY(the_signal.type() == SignalType::Sample); - return the_signal.get(); + VERIFY(the_signal.has_value() && the_signal->type() == SignalType::Sample); + return the_signal->get(); } -Signal NoteTrack::current_clips_signal() +void NoteTrack::compute_current_clips_signal() { u32 time = m_transport->time(); // Find the currently playing clip. @@ -68,26 +71,25 @@ Signal NoteTrack::current_clips_signal() break; } } - if (playing_clip == nullptr) { - return Signal(Vector()); - } - // Find the playing notes inside the clip. - Vector playing_notes; + auto& current_notes = m_current_signal.get(); + m_current_signal.get().clear_with_capacity(); + + if (playing_clip == nullptr) + return; + // FIXME: performance? for (auto& note_list : playing_clip->notes()) { for (auto& note : note_list) { if (note.on_sample >= time && note.off_sample >= time) break; if (note.on_sample <= time && note.off_sample >= time) - // FIXME: This copies the note, but we don't rely on playing_clip to keep its notes around. - playing_notes.append(note); + current_notes.set(note.pitch, note); } } - return Signal(playing_notes); } -Signal AudioTrack::current_clips_signal() +void AudioTrack::compute_current_clips_signal() { // Find the currently playing clip. u32 time = m_transport->time(); @@ -99,12 +101,12 @@ Signal AudioTrack::current_clips_signal() } } if (playing_clip == nullptr) { - return Signal(static_cast(SAMPLE_OFF)); + m_current_signal = Signal(static_cast(SAMPLE_OFF)); } // Index into the clip's samples. u32 effective_sample = time - playing_clip->start(); - return Signal(playing_clip->sample_at(effective_sample)); + m_current_signal = Signal(playing_clip->sample_at(effective_sample)); } } diff --git a/Userland/Libraries/LibDSP/Track.h b/Userland/Libraries/LibDSP/Track.h index 95f075b3f8..af873f791c 100644 --- a/Userland/Libraries/LibDSP/Track.h +++ b/Userland/Libraries/LibDSP/Track.h @@ -19,6 +19,7 @@ class Track : public Core::Object { public: Track(NonnullRefPtr transport) : m_transport(move(transport)) + , m_current_signal(Sample {}) { } virtual ~Track() override = default; @@ -36,10 +37,12 @@ protected: bool check_processor_chain_valid_with_initial_type(SignalType initial_type) const; // Subclasses override to provide the base signal to the processing chain - virtual Signal current_clips_signal() = 0; + virtual void compute_current_clips_signal() = 0; NonnullRefPtrVector m_processor_chain; - NonnullRefPtr const m_transport; + NonnullRefPtr m_transport; + // The current signal is stored here, to prevent unnecessary reallocation. + Signal m_current_signal; }; class NoteTrack final : public Track { @@ -50,7 +53,7 @@ public: NonnullRefPtrVector const& clips() const { return m_clips; } protected: - virtual Signal current_clips_signal() override; + virtual void compute_current_clips_signal() override; private: NonnullRefPtrVector m_clips; @@ -64,7 +67,7 @@ public: NonnullRefPtrVector const& clips() const { return m_clips; } protected: - virtual Signal current_clips_signal() override; + virtual void compute_current_clips_signal() override; private: NonnullRefPtrVector m_clips;