librosa 互換性
libsonare の関数が Python の librosa ライブラリにどのように対応するかを説明します。
このページの読み方
概要
libsonare は、librosa と同じような MIR(music information retrieval:音声からテンポ・キー・ピッチなどの音楽的特徴を抽出する分野)の基本部品を提供します。C++、Python バインディング、Node.js ネイティブバインディング、WebAssembly での利用を想定しています。librosa の完全なドロップイン置き換えではありません。API、既定値、数値計算の細部は異なる場合があります。libsonare のテストスイートでは、一部の機能について librosa 0.11 の参照値と比較しています。
目的別マップ
長い対応表を見る前に、この表で入口を選んでください。
| librosa コードでやっていること | libsonare で使うもの | 注意点 |
|---|---|---|
| ファイルを読み込み、単発解析する | Audio.from_file(...) のあと detect_bpm, detect_key, analyze | ブラウザ/WASM はファイルをデコードしません。先に Web Audio または Audio.fromMemory* で PCM にします |
| ML 用のスペクトログラム特徴を作る | stft, melSpectrogram / mel_spectrogram, mfcc, pcen | 比較時は n_fft, hop_length, n_mels, n_mfcc を明示してください |
| クロマや和声特徴を計算する | chroma, chromaCqt / chroma_cqt, nnlsChroma / nnls_chroma, tonnetz | chromaCqt / chroma_cqt が librosa.feature.chroma_cqt の直接の相当。nnlsChroma は別物の NNLS 音符活性化クロマです |
| テンポ、ビート、オンセット、パルスを見る | onsetEnvelope, detectOnsets, detectBeats, detectBpm, tempogram, plp | 高レベル検出器はビート/オンセット時刻を秒で返します |
| 音声を編集・変換する | hpss, hpssWithResidual / hpss_with_residual, timeStretch / time_stretch, phaseVocoder / phase_vocoder, pitchShift / pitch_shift, remix, trimSilence / trim_silence | フェーズボコーダー、HPSS、リサンプリングの細部は librosa と異なります |
| 単位変換や配列整形をする | framesToSamples, samplesToFrames, frameSignal, padCenter, fixLength, vectorNormalize | JS は camelCase、Python は snake_case です |
| 特徴量から近似音声を復元する | melToAudio, mfccToAudio | Griffin-Lim による位相推定なので、復元はロスがあります |
PCEN とは?
PCEN(Per-Channel Energy Normalization)は、メルスペクトログラムを対数スケール化する代わりの手法です。周波数バンドごとに自動ゲイン制御をかけ、定常的な背景ノイズを抑えてラウドネスを平準化します。ML や音響イベント検出での頑健性を高めることがよくあります。
検証カバレッジ
ここでいう互換性は「API が同一」という意味ではありません。librosa の挙動を参照し、近い結果になるかをテストしている、という意味です。
libsonare リポジトリには、STFT、Mel/MFCC、chroma、CQT について librosa 参照比較テストがあります。pitch、tuning、onset/beat/tempo、tempogram/PLP、PCEN についても同様です。spectral contrast/poly features/zero crossings、dB 変換、フレーミング/シーケンスヘルパー、silence trim/split も対象です。HPSS、harmonic/decompose/NN filter/remix/phase vocoder、tonnetz など、その他の機能についてもテストがあります。
下の許容誤差は、移行時の目安として読んでください。すべての入力で厳密に同じ数値になることを保証するものではありません。
これらの参照テストが確認しているのは、対象となる低レベルヘルパーが librosa と一致するかどうかであり、キー・コード・ビートといった高レベルの結果がお手元の素材で音楽的に正しいかどうかではありません。その違いと、自分で精度を測る方法は 実装検証: 精度の境界 と FAQ を参照してください。
機能比較
サポートされている機能
コア/IO
| librosa | libsonare | 備考 |
|---|---|---|
librosa.load() | Audio::from_file() | 標準は WAV/MP3。FFmpeg 有効ビルドでは FFmpeg 対応形式。最初のフレームの前にジャンクがある MP3 も読み込め、マルチチャンネルの WAVE_FORMAT_EXTENSIBLE ファイルは宣言されたスピーカーマスクに従ってモノラルへ畳み込まれます |
librosa.resample() | resample() | librosa 0.11 は標準で soxr、libsonare は r8brain を使用 |
librosa.stft() | Spectrogram::compute() / stft() | 既定値は互換。小さな数値差は発生します |
librosa.istft() | Spectrogram::to_audio() | OLA 再構成 |
librosa.power_to_db() | powerToDb() / power_to_db() | ref/amin/top_db 対応 |
librosa.amplitude_to_db() | amplitudeToDb() / amplitude_to_db() | 同上 |
librosa.db_to_power() | dbToPower() / db_to_power() | power_to_db の逆変換 |
librosa.db_to_amplitude() | dbToAmplitude() / db_to_amplitude() | amplitude_to_db の逆変換 |
エフェクト
| librosa | libsonare | 備考 |
|---|---|---|
librosa.effects.hpss() | hpss() | メディアンフィルターによる分離 |
residual を含む librosa.effects.hpss() 相当 | hpssWithResidual() / hpss_with_residual() | 倍音成分、打撃成分、残差信号を返す |
librosa.effects.harmonic() | harmonic() | 倍音成分のみ |
librosa.effects.percussive() | percussive() | 打撃成分のみ |
librosa.effects.time_stretch() | time_stretch() / timeStretch() | フェーズボコーダー |
librosa.phase_vocoder() | phaseVocoder() / phase_vocoder() | 直接のフェーズボコーダー時間伸縮 |
librosa.effects.pitch_shift() | pitch_shift() / pitchShift() | タイムストレッチとリサンプリング |
librosa.effects.remix() | remix() | 区間スライスの並べ替え/連結。区間単位はサンプル |
| (librosa に相当なし) | remixAlignedIntervals() / remix_aligned_intervals() | 単一チャンネルからゼロクロス整列済みの切り出し区間を 1 組だけ求め、ステレオの全チャンネルに同一適用できるようにする。ゼロクロス整列はチャンネルごとに答えが変わる処理なので、各チャンネルを個別に remix() で整列させるとステレオのズレを生む |
librosa.effects.preemphasis() | preemphasis() | coef、任意の zi |
librosa.effects.deemphasis() | deemphasis() | プリエンファシスの逆 |
librosa.effects.trim() | trimSilence() / trim_silence() | WASM/Node は { audio, startSample, endSample }、Python は (audio, start_sample, end_sample) を返す。最後のホップ境界のフレームより後ろにしか音がない場合も、トリムされずに返されるのではなくその音が残る |
librosa.effects.split() | splitSilence() / split_silence() | WASM/Node はフラットな Int32Array、Python は list[tuple[int, int]] を返す |
特徴量(スペクトル/ピッチ/クロマ)
| librosa | libsonare | 備考 |
|---|---|---|
librosa.feature.melspectrogram() | MelSpectrogram::compute() / melSpectrogram() | Slaney 正規化 |
librosa.feature.mfcc() | MelSpectrogram::mfcc() / mfcc() | DCT-II。librosa と合わせる場合は n_mfcc を明示してください。末尾の lifter(ケプストラルリフタリング、既定 0 = リフタリングなし)は librosa の lifter に対応します |
librosa.feature.chroma_stft() | Chroma::compute() / chroma() | STFT ベース。各フレームは 12 個のピッチクラス値の最大が 1.0 になるよう正規化され(L-infinity/最大値正規化)、librosa の既定 norm=np.inf と一致。ただし chroma() は tuning を取らず、自動推定も行いません(「既知の違い」を参照) |
librosa.feature.spectral_centroid() | spectralCentroid() / spectral_centroid() | フレーム単位 |
librosa.feature.spectral_bandwidth() | spectralBandwidth() / spectral_bandwidth() | フレーム単位 |
librosa.feature.spectral_rolloff() | spectralRolloff() / spectral_rolloff() | roll_percent 対応 |
librosa.feature.spectral_flatness() | spectralFlatness() / spectral_flatness() | フレーム単位 |
librosa.feature.spectral_contrast() | spectralContrast() / spectral_contrast() | 行列形状は (n_bands + 1) x n_frames |
librosa.feature.poly_features() | polyFeatures() / poly_features() | 行列形状は (order + 1) x n_frames |
librosa.feature.zero_crossing_rate() | zeroCrossingRate() / zero_crossing_rate() | フレーム単位 |
librosa.zero_crossings() | zeroCrossings() / zero_crossings() | ゼロ交差サンプル位置 |
librosa.feature.rms() | rmsEnergy() / rms_energy() | フレーム単位 |
librosa.feature.tonnetz() | tonnetz() | 入力: row-major クロマグラム |
librosa.cqt() | cqt() | 定 Q 変換の振幅 |
librosa.vqt() | vqt() | 可変 Q 変換。gamma で Q を制御(省略、Python では None で自動の帯域幅) |
librosa.feature.chroma_cqt() | chromaCqt() / chroma_cqt() | 定 Q クロマグラム。librosa.feature.chroma_cqt の直接の相当 |
| (librosa に厳密な clone なし) | nnlsChroma() / nnls_chroma() | 追加の NNLS 音符活性化クロマ。librosa に厳密な相当なし |
librosa.feature.chroma_cens() | chromaCens() / chroma_cens() | CENS(Chroma Energy Normalized Statistics)クロマ。平滑化・L1 正規化済み |
| (librosa に厳密な相当なし) | bassChroma() / bass_chroma() | CQT ベースの低域クロマ。ベース音・転回形の推定向け |
librosa.hybrid_cqt() | hybridCqt() / hybrid_cqt() | ハイブリッド CQT(低域ビンは CQT、高域ビンは pseudo-CQT) |
librosa.pseudo_cqt() | pseudoCqt() / pseudo_cqt() | 近似的(低精度)CQT |
librosa.feature.tempogram() | tempogram() | 自己相関(既定)。libsonare 独自の拡張として mode='cosine' の窓内コサイン類似度 |
librosa.feature.fourier_tempogram() | fourierTempogram() / fourier_tempogram() | 複素フーリエテンポグラム |
| (テンポオクターブ不変版) | cyclicTempogram() / cyclic_tempogram() | 巡回テンポグラム。librosa に厳密な相当なし |
librosa.feature.tempogram_ratio() | tempogramRatio() / tempogram_ratio() | テンポグラム比特徴量 |
librosa.pcen() | pcen() | time_constant/gain/bias/power/eps |
librosa.pyin() | pitchPyin() / pitch_pyin() | 確率的 YIN。fillNa / fill_na で無声音 f0 を NaN のままにするか 0 にするかを選択 |
librosa.yin() | pitchYin() / pitch_yin() | YIN。すべてのフレームで有限の周期推定値を返し、有声かどうかは別に報告 |
librosa.pitch_tuning() | pitchTuning() / pitch_tuning() | 周波数列からチューニングずれを推定 |
librosa.estimate_tuning() | estimateTuning() / estimate_tuning() | 音声からチューニングずれを推定。librosa と同じく bins_per_octave の 1 ビンに対する端数で、12 のときは解析の tuning オプションの単位と一致します(そちらは 'auto' も受け付けます) |
分解とラウドネス
| librosa / 標準 | libsonare | 備考 |
|---|---|---|
librosa.decompose.decompose() | decompose() | 行優先スペクトログラムから NMF 分解行列を返す |
librosa.decompose.decompose(init=...) | decomposeWithInit() / decompose_with_init() | 初期化方式を選べる NMF。init='random'(既定)または init='nndsvd'(SVD によるウォームスタート) |
librosa.decompose.nn_filter() | nnFilter() / nn_filter() | 近傍フィルター |
| (librosa に相当なし) | decomposeStems() / decompose_stems() | NMF ベースのステム分離(音源分離)。同じ分解から各成分のソフトマスクを作り、元の複素スペクトログラムに適用するため、各成分は入力の位相をそのまま保持し、全成分を足すと入力に戻る |
| ITU-R BS.1770 / EBU R128 | lufsInterleaved() / lufs_interleaved() | インターリーブサンプルからマルチチャンネル Integrated loudness を測定 |
| EBU Tech 3342 LRA | ebur128LoudnessRange() / ebur128_loudness_range() | LU 単位の loudness range |
ここでの NMF と NNLS とは?
NMF(非負値行列因子分解)は、スペクトログラムを少数の繰り返し現れるスペクトル「テンプレート」と、それぞれが時間方向にどれだけ強く働いているかへ分解します。重なった音を切り分けるのに役立ちます。NNLS(非負最小二乗)はこれに関連する当てはめで、nnlsChroma が各音符の活性度を推定するために使い、素のスペクトログラムより整理されたクロマを返します。
decompose() が返すのは振幅スペクトログラムの分解結果で、位相情報を持ちません。これを音声に戻すには位相推定が必要になり、結果は実用的なステムとしては使えません。decomposeStems() は代わりに元の複素スペクトログラムを成分ごとにマスク・逆変換するため、各出力ステムは元の位相をそのまま保持します。
NNDSVD シードと再現性
NNDSVD(init='nndsvd')は入力の主成分特異ベクトルを倍精度で解いてシードを作るため、同じ入力からはどのプラットフォームでも同じ分解結果が得られます。これは精度ではなく再現性の性質です。振幅スペクトログラムの下位の特異ベクトルは単精度のノイズフロアに埋もれるため、単精度でシードすると対象データの合計順序に結果が依存し、対象が変わると成分も変わってしまいます。形状、非負性、再構成品質はどちらの実装でも変わりませんが、保存済みの分解結果や、単精度のシードで作ったステムレンダーは、この実装が出す成分とは一致しません。
逆再構成
librosa.feature.inverse.* に対応します。位相は Griffin-Lim で推定するため往復は近似です。逆変換特徴量 を参照してください。
| librosa | libsonare | 備考 |
|---|---|---|
librosa.feature.inverse.mel_to_stft() | melToStft() / mel_to_stft() | メルパワー → 線形 STFT 振幅(librosa の既定 power=2.0 を平方根で戻すため、呼び出し側でさらに平方根を取る必要はありません)。fmin/fmax/htk でカスタムメル域・HTK も往復可。順変換の結果(melToStft({ result })、mel_result_to_stft)を渡してパラメータを引き継ぐこともできます |
(mel_to_stft + librosa.griffinlim) | melToAudio() / mel_to_audio() | メルパワー → 音声(Griffin-Lim) |
librosa.feature.inverse.mfcc_to_mel() | mfccToMel() / mfcc_to_mel() | MFCC → メルパワー |
librosa.feature.inverse.mfcc_to_audio() | mfccToAudio() / mfcc_to_audio() | MFCC → 音声(Griffin-Lim) |
オンセット/ビート/テンポ
| librosa | libsonare | 備考 |
|---|---|---|
librosa.onset.onset_strength() | onsetEnvelope() / onset_envelope() | スペクトルフラックス(C++ の自由関数は compute_onset_strength()) |
librosa.onset.onset_strength_multi() | onsetStrengthMulti() / onset_strength_multi() | マルチバンドのオンセット強度(既定 nBands=3)。WASM/Node は { nBands, nFrames, data } を返す |
librosa.onset.onset_detect() | detectOnsets() / detect_onsets() | オンセット時刻 |
librosa.beat.beat_track() | BeatAnalyzer / detectBeats() | DP ベース |
librosa.beat.tempo()(0.10 以降は非推奨で、librosa.feature.tempo() に置き換え) | BpmAnalyzer / detectBpm() | オンセットの自己相関と、整数比クラスターによる投票。オクターブの選び方が異なります(既知の違い参照) |
librosa.beat.plp() | plp() | PLP(Predominant Local Pulse。支配的な局所パルス) |
librosa.util.peak_pick() | peakPick() / peak_pick() | ピーク位置のインデックス |
構造セグメンテーション
| librosa | libsonare | 備考 |
|---|---|---|
librosa.segment.recurrence_matrix() | segmentRecurrenceMatrix() / recurrence_matrix() | 特徴量列どうしの自己類似度 |
librosa.segment.cross_similarity() | segmentCrossSimilarity() / cross_similarity() | 2 つの特徴量系列の間の類似度 |
librosa.segment.recurrence_to_lag() | segmentRecurrenceToLag() / recurrence_to_lag() | librosa と同じラグ×時間のレイアウト。既定の pad: true では n × n の recurrence から 2n × n が返り、pad: false なら n × n |
librosa.segment.lag_to_recurrence() | segmentLagToRecurrence() / lag_to_recurrence() | ラグ行列の高さは n 行でも 2n 行でも受け付ける |
librosa.segment.path_enhance() | segmentPathEnhance() / path_enhance() | n × n の recurrence の対角パスを強調 |
librosa.segment.agglomerative() | segmentAgglomerative() / agglomerative() | 特徴量の列ごとに 1 つのラベル |
librosa.segment.subsegment() | segmentSubsegment() / subsegment() | 親セグメントごとにフレーム境界を細分化 |
ユーティリティ
| librosa | libsonare | 備考 |
|---|---|---|
librosa.util.frame() | frameSignal() / frame_signal() | row-major フレーム |
librosa.util.pad_center() | padCenter() / pad_center() | 指定サイズで中央寄せパディング |
librosa.util.fix_length() | fixLength() / fix_length() | 切り詰めまたはパディング |
librosa.util.fix_frames() | fixFrames() / fix_frames() | フレーム範囲を制限 |
librosa.util.normalize() | vectorNormalize() / vector_normalize() | norm_type: 0=inf, 1=L1, 2=L2, 3=power |
librosa.frames_to_samples() | framesToSamples() / frames_to_samples() | フレーム → サンプル |
librosa.samples_to_frames() | samplesToFrames() / samples_to_frames() | サンプル → フレーム |
librosa.frames_to_time() | framesToTime() / frames_to_time() | フレーム → 秒。WASM と Node ではリクエストオブジェクト({ frames, sr, hopLength })も受け付け、timeToFrames・framesToSamples・samplesToFrames も同様 |
librosa.time_to_frames() | timeToFrames() / time_to_frames() | 秒 → フレーム |
librosa にない高レベル解析
librosa は低レベル DSP の充実が強みで、上位の音楽解析は別ツールに任せる設計です。libsonare はそれらの上位タスクを 1 つのライブラリにまとめています。
| libsonare | 説明 |
|---|---|
KeyAnalyzer | 音楽キー検出(Krumhansl-Kessler、Temperley、Sha'ath、Faraldo、Bellman-Budge のプロファイルとの Krumhansl-Schmuckler 相関) |
ChordAnalyzer | コード認識(フルテンプレートセット有効時は 12 ルート × 24 クオリティ。analyze() 内での既定がトライアドのみである点は 認識できるコードの種類は? を参照) |
SectionAnalyzer | 楽曲構造解析(イントロ/Aメロ/サビなど) |
TimbreAnalyzer | 音色特性(ブライトネス、温かみ、密度ほか) |
DynamicsAnalyzer | ラウドネス・ダイナミックレンジ・クレストファクター |
RhythmAnalyzer | 拍子、グルーブ、シンコペーション、規則性 |
ストリーミング
さらに、StreamAnalyzer による「音声が届くにつれて更新される」リアルタイム BPM/キー/コード推定も libsonare 固有の機能です(librosa にはストリーミング API はありません)。
関数マッピング
以下の libsonare のスニペットは import libsonare as sonare(Python)または @libraz/libsonare からの名前付きインポート(JavaScript)を前提とします。JavaScript のスニペットはブラウザでも Node でもそのまま動きます。C++ の形は C++ API にあります。
STFT
librosa:
S = librosa.stft(
y,
n_fft=2048,
hop_length=512,
win_length=None,
window='hann',
center=True
)libsonare:
const result = stft(samples, sampleRate, 2048, 512);result = sonare.stft(samples, sample_rate, n_fft=2048, hop_length=512)sonare::StftConfig config;
config.n_fft = 2048;
config.hop_length = 512;
config.window = sonare::WindowType::Hann;
config.center = true;
auto spec = sonare::Spectrogram::compute(audio, config);# STFT 行列全体を出力する CLI はありません。CLI ではスペクトル要約を使います。
sonare spectral song.wav --n-fft 2048 --hop-length 512 --jsonメルスペクトログラム
librosa:
mel = librosa.feature.melspectrogram(
y=y, sr=sr,
n_fft=2048, hop_length=512,
n_mels=128, fmin=0.0, fmax=None,
htk=False, norm='slaney'
)
mel_db = librosa.power_to_db(mel, ref=np.max)libsonare:
const mel = melSpectrogram(samples, sampleRate, 2048, 512, 128);
// mel.power - パワースペクトル
// mel.db - dB スケールmel = sonare.mel_spectrogram(samples, sample_rate, n_fft=2048, hop_length=512, n_mels=128)
# mel.power - パワースペクトル
# mel.db - dB スケールsonare mel song.wav --n-fft 2048 --hop-length 512 --n-mels 128 --jsonMFCC
librosa:
mfcc = librosa.feature.mfcc(
y=y, sr=sr, n_mfcc=13,
n_fft=2048, hop_length=512, n_mels=128
)libsonare:
const result = mfcc(samples, sampleRate, 2048, 512, 128, 13);
// result.coefficients - [nMfcc x nFrames]result = sonare.mfcc(samples, sample_rate, n_fft=2048, hop_length=512, n_mels=128, n_mfcc=13)
# result.coefficients - [n_mfcc x n_frames]# MFCC 係数をそのまま出力する CLI はありません。ソースビルド C++ CLI では MFCC からの音声プレビューを作れます。
sonare mfcc-to-audio song.wav --n-fft 2048 --hop-length 512 --n-mels 128 --n-mfcc 13 -o mfcc-preview.wavDCT-II とは?なぜ MFCC で使う?
MFCC は Mel-Frequency Cepstral Coefficients(メル周波数ケプストラム係数)の略です。メルスペクトログラムを作り、その対数をとったあと、libsonare は周波数軸方向に DCT-II(タイプ II 離散コサイン変換)を適用します。DCT は実数だけを生み、エネルギーを先頭の数係数に集める FFT のようなもので、n_mfcc 個だけ残せばスペクトルの形(「ケプストラム」)をコンパクトに要約でき、細部は捨てられます。だから MFCC はフルスペクトルではなく、小さく ML 向けの音色記述子になります。
HPSS
librosa:
y_harm, y_perc = librosa.effects.hpss(y, kernel_size=31)libsonare:
const result = hpss(samples, sampleRate, 31, 31);
// result.harmonic
// result.percussiveresult = sonare.hpss(samples, sample_rate, kernel_harmonic=31, kernel_percussive=31)
# result.harmonic
# result.percussivesonare hpss song.wav -o separated --jsonビート追跡
librosa:
tempo, beats = librosa.beat.beat_track(y=y, sr=sr, start_bpm=120)
beat_times = librosa.frames_to_time(beats, sr=sr, hop_length=512)libsonare:
const bpm = detectBpm(samples, sampleRate);
const beats = detectBeats(samples, sampleRate); // すでに秒単位bpm = sonare.detect_bpm(samples, sample_rate)
beats = sonare.detect_beats(samples, sample_rate) # すでに秒単位sonare bpm song.wav --json
sonare beats song.wav --json既定のパラメータ
| パラメータ | librosa | libsonare |
|---|---|---|
sr | 22050 | 単体の解析/特徴量/ラウドネスヘルパーはすべて既定 22050。lufs/true-peak にはバッファの実レートを渡してください。Audio/Spectrogram クラスのメソッドは読み込んだファイルのレートを使います。 |
n_fft | 2048 | librosa 風の特徴量関数ではバッファのサンプル数で 2048。音声を元のレートで受け取る音楽解析器(テンポ、ビート、オンセット、キー、リズム、コード、音色)は 22050 Hz 換算のサンプル数として読み、入力のレートに合わせて再スケールするので、どのレートでもウィンドウは同じ時間幅になります |
hop_length | 512 | 512 |
win_length | n_fft | n_fft |
window | 'hann' | Hann |
center | True | true |
n_mels | 128 | 128 |
fmin | 0.0 | Mel / 逆変換ヘルパーは 0.0。ピッチ検出は 65.0 Hz、CQT/VQT は C1(32.70319566 Hz) |
fmax | sr/2 | sr/2 |
n_mfcc | 20 | 全バインディングの単体 mfcc() / Audio.mfcc() は 20。analyzer/音色抽出の経路は 13 |
n_chroma | 12 | 12 |
librosa の出力と比較する場合は、実行環境ごとの既定値に頼らず、パラメータを明示してください。
Mel スケール式
Slaney(librosa 既定、libsonare 既定)
f < 1000 Hz の場合: mel = 3 * f / 200
f >= 1000 Hz の場合: mel = 15 + 27 * log10(f / 1000) / log10(6.4)HTK
mel = 2595 * log10(1 + f / 700)libsonare は Slaney 変換ヘルパーを公開しており、C++ コアの Mel 設定では HTK 形式のフィルターバンク生成にも対応しています。
const melSlaney = hzToMel(hz); // Slaney(デフォルト)mel_slaney = sonare.hz_to_mel(hz) # Slaney(デフォルト)# Hz/Mel 変換専用 CLI はありません。この変換は上の API から使います。参照用の許容誤差ガイドライン
これは libsonare の librosa 0.11 参照テストで使っている実用上の比較目安です。回帰テストや移行確認のための指標であり、任意の音源に対する精度保証ではありません。
| 機能 | 許容誤差 | 備考 |
|---|---|---|
| STFT 振幅 | 集計値は約0.1%。個別ビンはより大きくずれる場合あり | float32 / float64、窓処理、ゼロ近傍の差 |
| Mel フィルターバンク | 参照テストの合計値/最大値で約0.1% | フィルターバンク生成 |
| MFCC | 平均/標準偏差の参照チェックで約10-15% | DCT と log-Mel の細部 |
| クロマ | < 5% | ピッチマッピング |
| BPM | 数%程度。半分/倍テンポになる場合あり | テンポ候補の違い |
| ビート時刻 | 数十 ms からインパルス列テストで約80 ms 程度 | 位相アライメント |
既知の違い
1. リサンプリング
- librosa 0.11: 標準は
soxr_hq。複数のリサンプラーを選択可能 - libsonare:
r8brain-freeを使用(24ビット品質)
リサンプリング後の特徴量には小さな差が出る場合があります。
2. CQT
- librosa:
cqt()とvqt()は複素係数を返します - libsonare: JavaScript と Python の
cqt()とvqt()は振幅を返し、frequenciesが添えられます。C++ の結果は複素係数も保持します。既定値(C1 のfmin、84 ビン、1 オクターブあたり 12 ビン)は librosa と同じで、gammaを省略すると自動の帯域幅が選ばれます。カーネルは、渡したfmin、filter_scale、gammaの値そのものから作られます
3. 窓の正規化
- librosa: 解析窓と合成窓が同一で、
istftはオーバーラップ加算した出力をその窓の二乗和で割ります - libsonare: 解析側に周期窓、合成側に対称窓を使い、
toAudio()は両者の積の累積和で割ります
どちらのライブラリも窓そのものをスケーリングせず、オーバーラップ加算後に正規化するため、逆 STFT のゲインは両者とも保たれます。レベルを「補正」する目的で再構成後の音声を元音源のピークや RMS に合わせ直さないでください。減衰する素材や無音を含む素材では、すでに正しいレベルを壊してしまいます。
COLA とは?
COLA は Constant Overlap-Add(定数オーバーラップ加算)の略です。STFT から音声を再構成するとき、重なり合う窓掛けフレームを足し合わせます。重なる窓がどのサンプル位置でも一定値に合算されるなら、再構成のゲインはどこでも均一になります。これが COLA 条件です。解析側だけでなく合成側にも窓を掛けるため、一定であるべき量は窓そのものの和ではなく窓の積の和です。どちらのライブラリも、窓とホップの組み合わせがこの条件を満たすことを前提にしていません。オーバーラップ加算しながらサンプルごとに窓の積を累積し、最後にそれで割るので、どの窓とホップの組み合わせでも再構成ゲインは平坦になります。
4. クロマのチューニング基準
- librosa:
chroma_stftの既定はtuning=Noneで、estimate_tuning()を信号に対して実行し、ピッチクラスの格子を録音に合わせ直します - libsonare: 単体の
chroma()は A440 固定でtuningを取りません。音楽解析の呼び出し(analyze、detectChords、detectKey)は既定0のtuningを取り、tuning: 'auto'(Python はtuning="auto")で音声から測定します
A440 から外れた素材では、両者のクロマグラムは許容誤差の範囲ではなく構造的に食い違います。libsonare 側はエネルギーが隣のピッチクラスへにじみ、キーやコードの結果も劣化します。キーとコードには tuning: 'auto'(楽曲解析を参照) を渡してください。各結果は使われたセミトーン端数を報告します。librosa のクロマグラムそのものに合わせるには、estimateTuning()/estimate_tuning() でずれを求め、自前のパイプラインで適用します。12 ビン/オクターブのとき、これは tuning オプションと同じ単位です。
5. テンポのオクターブ選択
- librosa:
start_bpmを中心とする対数正規分布の事前分布でテンポ候補に重みを付けます - libsonare: 自己相関ピークに票を入れ、整数比で関係するテンポ同士をクラスターにまとめ、勝ったクラスターの中に十分な支持を持つ 80〜180 BPM のメンバーがあればそれを報告します(テンポと BPM)
選び方が異なるため、速い素材や遅い素材ではハーフタイムとダブルタイムの結果が食い違うことがあります。
6. オンセットのデトレンド
- librosa:
detrend=Trueはオンセット包絡線に DC ブロッカー(IIR フィルタ)を適用します - libsonare:
detrend=trueは包絡線の平均値を引きます(先頭のlagフレームは除外)
形は一致しますが、曲の冒頭付近では値が正確には一致しません。
移行ガイド
Python から TypeScript へ
librosa.load() は標準でモノラル化し、22050 Hz にリサンプルします。ブラウザではまずファイルをデコードし、必要に応じてモノラルへダウンミックスし、同じ挙動に合わせたい場合は明示的にリサンプルしてください。
変更前 (Python):
import librosa
y, sr = librosa.load('audio.mp3', sr=22050)
tempo, beats = librosa.beat.beat_track(y=y, sr=sr)
print(f"BPM: {tempo}")変更後 (TypeScript):
import { init, detectBpm, resample } from '@libraz/libsonare';
await init();
// AudioContext からオーディオを取得
// 必要に応じて、解析前にステレオをモノラルへダウンミックスします。
const samples = audioBuffer.getChannelData(0);
// オプションで 22050 にリサンプル
const resampled = resample(samples, audioBuffer.sampleRate, 22050);
const bpm = detectBpm(resampled, 22050);
console.log(`BPM: ${bpm}`);Python から C++ へ
Audio::from_file() はデコードしたファイルのサンプルレートを保持します。librosa.load(..., sr=22050) と合わせる場合は明示的にリサンプルしてください。
変更前 (Python):
import librosa
y, sr = librosa.load('audio.mp3')
chroma = librosa.feature.chroma_stft(y=y, sr=sr)変更後 (C++):
#include <sonare.h>
auto audio = sonare::Audio::from_file("audio.mp3");
auto chroma = sonare::Chroma::compute(audio);
auto energy = chroma.mean_energy();パフォーマンス比較
ネイティブとブラウザでは結果の見え方が違います。設計上、両者は異なる FFT バックエンドで動くためです。
ネイティブでは、libsonare の変換処理は SIMD の FFT カーネルで動くため、変換処理が支配的な機能(STFT 自体と、メルや MFCC などその上に構築される機能全般)で librosa を上回ります。これに加えて、反復的なアルゴリズム(HPSS・pYIN)と総合解析パイプラインでも大きく優位です。
WebAssembly ビルドはスカラー FFT のみを使います。両方の FFT バックエンドを積むと、解析専用モジュールのサイズ予算を超えてしまうため、BUILD_WASM では SIMD 経路をビルドから外しています。その結果、ブラウザビルドの変換処理が支配的な機能は、ネイティブ実行の librosa とほぼ同等にとどまり、上回るわけではありません。
機能別の数値、ハードウェア構成、計測手法、再現手順は 1 か所にまとめ、実行環境ごとに分けて記載しています(ベンチマーク を参照)。このページに数値の複製を置かないのは、更新時のズレを防ぐためです。