クーの自由研究

素朴な疑問を実験します。ボクと一緒に螺旋階段を頂上まで登ってみませんか?貴方の影についていきます。

計算機音楽の自由研究(準備:その3)フーリエ変換しないで学習?

はじめに

サウンドデータベースは地道に録音中ですが、完成をまっていたのではなかなか実験が開始できないので、現在録音ができている範囲のデータベースで基本的な実験をします。今回はその予告(予想/仮説)です。

お題:音をフーリエ変換もせずにそのまま自己符号化器をかけるとどうなるか

普通であれば、音をフーリエ変換したり、mfccのパッケージで前処理したりしてから行うところですが、あえて、「波形をそのまま学習」させてみます。だめと分かっていてもやりたいのです。
とはいえ、(サウンドデータベース)サンプルは1音32768サンプル(16bit)なので、MNISTの手書き数字学習と比べても、データの「桁」が違ってしまい、ボクの非力なPCでは実験になりません。せめてMNISTのオーダ近くにまでデータを縮小して実験したいと思います。
MNISTは28×28=784でした。
幸い「音」はサンプリング周波数をかえて「リサンプリング」すれば、データ容量を少なくできます。16bit→8bit、サンプリング周波数を1/12の4KHz にします。これで2KHzまでの周波数であれば再生可能です。当然音は丸くなり悪くなります。

pythonやそのライブラリには「あるかな?」と思ったライブラリはだいたいあります。ダウンサンプリングの操作もPython標準のライブラリでできるようなので、やってみます。
通常はリサンプリングする場合は、(リ)サンプリング周波数の1/2の周波数をリミットにフィルタをかけてから演算しますが、これらも同時にやってくれる(ような)のでとても楽です。

これにより、32768(16Bit) が 2731(8bit) にまで落としたので、なんとかボクのマシンで自己符号化器にかけられそうです。

ちなみに「リサンプリング」で元の音がどれくらい音が悪くなるか貼ってみます。

元の音(ピアノ C音 (MIDI Note=24, 36, 48, 60, 72, 84) Sampling  48KHz 16Bit)

 

リサンプリングした音(ピアノ C音 (MIDI Note=24, 36, 48, 60, 72, 84) Sampling  4KHz 8Bit)

 

こんな感じになります。
中央C MIDI=60より上は音質的にきびしそうなので、MIDI=60以下の範囲で学習してみます。

この「リサンプリングした方の音」(のデータ)をそのまま自己符号化器にかけて、どれくらい復元できるかやってみようとおもいます。
自己符号化器なので、そこそこの復元はできるとは思いますが、音にしたときにどんな感じになるのか、「ボク、とっても気になります。」

と、いう訳で、お題「フーリエ変換もせずに、そのまま自己符号化器をかけるとどんな音が復元できるのか?」。。。

音はすこしでも波形を崩すとかなり酷いことになるので、あんまり期待できなさそうですが、いよいよ実験です!

リサンプリングのプログラムなど

ほとんど需要がないと思いますが、リサンプリングのプログラムを貼ってみます。audioop はpythonの標準ライブラリです。使用方法はPythonドキュメントにあります。

48KHz 16Bit を4KHz 8Bit にダウンリサンプリングするベタベタプログラムです。


import os
import wave
import audioop

def downsampleWav(src, dst, inrate=48000, outrate=8000, inchannels=1, outchannels=1):
if not os.path.exists(src):
print ('Source not found!')
return False

if not os.path.exists(os.path.dirname(dst)):
os.makedirs(os.path.dirname(dst))

try:
s_read = wave.open(src, 'r')
s_write = wave.open(dst, 'w')
except:
print ('Failed to open files!')
return False

n_frames = s_read.getnframes()
data = s_read.readframes(n_frames)

try:
# Infile must be 16bit audio // 入力は2バイト(16bit)指定です
converted = audioop.ratecv(data, 2, inchannels, inrate, outrate, None)
if outchannels == 1:
converted = audioop.tomono(converted[0], 2, 1, 0)
# Convert 16bit to 8 bit // 2バイト(16bit)長から1バイト(8bit)長へ変換します
new_frames = audioop.lin2lin(converted, 2, 1)
# add Bias because 8bit // 8bitなので、中央値128としてバイアスします
new_frames = audioop.bias(new_frames, 1, 128)
except:
print ('Failed to downsample wav')
return False

try:
# Adjust frame rate // 何故かしらリサンプリングで指定の半分のレートで変換されるので調整してます
s_write.setparams((outchannels, 1, outrate / 2, 0, 'NONE', 'Uncompressed'))
s_write.writeframes(new_frames)
except:
print ('Failed to write wav')
return False

try:
s_read.close()
s_write.close()
except:
print ('Failed to close wav files')
return False

return True

# 録音済の48K 16Bitのサウンドを 4K 8Bitに出力します。
downsampleWav("H:\\SoundDB\\02\\02001\\Check024.wav", "H:\\SoundDB\\02\\02001\\Resample024.wav")
downsampleWav("H:\\SoundDB\\02\\02001\\Check036.wav", "H:\\SoundDB\\02\\02001\\Resample036.wav")
downsampleWav("H:\\SoundDB\\02\\02001\\Check048.wav", "H:\\SoundDB\\02\\02001\\Resample048.wav")
downsampleWav("H:\\SoundDB\\02\\02001\\Check060.wav", "H:\\SoundDB\\02\\02001\\Resample060.wav")
downsampleWav("H:\\SoundDB\\02\\02001\\Check072.wav", "H:\\SoundDB\\02\\02001\\Resample072.wav")
downsampleWav("H:\\SoundDB\\02\\02001\\Check084.wav", "H:\\SoundDB\\02\\02001\\Resample084.wav")

クーの今日のお菓子

f:id:np2LKoo:20170719232311j:plaincookpadより)

今日のお菓子は豆乳プリンメープルシロップかけ)、または豆乳もち(黒蜜かけ)です。レシピはクックパッドなどにいろいろ載っていますのでお好みで。絶品です。見た目はクックパッドのようにはなかなかいきませんが、味は最高です。砂糖はほとんど入れないほうが、黒蜜やメープルシロップとマッチする感じです。

ボクはかえるなのに、前世はクワガタではないかと思うくらい「メープルシロップ」大好きです。でも豆乳シリーズは豆乳もち+黒蜜+きなこかけの方がベストマッチな感じがします。。