mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 05:57:44 +00:00
Piano+LibDSP: Move Track to LibDSP
This is a tangly commit and it fixes all the bugs that a plain move would have caused (i.e. we need to touch other logic which had wrong assumptions).
This commit is contained in:
parent
125122a9ab
commit
4941cffdd0
29 changed files with 322 additions and 413 deletions
|
@ -4,6 +4,8 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "AK/NonnullRefPtr.h"
|
||||
#include "AK/Userspace.h"
|
||||
#include <AK/FixedArray.h>
|
||||
#include <AK/NoAllocationGuard.h>
|
||||
#include <AK/Optional.h>
|
||||
|
@ -41,6 +43,27 @@ bool Track::check_processor_chain_valid_with_initial_type(SignalType initial_typ
|
|||
return true;
|
||||
}
|
||||
|
||||
float Track::volume() const
|
||||
{
|
||||
// FIXME: This is a hack until we have a Master processor
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
void Track::set_volume(float volume) const
|
||||
{
|
||||
// FIXME: This is a hack until we have a Master processor
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
NonnullRefPtr<Synthesizers::Classic> Track::synth()
|
||||
{
|
||||
return static_ptr_cast<Synthesizers::Classic>(m_processor_chain.ptr_at(0));
|
||||
}
|
||||
NonnullRefPtr<Effects::Delay> Track::delay()
|
||||
{
|
||||
return static_ptr_cast<Effects::Delay>(m_processor_chain.ptr_at(1));
|
||||
}
|
||||
|
||||
bool AudioTrack::check_processor_chain_valid() const
|
||||
{
|
||||
return check_processor_chain_valid_with_initial_type(SignalType::Sample);
|
||||
|
@ -61,6 +84,7 @@ void Track::current_signal(FixedArray<Sample>& output_signal)
|
|||
{
|
||||
// This is real-time code. We must NEVER EVER EVER allocate.
|
||||
NoAllocationGuard guard;
|
||||
VERIFY(m_secondary_sample_buffer.type() == SignalType::Sample);
|
||||
VERIFY(output_signal.size() == m_secondary_sample_buffer.get<FixedArray<Sample>>().size());
|
||||
|
||||
compute_current_clips_signal();
|
||||
|
@ -85,34 +109,48 @@ void Track::current_signal(FixedArray<Sample>& output_signal)
|
|||
|
||||
void NoteTrack::compute_current_clips_signal()
|
||||
{
|
||||
// Consider the entire time duration.
|
||||
TODO();
|
||||
// FIXME: Handle looping properly
|
||||
u32 start_time = m_transport->time();
|
||||
VERIFY(m_secondary_sample_buffer.type() == SignalType::Sample);
|
||||
size_t sample_count = m_secondary_sample_buffer.get<FixedArray<Sample>>().size();
|
||||
u32 end_time = start_time + static_cast<u32>(sample_count);
|
||||
|
||||
u32 time = m_transport->time();
|
||||
// Find the currently playing clip.
|
||||
NoteClip* playing_clip = nullptr;
|
||||
// Find the currently playing clips.
|
||||
// We can't handle more than 32 playing clips at a time, but that is a ridiculous number.
|
||||
Array<RefPtr<NoteClip>, 32> playing_clips;
|
||||
size_t playing_clips_index = 0;
|
||||
for (auto& clip : m_clips) {
|
||||
if (clip.start() <= time && clip.end() >= time) {
|
||||
playing_clip = &clip;
|
||||
break;
|
||||
// A clip is playing if its start time or end time fall in the current time range.
|
||||
// Or, if they both enclose the current time range.
|
||||
if ((clip.start() <= start_time && clip.end() >= end_time)
|
||||
|| (clip.start() >= start_time && clip.start() < end_time)
|
||||
|| (clip.end() > start_time && clip.end() <= end_time)) {
|
||||
VERIFY(playing_clips_index < playing_clips.size());
|
||||
playing_clips[playing_clips_index++] = clip;
|
||||
}
|
||||
}
|
||||
|
||||
auto& current_notes = m_current_signal.get<RollNotes>();
|
||||
m_current_signal.get<RollNotes>().clear_with_capacity();
|
||||
m_current_signal.get<RollNotes>().fill({});
|
||||
|
||||
if (playing_clip == nullptr)
|
||||
if (playing_clips_index == 0)
|
||||
return;
|
||||
|
||||
// FIXME: performance?
|
||||
for (auto const& note_list : playing_clip->notes()) {
|
||||
for (auto const& note : note_list) {
|
||||
if (note.on_sample >= time && note.off_sample >= time)
|
||||
break;
|
||||
if (note.on_sample <= time && note.off_sample >= time)
|
||||
current_notes.set(note.pitch, note);
|
||||
for (auto const& playing_clip : playing_clips) {
|
||||
if (playing_clip.is_null())
|
||||
break;
|
||||
for (auto const& note : playing_clip->notes()) {
|
||||
if (note.is_playing_during(start_time, end_time))
|
||||
current_notes[note.pitch] = note;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& keyboard_note : m_keyboard->notes()) {
|
||||
if (!keyboard_note.has_value() || !keyboard_note->is_playing_during(start_time, end_time))
|
||||
continue;
|
||||
// Always overwrite roll notes with keyboard notes.
|
||||
current_notes[keyboard_note->pitch] = keyboard_note;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioTrack::compute_current_clips_signal()
|
||||
|
@ -121,4 +159,23 @@ void AudioTrack::compute_current_clips_signal()
|
|||
TODO();
|
||||
}
|
||||
|
||||
void NoteTrack::set_note(RollNote note)
|
||||
{
|
||||
for (auto& clip : m_clips) {
|
||||
if (clip.start() <= note.on_sample && clip.end() >= note.on_sample)
|
||||
clip.set_note(note);
|
||||
}
|
||||
}
|
||||
|
||||
void NoteTrack::remove_note(RollNote note)
|
||||
{
|
||||
for (auto& clip : m_clips)
|
||||
clip.remove_note(note);
|
||||
}
|
||||
|
||||
void NoteTrack::add_clip(u32 start_time, u32 end_time)
|
||||
{
|
||||
m_clips.append(AK::make_ref_counted<NoteClip>(start_time, end_time));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue