ボイスロイドの音声から UTAU 音源用 WAVE を作る支援 Python スクリプト

ボイスロイドの音声からUTAU用のWAVEを作る場合、普通に一音ずつ発声させて名前付けて保存……とかやってるとめんどうくさいので、まとめて発声させてそこから適切なファイル名付けて切り出す Python スクリプト作って使いました。

とりあえず、自分の持ってるゆかりさんとずん子さん

VOICEROID+ 結月ゆかり

VOICEROID+ 結月ゆかり

VOICEROID+ 東北ずん子

VOICEROID+ 東北ずん子

ではうまく動作しましたので公開しておきます。

1. ボイスロイドから WAVE 出力

hoge.txt という名前で以下の内容のテキストファイルを作って、それを発声させて hoge.wav という名前で出力してください。

(ずん子さんの場合、抑揚を「0」にした方が良いようです)*1

あー
いー
うー
えー
おー
かー
きー
くー
けー
こー
さー
しー
すー
せー
そー
たー
ちー
つー
てー
とー
なー
にー
ぬー
ねー
のー
はー
ひー
ふー
へー
ほー
まー
みー
むー
めー
もー
やー
ゆー
よー
らー
りー
るー
れー
ろー
わー
をー

がー
ぎー
ぐー
げー
ごー
ざー
じー
ずー
ぜー
ぞー
だー
でー
どー
ばー
びー
ぶー
べー
ぼー
ぱー
ぴー
ぷー
ぺー
ぽー
きゃー
きゅー
きょー
しゃー
しゅー
しょー
ちゃー
ちゅー
ちょー
にゃー
にゅー
にょー
ひゃー
ひゅー
ひょー
みゃー
みゅー
みょー
りゃー
りゅー
りょー
ぎゃー
ぎゅー
ぎょー
じゃー
じゅー
じょー
びゃー
びゅー
びょー
ぴゃー
ぴゅー
ぴょー
いぇー
きぇー
しぇー
ちぇー
にぇー
ひぇー
みぇー
りぇー
ぎぇー
じぇー
びぇー
ぴぇー
うぁー
うぃー
うぇー
うぉー
くぁー
くぃー
くぇー
くぉー
すぁー
すぃー
すぇー
すぉー
つぁー
つぃー
つぇー
つぉー
ぬぁー
ぬぃー
ぬぇー
ぬぉー
ふぁー
ふぃー
ふぇー
ふぉー
むぁー
むぃー
むぇー
むぉー
るぁー
るぃー
るぇー
るぉー
ぐぁー
ぐぃー
ぐぇー
ぐぉー
ずぁー
ずぃー
ずぇー
ずぉー
ぶぁー
ぶぃー
ぶぇー
ぶぉー
ぷぁー
ぷぃー
ぷぇー
ぷぉー
てぃー
でぃー
てゅー
でゅー
とぅー
どぅー

2. Python スクリプトで切り分け

以下の内容の Python スクリプトを適当な名前で作り hoge.txt と同じフォルダに入れて実行してください。

hoge というフォルダが出来て、その中に各行の(末尾から「ー」を取った)名前の .wav が作られます。

import os
import os.path
import wave
import struct

reclist = 'hoge.txt'
directory = 'hoge'

try:
    os.mkdir(directory)
except OSError:
    pass
w = wave.open('hoge.wav', 'rb')
nchannels,  sampwidth, framerate, nframes, comptype, compname = w.getparams()
print nchannels,  sampwidth, framerate, nframes, comptype, compname
waves = w.readframes(nframes)
w.close()

wavedata = []
for i in range(0, len(waves), 2):
    wavedata.append(struct.unpack('h', waves[i:i+2])[0])
print len(wavedata)

data = []
nodata = 0
start = 0
for i in range(len(wavedata)):
    if wavedata[i] == 0:
        nodata += 1
    else:
        if nodata > 10000:
            data.append(wavedata[start:i])
            nodata = 0
            start = i
data.append(wavedata[start:])
if not any(data[0]):
    data = data[1:]
print u'wave 分割数', len(data)
f = open(reclist, 'rb')
n = unicode(f.read(), 'cp932').strip()
f.close()
names = n.split()
print u'書き出し .wav 数', len(names)

for name, wavedata in zip(names, data):
    name = name.strip(u'ー')
    filename = os.path.join(directory, name + '.wav')
    print filename, len(wavedata)
    wavedata = ''.join([struct.pack('h', x) for x in wavedata])
    w = wave.open(filename, 'wb')
    w.setparams((nchannels,  sampwidth, framerate, 0, comptype, compname))
    w.writeframes(wavedata)
    w.close()

## パブリック・ドメイン。好きに流用してください

3. setParam で oto.ini を作る

UTAU音源の設定の仕方は詳しく書きませんのでムックや入門Webページなどを参考に。*2

UTAUスターターパック (100%ムックシリーズ)

UTAUスターターパック (100%ムックシリーズ)

ちなみに今回は

「原音パラメータファイル(oto.ini)を読み込みますか?
→「パラメータを自動的に生成する」
「処理対象の音声データの種類を選んで下さい。」
→「単独発声データ(setParamで推定)」
→「全wavに対して実行」
「ファイル→原音パラメータの保存」で「oto.ini」を保存

という感じでやってみました。

hoge フォルダを適当な名前に変えて UTAU の voice フォルダの中へ

UTAU の使い方についても(以下略

ほんとうは原音設定をちゃんと調整するべきなんでしょうが私も「とりあえずやってみた」段階ですので、あとは各自工夫ねがいます。

*1:抑揚がデフォルトのままだとこんなことにっ!

*2:というか今回初めてやってみたので自分でもよく分かっていないという