Ξ-W2-T1 remediation: print master gain into the bake, derive the window from the dialed sound, reset play mode to Trigger
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// bake_plan — the programmed note resolved against a concrete sample rate: the frame
|
||||
// window the offline pass renders, and the two event frames inside it.
|
||||
// bake_plan — the programmed note resolved against a concrete sample rate: the frames the
|
||||
// offline pass renders, the slice of them the capture keeps, and the two event frames.
|
||||
//
|
||||
// Separate from bake_render because the plan is what a preview and a bake must agree on;
|
||||
// the render is only one consumer of it.
|
||||
@@ -9,36 +9,49 @@
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
#include "core/instrument/engine/play_params.h" // SampleData (the dialed sound)
|
||||
#include "core/instrument/note/note_program.h"
|
||||
|
||||
namespace reasampler::instrument::bake {
|
||||
|
||||
// Until the capture-signal popup ships, the bake needs a program to render. A zero end
|
||||
// offset ends the capture exactly at note-off, which truncates every release — so the
|
||||
// default opens the window past the gate by this much.
|
||||
inline constexpr double kDefaultReleaseTailMs = 500.0;
|
||||
// The render's frame ceiling, refused like any other degenerate window. A legal offset
|
||||
// magnitude reaches ~11.6 days, and renderBake allocates two channel buffers plus an
|
||||
// interleaved one from the window — an unbounded one is a bad_alloc inside a UI tick, not a
|
||||
// long bake. ~5.5 minutes at 48 kHz, past any musical programmed note.
|
||||
inline constexpr std::int64_t kMaxBakeFrames = 16'000'000;
|
||||
|
||||
// The program a bake uses when nothing has been entered: one quarter note at the default
|
||||
// velocity, opening at note-on and closing kDefaultReleaseTailMs after the release starts.
|
||||
note::NoteProgram defaultBakeProgram();
|
||||
// The program a bake uses until the capture-signal popup ships: one quarter note at the
|
||||
// default velocity, opening at note-on, with the END offset derived from `dialed` — Gate's
|
||||
// release, or Trigger's play span, at `renderSampleRate` (the rate the bake will render at,
|
||||
// which is what the engine's frame counts are actually consumed against). Derived rather
|
||||
// than constant because the release knob alone spans two seconds, so any fixed tail cuts a
|
||||
// long decay mid-flight.
|
||||
note::NoteProgram defaultBakeProgram(const SampleData& dialed, int renderSampleRate,
|
||||
note::Tempo tempo);
|
||||
|
||||
// The render window in frames. Frame 0 is the start of the captured file, NOT note-on:
|
||||
// a negative start offset opens the capture before the note, and noteOnFrame is where the
|
||||
// note actually lands inside it.
|
||||
// The render window in frames. TWO domains meet here: `totalFrames` is the captured FILE's
|
||||
// length, everything else counts RENDER frames from whichever comes first, note-on or the
|
||||
// capture opening. A positive start offset (legal — it trims the attack) puts note-on at
|
||||
// render frame 0 and the file's frame 0 `leadInFrames` later; a negative one does the
|
||||
// reverse, and the file opens on silence before the note. Either event frame may sit past
|
||||
// the render, which then closes before the note ever fires — a legal empty capture.
|
||||
struct BakePlan {
|
||||
std::int64_t totalFrames = 0;
|
||||
std::int64_t noteOnFrame = 0; // in [0, totalFrames]
|
||||
std::int64_t noteOffFrame = 0; // in [noteOnFrame, totalFrames]
|
||||
std::int64_t totalFrames = 0; // frames in the captured file
|
||||
std::int64_t leadInFrames = 0; // rendered ahead of the file's frame 0, then discarded
|
||||
std::int64_t noteOnFrame = 0; // both in render frames
|
||||
std::int64_t noteOffFrame = 0;
|
||||
// The capture's root: rendering AT root is what makes the root survivable, which is
|
||||
// why the root parameter is the one processing control a bake does not reset.
|
||||
int note = 60;
|
||||
int velocity = 100;
|
||||
int sampleRate = 0;
|
||||
|
||||
std::int64_t renderFrames() const { return leadInFrames + totalFrames; }
|
||||
};
|
||||
|
||||
// nullopt for a collapsed window, a non-positive rate, or a window that rounds to no
|
||||
// frames — a degenerate buffer is refused rather than rendered. `rootNote` and the
|
||||
// resolved velocity are clamped into MIDI range.
|
||||
// nullopt for a collapsed window, a non-positive rate, a window that rounds to no frames,
|
||||
// or one past kMaxBakeFrames — a buffer that is degenerate or unholdable is refused rather
|
||||
// than rendered. `rootNote` and the resolved velocity are clamped into MIDI range.
|
||||
std::optional<BakePlan> planBake(const note::ResolvedNote& resolved, int sampleRate,
|
||||
int rootNote);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user