diff --git a/packages/app/studio/src/ui/header/TimeStateDisplay.tsx b/packages/app/studio/src/ui/header/TimeStateDisplay.tsx index 63a5e5e6c..29d4e6585 100644 --- a/packages/app/studio/src/ui/header/TimeStateDisplay.tsx +++ b/packages/app/studio/src/ui/header/TimeStateDisplay.tsx @@ -29,7 +29,10 @@ import { Propagation } from "@opendaw/lib-box"; const className = Html.adoptStyleSheet(css, "TimeStateDisplay"); -/** Parameters for constructing {@link TimeStateDisplay}. */ +/** Parameters for constructing {@link TimeStateDisplay}. + * + * @public + */ export type Construct = { /** Lifecycle managing subscriptions. */ lifecycle: Lifecycle; @@ -43,6 +46,9 @@ const maxBpm = 1000.0; /** * Displays transport position, tempo and meter. * + * @param lifecycle - Lifecycle managing subscriptions. + * @param service - Service providing access to engine and project. + * * @public */ export const TimeStateDisplay = ({ lifecycle, service }: Construct) => { diff --git a/packages/app/studio/src/ui/timeline/SnapSelector.tsx b/packages/app/studio/src/ui/timeline/SnapSelector.tsx index 3d0155b70..540798d58 100644 --- a/packages/app/studio/src/ui/timeline/SnapSelector.tsx +++ b/packages/app/studio/src/ui/timeline/SnapSelector.tsx @@ -10,7 +10,10 @@ import {Colors} from "@opendaw/studio-core" const className = Html.adoptStyleSheet(css, "SnapSelector") -/** Parameters for constructing {@link SnapSelector}. */ +/** Parameters for constructing {@link SnapSelector}. + * + * @public + */ export type Construct = { /** Lifecycle managing subscriptions. */ lifecycle: Lifecycle @@ -21,6 +24,9 @@ export type Construct = { /** * Dropdown for selecting timeline snap resolution. * + * @param lifecycle - Lifecycle managing subscriptions. + * @param snapping - Snap settings that provide available options. + * * @example * ```tsx * diff --git a/packages/app/studio/src/ui/timeline/TimeAxis.tsx b/packages/app/studio/src/ui/timeline/TimeAxis.tsx index c290052d9..eb054e173 100644 --- a/packages/app/studio/src/ui/timeline/TimeAxis.tsx +++ b/packages/app/studio/src/ui/timeline/TimeAxis.tsx @@ -20,7 +20,10 @@ const className = Html.adoptStyleSheet(css, "time-axis") const MIN_TRACK_DURATION = 8 * PPQN.Bar const MAX_TRACK_DURATION = 1024 * PPQN.Bar -/** Parameters for constructing {@link TimeAxis}. */ +/** Parameters for constructing {@link TimeAxis}. + * + * @public + */ export type Construct = { /** Lifecycle managing subscriptions. */ lifecycle: Lifecycle diff --git a/packages/app/studio/src/ui/timeline/TimeGrid.ts b/packages/app/studio/src/ui/timeline/TimeGrid.ts index 099bae94c..69a6e21ac 100644 --- a/packages/app/studio/src/ui/timeline/TimeGrid.ts +++ b/packages/app/studio/src/ui/timeline/TimeGrid.ts @@ -1,12 +1,16 @@ /** - * Helpers for walking the musical grid of the timeline. Provides iteration + * Helpers for walking the musical grid of the timeline. Provides iteration * utilities that call back for each bar, beat or subdivision within a range. */ import {PPQN} from "@opendaw/lib-dsp" import {int, quantizeFloor} from "@opendaw/lib-std" import {TimelineRange} from "@/ui/timeline/TimelineRange.ts" -/** Utilities for iterating over timeline grid divisions. */ +/** + * Utilities for iterating over timeline grid divisions. + * + * @public + */ export namespace TimeGrid { /** * Time signature expressed as `[nominator, denominator]`. @@ -22,6 +26,11 @@ export namespace TimeGrid { /** * Iterates over grid fragments within the given range and calls `designer` * for each division. + * + * @param param0 - Time signature `[nominator, denominator]`. + * @param range - Visible timeline range to iterate over. + * @param designer - Callback receiving details about each fragment. + * @param options - Optional minimum pixel length of a fragment. */ export const fragment = ([nominator, denominator]: Signature, range: TimelineRange, designer: Designer, options?: Options): void => { diff --git a/packages/docs/docs-dev/architecture/tempo.md b/packages/docs/docs-dev/architecture/tempo.md index c78863fd6..a7e1447f3 100644 --- a/packages/docs/docs-dev/architecture/tempo.md +++ b/packages/docs/docs-dev/architecture/tempo.md @@ -1,6 +1,9 @@ -# Tempo +# Tempo -openDAW expresses musical time in pulses per quarter note (PPQN). A bar in 4/4 time contains 3,840 pulses, providing a stable grid for sequencing and rendering. +openDAW expresses musical time in pulses per quarter note (PPQN). A bar in 4/4 +time contains 3 840 pulses, providing a stable grid for sequencing and +rendering. The PPQN utility collects conversions between pulses, seconds and +samples and provides helpers for formatting musical positions. ## Conversions @@ -11,5 +14,17 @@ const pulses = PPQN.secondsToPulses(1.5, 120); const seconds = PPQN.pulsesToSeconds(PPQN.Bar, 90); ``` -The timeline renders this grid via `TimeGrid` and `TimeAxis`, while `BPMTools.detect` can estimate the tempo of audio buffers. +## Tempo Detection + +The `BPMTools.detect` function estimates the tempo of PCM buffers. It is +optimised for typical music ranges and returns a floating‑point BPM value. + +```ts +import {BPMTools} from "@opendaw/lib-dsp"; + +const bpm = BPMTools.detect(buffer, sampleRate); +``` + +The timeline renders the musical grid via `TimeGrid` and `TimeAxis` and keeps it +in sync with tempo and meter changes. diff --git a/packages/docs/docs-user/features/timeline.md b/packages/docs/docs-user/features/timeline.md index 7bfd6160a..63f338191 100644 --- a/packages/docs/docs-user/features/timeline.md +++ b/packages/docs/docs-user/features/timeline.md @@ -39,6 +39,10 @@ import {PPQN} from "@opendaw/lib-dsp"; // Seconds per bar at 128 BPM const barSeconds = PPQN.pulsesToSeconds(PPQN.Bar, 128); + +// Estimate tempo of an audio buffer +import {BPMTools} from "@opendaw/lib-dsp"; +const bpm = BPMTools.detect(buffer, sampleRate); ``` ## Example Integration diff --git a/packages/lib/dsp/src/bpm-tools.ts b/packages/lib/dsp/src/bpm-tools.ts index ddab7b524..fcc357fb6 100644 --- a/packages/lib/dsp/src/bpm-tools.ts +++ b/packages/lib/dsp/src/bpm-tools.ts @@ -6,6 +6,8 @@ import {int} from "@opendaw/lib-std" * The detector is optimised for music with tempos in the 90‑180 BPM range and * operates on mono PCM data. It is a port of Mark Hills' `bpm(1)` algorithm with * a small penalty applied to very slow candidates to avoid half‑tempo aliases. + * + * @public */ export namespace BPMTools { /** diff --git a/packages/lib/dsp/src/fractions.ts b/packages/lib/dsp/src/fractions.ts index ac544500a..0a1ce88af 100644 --- a/packages/lib/dsp/src/fractions.ts +++ b/packages/lib/dsp/src/fractions.ts @@ -4,7 +4,11 @@ import {PPQN, ppqn} from "./ppqn" /** Tuple representing a musical fraction `n/d`. */ export type Fraction = Readonly<[int, int]> -/** Helpers for working with musical fractions. */ +/** + * Helpers for working with musical fractions. + * + * @public + */ export namespace Fraction { /** Creates a builder for accumulating fractions. */ export const builder = () => new Builder() diff --git a/packages/lib/dsp/src/ppqn.ts b/packages/lib/dsp/src/ppqn.ts index af58aef19..a3910005f 100644 --- a/packages/lib/dsp/src/ppqn.ts +++ b/packages/lib/dsp/src/ppqn.ts @@ -1,5 +1,10 @@ -// Pulses per quarter note (PPQN) -// 960 = 3*5*2^6 +/** + * Utilities and constants for pulses per quarter note (PPQN). + * A single bar in 4/4 time consists of 3,840 pulses where a quarter note equals + * 960 pulses (3 × 5 × 2^6). + * + * @public + */ import {int} from "@opendaw/lib-std" @@ -17,6 +22,7 @@ const SemiQuaver = Quarter >>> 2 // 240 * * @param nominator - Beats per bar. * @param denominator - Note value representing one beat. + * @returns Total pulses per bar. */ const fromSignature = (nominator: int, denominator: int) => Math.floor(Bar / denominator) * nominator /** @@ -25,6 +31,7 @@ const fromSignature = (nominator: int, denominator: int) => Math.floor(Bar / den * @param ppqn - Pulse count to decompose. * @param nominator - Beats per bar. * @param denominator - Note value representing one beat. + * @returns Decomposed musical components. */ const toParts = (ppqn: ppqn, nominator: int = 4, denominator: int = 4) => { const lowerPulses = fromSignature(1, denominator) diff --git a/packages/lib/std/src/time-span.ts b/packages/lib/std/src/time-span.ts index b42f0b0dd..a3317e897 100644 --- a/packages/lib/std/src/time-span.ts +++ b/packages/lib/std/src/time-span.ts @@ -1,11 +1,15 @@ /** * Time span calculation utilities. + * + * @public */ import { int, Unhandled } from "./lang"; /** * Represents a span of time with millisecond precision and provides * convenient factory methods and conversions. + * + * @public */ export class TimeSpan { /** Time span representing positive infinity. */ diff --git a/packages/studio/core/src/Engine.ts b/packages/studio/core/src/Engine.ts index e4f8b9ce9..db21f1a36 100644 --- a/packages/studio/core/src/Engine.ts +++ b/packages/studio/core/src/Engine.ts @@ -1,5 +1,7 @@ /** * Public interfaces for controlling the audio engine and reacting to note events. + * + * @packageDocumentation */ import {ppqn} from "@opendaw/lib-dsp" import {