diff --git a/include/halp/audio.hpp b/include/halp/audio.hpp index 828ae49a..d2b9a7b3 100644 --- a/include/halp/audio.hpp +++ b/include/halp/audio.hpp @@ -201,6 +201,18 @@ struct tick int frames{}; }; +/** + * Contains the info about the current audio buffer and the bar and quarter notes it's + * associated with, so that the musical audio rendering utilities can do their job of + * playing back the musical notes, etc. + * They need to know when we are in the score. + * + * The quarter notes have their index starting at 0. + * The position of the bars are in quarters. (in 4/4, the first bar has position 0.0 and the + * second one has a position of 4.0) + * + * This struct is usually created and destroyed thousands of times per second. + */ struct tick_musical { /** @@ -218,18 +230,41 @@ struct tick_musical int denom; } signature; + /** + * The total number of samples since the beginning of the playback of the score. + */ int64_t position_in_frames{}; + /** + * Playback time since the beginning of the score. + */ double position_in_nanoseconds{}; - // Quarter note of the first sample in the buffer + /** + * Quarter note of the first sample in this buffer + * This is a double. + * + * The first quarter note in a score has index 0. + * + * For example: + * - 3.95 would be slightly before the 2nd bar. + * - 4.05 would be slightly after the beginning of the 2nd bar. + */ quarter_note start_position_in_quarters{}; - // Quarter note of the first sample in the next buffer - // (or one past the last sample of this buffer, e.g. a [closed; open) interval like C++ begin / end) + /** + * Quarter note of the first sample in the next buffer + * (or one past the last sample of this buffer, e.g. a [closed; open) interval like C++ begin / end) + */ quarter_note end_position_in_quarters{}; - // Position of the last signature change in quarter notes (at the start of the tick) + /** + * Position of the last signature change in quarter notes (at the start of the tick) + * + * For example: 0.0 if the signature never changes in the score. + * If we change the time signature at some, we'll give it the index (in quarter) of the + * bar when it last changed. + */ quarter_note last_signature_change{}; // Position of the last bar relative to start in quarter notes diff --git a/tests/objects/patternal.cpp b/tests/objects/patternal.cpp index dcac97fc..c04763ff 100644 --- a/tests/objects/patternal.cpp +++ b/tests/objects/patternal.cpp @@ -39,9 +39,9 @@ TEST_CASE("The input pattern is stored correctly", "[advanced][patternal]") // Create the input pattern: patternalProcessor.inputs.patterns.value = { - (Pattern) {42, {127, 127, 127, 127}}, // hi-hat - (Pattern) {38, {0, 127, 0, 127}}, // snare - (Pattern) {35, {127, 0, 127, 0}}, // bass drum + {42, {127, 127, 127, 127}}, // hi-hat + {38, {0, 127, 0, 127}}, // snare + {35, {127, 0, 127, 0}}, // bass drum }; // Check that the input pattern is stored correctly: @@ -71,13 +71,13 @@ TEST_CASE("MIDI messages are output properly", "[advanced][patternal]") static constexpr double tickDuration = samplingRate / bufferSize; // seconds static constexpr double ticksPerSecond = 1.0 / tickDuration; static constexpr double testDuration = 3.0; // seconds - static constexpr double NS_PER_S = 1000000; + static constexpr double NS_PER_S = 1000000000; Processor patternalProcessor; patternalProcessor.inputs.patterns.value = { - (Pattern) {noteHiHat, {127, 127, 127, 127}}, // hi-hat - (Pattern) {noteSnare, {0, 127, 0, 127}}, // snare - (Pattern) {noteBassDrum, {127, 0, 127, 0}}, // bass drum + {noteHiHat, {127, 127, 127, 127}}, // hi-hat + {noteSnare, {0, 127, 0, 127}}, // snare + {noteBassDrum, {127, 0, 127, 0}}, // bass drum }; // Check the output on each tick: @@ -90,16 +90,22 @@ TEST_CASE("MIDI messages are output properly", "[advanced][patternal]") // INFO("Test tick " << tickIndex); pos_in_frames += bufferSize; pos_in_ns += tickDuration / NS_PER_S; + double timeNow = tickIndex * tickDuration; + double timeAtEndOfTick = (tickIndex + 1) * tickDuration; + tick_musical tk; - // TODO tk.start_position_quarter = - // TODO tk.end_position_quarter = tk.tempo = 120; // 120 BPM. One beat lasts 500 ms. tk.signature.num = 4; tk.signature.denom = 4; tk.frames = bufferSize; - tk.position_in_nanoseconds = pos_in_ns; + tk.position_in_nanoseconds = pos_in_ns; // We don't really need to set this pos in ns. tk.position_in_frames = pos_in_frames; - double timeNow = tickIndex * tickDuration; + tk.last_signature_change = 0; // The signature never changes. + tk.start_position_in_quarters = TODO; + tk.end_position_in_quarters = TODO; + tk.bar_at_start = TODO; + tk.bar_at_end = TODO; + patternalProcessor(tk); // Test the 1st tick: @@ -140,9 +146,5 @@ TEST_CASE("MIDI messages are output properly", "[advanced][patternal]") } // TODO: check the other ticks } - - // TODO check somethig with: - // - start_position_quarter - // - last_signature_change }