CREPE のインストール,CREPE を用いた音声分析プログラム(音のピッチ推定)(Python,PyTorch を使用)(Windows 上)

要約

Windows 環境で CREPE を用いて音声ファイルのピッチ推定を行う.ここでは,PyTorch 実装である torchcrepe ライブラリを使用する.前準備として,Git,7-Zip,Python,Build Tools for Visual Studio,NVIDIA 関連ツール,PyTorch のインストール方法を示す.続いて,torchcrepe の動作確認手順,およびピッチ推定用の Python プログラムを示す.このプログラムは,選択した音声ファイルを torchcrepe で処理し,結果を出力フォルダに保存する.音声ファイルのサンプリングレート,長さ,周波数,周期性などの情報を表示し,周波数と周期性のグラフも描画する.

CREPE

CREPE(Convolutional Representation for Pitch Estimation)は,深層学習を用いたモノフォニック音声のピッチ推定手法である.

特徴

  1. 時間領域の音声波形を直接入力とし,畳み込みニューラルネットワーク(CNN)を用いて360次元のピッチアクティベーションを出力する.
  2. ピッチアクティベーションは,6オクターブの音域を20セント間隔で分割した360個の音高候補に対する活性度を表す数値ベクトルである.

性能評価

  1. RWC-synth と MDB-stem-synth の2つのデータセットを用いて,従来手法である pYIN や SWIPE との比較が行われた.
  2. 評価指標として,Raw Pitch Accuracy(RPA)と Raw Chroma Accuracy(RCA)が用いられた.
  3. 実験の結果,CREPE は多様な音色やノイズに対して従来手法よりロバスト性に優れ,高精度なピッチ推定が可能であることが示された.

応用分野

  1. 旋律抽出やイントネーション分析など,ピッチ情報を必要とする音声処理タスクに応用できる.
  2. 音楽情報処理における音高推定や,言語学における韻律分析にも活用できる.

文献

CREPE: A Convolutional Representation for Pitch Estimation Jong Wook Kim, Justin Salamon, Peter Li, Juan Pablo Bello. Proceedings of the IEEE International Conference on Acoustics, Speech, and Signal Processing (ICASSP), also arXiv:1802.06182v1 [eess.AS], 2018.

https://arxiv.org/pdf/1802.06182v1

CREPE の GitHub の公式ページ(TensorFlow 実装): https://github.com/marl/crepe

ここでは,PyTorch 実装である torchcrepe を使用する.torchcrepe の GitHub の公式ページ: https://github.com/maxrmorrison/torchcrepe

前準備

Build Tools for Visual Studio 2026(ビルドツール)のインストール

Build Tools for Visual Studio 2026(ビルドツール)のインストールを行い、C/C++ コードのビルド環境を整える。

[Build Tools for Visual Studio 2026(ビルドツール)のインストール手順を見るには、ここをクリック]

Windows での Build Tools for Visual Studio 2026 のインストール

Build Tools for Visual Studio は,Visual Studio の IDE を含まない C/C++ コンパイラ,ライブラリ,ビルドツール等のコマンドライン向け開発ツールセットである。インストール済みの場合,この手順は不要である。

以下のコマンドは、Build Tools が未インストールの場合は winget で新規インストールし、インストール済みの場合は setup.exe modify でコンポーネントを追加する(バージョンは変更しない)。

インストールコマンドの実行方法

管理者権限コマンドプロンプトを起動する(手順:Windows キーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。そして、コマンド全体をコマンドプロンプトにコピー&ペーストする。

REM ============================================================
REM Visual C++ 再頒布可能パッケージ (VCRedist 2015-)
REM ============================================================
winget install --scope machine --id Microsoft.VCRedist.2015+.x64 -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --override "/quiet /norestart"
if not "%ERRORLEVEL%"=="0" ( color 0c & echo VCRedist のインストールに失敗しました & ping 127.0.0.1 -n 6 >nul & color )

REM ============================================================
REM Visual Studio Build Tools + Desktop development with C++
REM (VCTools、MSBuildTools、CMake連携、Clang、Windows 11 SDK)
REM ============================================================
REM 進行中のインストーラーを停止(ロック競合回避。対象プロセスが存在しない場合は
REM taskkillがエラーを返すが、これは想定内であるため出力のみ抑制する)
taskkill /F /IM vs_setup.exe /T >nul 2>&1
taskkill /F /IM vs_installer.exe /T >nul 2>&1
taskkill /F /IM vs_installerservice.exe /T >nul 2>&1
taskkill /F /IM msiexec.exe /T >nul 2>&1

REM Build Tools + Desktop development with C++(VCTools)+ 追加コンポーネント(一括)
REM 未インストール時: winget で新規インストール
REM インストール済み時: setup.exe modify でコンポーネント追加(バージョンは変更しない)
winget list --id Microsoft.VisualStudio.BuildTools 2>nul | findstr /i "BuildTools" >nul 2>&1
if %ERRORLEVEL% EQU 0 (
    for /f "usebackq delims=" %P in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -property installationPath`) do start /wait "" "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" modify --installPath "%P" --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Component.VC.CMake.Project --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --add Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --add Microsoft.VisualStudio.Component.VC.v143.x86.x64 --includeRecommended --quiet --norestart --nocache
    if not "%ERRORLEVEL%"=="0" ( color 0c & echo Build Tools のコンポーネント追加に失敗しました & ping 127.0.0.1 -n 6 >nul & color )
) else (
    winget install --scope machine --id Microsoft.VisualStudio.BuildTools -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --override "--quiet --wait --norestart --nocache --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Component.VC.CMake.Project --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --add Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --add Microsoft.VisualStudio.Component.VC.v143.x86.x64"
    if not "%ERRORLEVEL%"=="0" ( color 0c & echo Build Tools のインストールに失敗しました & ping 127.0.0.1 -n 6 >nul & color )
)

REM
REM BuildTools のインストールパスを vswhere.exe で取得(メジャーバージョンに依存しない)
set "VSWHERE=C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
set "BT_PATH="
for /f "usebackq delims=" %P in (`"%VSWHERE%" -products Microsoft.VisualStudio.Product.BuildTools -property installationPath`) do set "BT_PATH=%P"
if not defined BT_PATH ( color 0c & echo Build Tools のインストールパスを取得できませんでした & ping 127.0.0.1 -n 6 >nul & color )

REM 破損時の修復(任意、動作がおかしくなった場合)
REM if defined BT_PATH "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" repair --installPath "%BT_PATH%" --quiet --norestart
REM 導入確認(インストールパスが表示されれば正常)
"%VSWHERE%" -products * -requires Microsoft.VisualStudio.Workload.VCTools -property installationPath

上記のコマンドでは、Build Tools 本体と Visual C++ 再頒布可能パッケージをインストールし、続いて以下のコンポーネントを追加している。

追加のコンポーネントが必要になった場合は Visual Studio Installer で個別にインストールできる。

インストール完了の確認

winget list Microsoft.VisualStudio.BuildTools

Visual Studio を必要とするとき

Visual Studio の機能を必要とする場合は,追加インストールできる。

Python 3.12 のインストール

Pythonのインストールを行い、Pythonのプログラムを実行する環境を整える。扱う環境は、Windows搭載パソコンである。金子研究室では、Python 3.12.10を推奨する。

[Windows での Python 3.12 のインストール手順を見るには、ここをクリック]

Windows での Python 3.12 のインストール

以下のいずれかの方法でPython 3.12をインストールする。Pythonがインストール済みの場合、この手順は不要である。

方法 1:winget によるインストール

インストールコマンドの実行方法

管理者権限コマンドプロンプトを起動する(手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。そして、コマンド全体をコマンドプロンプトにコピー&ペーストする。

--scope machine を指定することで、システム全体(全ユーザー向け)にインストールされる。このオプションの実行には管理者権限が必要である。インストール完了後、コマンドプロンプトを再起動するとPATHが反映される。

REM Python 3.12 をシステム領域にインストール
winget install --id Python.Python.3.12 -e --scope machine --silent --accept-source-agreements --accept-package-agreements --override "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0 Include_pip=1 Include_launcher=1 InstallLauncherAllUsers=1 TargetDir=\"C:\Program Files\Python312\""
if not "%ERRORLEVEL%"=="0" ( color 0c & echo Python 3.12 のインストールに失敗しました & ping 127.0.0.1 -n 6 >nul & color )

REM Python と Scripts を PATH 先頭に追加
powershell -NoProfile -Command "$p='C:\Program Files\Python312'; $s=\"$p\Scripts\"; if(Test-Path $p){$k=[Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SYSTEM\CurrentControlSet\Control\Session Manager\Environment',$true); $c=$k.GetValue('Path','',[Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames); $t=$k.GetValueKind('Path'); $new=$c; if((';'+$new+';') -notlike \"*;$p;*\"){$new=$p+';'+$new}; if((';'+$new+';') -notlike \"*;$s;*\"){$new=$s+';'+$new}; if($new -ne $c){$k.SetValue('Path',$new,$t)}; $k.Close()}"

REM 現在のセッションにも反映(システムPATHを再取得して連結)
for /f "usebackq tokens=2,*" %A in (`reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path`) do set "PATH=%B"

REM pip / wheel の更新
python -m pip install --no-user -U pip wheel
if not "%ERRORLEVEL%"=="0" ( color 0c & echo pip / wheel の更新に失敗しました & ping 127.0.0.1 -n 6 >nul & color )

方法 2:インストーラーによるインストール

  1. Python公式サイト(https://www.python.org/downloads/)にアクセスし、「Download Python 3.x.x」ボタンからWindows用インストーラーをダウンロードする。
  2. ダウンロードしたインストーラーを実行する。
  3. 初期画面の下部に表示される「Add python.exe to PATH」にチェックを入れてから「Customize installation」を選択する。このチェックを入れ忘れると、コマンドプロンプトから python コマンドを実行できない。
  4. 「Install Python 3.xx for all users」にチェックを入れ、「Install」をクリックする。

インストールの確認

コマンドプロンプトで以下を実行する。

python --version

バージョン番号(例:Python 3.12.x)が表示されればインストール成功である。「'python' は、内部コマンドまたは外部コマンドとして認識されていません。」と表示される場合は、インストールが正常に完了していない。

Git のインストール(Windows 上) [クリックして展開]

管理者権限コマンドプロンプトで以下を実行する.管理者権限は,winget の --scope machine オプションでシステム全体にインストールするために必要となる.

REM Git をシステム領域にインストール
winget install --scope machine --id Git.Git -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --override "/VERYSILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS=""icons,ext\reg\shellhere,assoc,assoc_sh"" /o:PathOption=Cmd /o:CRLFOption=CRLFCommitAsIs /o:BashTerminalOption=MinTTY /o:DefaultBranchOption=main /o:EditorOption=VIM /o:SSHOption=OpenSSH /o:UseCredentialManager=Enabled /o:PerformanceTweaksFSCache=Enabled /o:EnableSymlinks=Disabled /o:EnableFSMonitor=Disabled"

7-Zip のインストール(Windows 上) [クリックして展開]

管理者権限コマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトを起動するには、Windows キーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択する。

REM 7-Zip をシステム領域にインストール
winget install --scope machine --id 7zip.7zip -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements
REM 7-Zip のパス設定
powershell -NoProfile -Command "$p='C:\Program Files\7-Zip'; $c=[Environment]::GetEnvironmentVariable('Path','Machine'); if((Test-Path $p) -and $c -notlike \"*$p*\"){[Environment]::SetEnvironmentVariable('Path',\"$p;$c\",'Machine')}"

Build Tools for Visual Studio 2026(ビルドツール)のインストール

Build Tools for Visual Studio 2026(ビルドツール)のインストールを行い、C/C++ コードのビルド環境を整える。

[Build Tools for Visual Studio 2026(ビルドツール)のインストール手順を見るには、ここをクリック]

Windows での Build Tools for Visual Studio 2026 のインストール

Build Tools for Visual Studio は,Visual Studio の IDE を含まない C/C++ コンパイラ,ライブラリ,ビルドツール等のコマンドライン向け開発ツールセットである。インストール済みの場合,この手順は不要である。

以下のコマンドは、Build Tools が未インストールの場合は winget で新規インストールし、インストール済みの場合は setup.exe modify でコンポーネントを追加する(バージョンは変更しない)。

インストールコマンドの実行方法

管理者権限コマンドプロンプトを起動する(手順:Windows キーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。そして、コマンド全体をコマンドプロンプトにコピー&ペーストする。

REM ============================================================
REM Visual C++ 再頒布可能パッケージ (VCRedist 2015-)
REM ============================================================
winget install --scope machine --id Microsoft.VCRedist.2015+.x64 -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --override "/quiet /norestart"
if not "%ERRORLEVEL%"=="0" ( color 0c & echo VCRedist のインストールに失敗しました & ping 127.0.0.1 -n 6 >nul & color )

REM ============================================================
REM Visual Studio Build Tools + Desktop development with C++
REM (VCTools、MSBuildTools、CMake連携、Clang、Windows 11 SDK)
REM ============================================================
REM 進行中のインストーラーを停止(ロック競合回避。対象プロセスが存在しない場合は
REM taskkillがエラーを返すが、これは想定内であるため出力のみ抑制する)
taskkill /F /IM vs_setup.exe /T >nul 2>&1
taskkill /F /IM vs_installer.exe /T >nul 2>&1
taskkill /F /IM vs_installerservice.exe /T >nul 2>&1
taskkill /F /IM msiexec.exe /T >nul 2>&1

REM Build Tools + Desktop development with C++(VCTools)+ 追加コンポーネント(一括)
REM 未インストール時: winget で新規インストール
REM インストール済み時: setup.exe modify でコンポーネント追加(バージョンは変更しない)
winget list --id Microsoft.VisualStudio.BuildTools 2>nul | findstr /i "BuildTools" >nul 2>&1
if %ERRORLEVEL% EQU 0 (
    for /f "usebackq delims=" %P in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -property installationPath`) do start /wait "" "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" modify --installPath "%P" --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Component.VC.CMake.Project --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --add Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --add Microsoft.VisualStudio.Component.VC.v143.x86.x64 --includeRecommended --quiet --norestart --nocache
    if not "%ERRORLEVEL%"=="0" ( color 0c & echo Build Tools のコンポーネント追加に失敗しました & ping 127.0.0.1 -n 6 >nul & color )
) else (
    winget install --scope machine --id Microsoft.VisualStudio.BuildTools -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --override "--quiet --wait --norestart --nocache --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Component.VC.CMake.Project --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --add Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --add Microsoft.VisualStudio.Component.VC.v143.x86.x64"
    if not "%ERRORLEVEL%"=="0" ( color 0c & echo Build Tools のインストールに失敗しました & ping 127.0.0.1 -n 6 >nul & color )
)

REM
REM BuildTools のインストールパスを vswhere.exe で取得(メジャーバージョンに依存しない)
set "VSWHERE=C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
set "BT_PATH="
for /f "usebackq delims=" %P in (`"%VSWHERE%" -products Microsoft.VisualStudio.Product.BuildTools -property installationPath`) do set "BT_PATH=%P"
if not defined BT_PATH ( color 0c & echo Build Tools のインストールパスを取得できませんでした & ping 127.0.0.1 -n 6 >nul & color )

REM 破損時の修復(任意、動作がおかしくなった場合)
REM if defined BT_PATH "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" repair --installPath "%BT_PATH%" --quiet --norestart
REM 導入確認(インストールパスが表示されれば正常)
"%VSWHERE%" -products * -requires Microsoft.VisualStudio.Workload.VCTools -property installationPath

上記のコマンドでは、Build Tools 本体と Visual C++ 再頒布可能パッケージをインストールし、続いて以下のコンポーネントを追加している。

追加のコンポーネントが必要になった場合は Visual Studio Installer で個別にインストールできる。

インストール完了の確認

winget list Microsoft.VisualStudio.BuildTools

Visual Studio を必要とするとき

Visual Studio の機能を必要とする場合は,追加インストールできる。

NVIDIA CUDA Toolkit 12.8のインストール(GPU を使用する場合)

以下のコマンドを管理者権限コマンドプロンプトで実行する (手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。

REM NVIDIA CUDA Toolkit 12.8 をシステム領域にインストール
winget install --scope machine --id Nvidia.CUDA --version 12.8 -e --silent --disable-interactivity --force --uninstall-previous --accept-source-agreements --accept-package-agreements --override "-s -n"

REM 環境変数TEMP, TMPの設定(一時ファイルの保存先を短いパスに変更)
mkdir C:\TEMP
set "TEMP_PATH=C:\TEMP"
setx TEMP "%TEMP_PATH%" /M >nul
setx TMP "%TEMP_PATH%" /M >nul
PyTorch は cuDNN のライブラリを wheel パッケージ内に同梱しているため,TensorFlow の場合と異なり,NVIDIA cuDNN や zlib を別途手動でインストールする必要はない.

PyTorch のインストール(Windows 上)

  1. 以下の手順を管理者権限コマンドプロンプトで実行する (手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。
  2. PyTorch のインストール

    注意】 PyTorch のインストールコマンドは,OS,Python バージョン,CUDA バージョンによって異なる.以下の PyTorch 公式サイトで,使用する環境に合ったインストールコマンドを確認する.

    PyTorch 公式サイト(インストールページ): https://pytorch.org/get-started/locally/

    次のコマンドを実行することにより,PyTorch と関連パッケージ(torchcrepe,scipy,pandas,matplotlib)がインストール(インストール済みのときは最新版に更新)される.以下は CUDA 12.8 環境向けの一例である.

    python -m pip uninstall -y torch torchvision torchaudio torchcrepe
    python -m pip install -U torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
    python -m pip install -U torchcrepe scipy pandas matplotlib tqdm
    
  3. インストールの確認
    python -c "import torch; print(f'PyTorch Version: {torch.__version__}'); print(f'CUDA Available: {torch.cuda.is_available()}')"
    

torchcrepe の動作確認(Windows 上)

torchcrepe は前準備の手順で既にインストール済みである.ここでは動作確認を行う.

  1. Windows で,コマンドプロンプトを実行する
  2. エディタを起動する
    cd /d c:%HOMEPATH%
    notepad check_torchcrepe.py
    
  3. エディタで,次のプログラムを保存する.torchcrepe に同梱されているテスト用音声ファイルを用いて,ピッチ推定が正常に動作するかを確認する.
    import torchcrepe
    
    # torchcrepe に同梱のテスト用音声ファイルを読み込む
    audio, sr = torchcrepe.load.audio('assets/test.wav')
    
    # 5 ミリ秒のホップ長を使用
    hop_length = int(sr / 200.)
    
    # 音声に適した周波数範囲(人の声の場合の例)
    fmin = 50
    fmax = 550
    
    # モデルの容量として "tiny" または "full" を選択
    model = 'tiny'
    
    # CPU で実行する場合
    device = 'cpu'
    
    pitch = torchcrepe.predict(audio, sr, hop_length, fmin, fmax, model,
                                batch_size=2048, device=device)
    
    print("pitch shape:", pitch.shape)
    print("pitch (Hz), first 10 frames:", pitch[0, :10])
    
  4. Python プログラムの実行
    python check_torchcrepe.py
    
  5. エラーメッセージが出ず,ピッチ(周波数)の値が表示されることを確認する.

CREPE のプログラム

プログラム1つめ

  1. Windows で,コマンドプロンプトを実行する
  2. エディタを起動する
    cd /d c:%HOMEPATH%
    notepad pycrepe.py
    
  3. エディタで,次のプログラムを保存する

    【説明】

    このプログラムは,選択した音声ファイルをPyTorch 実装の torchcrepe ライブラリで解析し,ピッチ情報を抽出する.主な機能は次の通りである.

    1. ユーザーが音声ファイル(WAV形式)を選択できる.
    2. 音声ファイルを処理し,ピッチ情報(周波数,周期性)を抽出する.周期性(periodicity)は,TensorFlow 版 CREPE のアクティベーションに相当する信頼度の指標である.
    3. 抽出された情報を,指定された出力フォルダ内のテキストファイルに保存する.
    4. 周波数と周期性の平均と標準偏差を計算し,画面に表示する.
    5. 周波数のグラフを ASCII 文字で描画し,画面に表示する.

    【使用法】

    1. プログラムを実行すると,「音声ファイルを選択してください.複数選択できます.」というメッセージが表示される.このとき,複数のファイルを選択することもできる.
    2. 「出力フォルダを選択してください.」というメッセージが表示される.結果を保存する出力フォルダを選択できる.
    3. 進捗状況がプログレスバーで表示される.
    4. 音声ファイル名,出力ファイルのパス,サンプリングレート,音声の長さ(秒),周波数の平均と標準偏差,周期性の平均と標準偏差,周波数のグラフ(ASCII文字で描画)が表示される.
    5. 出力フォルダには,各音声ファイルの結果がテキストファイルで保存される.
    import os
    import tkinter as tk
    from tkinter import filedialog
    
    import torch
    import torchcrepe
    from scipy.io import wavfile
    from tqdm import tqdm
    
    # パラメータの設定
    CONFIG = {
        "hop_length_ms": 10,  # ピッチ推定のホップ長(ミリ秒)
        "fmin": 50,            # 推定する周波数の下限(Hz)
        "fmax": 550,           # 推定する周波数の上限(Hz)
        "model": "tiny",       # モデルの容量:"tiny" または "full"
        "device": "cuda:0" if torch.cuda.is_available() else "cpu",
    }
    
    def select_files(file_type, file_extension):
        """ファイルを選択する関数"""
        try:
            if 'google.colab' in str(get_ipython()):
                from google.colab import files
                uploaded = files.upload()
                file_paths = list(uploaded.keys())
            else:
                root = tk.Tk()
                root.withdraw()
                file_paths = filedialog.askopenfilenames(filetypes=[(file_type, file_extension)])
        except NameError:
            root = tk.Tk()
            root.withdraw()
            file_paths = filedialog.askopenfilenames(filetypes=[(file_type, file_extension)])
        return file_paths
    
    def select_output_folder():
        """出力フォルダを選択する関数"""
        root = tk.Tk()
        root.withdraw()
        output_folder = filedialog.askdirectory(title="Select output folder")
        return output_folder
    
    def process_audio_file(audio_path, output_folder):
        """音声ファイルを処理する関数"""
        try:
            sr, audio = wavfile.read(audio_path)
            audio_tensor = torch.tensor(audio, dtype=torch.float32).unsqueeze(0)
            # 音声データを [-1, 1] の範囲に正規化
            audio_tensor = audio_tensor / audio_tensor.abs().max()
    
            hop_length = int(sr / (1000.0 / CONFIG["hop_length_ms"]))
            frequency, periodicity = torchcrepe.predict(
                audio_tensor, sr, hop_length,
                CONFIG["fmin"], CONFIG["fmax"], CONFIG["model"],
                batch_size=2048, device=CONFIG["device"],
                return_periodicity=True
            )
            frequency = frequency.squeeze(0).cpu().numpy()
            periodicity = periodicity.squeeze(0).cpu().numpy()
    
            audio_name = os.path.splitext(os.path.basename(audio_path))[0]
            output_file = os.path.join(output_folder, f"{audio_name}_result.txt")
    
            with open(output_file, "w") as file:
                file.write(f"Processing audio file: {audio_path}\n")
                file.write(f"Frequency: {frequency}\n")
                file.write(f"Periodicity: {periodicity}\n")
    
            audio_length = len(audio) / sr
            return audio_name, output_file, frequency, periodicity, sr, audio_length
    
        except Exception as e:
            print(f"Error processing audio file: {audio_path}")
            print(f"Error message: {str(e)}")
            return None, None, None, None, None, None
    def plot_line_graph(data, width=50, height=20, min_value=None, max_value=None):
        if min_value is None:
            min_value = data.min()
        if max_value is None:
            max_value = data.max()
    
        if max_value - min_value == 0:
            print("Cannot plot a graph with constant values.")
            return
    
        normalized_data = [(val - min_value) / (max_value - min_value) for val in data]
        graph = [" "] * (width * height)
    
        for i in range(len(normalized_data)):
            x = i * (width - 1) // (len(normalized_data) - 1)
            y = int((1 - normalized_data[i]) * (height - 1))
            graph[y * width + x] = "*"
    
        for y in range(height):
            print("".join(graph[y * width : (y + 1) * width]))
    
    def main():
        """メイン関数"""
        print('音声ファイルを選択してください。複数選択できます。')
        audio_paths = select_files("Audio Files", "*.wav")
    
        if not audio_paths:
            print("No audio files selected. Exiting.")
            return
    
        print('出力フォルダを選択してください。')
        output_folder = select_output_folder()
    
        if not output_folder:
            print("No output folder selected. Exiting.")
            return
    
        print("Processing audio files...")
        results = []
        for audio_path in tqdm(audio_paths, desc="Progress"):
            result = process_audio_file(audio_path, output_folder)
            results.append(result)
    
        print("Processing completed.")
        print("\nResults:")
        for audio_name, output_file, frequency, periodicity, sr, audio_length in results:
            if audio_name is not None:
                print(f"Audio file: {audio_name}")
                print(f"Output file: {output_file}")
                print(f"Sampling rate: {sr} Hz")
                print(f"Audio length: {audio_length:.2f} seconds")
                print(f"Frequency summary: Mean={frequency.mean():.2f}, Std={frequency.std():.2f}")
                print(f"Periodicity summary: Mean={periodicity.mean():.2f}, Std={periodicity.std():.2f}")
                print("Frequency graph:")
                plot_line_graph(frequency, width=50, height=20)
                print("---")
    
    if __name__ == "__main__":
        main()
    
  4. Python プログラムの実行

    プログラムを pycrepe.py のようなファイル名で保存したので, 「python pycrepe.py」のようなコマンドで実行する.

    python pycrepe.py
    
  5. ファイルダイアログが開くので,音声ファイルを選ぶ.

    このとき,音声ファイルを複数選ぶことができる.

  6. 次に出力結果を保存するフォルダを選ぶ.
  7. 結果の確認

プログラム2つめ

  1. Windows で,コマンドプロンプトを実行する
  2. エディタを起動する
    cd /d c:%HOMEPATH%
    notepad pycrepeplt.py
    
  3. エディタで,次のプログラムを保存する

    【説明】

    このプログラムは,選択した音声ファイルをPyTorch 実装の torchcrepe ライブラリで解析し,ピッチ情報を抽出する.主な機能は次の通りである.

    1. ユーザーが音声ファイル(WAV形式)を選択できる.
    2. 音声ファイルを処理し,ピッチ情報(時間,周波数,周期性)を抽出する.周期性(periodicity)は,TensorFlow 版 CREPE のアクティベーションに相当する信頼度の指標である.
    3. 抽出された情報を,指定された出力フォルダ内のテキストファイルに保存する.
    4. 周波数と周期性の平均と標準偏差を計算し,画面に表示する.
    5. ピッチの散布図と周期性の折れ線グラフを生成し,出力フォルダに保存する.

    【使用法】

    1. プログラムを実行すると,「音声ファイルを選択してください.複数選択できます.」というメッセージが表示される.このとき,複数のファイルを選択することもできる.
    2. 「出力フォルダを選択してください.」というメッセージが表示される.結果を保存する出力フォルダを選択できる.
    3. 進捗状況がプログレスバーで表示される.
    4. 音声ファイル名,出力ファイルのパス,サンプリングレート,音声の長さ(秒),周波数の平均と標準偏差,周期性の平均と標準偏差が表示される.
    5. 出力フォルダには,各音声ファイルの結果がテキストファイルで保存される.
    6. 出力フォルダには,各音声ファイルのピッチの散布図と周期性の折れ線グラフが画像ファイルで保存される.
    import os
    import tkinter as tk
    from tkinter import filedialog
    
    import torch
    import torchcrepe
    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.io import wavfile
    from tqdm import tqdm
    
    # パラメータの設定
    CONFIG = {
        "hop_length_ms": 10,  # ピッチ推定のホップ長(ミリ秒)
        "fmin": 50,            # 推定する周波数の下限(Hz)
        "fmax": 550,           # 推定する周波数の上限(Hz)
        "model": "tiny",       # モデルの容量:"tiny" または "full"
        "device": "cuda:0" if torch.cuda.is_available() else "cpu",
    }
    
    def select_files(file_type, file_extension):
        """ファイルを選択する関数"""
        try:
            if 'google.colab' in str(get_ipython()):
                from google.colab import files
                uploaded = files.upload()
                file_paths = list(uploaded.keys())
            else:
                root = tk.Tk()
                root.withdraw()
                file_paths = filedialog.askopenfilenames(filetypes=[(file_type, file_extension)])
        except NameError:
            root = tk.Tk()
            root.withdraw()
            file_paths = filedialog.askopenfilenames(filetypes=[(file_type, file_extension)])
        return file_paths
    
    def select_output_folder():
        """出力フォルダを選択する関数"""
        root = tk.Tk()
        root.withdraw()
        output_folder = filedialog.askdirectory(title="Select output folder")
        return output_folder
    
    def process_audio_file(audio_path, output_folder):
        """音声ファイルを処理する関数"""
        try:
            sr, audio = wavfile.read(audio_path)
            audio_tensor = torch.tensor(audio, dtype=torch.float32).unsqueeze(0)
            audio_tensor = audio_tensor / audio_tensor.abs().max()
    
            hop_length = int(sr / (1000.0 / CONFIG["hop_length_ms"]))
            frequency, periodicity = torchcrepe.predict(
                audio_tensor, sr, hop_length,
                CONFIG["fmin"], CONFIG["fmax"], CONFIG["model"],
                batch_size=2048, device=CONFIG["device"],
                return_periodicity=True
            )
            frequency = frequency.squeeze(0).cpu().numpy()
            periodicity = periodicity.squeeze(0).cpu().numpy()
            time = np.arange(len(frequency)) * hop_length / sr
    
            audio_name = os.path.splitext(os.path.basename(audio_path))[0]
            output_file = os.path.join(output_folder, f"{audio_name}_result.txt")
    
            with open(output_file, "w") as file:
                file.write(f"Processing audio file: {audio_path}\n")
                file.write(f"Time: {time}\n")
                file.write(f"Frequency: {frequency}\n")
                file.write(f"Periodicity: {periodicity}\n")
    
            audio_length = len(audio) / sr
            return audio_name, output_file, time, frequency, periodicity, sr, audio_length
    
        except Exception as e:
            print(f"Error processing audio file: {audio_path}")
            print(f"Error message: {str(e)}")
            return None, None, None, None, None, None, None
    
    def visualize_pitch(time, frequency, output_folder, audio_name):
        """ピッチを散布図でビジュアライズする関数"""
        plt.figure(figsize=(10, 4))
        plt.scatter(time, frequency)
        plt.xlabel("Time (s)")
        plt.ylabel("Frequency (Hz)")
        plt.title(f"Pitch Estimation - {audio_name}")
        plt.grid(True)
        plt.tight_layout()
        plt.savefig(os.path.join(output_folder, f"{audio_name}_pitch.png"))
        plt.close()
    
    def visualize_periodicity(time, periodicity, output_folder, audio_name):
        """周期性を折れ線グラフでビジュアライズする関数"""
        plt.figure(figsize=(10, 4))
        plt.plot(time, periodicity)
        plt.xlabel("Time (s)")
        plt.ylabel("Periodicity")
        plt.title(f"Periodicity - {audio_name}")
        plt.grid(True)
        plt.tight_layout()
        plt.savefig(os.path.join(output_folder, f"{audio_name}_periodicity.png"))
        plt.close()
    
    def main():
        """メイン関数"""
        print('音声ファイルを選択してください。複数選択できます。')
        audio_paths = select_files("Audio Files", "*.wav")
    
        if not audio_paths:
            print("No audio files selected. Exiting.")
            return
    
        print('出力フォルダを選択してください。')
        output_folder = select_output_folder()
    
        if not output_folder:
            print("No output folder selected. Exiting.")
            return
    
        print("Processing audio files...")
        results = []
        for audio_path in tqdm(audio_paths, desc="Progress"):
            result = process_audio_file(audio_path, output_folder)
            results.append(result)
    
        print("Processing completed.")
        print("\nResults:")
        for audio_name, output_file, time, frequency, periodicity, sr, audio_length in results:
            if audio_name is not None:
                print(f"Audio file: {audio_name}")
                print(f"Output file: {output_file}")
                print(f"Sampling rate: {sr} Hz")
                print(f"Audio length: {audio_length:.2f} seconds")
                print(f"Frequency summary: Mean={frequency.mean():.2f}, Std={frequency.std():.2f}")
                print(f"Periodicity summary: Mean={periodicity.mean():.2f}, Std={periodicity.std():.2f}")
                visualize_pitch(time, frequency, output_folder, audio_name)
                visualize_periodicity(time, periodicity, output_folder, audio_name)
                print("---")
    
    if __name__ == "__main__":
        main()
    
  4. Python プログラムの実行

    プログラムを pycrepeplt.py のようなファイル名で保存したので, 「python pycrepeplt.py」のようなコマンドで実行する.

    python pycrepeplt.py
    
  5. ファイルダイアログが開くので,音声ファイルを選ぶ.

    このとき,音声ファイルを複数選ぶことができる.

  6. 次に出力結果を保存するフォルダを選ぶ.
  7. 結果の確認

    指定した「出力結果を保存するフォルダ」に png 形式の画像ファイルができるので確認.