mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 04:28:13 +00:00

Previously, a collection of notes (Vector or Array) would be created and promptly deleted for every sample (at least 44 thousand times per second!). This was measured to be one of the most significant performance drawbacks as well as the most obvious performance improvement I could currently find here. Although it will not cause Piano to lag currently (at least on virtualized systems), I see an incoming issue once we get the capability to use more processors. Now, we use a HashMap correlating pitches to notes, and Track reuses the data structure in order to avoid reallocations. That is the reason for introducing the fast clear_with_capacity to HashMap.
76 lines
2.2 KiB
C++
76 lines
2.2 KiB
C++
/*
|
|
* Copyright (c) 2021, kleines Filmröllchen <malu.bertsch@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "Clip.h"
|
|
#include "Music.h"
|
|
#include "Processor.h"
|
|
#include <LibCore/Object.h>
|
|
|
|
namespace LibDSP {
|
|
|
|
// A track is also known as a channel and serves as a container for the audio pipeline: clips -> processors -> mixing & output
|
|
class Track : public Core::Object {
|
|
C_OBJECT_ABSTRACT(Track)
|
|
public:
|
|
Track(NonnullRefPtr<Transport> transport)
|
|
: m_transport(move(transport))
|
|
, m_current_signal(Sample {})
|
|
{
|
|
}
|
|
virtual ~Track() override = default;
|
|
|
|
virtual bool check_processor_chain_valid() const = 0;
|
|
bool add_processor(NonnullRefPtr<Processor> new_processor);
|
|
|
|
// Creates the current signal of the track by processing current note or audio data through the processing chain
|
|
Sample current_signal();
|
|
|
|
NonnullRefPtrVector<Processor> const& processor_chain() const { return m_processor_chain; }
|
|
NonnullRefPtr<Transport> const transport() const { return m_transport; }
|
|
|
|
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 void compute_current_clips_signal() = 0;
|
|
|
|
NonnullRefPtrVector<Processor> m_processor_chain;
|
|
NonnullRefPtr<Transport> m_transport;
|
|
// The current signal is stored here, to prevent unnecessary reallocation.
|
|
Signal m_current_signal;
|
|
};
|
|
|
|
class NoteTrack final : public Track {
|
|
public:
|
|
virtual ~NoteTrack() override = default;
|
|
|
|
bool check_processor_chain_valid() const override;
|
|
NonnullRefPtrVector<NoteClip> const& clips() const { return m_clips; }
|
|
|
|
protected:
|
|
virtual void compute_current_clips_signal() override;
|
|
|
|
private:
|
|
NonnullRefPtrVector<NoteClip> m_clips;
|
|
};
|
|
|
|
class AudioTrack final : public Track {
|
|
public:
|
|
virtual ~AudioTrack() override = default;
|
|
|
|
bool check_processor_chain_valid() const override;
|
|
NonnullRefPtrVector<AudioClip> const& clips() const { return m_clips; }
|
|
|
|
protected:
|
|
virtual void compute_current_clips_signal() override;
|
|
|
|
private:
|
|
NonnullRefPtrVector<AudioClip> m_clips;
|
|
};
|
|
|
|
}
|