人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

SPTKの使い方 (2) 音声波形の切り出し

SPTKの使い方 (1)(2012/7/1)のつづき。

今回は、音声波形の一部を切り出すbcutコマンドを使ってみます。これよく使うので便利です。音声ファイルdata.short(rawファイルです)の1000サンプル目から11000サンプル目を切り出したいときは、

bcut +s -s 1000 -e 11000 < data.short > part.short

これだけ。元のdata.shortとpart.shortを図示してみると1000サンプル目から11000サンプル目が切り出されていることがわかります。音声を聞いてみると「青い植」と言っています(笑)

f:id:aidiary:20120701120836p:plain
f:id:aidiary:20120704205650p:plain

ちなみにdata.shortのサンプリング周波数は16000Hzなので、1秒間に16000サンプルあります。つまり、1000サンプルから11000サンプルは秒に直すと、

1000   (sample) = 1000 / 16000 (s)   = 0.0625 (s)
11000 (sample) = 11000 / 16000 (s) = 0.6875 (s)

となります。逆に秒をサンプルに変換したいときは、秒にサンプリング周波数をかければOK。

サントラのMP3ファイルから音声を切り出す

今年の目標(2012/1/1)として類似楽曲検索のプロトタイプを作ろうと思ってます。その場合、楽曲から音声特徴量を抽出するわけですが、楽曲全体から抽出するのでは長すぎて処理も重くなるので中心から30秒間だけ切り出すことを考えています。そのためのスクリプトをPythonで実装してみます(こういうのはシェルスクリプトの方が楽かも)。せっかく、bcutの使い方を覚えたので使ってみました。

iTunesの下にあるFinal Fantasy IVのサントラにあるすべてのmp3を対象にしてみました。ちなみにこのCDは私が初めて買ったCDです(笑)FFの4, 5, 6, 7はサントラ持ってるので後で類似楽曲検索の実験データセットとして使おうと思ってます。

#coding:utf-8
import os
import sys

targetDir = u"~/Music/iTunes/iTunes Music/植松伸夫/Final Fantasy IV"
outputDir = u"./raw"

if __name__ == "__main__":
    # 出力ディレクトリがなかったら作る
    if not os.path.exists(outputDir):
        os.mkdir(outputDir)

    # ターゲットの元にあるすべてのmp3が対象
    for file in os.listdir(targetDir):
        if not file.endswith(".mp3"): continue
        mp3file = os.path.join(targetDir, file)
        rawfile = os.path.join(outputDir, file.replace(".mp3", ".raw"))
        print mp3file, "=>", rawfile

        # mp3を16kHz、32bitでリサンプリング
        os.system("lame --resample 16 -b 32 -a '%s' temp.mp3" % mp3file)
        # mp3をwavに変換
        os.system("lame --decode temp.mp3 temp.wav")
        # wavをrawに変換
        os.system("sox temp.wav temp.raw")

        # ファイルサイズ取得
        size = os.path.getsize("temp.raw")
        
        # 波形のサンプル数を求める
        # 1サンプルはshort型(2byte)なのでファイルサイズを2で割ればOK
        numsample = size / 2
        
        # 中央から前後period秒だけ抽出
        fs = 16000
        period = 15
        center = numsample / 2
        start = center - fs * period
        end = center + fs * period
        # 30秒未満の曲の場合は範囲を狭める
        if start < 0: start = 0
        if end > numsample - 1: end = numsample - 1
        os.system("bcut +s -s %d -e %d < '%s' > '%s'" % (start, end, "temp.raw", rawfile))

    # 後片付け
    os.remove("temp.mp3")
    os.remove("temp.wav")
    os.remove("temp.raw")

このスクリプトを実行するには、lameとsoxというツールが必要です。このツールも便利なので後で使い方をまとめておかないと。実行が終了するとrawというディレクトリの下に中心から30秒だけ切り出したrawファイル(16000Hz)が作られます。

cd raw
ls
01 プレリュード.raw
02 赤い翼.raw
03 バロン王国.raw
04 愛のテーマ.raw
05 オープニング.raw
06 街のテーマ.raw

36 踊る人形カルコブリーナ.raw
37 ゾットの塔.raw
38 幻獣の街.raw
39 魔導船.raw
40 もう一つの月.raw
41 月の民.raw
42 巨人のダンジョン.raw
43 最後の闘い.raw
44 エンディング・テーマ.raw