diff options
author | kleines Filmröllchen <filmroellchen@serenityos.org> | 2022-05-13 10:13:14 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-05-26 10:24:43 +0100 |
commit | 37b340a6984c7f76d0a26319a1f164b82a7de037 (patch) | |
tree | e482e2c2b24902debcfedcc37d5739a6b58dfeef /Userland | |
parent | a54b68114940d070e309c0b6c0e0691fec4c4cb3 (diff) | |
download | serenity-37b340a6984c7f76d0a26319a1f164b82a7de037.zip |
LibDSP: Introduce the Keyboard
This is a class for handling user MIDI input, which is combined by the
Track with roll note data if applicable.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibDSP/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibDSP/Keyboard.cpp | 68 | ||||
-rw-r--r-- | Userland/Libraries/LibDSP/Keyboard.h | 58 | ||||
-rw-r--r-- | Userland/Libraries/LibDSP/Music.h | 1 |
4 files changed, 128 insertions, 0 deletions
diff --git a/Userland/Libraries/LibDSP/CMakeLists.txt b/Userland/Libraries/LibDSP/CMakeLists.txt index a5de6f120e..34fa31957a 100644 --- a/Userland/Libraries/LibDSP/CMakeLists.txt +++ b/Userland/Libraries/LibDSP/CMakeLists.txt @@ -3,6 +3,7 @@ set(SOURCES Track.cpp Effects.cpp Synthesizers.cpp + Keyboard.cpp ) serenity_lib(LibDSP dsp) diff --git a/Userland/Libraries/LibDSP/Keyboard.cpp b/Userland/Libraries/LibDSP/Keyboard.cpp new file mode 100644 index 0000000000..38483243a2 --- /dev/null +++ b/Userland/Libraries/LibDSP/Keyboard.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021-2022, kleines Filmröllchen <filmroellchen@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "Keyboard.h" +#include "Music.h" +#include <AK/Error.h> +#include <AK/NumericLimits.h> + +namespace LibDSP { + +void Keyboard::set_keyboard_note(u8 pitch, Keyboard::Switch note_switch) +{ + VERIFY(pitch < note_frequencies.size()); + + if (note_switch == Switch::Off) { + m_pressed_notes.remove(pitch); + return; + } + + auto fake_note = RollNote { + .on_sample = m_transport->time(), + .off_sample = NumericLimits<u32>::max(), + .pitch = pitch, + .velocity = NumericLimits<i8>::max(), + }; + + m_pressed_notes.set(pitch, fake_note); +} +void Keyboard::set_keyboard_note_in_active_octave(i8 octave_offset, Switch note_switch) +{ + u8 real_note = octave_offset + (m_virtual_keyboard_octave - 1) * notes_per_octave; + set_keyboard_note(real_note, note_switch); +} + +void Keyboard::change_virtual_keyboard_octave(Direction direction) +{ + if (direction == Direction::Up) { + if (m_virtual_keyboard_octave < octave_max) + ++m_virtual_keyboard_octave; + } else { + if (m_virtual_keyboard_octave > octave_min) + --m_virtual_keyboard_octave; + } +} + +ErrorOr<void> Keyboard::set_virtual_keyboard_octave(u8 octave) +{ + if (octave <= octave_max && octave >= octave_min) { + m_virtual_keyboard_octave = octave; + return {}; + } + return Error::from_string_literal("Octave out of range"); +} + +bool Keyboard::is_pressed(u8 pitch) const +{ + return m_pressed_notes.get(pitch).has_value() && m_pressed_notes.get(pitch)->is_playing(m_transport->time()); +} + +bool Keyboard::is_pressed_in_active_octave(i8 octave_offset) const +{ + return is_pressed(octave_offset + virtual_keyboard_octave_base()); +} + +} diff --git a/Userland/Libraries/LibDSP/Keyboard.h b/Userland/Libraries/LibDSP/Keyboard.h new file mode 100644 index 0000000000..fa69bd29b2 --- /dev/null +++ b/Userland/Libraries/LibDSP/Keyboard.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021-2022, kleines Filmröllchen <filmroellchen@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/NonnullRefPtr.h> +#include <AK/RefCounted.h> +#include <LibDSP/Music.h> +#include <LibDSP/Transport.h> + +namespace LibDSP { + +class Keyboard : public RefCounted<Keyboard> { + +public: + enum class Direction : bool { + Down, + Up, + }; + enum class Switch : bool { + Off, + On, + }; + + Keyboard(NonnullRefPtr<Transport> transport) + : m_transport(move(transport)) + { + } + + u8 virtual_keyboard_octave() const { return m_virtual_keyboard_octave; } + u8 virtual_keyboard_octave_base() const { return (m_virtual_keyboard_octave - octave_min) * 12; } + // Automatically clips the octave between the minimum and maximum. + void change_virtual_keyboard_octave(Direction); + // Errors out if the set octave is out of range. + ErrorOr<void> set_virtual_keyboard_octave(u8 octave); + + void set_keyboard_note(u8 pitch, Switch note_switch); + void set_keyboard_note_in_active_octave(i8 octave_offset, Switch note_switch); + + RollNotes const& notes() const { return m_pressed_notes; } + Optional<RollNote> note_at(u8 pitch) const { return m_pressed_notes.get(pitch); } + bool is_pressed(u8 pitch) const; + bool is_pressed_in_active_octave(i8 octave_offset) const; + +private: + u8 m_virtual_keyboard_octave { 4 }; + RollNotes m_pressed_notes; + + NonnullRefPtr<Transport> m_transport; + + static constexpr int const octave_min = 1; + static constexpr int const octave_max = 7; +}; + +} diff --git a/Userland/Libraries/LibDSP/Music.h b/Userland/Libraries/LibDSP/Music.h index e82a57b789..884189a348 100644 --- a/Userland/Libraries/LibDSP/Music.h +++ b/Userland/Libraries/LibDSP/Music.h @@ -196,6 +196,7 @@ constexpr Array<double, 84> note_frequencies = { 3951.0664100489994, }; +constexpr size_t const notes_per_octave = 12; constexpr double const middle_c = note_frequencies[36]; } |