Zrythm v2.0.0-alpha.1+31.4967fd053471
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
chord_track.h
1// SPDX-FileCopyrightText: © 2018-2020, 2024-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "dsp/chord_audition_state.h"
7#include "structure/arrangement/arranger_object_owner.h"
8#include "structure/arrangement/chord_region.h"
9#include "structure/arrangement/scale_object.h"
10#include "structure/tracks/track.h"
11#include "utils/qt.h"
12
13#include <QTimer>
14
15namespace zrythm::structure::tracks
16{
21class ChordTrack
22 : public Track,
23 public arrangement::ArrangerObjectOwner<arrangement::ChordRegion>,
24 public arrangement::ArrangerObjectOwner<arrangement::ScaleObject>
25{
26 Q_OBJECT
27 QML_ELEMENT
28 QML_UNCREATABLE ("")
29 DEFINE_ARRANGER_OBJECT_OWNER_QML_PROPERTIES (
30 ChordTrack,
31 chordRegions,
33 DEFINE_ARRANGER_OBJECT_OWNER_QML_PROPERTIES (
34 ChordTrack,
35 scaleObjects,
37
38public:
39 using ScaleObject = arrangement::ScaleObject;
40 using ChordRegion = arrangement::ChordRegion;
41 using ChordObject = arrangement::ChordObject;
42 using ScaleObjectPtr = ScaleObject *;
43 using NotePitchToPitchesFunc = std::function<
44 std::optional<dsp::ChordDescriptor::ChordPitches> (midi_byte_t)>;
45
46 ChordTrack (FinalTrackDependencies dependencies);
47
48 // ========================================================================
49 // QML Interface
50 // ========================================================================
51
63 Q_INVOKABLE void auditionChord (
64 const zrythm::dsp::ChordDescriptor * descriptor,
65 bool on,
66 midi_byte_t velocity = dsp::ChordAuditionState::kDefaultVelocity);
67
72 Q_INVOKABLE void previewChord (
73 const zrythm::dsp::ChordDescriptor * descriptor,
74 int duration_ms = 400);
75
76 // ========================================================================
77
78 std::optional<dsp::ChordDescriptor::ChordPitches>
79 note_pitch_to_pitches (midi_byte_t note_pitch) const
80 {
81 assert (note_pitch_to_pitches_.has_value ());
82 return std::invoke (*note_pitch_to_pitches_, note_pitch);
83 }
84
85 // FIXME: eventually this dependency should be injected via a constructor
86 // argument
87 void set_note_pitch_to_pitches_func (NotePitchToPitchesFunc func)
88 {
89 note_pitch_to_pitches_ = func;
90 }
91
92 ScaleObject * get_scale_at (size_t index) const;
93
109 const dsp::MidiEventBuffer &src,
110 const NotePitchToPitchesFunc &note_to_pitches,
111 midi_byte_t velocity,
112 std::pair<units::sample_u32_t, units::sample_u32_t> range);
113
118 ChordObject * get_chord_at_ticks (units::precise_tick_t timeline_ticks) const;
119
124 ScaleObject * get_scale_at_ticks (units::precise_tick_t timeline_ticks) const;
125
126 // ========================================================================
127 // QML Interface
128 // ========================================================================
129
130 Q_INVOKABLE ChordObject * chordAtTicks (double ticks) const;
131 Q_INVOKABLE ScaleObject * scaleAtTicks (double ticks) const;
132
133 friend void init_from (
134 ChordTrack &obj,
135 const ChordTrack &other,
136 utils::ObjectCloneType clone_type);
137
138 std::string
139 get_field_name_for_serialization (const ChordRegion *) const override
140 {
141 return "regions";
142 }
143 std::string
144 get_field_name_for_serialization (const ScaleObject *) const override
145 {
146 return "scales";
147 }
148
149private:
150 friend void to_json (nlohmann::json &j, const ChordTrack &track)
151 {
152 to_json (j, static_cast<const Track &> (track));
153 to_json (j, static_cast<const ArrangerObjectOwner<ChordRegion> &> (track));
154 to_json (j, static_cast<const ArrangerObjectOwner<ScaleObject> &> (track));
155 }
156 friend void from_json (const nlohmann::json &j, ChordTrack &track)
157 {
158 from_json (j, static_cast<Track &> (track));
159 from_json (j, static_cast<ArrangerObjectOwner<ChordRegion> &> (track));
160 from_json (j, static_cast<ArrangerObjectOwner<ScaleObject> &> (track));
161 }
162
163 bool initialize ();
164
165 dsp::ChordAuditionState audition_state_;
166
168 dsp::ChordDescriptor::ChordPitches previewing_pitches_;
169 utils::QObjectUniquePtr<QTimer> preview_timer_;
170
171 void stopPreview ();
172
173 std::optional<NotePitchToPitchesFunc> note_pitch_to_pitches_;
174};
175
176} // namespace zrythm::structure::tracks
Describes a musical chord by its root note, type, accent, inversion, and optional bass note.
Packed contiguous buffer for RT MIDI events.
A chord placed inside a ChordRegion on the chord track.
ChordObject * get_chord_at_ticks(units::precise_tick_t timeline_ticks) const
Returns the ChordObject at the given Position in the TimelineArranger.
Q_INVOKABLE void previewChord(const zrythm::dsp::ChordDescriptor *descriptor, int duration_ms=400)
Auditions descriptor for duration_ms milliseconds, then stops automatically.
static void transform_chord_and_append(dsp::MidiEventBuffer &dest, const dsp::MidiEventBuffer &src, const NotePitchToPitchesFunc &note_to_pitches, midi_byte_t velocity, std::pair< units::sample_u32_t, units::sample_u32_t > range)
Transforms note-on/off events into chord events.
ScaleObject * get_scale_at_ticks(units::precise_tick_t timeline_ticks) const
Returns the ScaleObject at the given Position in the TimelineArranger.
Q_INVOKABLE void auditionChord(const zrythm::dsp::ChordDescriptor *descriptor, bool on, midi_byte_t velocity=dsp::ChordAuditionState::kDefaultVelocity)
Start or stop auditioning a chord.
Track(Type type, std::optional< PortType > in_signal_type, std::optional< PortType > out_signal_type, TrackFeatures enabled_features, BaseTrackDependencies dependencies)
Constructor to be used by subclasses.
std::uint8_t midi_byte_t
MIDI byte.
Definition midi.h:43