JavaScript/TypeScript オーディオとストリーミング API
Audio クラス
Audio クラスは、よく使う関数をメソッド形式で呼ぶための入口です。サンプルとサンプルレートを内部で保持するため、各呼び出しで渡し直す必要がありません。
Audio.fromBuffer(samples, sampleRate)
サンプルデータから Audio インスタンスを作成します。
const audio = Audio.fromBuffer(samples, 44100);sampleRate は省略可能で、既定は 48000 です。保持された値はすべてのインスタンスメソッドに渡されるため、必ずバッファ本来のサンプルレートを指定してください。
Audio.fromMemory(bytes)
WAV や MP3 などのエンコード済みオーディオバイト列(Uint8Array)をネイティブ WASM デコーダでデコードし、Audio インスタンスを返します。同梱デコーダが対応しない形式の場合は SonareError をスローします。
const audio = Audio.fromMemory(new Uint8Array(await file.arrayBuffer()));Audio.fromMemoryWithBrowserFallback(bytes, options?)
async で Promise<Audio> を返します。まず Audio.fromMemory を試みます。同梱デコーダが AAC・OGG・FLAC などの形式を読めない場合は、ブラウザのコーデックスタック(AudioContext.decodeAudioData)で代わりにデコードします。ブラウザでデコードしたマルチチャンネル音声は、返される Audio オブジェクトが 1 本のサンプル列を持つようにモノラルへダウンミックスされます。任意の BrowserAudioDecodeOptions(audioContext / createAudioContext / targetSampleRate)を受け取り、このヘルパー自身が生成したコンテキストは後で閉じられます。
const audio = await Audio.fromMemoryWithBrowserFallback(
new Uint8Array(await file.arrayBuffer()),
);プロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
audio.data | Float32Array | サンプルデータ |
audio.length | number | サンプル数 |
audio.sampleRate | number | サンプルレート(Hz) |
audio.duration | number | 長さ(秒) |
インスタンスメソッド
Audio クラスは、よく使う単発ヘルパーをメソッド形式で呼ぶための入口です。サンプルとサンプルレートを内部に保持するので、毎回渡す必要がありません。
analyzeSections(...)、analyzeMelody(...)、analyzeDynamics(...)、analyzeTimbre(...)、ルーム音響系の関数は、WASM パッケージでは独立した関数として呼び出します。
import {
init,
Audio,
analyzeSections,
analyzeMelody,
analyzeDynamics,
analyzeTimbre,
detectAcoustic,
} from '@libraz/libsonare';
await init();
const audio = Audio.fromBuffer(samples, 44100);
// 解析
const bpm = audio.detectBpm();
const key = audio.detectKey();
const keyCandidates = audio.detectKeyCandidates();
const beats = audio.detectBeats();
const downbeats = audio.detectDownbeats();
const onsets = audio.detectOnsets();
const result = audio.analyze();
const chords = audio.detectChords({ useHmm: true });
const sections = analyzeSections(audio.data, audio.sampleRate);
const melody = analyzeMelody(audio.data, audio.sampleRate);
const dynamics = analyzeDynamics(audio.data, audio.sampleRate);
const timbre = analyzeTimbre(audio.data, audio.sampleRate);
const acoustic = detectAcoustic(audio.data, audio.sampleRate);
// エフェクト
const { harmonic, percussive } = audio.hpss();
const corrected = audio.pitchCorrectToMidi(68.7, 69);
const held = audio.noteStretch({ onsetSample: 12000, offsetSample: 24000, stretchRatio: 1.25 });
const voice = audio.voiceChange({ pitchSemitones: 3, formantFactor: 1.05 });
const stretched = audio.timeStretch(1.5);
const shifted = audio.pitchShift(2);
const normalized = audio.normalize(-3.0);
const trimmed = audio.trim(-60.0);
// 特徴抽出
const stftResult = audio.stft();
const mel = audio.melSpectrogram();
const mfcc = audio.mfcc();
const chroma = audio.chroma();
const nnls = audio.nnlsChroma();
const env = audio.onsetEnvelope();
const loudness = audio.lufs();
const centroid = audio.spectralCentroid();
const bandwidth = audio.spectralBandwidth();
const rolloff = audio.spectralRolloff();
const flatness = audio.spectralFlatness();
const zcr = audio.zeroCrossingRate();
const rms = audio.rmsEnergy();
const pitch = audio.pitchPyin();
// リサンプリング
const resampled = audio.resample(22050);引数の既定値(nFft、hopLength、nMels など)はスタンドアロン関数と同じです。
メータリング
デコード済みバッファから、レベル、ダイナミクス、ステレオイメージの統計値を返す単体メーターです。マスタリングチェーンやストリーミングエンジンとは独立しています。
Float32Array、またはステレオの左右ペアを渡すと、値またはレポートが返ります。
各関数は、validate フラグ(既定 true)を持つ options を任意で受け取ります。ホットパスでは validate: false を指定して、JavaScript 側の O(n) の NaN/Inf 事前スキャンを省略できます。ただし非有限のサンプルをコアへ通すための手段ではありません。ネイティブ層が必ず再検証するため、NaN/Inf を含むバッファは変わらず例外になります(該当インデックスを示さない、汎用のネイティブメッセージになるだけです)。空バッファのチェックは常に実行されます。
単一チャンネルのレベルメーター
// サンプルピーク(dBFS)
function meteringPeakDb(samples: Float32Array, sampleRate?: number, options?: ValidateOptions): number
// RMS レベル(dBFS)
function meteringRmsDb(samples: Float32Array, sampleRate?: number, options?: ValidateOptions): number
// クレストファクター(ピーク − RMS、dB)
function meteringCrestFactorDb(samples: Float32Array, sampleRate?: number, options?: ValidateOptions): number
// 平均(DC)オフセット(リニア振幅)
function meteringDcOffset(samples: Float32Array, sampleRate?: number, options?: ValidateOptions): number
// サンプル間ピーク(ISP、いわゆる True Peak)を dBFS で返す。oversampleFactor は 1..16 の 2 の冪(0 / 省略で 4)
function meteringTruePeakDb(samples: Float32Array, sampleRate?: number, oversampleFactor?: number, options?: ValidateOptions): number
// thresholdDb 未満のフレームの割合、範囲 [0, 1]。thresholdDb 既定 -45、
// frameLength 既定 1024、hopLength 既定 256。
function meteringSilenceRatio(
samples: Float32Array,
sampleRate?: number,
thresholdDb?: number,
frameLength?: number,
hopLength?: number,
options?: ValidateOptions
): numberステレオのレベルメーター
単一チャンネルのメーターが必要とする 0.5 * (left + right) のダウンミックスではなく、左右 2 チャンネルをそのまま読むレベルメーターです。上のメーターと違い、リクエストオブジェクト専用です。位置引数のオーバーロードはなく、位置引数で呼ぶと例外になります。
// Crest factor over a channel pair, dB. Peak is taken across both channels
// and RMS is measured over the two together.
function meteringCrestFactorDbStereo(request: MeteringStereoRequest): number
interface MeteringStereoRequest extends ValidateOptions {
left: Float32Array;
right: Float32Array;
sampleRate?: number;
}const crestDb = meteringCrestFactorDbStereo({ left, right, sampleRate });左右が逆相になりうる素材では、こちらを使ってください。逆相のペアはダウンミックスで打ち消し合い、RMS が小さく出るぶんクレストファクターが過大に出ます。完全な逆相ペアでの実測値は、ステレオ版が 11.64 dB、ダウンミックス経由が 0.00 dB でした。
meteringStereoCorrelation と meteringStereoWidth も、位置引数形式に加えて同じ MeteringStereoRequest を受け付けます。
クリッピングとダイナミックレンジ
function meteringDetectClipping(
samples: Float32Array,
sampleRate?: number,
options?: MeteringDetectClippingOptions
): ClippingReport
interface MeteringDetectClippingOptions extends ValidateOptions {
threshold?: number; // 線形絶対値のしきい値。既定: 0.999
minRegionSamples?: number; // 報告する最小連続長。既定: 1
}
function meteringDynamicRange(
samples: Float32Array,
sampleRate?: number,
options?: MeteringDynamicRangeOptions
): DynamicRangeReport
interface MeteringDynamicRangeOptions extends ValidateOptions {
windowSec?: number; // 0 / 省略で 3 秒
hopSec?: number; // 0 / 省略で 1 秒
lowPercentile?: number; // 省略または負値で 0.10(0 は文字どおり 0 パーセンタイル)
highPercentile?: number; // 省略または負値で 0.95
}
interface ClippingReport {
clippedSamples: number;
clippingRatio: number;
maxClippedPeak: number;
regions: ClippingRegion[];
}
interface ClippingRegion {
startSample: number;
endSample: number;
length: number;
peak: number;
}
interface DynamicRangeReport {
dynamicRangeDb: number;
lowPercentileDb: number;
highPercentileDb: number;
windowRmsDb: Float32Array;
}ステレオイメージ
// チャンネル間の非中心化相関(コサイン類似度、−1..1)
function meteringStereoCorrelation(left: Float32Array, right: Float32Array, sampleRate?: number, options?: ValidateOptions): number
// ミッド/サイドのステレオ幅: 0 = モノラル、約 1 = 広いステレオ。上限なし
// (完全な逆相などでミッド信号が無音なら Infinity)
function meteringStereoWidth(left: Float32Array, right: Float32Array, sampleRate?: number, options?: ValidateOptions): number
// Mid/side point series. One point per sample by default; pass maxPoints for a
// display-sized, deterministically decimated point set (0 / >= length = one point per sample).
function meteringVectorscope(left: Float32Array, right: Float32Array, sampleRate?: number, options?: ScopeOptions): VectorscopeReport
// Phase-scope point series plus summary stats. maxPoints decimates the point cloud the same way;
// the summary stats are always computed over the full-resolution signal.
function meteringPhaseScope(left: Float32Array, right: Float32Array, sampleRate?: number, options?: ScopeOptions): PhaseScopeReport
interface ScopeOptions extends ValidateOptions {
maxPoints?: number; // 0 / omit / >= length = one point per input sample
}
// Deprecated aliases: pass maxPoints to meteringVectorscope / meteringPhaseScope instead.
// They simply delegate and are kept for backward compatibility.
function meteringVectorscopeDecimated(left: Float32Array, right: Float32Array, sampleRate?: number, maxPoints?: number, options?: ValidateOptions): VectorscopeReport
function meteringPhaseScopeDecimated(left: Float32Array, right: Float32Array, sampleRate?: number, maxPoints?: number, options?: ValidateOptions): PhaseScopeReport
interface VectorscopeReport {
mid: Float32Array;
side: Float32Array;
}
interface PhaseScopeReport {
mid: Float32Array;
side: Float32Array;
radius: Float32Array;
angleRad: Float32Array;
correlation: number;
averageAbsAngleRad: number;
maxRadius: number;
}meteringStereoCorrelation・meteringStereoWidth・meteringVectorscope・meteringPhaseScope は left と right が同じ長さである必要があります。
meteringStereoWidth は正規化された百分率ではなく、サイド/ミッドのエネルギー比です。0 は完全なモノラル、約 1 は広いステレオ、より大きな有限値はデコリレーションまたは逆相成分が増えていることを表します。2 にクランプしてはいけません。ミッドチャンネルが無音なら、意図的に Infinity を返します。
スペクトラムスナップショット
meteringSpectrum は信号全体を Welch 平均したものです(50% オーバーラップの Hann フレームに分割し、各パワースペクトルを平均)。時間平均しないフレーム単独のスナップショットが必要な場合は meteringSpectrumFrame を使い、frameOffset 位置引数で解析フレームの開始位置を指定します。
function meteringSpectrum(
samples: Float32Array,
sampleRate?: number,
options?: SpectrumOptions & ValidateOptions
): SpectrumReport
// フレーム単独の真のスナップショット(Hann 窓を掛けた nFft の FFT 1 回)。meteringSpectrum のように
// 時間平均しない。解析フレームは [frameOffset, frameOffset + nFft) を対象とし、末尾を超えた分はゼロ埋め。
function meteringSpectrumFrame(
samples: Float32Array,
sampleRate?: number,
frameOffset?: number,
options?: SpectrumOptions & ValidateOptions
): SpectrumReport
interface SpectrumOptions {
nFft?: number; // 0 / 省略で 2048
applyOctaveSmoothing?: boolean;
octaveFraction?: number; // 例: 3 = 1/3 オクターブ。0 / 省略で 3
dbRef?: number; // 0 / 省略で 1.0
dbAmin?: number; // 0 / 省略でライブラリの下限値
}
interface SpectrumReport {
frequencies: Float32Array;
magnitude: Float32Array;
power: Float32Array;
db: Float32Array;
nFft: number;
sampleRate: number;
}テイク: 位置合わせと共通の無音
同じパートを複数回録ったテイクを扱う、バッファ単位のヘルパーです。録音からコンピングまでの流れの中でどこに位置するかは 録音とテイク にあります。ここではシグネチャを載せます。
alignTakeToReference(request)
function alignTakeToReference(request: AlignTakeToReferenceRequest): AlignTakeToReferenceResult
interface AlignTakeToReferenceRequest {
reference: Float32Array; // ガイドテイクまたは伴奏。空でなく、すべて有限値
take: Float32Array; // その下に合わせるテイク。条件は同じ
sampleRate: number; // 両バッファ共通のレート [8000, 384000]。異なるなら先にリサンプル
hopLength?: number; // クロマのホップ(サンプル)。省略で 512。正の整数。0 は既定にならず拒否
binsPerOctave?: number; // オクターブあたりの CQT ビン数。省略で 12。正の 12 の倍数。0 は拒否
}
interface AlignTakeToReferenceResult {
anchors: ProjectWarpAnchor[]; // 2 個以上、有限で狭義単調増加の { warpSample, sourceSample }
alignment: { meanResidualFrames: number; referenceFrames: number; takeFrames: number };
}両者のクロマグラムを位置合わせし、その経路を テイク側 のクリップに Project.setWarpMap で渡せるアンカーへ縮約します。warpSample はリファレンスのタイムライン上の位置、sourceSample はそれに対応するテイク内の位置です。空または非有限のバッファと範囲外の sampleRate は RangeError で拒否します。解像度フィールドの 0、クロマ 2 フレーム分に満たない短い信号、相異なるアンカーが 2 個得られない組み合わせは SonareError の InvalidParameter になります。合わせようのない組み合わせは、使えないマップを返す代わりにエラーとして報告されます。alignment は参考情報で、これによって呼び出しが失敗することはありません。takeFrames / referenceFrames がアンカーの表す全体のレート差、meanResidualFrames が経路が一定レートからどれだけ外れたかで、しきい値は呼び出し側で決めます。
splitSilenceCommonWithReport(request)
function splitSilenceCommonWithReport(request: SplitSilenceCommonRequest): {
intervals: Int32Array; // 同じリクエストに対する splitSilenceCommon の戻り値そのもの
report: SilenceCommonReport;
}
interface SilenceCommonReport {
silenceCeilingDb: number; // すべての信号に無音が残る最大の topDb
maxSignalIntervals: number; // 最も細かく分かれた信号が単独で出した区間数(和集合で結合する前)
minSignalIntervals: number; // 最も分かれなかった信号について同じもの
}リクエスト(signals、topDb 60、frameLength 2048、hopLength 512)、返す区間、拒否条件は ヘルパー の splitSilenceCommon と同一です。名前の「共通」は、各テイクが鳴っている区間の和集合を取ることで、残った隙間がどのテイクでも無音になることを指します。レポートがあるのは、全体を覆う区間が 1 つだけ返る結果に 3 つの原因があり、区間リストではそれを区別できないからです。silenceCeilingDb を渡した topDb と見比べてください。0 に近ければ、鳴りっぱなしのテイクがあり、しきい値をどう変えても隙間は出ません。topDb より低ければしきい値が緩すぎたので、ceiling を下回る topDb で同じ入力が切れます。topDb 以上なのに区間が 1 つなら、どのテイクにも無音はあるが位置が揃っていないので、alignTakeToReference の出番です。区間数は形の情報でしかありません。一度鳴って止まるテイクは 1 で、無音がまったくないテイクと同じ値になります。
remixAlignedIntervals(...)
1 チャンネル分のサンプルと、フラットな (start, end) の区間リスト(splitSilenceCommon の戻り値と同じ形)を受け取り、ゼロクロスに吸着させた同じリストを返します。remix が全チャンネルを同一のフレームで切るためのものです。alignTakeToReference の戻り値は受け取りません。その戻り値はワープアンカーであってカット位置ではありません。詳細は remixAlignedIntervals を参照してください。
Mixer のストリップ: addStrip と settle
シーンドキュメントでは表現できない Mixer のメソッド 2 つです。シーン、ルーティング、コンパイルのタイミングは ミキシングエンジン にあります。
// 構築済みのミキサーにストリップを追加する。戻り値はなく、以後はインデックスで参照する。
// stripById(id) は呼び出し前の stripCount() と一致する。グラフは dirty になり、
// compile() または次の processStereo() で再構築される。
addStrip(id: string, metering?: StripMeteringOptions): void
interface StripMeteringOptions {
enabled?: boolean; // 両メーター。false で両方省く(48 kHz でストリップあたり約 1.4 MB → 約 145 KB)。既定 true
lufs?: boolean; // LUFS 測定。既定 true
truePeak?: boolean; // サンプル間ピーク測定。既定 true
truePeakOversample?: number; // [0, 16]。2x / 4x / 8x に丸められる。0 / 省略で 4x
}
// ストリップの入力トリム、フェーダー、パン、幅のスムーザーを設定済みの値に揃える。
settle(stripIndex: number): voidaddStrip は id の重複、[0, 16] 外の truePeakOversample、型の違う metering フィールド、プレーンオブジェクトでない metering で例外を投げ、そのストリップは追加されません。メーター構成はストリップ構築時に固定され、後から変えるセッターはありません。明示的な接続のないストリップはコンパイル時にマスターへ配線されるので、シーンを編集しなくても新しいストリップは聞こえます。呼び出し側が変えなければならないのは入力の方です。processStereo はストリップ数と同じ数のチャンネルペアを要求するため、新しいインデックスの分だけ配列を増やすまで例外になります。
settle が必要になるのは、設定したばかりのストリップをオフラインでレンダリングする ときです。レベル系の操作子はライブのフェーダー向けにスムージング(約 5 ms)されているため、setFaderDb / setPan / setWidth / setInputTrimDb の直後の最初のブロック、あるいは fromSceneJson 直後(フェーダーのスムーザーはユニティから始まる)の最初のブロックは、スムーザーの初期値から目標値へ徐々に移っていきます。−3 dB の 1 ストリップのシーンでは、最初のサンプルが 5.8 dB 高く実測されました。最後の操作の後、最初のブロックの前に呼んでください。ライブのループではこの滑らかな変化こそが目的なので不要です。自動化、メーター、インサートの状態には触れず、何も消しません。範囲外のインデックスは拒否します。
ストリーミング API
ストリーミング API を使うと、リアルタイムの音声解析とビジュアライゼーションができます。バッチ解析とは異なり、ストリーミングは音声をチャンクごとに処理し、低レイテンシを実現します。
使い分け
- バッチ API: 録音済みファイル、総合解析(BPM、キー、コード、セクション)
- ストリーミング API: ライブ音声、ビジュアライゼーション、リアルタイムフィードバック
この節は StreamAnalyzer の型/クラスリファレンスです。実際に動かすレシピ、AudioWorklet ブリッジ、出力フォーマットの詳細、プログレッシブ推定の解説は リアルタイムとストリーミング を参照してください。
StreamConfig
StreamAnalyzer の設定オプション。
interface StreamConfig {
sampleRate?: number; // デフォルト: 44100(ストリームの既定。22050 ではない)
nFft?: number; // デフォルト: 2048
hopLength?: number; // デフォルト: 512
nMels?: number; // デフォルト: 128
fmin?: number; // デフォルト: 0
fmax?: number; // デフォルト: 0(= sr/2)
tuningRefHz?: number; // デフォルト: 440
computeMel?: boolean; // デフォルト: true
computeChroma?: boolean; // デフォルト: true
computeOnset?: boolean; // デフォルト: true
computeSpectral?: boolean; // デフォルト: true
emitEveryNFrames?: number; // デフォルト: 1(スロットリングなし)
magnitudeDownsample?: number;// デフォルト: 1
maxPendingFrames?: number; // デフォルト: 4096。超過時は新たに生成した出力フレームを破棄
maxProgressionEntries?: number; // デフォルト: 4096。コード/小節進行をそれぞれ保持する上限で、超過時は最古を破棄
keyUpdateIntervalSec?: number; // デフォルト: 5
bpmUpdateIntervalSec?: number; // デフォルト: 10
window?: number; // 0=Hann(既定), 1=Hamming, 2=Blackman, 3=Rectangular
outputFormat?: 0; // レガシー。省略するか Float32(0)を使う
}outputFormat はソース互換性のためだけに残っており、指定する場合は 0 でなければなりません。量子化読み出しは readFramesU8 または readFramesI16 を明示して選びます。内部解析は常に float です。リアルタイムとストリーミング を参照してください。
computeMagnitude フラグはなく、指定するとコンストラクタが例外を投げます。マグニチュードのフレームは StreamAnalyzer の読み出し経路では公開されないためです。マグニチュードのデータが必要な場合は、オフラインで stft/stftDb を使うか、スペクトラムメータリングのヘルパーを使ってください。
streamAnalyzerConfigDefaults() は、上記の各フィールドについてライブラリの既定値を保持した、すべての項目が入った StreamConfigDefaults オブジェクト(Required<StreamConfig>)を返します。設定 UI の既定値として使ったり、ユーザー指定の設定との差分計算に使えます。StreamAnalyzer 自身も、省略されたフィールドにはこの同じ既定値を適用します。
StreamAnalyzer クラス
class StreamAnalyzer {
constructor(config: StreamConfig);
// 音声チャンクを処理(内部オフセット追跡)
process(samples: Float32Array): void;
// 明示的で連続したサンプルオフセットで処理。ギャップ、シーク、または process() からの切り替え前には reset() が必要
processWithOffset(samples: Float32Array, sampleOffset: number): void;
// 読み取り可能なフレーム数
availableFrames(): number;
// 処理済みフレームを読み取り(完全な float 精度)
readFrames(maxFrames: number): FrameBuffer;
// 帯域削減転送/可視化向けの量子化読み出し
// (quantizeConfig を渡すと音量が極端に大きい/小さいストリームの量子化範囲を調整できる;
// リアルタイムとストリーミング → カスタム量子化範囲 を参照)
readFramesU8(maxFrames: number, quantizeConfig?: StreamQuantizeConfig): StreamFramesU8; // Uint8 特徴量配列
readFramesI16(maxFrames: number, quantizeConfig?: StreamQuantizeConfig): StreamFramesI16; // Int16 特徴量配列
// 新しいストリーム用に状態をリセット
reset(baseSampleOffset?: number): void;
// 統計情報と、音声が届くにつれて更新される推定を取得
stats(): AnalyzerStats;
// 処理済みの総フレーム数
frameCount(): number;
// 現在の時間位置(秒)
currentTime(): number;
// サンプルレートを取得
sampleRate(): number;
// パターンロックタイミング用の予想総再生時間を設定
setExpectedDuration(durationSeconds: number): void;
// 大音量/圧縮音声用のノーマライゼーションゲインを設定
setNormalizationGain(gain: number): void;
// チューニング基準周波数を設定(デフォルト: 440 Hz)
setTuningRefHz(refHz: number): void;
// リソースを解放(使用終了時に呼び出し)。`delete()` が正規で、`dispose()` はその alias。
delete(): void;
dispose(): void;
}FrameBuffer
postMessage での効率的な転送用の Structure-of-Arrays 形式。
interface FrameBuffer {
nFrames: number;
nMels: number;
nChroma: number; // クロマがあれば 12、なければ 0
featureFlags: number; // MEL=1, CHROMA=2, ONSET=4, SPECTRAL=8
timestamps: Float32Array; // [nFrames]
mel: Float32Array; // [nFrames * nMels]。MEL がなければ空
chroma: Float32Array; // [nFrames * nChroma]。CHROMA がなければ空
onsetStrength: Float32Array; // [nFrames]。ONSET がなければ空
rmsEnergy: Float32Array; // [nFrames]
spectralCentroid: Float32Array;// [nFrames]。SPECTRAL がなければ空
spectralFlatness: Float32Array;// [nFrames]。SPECTRAL がなければ空
chordRoot: Int32Array; // [nFrames]。CHROMA がなければ空
chordQuality: Int32Array; // [nFrames]。CHROMA がなければ空
chordConfidence: Float32Array; // [nFrames]。CHROMA がなければ空
}ChordChange
検出されたコード変化。
interface ChordChange {
root: PitchClass;
quality: ChordQuality;
startTime: number;
confidence: number;
}BarChord
小節境界で検出されたコード(ビート同期)。
interface BarChord {
barIndex: number;
root: PitchClass;
quality: ChordQuality;
startTime: number;
confidence: number;
}PatternScore
既知のコード進行パターンの一致スコア。
interface PatternScore {
name: string; // パターン名(例: "royalRoad", "pop")
score: number; // 一致スコア(0-1)
}AnalyzerStats
interface AnalyzerStats {
totalFrames: number;
totalSamples: number;
durationSeconds: number;
pendingFrames: number; // 現在バッファされている未読フレーム数
droppedOutputFrames: number; // 上限で新たに生成されたフレームを破棄した数
droppedChordProgressionEntries: number; // 上限到達時に破棄された最古のコード進行エントリ数
droppedBarProgressionEntries: number; // 上限到達時に破棄された最古の小節進行エントリ数
estimate: ProgressiveEstimate;
}ProgressiveEstimate
処理された音声が増えるにつれて精度が向上する BPM、キー、コードの推定値。
interface ProgressiveEstimate {
// BPM 推定
bpm: number; // 未推定の場合は 0
bpmConfidence: number; // 0-1、時間とともに増加
bpmCandidateCount: number;
// キー推定
key: PitchClass; // 0-11(C-B)
keyMinor: boolean;
keyConfidence: number; // 0-1、時間とともに増加
// コード推定(現在)
chordRoot: PitchClass;
chordQuality: ChordQuality;
chordConfidence: number;
chordStartTime: number;
chordProgression: ChordChange[]; // 検出されたコード変化
barChordProgression: BarChord[]; // 小節同期コード
currentBar: number; // 現在の小節インデックス
barDuration: number; // 小節の長さ(秒)
// パターン検出
votedPattern: BarChord[]; // 各パターン位置の投票済みコード
patternLength: number; // 繰り返しパターンの長さ(デフォルト: 4小節)
detectedPatternName: string; // 最も一致するパターン名(例: "royalRoad")
detectedPatternScore: number; // 一致スコア(0-1)
allPatternScores: PatternScore[]; // 全既知パターンのスコア
// 統計情報
accumulatedSeconds: number;
usedFrames: number;
updated: boolean; // このフレームで推定が更新された場合 true
}使い方、AudioWorklet 統合、タイミング
StreamAnalyzer を実際に動かすレシピ(AudioWorklet からブロックを流し込む、フレームを読み出す、emitEveryNFrames でスロットリングする、FrameBuffer のストリーム時間タイムスタンプを AudioContext.currentTime に対応付ける)は、AudioWorklet ハンドシェイクとデータフロー図とともに リアルタイムとストリーミング にあります。
WASM オブジェクトの解放
StreamAnalyzer、Mixer、StreamingEqualizer、StreamingMasteringChain は WASM ヒープメモリを指す embind ハンドルで、JavaScript のガベージコレクタは回収できません。使い終わったら delete() を呼んでください(StreamAnalyzer は dispose() も受け付け、一部のクラスは destroy() を alias として公開します)。analyze() のような通常の関数は普通の JS 値を返すので後始末は不要です。Node ネイティブの解放方法は異なるため、ネイティブバインディング を参照してください。