SoXで音声感知録音:その6 話し声を準リアルタイム録音2

2015-08-14

旧ブログ

t f B! P L

前の関連記事:SoXで音声ファイルを分割してvadエフェクトをかけるバッチファイル


SoXで音声感知録音:その5 話し声を準リアルタイム録音のsht_f_del.batを変更してSoXで音声ファイルを分割してvadエフェクトをかけるバッチファイルと同様に指定した秒数で分割したファイルにvadエフェクトをかけ直すようにしました。それに伴いsettings.batも変更しています。sox_rec.batとsox_start.bat、sox_end.bat、sox_restart.batは変更ありません。

設定ファイルsettings.bat

rem データディレクトリに残すファイル数。記録中に処理させる場合は1以上にする。
set RF=1
rem 録音音声ファイル形式の設定(拡張子で判別)。
set EXT=wav
rem 出力音声ファイルの形式
set OUTEXT=flac
rem 出力音声ファイルの圧縮オプション
set OUTOPT=-C 6
rem 記録しない音声ファイルの長さ(秒以下)。
set SEC=3
rem vadエフェクト後に分割する間隔(秒)
set F_LEN=5
rem 1ファイル当たりの録音区間の秒数の設定(秒)。
set DUR=60
rem 分割処理後に削除する音声ファイルの長さ(秒)
set SEC2=1
rem ファイルを結合するときに一括処理するファイル数。大きくする程処理が速くなるがあまり大きくするとエラーがでる。
set BULK=200
rem ディレクトリ名の設定。スクリプトファイルのあるディレクトリの下層に作られる。
rem データディレクトリ名。
set DATA_DIR=sox_data
rem 改名後のデータをいれるディレクトリ名。
set RENAMED_DIR=renamed
rem 処理後のファイルの移動先ディレクトリ名。
set EXTRACTED_DIR=extracted
rem オリジナルファイル保存先ディレクトリ名。
set ORI_DIR=original
rem sox.exeへのパスの設定。環境変数PATHに設定しているときは不要。
rem Windows7 64bitの場合。
path %PATH%;C:\Program Files (x86)\sox-14-4-2
rem WindowsXPの場合。
path %PATH%;C:\Program Files\sox-14-4-2
rem sox.exeにパスが通っているかの確認。
set T=0
for /F "delims= " %%t in ('sox --version') do set T=%%t
if %T%==0 (
  cls
  echo sox.exeが見つかりません。
  echo.
  pause
  exit
)
rem SoXの既定の音声デバイスの設定。
set AUDIODRIVER=waveaudio
rem このスクリプトがあるディレクトリ。
set SD=%CD%
rem データディレクトリDATA_DIRのフルパス。
set DATA_DIR_P=%SD%\%DATA_DIR%
rem 改名後のデータをいれるディレクトリRENAMED_DIRのフルパス。
set RENAMED_DIR_P=%SD%\%DATA_DIR%\%RENAMED_DIR%
if not exist "%RENAMED_DIR_P%" (mkdir "%RENAMED_DIR_P%")
rem 処理後のファイルの移動先ディレクトリEXTRACTED_DIRのフルパス。
set EXTRACTED_DIR_P=%SD%\%DATA_DIR%\%EXTRACTED_DIR%
if not exist "%EXTRACTED_DIR_P%" (mkdir "%EXTRACTED_DIR_P%")
rem 再抽出の作業フォルダのフルパス
set TMP_DIR_P=%SD%\%DATA_DIR%\temp
if not exist "%TMP_DIR_P%" (mkdir "%TMP_DIR_P%")
set ORI_DIR_P=%SD%\%DATA_DIR%\%ORI_DIR%
if not exist "%ORI_DIR_P%" (mkdir "%ORI_DIR_P%")

録音した音声ファイルにvadエフェクトをかけるsht_f_del.bat


録音できていないときをチェックしてSoXで音声感知録音:その3 自動録音環境構築まとめのsox_killrestart.batを使ってSoXを再起動するようにしています。

vadエフェクトをかける前の音声ファイルもoriginalフォルダに保存しています。
@if(0)==(0) echo off
call settings.bat
echo %DATA_DIR%フォルダにある%EXT%ファイルを改名して%RENAMED_DIR%フォルダに移動させています。
for /F %%p in ('cscript.exe //nologo //E:JScript "%~f0"') do set FCNT=%%p
rem なぜか勝手にsoxがフリーズしているときがあるので、
rem 処理するファイルがなければsox再起動して終了。
if not %FCNT% GEQ 1 (
  call sox_killrestart.bat
  exit
)
cd "%EXTRACTED_DIR_P%"
setlocal enabledelayedexpansion
for %%f in ("%RENAMED_DIR_P%\*.%EXT%") do (
  rem 変換後のファイル名
  set F_NAME=%%~nf.wav
  echo %%fをwavに変換して抽出中。
  sox "%%f" !F_NAME! vad reverse vad reverse
  echo 元ファイルをmp3にして保存中。
  sox "%%f" -C -8.2 "%ORI_DIR_P%\%%~nf.mp3"
  del /Q "%%f"
 echo 抽出後の!F_NAME!の長さが%SEC%秒以下なら削除します。
  rem sox --iで測定できないときのためにTをリセットする。
  set T=0
  for /F "tokens=1 delims=." %%t in ('sox --i -D !F_NAME!') do set T=%%t
  if !T! LEQ %SEC% (
    del /Q !F_NAME!
    echo !F_NAME!の長さが%SEC%秒以下なので削除しました。
  )
  if !T! GTR %F_LEN% (
    echo !F_NAME!は%F_LEN%秒より長いので%F_LEN%秒ごとに分割してvadエフェクトをかけています。
    sox !F_NAME! "%TMP_DIR_P%\%%~nf-%%5n.wav" trim 0 %F_LEN% vad reverse vad reverse : newfile : restart
    del /Q !F_NAME!
    cd "%TMP_DIR_P%"
    for %%g in (%%~nf*.wav) do (
   echo 分割後の%%gのファイルの長さを調べています。
   set T=0
      for /F "tokens=1 delims=." %%t in ('sox --i -D %%g') do set T=%%t
      if !T! LEQ %SEC2% (
    echo %%gは%SEC2%秒以下なので削除します。
        del /Q "%%g"
      ) 
    )
    echo 分割した%%~nf.wavファイルを結合しています。
    rem 結合するファイルリストをリセット
    set F_LIST=
    rem ファイルリストの要素数
    set C=0
    for %%g in (*.wav) do (
      if !C! EQU %BULK% (
        set F_LIST=!F_LIST! "%%g"
        rem F_LISTのファイルをout0.wavと結合してout.wavにする。
        echo !C!個のファイルを結合中。
        sox "%EXTRACTED_DIR_P%\out0.wav" !F_LIST! "%EXTRACTED_DIR_P%\out.wav"
    rem out0.wavを削除してout.wavをout0.wavに改名する。
        del /Q "%EXTRACTED_DIR_P%\out0.wav"
        move "%EXTRACTED_DIR_P%\out.wav" "%EXTRACTED_DIR_P%\out0.wav"
        set F_LIST=
        set C=0
      ) else (
        if not exist "%EXTRACTED_DIR_P%\out0.wav" (
     echo 最初のファイル%%gを%EXTRACTED_DIR_P%\out0.wavにします。
          move "%%g" "%EXTRACTED_DIR_P%\out0.wav"
        ) else (
          echo %%gをファイルリスト!F_LIST!に追加します。
          set F_LIST=!F_LIST! "%%g"
          set /A C=!C!+1
        )
      )
    )
    if !C! GTR 0 (
   echo ファイルリスト!F_LIST!に!C!個残っているファイルをout0.wavに結合します。
      sox "%EXTRACTED_DIR_P%\out0.wav" !F_LIST! "%EXTRACTED_DIR_P%\out.wav"
   del /Q "%EXTRACTED_DIR_P%\out0.wav"
      move "%EXTRACTED_DIR_P%\out.wav" "%EXTRACTED_DIR_P%\out0.wav"
    )
    if exist "%EXTRACTED_DIR_P%\out0.wav" (
      echo out0.wavを分割前のファイル名!F_NAME!に戻します。
      move "%EXTRACTED_DIR_P%\out0.wav" "%EXTRACTED_DIR_P%\!F_NAME!"
    del /Q "*.wav"
    )
    cd "%EXTRACTED_DIR_P%"
  )
  if exist !F_NAME! (
    echo wavファイルを%OUTEXT%に変換します。
    sox !F_NAME! %OUTOPT% %%~nf.%OUTEXT%
    del /Q !F_NAME!
  )
)
endlocal
GOTO :EOF
@end
var sh = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var ext = sh.ExpandEnvironmentStrings("%EXT%");//改名対象拡張子。
var data_dir = sh.ExpandEnvironmentStrings("%DATA_DIR_P%");//データディレクトリdata_dirフルパス。
var renamed_dir = sh.ExpandEnvironmentStrings("%RENAMED_DIR_P%");//改名後のデータをいれるディレクトリrenamed_dirのフルパス。
var fldr = fso.GetFolder(data_dir); //データフォルダオブジェクトの取得。
var fc = new Enumerator(fldr.Files); //ファイルコレクションをEnumeratorオブジェクトにして取得。
var f, new_name, j;
var f_arr = [];//処理対象ファイルオブジェクトを格納する配列。
//RegExpオブジェクトを作成。
var re = new RegExp("^(\\d{4})(\\d{2})(\\d{2})_(\\d{2})(\\d{2})(\\d{2})_(\\d+)_(\\d+)\\." + ext + "$");
//ファイルコレクションの各ファイルに対して。
for (; !fc.atEnd() ; fc.moveNext()) {
    f = fc.item(); //ファイルオブジェクトの取得。
    //ファイル名の判別
    if (re.test(f.Name)) {
        f_arr.push(f);//処理対象となるファイルオブジェクトを配列に格納。ファイル名昇順に取得できているはず。
    } else {
        f.Delete();//処理対象とならないファイルは削除。
    }
}
var fn = f_arr.length - sh.ExpandEnvironmentStrings("%RF%")//処理するファイル数。
for (var i = 0; i < fn ; i++) {
    f = f_arr[i];//配列からファイルオブジェクトを取得。
    new_name = new_fname(re.exec(f.Name));//正規表現結果配列からファイル名を取得。
    try {
        j = 0;//「年月日_時分-年月日_時分」を示す要素番号。
        f.Move(renamed_dir + "\\" + new_name[j] + "." + ext);//改名して移動。
    } catch(e) {
        j = 1;//「年月日_時分秒-年月日_時分秒」を示す要素番号。
        f.Move(renamed_dir + "\\" + new_name[j] + "." + ext);//改名して移動。
    } 
}
WScript.Echo(fn);//バッチファイルに処理対象ファイル数を返す。
//正規表現結果配列から新しいファイル名を返す関数。戻り値は配列[年月日_時分-年月日_時分, 年月日_時分秒-年月日_時分秒]。
function new_fname(r) {
    //ファイル名から記録開始日時のDateオブジェクトを得る。1月を0として開始。
    var start_dt = new Date(r[1], r[2] - 1, r[3], r[4], r[5], r[6]);
    var int_sec = r[7] * 1000; //記録区間長(ミリ秒)
    var int_cnt = r[8]; //記録区間番号
    var start_ms = start_dt.getTime() + int_sec * (int_cnt - 1); //区間開始日時経過ミリ秒
    //経過ミリ秒を数字羅列に変換
    var end_n = date_num(start_ms + int_sec);//区間開始日時。
    var start_n = date_num(start_ms);//区間終了日時。
    var hhmm = start_n[0] + "-" + end_n[0];//新しいファイル名年月日_時分-年月日_時分。
    var hhmmss = start_n[0] + start_n[1] + "-" + end_n[0] + end_n[1];//新しいファイル名年月日_時分秒-年月日_時分秒。
    return [hhmm, hhmmss];
    //経過ミリ秒を年月日の数字羅列に変換する関数。戻り値は配列[年月日_時分, 秒]。
    function date_num(ms) {
        var dt = new Date();//Dateオブジェクトの生成。
        dt.setTime(ms);//経過ミリ秒からDateオブジェクトを取得。
        return [dt.getFullYear() + fm(dt.getMonth() + 1) + fm(dt.getDate()) + "_" + fm(dt.getHours()) + fm(dt.getMinutes()), fm(dt.getSeconds())];
        function fm(m) {
            return ("0" + m).slice(-2);//固定長2桁を返す。
        }
    }
}

次の関連記事:SoXで音声ファイルを結合するバッチファイル

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ