Skip to content

JavaScript/TypeScript オーディオとストリーミング API ​

Audio クラス ​

Audio クラスは、よく使う関数をメソッド形式で呼ぶための入口です。サンプルとサンプルレートを内部で保持するため、各呼び出しで渡し直す必要がありません。

Audio.fromBuffer(samples, sampleRate) ​

サンプルデータから Audio インスタンスを作成します。

typescript
const audio = Audio.fromBuffer(samples, 44100);

sampleRate は省略可能で、既定は 48000 です。保持された値はすべてのインスタンスメソッドに渡されるため、必ずバッファ本来のサンプルレートを指定してください。

Audio.fromMemory(bytes) ​

WAV や MP3 などのエンコード済みオーディオバイト列(Uint8Array)をネイティブ WASM デコーダでデコードし、Audio インスタンスを返します。同梱デコーダが対応しない形式の場合は SonareError をスローします。

typescript
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)を受け取り、このヘルパー自身が生成したコンテキストは後で閉じられます。

typescript
const audio = await Audio.fromMemoryWithBrowserFallback(
  new Uint8Array(await file.arrayBuffer()),
);

プロパティ ​

プロパティ型説明
audio.dataFloat32Arrayサンプルデータ
audio.lengthnumberサンプル数
audio.sampleRatenumberサンプルレート(Hz)
audio.durationnumber長さ(秒)

インスタンスメソッド ​

Audio クラスは、よく使う単発ヘルパーをメソッド形式で呼ぶための入口です。サンプルとサンプルレートを内部に保持するので、毎回渡す必要がありません。

analyzeSections(...)、analyzeMelody(...)、analyzeDynamics(...)、analyzeTimbre(...)、ルーム音響系の関数は、WASM パッケージでは独立した関数として呼び出します。

typescript
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 を含むバッファは変わらず例外になります(該当インデックスを示さない、汎用のネイティブメッセージになるだけです)。空バッファのチェックは常に実行されます。

単一チャンネルのレベルメーター ​

typescript
// サンプルピーク(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 チャンネルをそのまま読むレベルメーターです。上のメーターと違い、リクエストオブジェクト専用です。位置引数のオーバーロードはなく、位置引数で呼ぶと例外になります。

typescript
// 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;
}
typescript
const crestDb = meteringCrestFactorDbStereo({ left, right, sampleRate });

左右が逆相になりうる素材では、こちらを使ってください。逆相のペアはダウンミックスで打ち消し合い、RMS が小さく出るぶんクレストファクターが過大に出ます。完全な逆相ペアでの実測値は、ステレオ版が 11.64 dB、ダウンミックス経由が 0.00 dB でした。

meteringStereoCorrelation と meteringStereoWidth も、位置引数形式に加えて同じ MeteringStereoRequest を受け付けます。

クリッピングとダイナミックレンジ ​

typescript
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;
}

ステレオイメージ ​

typescript
// チャンネル間の非中心化相関(コサイン類似度、−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 位置引数で解析フレームの開始位置を指定します。

typescript
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) ​

typescript
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) ​

typescript
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 つです。シーン、ルーティング、コンパイルのタイミングは ミキシングエンジン にあります。

typescript
// 構築済みのミキサーにストリップを追加する。戻り値はなく、以後はインデックスで参照する。
// 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): void

addStrip は 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 の設定オプション。

typescript
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 クラス ​

typescript
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 形式。

typescript
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 ​

検出されたコード変化。

typescript
interface ChordChange {
  root: PitchClass;
  quality: ChordQuality;
  startTime: number;
  confidence: number;
}

BarChord ​

小節境界で検出されたコード(ビート同期)。

typescript
interface BarChord {
  barIndex: number;
  root: PitchClass;
  quality: ChordQuality;
  startTime: number;
  confidence: number;
}

PatternScore ​

既知のコード進行パターンの一致スコア。

typescript
interface PatternScore {
  name: string;   // パターン名(例: "royalRoad", "pop")
  score: number;  // 一致スコア(0-1)
}

AnalyzerStats ​

typescript
interface AnalyzerStats {
  totalFrames: number;
  totalSamples: number;
  durationSeconds: number;
  pendingFrames: number;       // 現在バッファされている未読フレーム数
  droppedOutputFrames: number; // 上限で新たに生成されたフレームを破棄した数
  droppedChordProgressionEntries: number; // 上限到達時に破棄された最古のコード進行エントリ数
  droppedBarProgressionEntries: number;   // 上限到達時に破棄された最古の小節進行エントリ数
  estimate: ProgressiveEstimate;
}

ProgressiveEstimate ​

処理された音声が増えるにつれて精度が向上する BPM、キー、コードの推定値。

typescript
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 ネイティブの解放方法は異なるため、ネイティブバインディング を参照してください。