mbrolaの「あ」

mbrola は mbrolaで狸囃し で紹介したように無料のボーカロイドソフトです。

このmbrolaに単音を発声させ、その音声を波形描画してみました。

f:id:S_E_Hyphen:20170824145555j:plain

ここでは220Hzの「ア」音を使っています。220Hzは音程で言えば低いほうの「A(ラ)」相当です。実際には、その倍音である440Hzや660Hz、880Hz成分が相当量含まれていることが確認できました。

  


 

#!/bin/bash
# 諸設定です
# 音声ファイル名はa220.wav
# 画像ファイル名はa220.ps
# テキスト形式の中間ファイルはa220.txt
# とします。
wavfile=a220.wav
psfile=`echo $wavfile | sed -e "s/wav/ps/g"`
ascfile=`echo $wavfile | sed -e "s/wav/txt/g"`
# mbloraで「a」音を発声させます。
# 500ミリ秒の長さです。
# AD変換のサンプリング周波数は22050Hzとします。
voice=a
freq=220
length=500
sample=22050

cat <<+ |\
mbrola jp3/jp3 /dev/stdin ${wavfile}
${voice} ${length} 0 ${freq}
+
remote_speeker file=${wavfile}

gmt gmtset FORMAT_DATE_MAP yy-mm-dd
gmt gmtset FONT_TITLE 12p,GothicBBB-Medium-UniJIS-UTF8-H
gmt gmtset FONT_LABEL 8p,GothicBBB-Medium-UniJIS-UTF8-H
gmt gmtset FONT_ANNOT_PRIMARY 8p,GothicBBB-Medium-UniJIS-UTF8-H

gmt psbasemap -JX25c/10c -R0/600/-1.0/1.0 \
-Bxa100+l"ミリ秒" \
-Bya0.5g1.0 \
-K -Y9c > $psfile

# soxコマンドでwav形式を取り扱い易いraw形式に変換します。
# raw形式は2バイト長整数なのでodコマンドで人間が読める形に
# 変換します。
sox ${wavfile} -t raw /dev/stdout rate $sample |\
od -w2 -t d2 -v -An |\
awk 'NF<1{print 0;next}{print $1}' > $ascfile
# GMTver5ではminmaxはgmtinfoというコマンドに統合されました。
min=`gmtinfo ${ascfile} -C -o0`
min=`expr $min \* -1`
max=`gmtinfo ${ascfile} -C -o1`
if [ $max -ge $min ]
then
mother=$max
else
mother=$min
fi

# 振幅は最大値で正規化しています。
# 横軸はサンプリング周波数で割って時間に変換しました。
cat $ascfile |\
awk --assign mother="$mother" \
--assign sample="$sample" \
'{print NR/sample*1000,$1/mother}' |\
gmt psxy -J -R -O -K >> $psfile

title="${voice}音 (${freq}Hz ${length}ミリ秒)"\
"サンプリング周波数 ${sample}Hz"
echo 350 0.8 $title |\
gmt pstext -J -R -F+a0.0+jLM+f12p -O -K >> $psfile

# フーリェ変換はSCILABを使用しています。
scilab -nw << _SCI_
fd=mopen('$ascfile');
s=mfscanf(-1,fd,'%f');
mclose(fd);

N=size(s,'*');
r=abs(fft(s));
f=${sample}*(0:(N/2))/N;
n=size(f,'*');
fd=mopen('$ascfile','w');
for i=1:n
mfprintf(fd,'%f %f\n',f(i),r(i));
end
mclose(fd);
_SCI_

# 振幅スペクトルを描画します。
# 計算はナイキスト周波数である11025Hzまでありますが、
# 描画は1000Hzまでとしました。
range=`\
cat $ascfile |\
awk '$1<1000{print}' |\
gmtinfo -I10/10000`
gmt psbasemap -JX10c/5c $range \
-BnSew \
-Bxa100+l"Hz" \
-Bya1000000 \
-O -K -Y-7c >> $psfile
cat $ascfile |\
awk '$1<1000{print}' |\
gmt psxy -J -R -O -K >> $psfile
echo 650 4500000 "振幅スペクトル" |\
gmt pstext -J -R -F+a0.0+jLM+f12p -O >> $psfile

jpgfile=`echo $psfile | sed -e "s/ps/jpg/g"`
convert -density 200 $psfile $jpgfile