Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
aalex committed Dec 19, 2024
1 parent 7c15a33 commit 1d5326c
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 19 deletions.
43 changes: 39 additions & 4 deletions include/halp/audio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
/**
Expand All @@ -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
Expand Down
32 changes: 17 additions & 15 deletions tests/objects/patternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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
}

0 comments on commit 1d5326c

Please sign in to comment.