【Scipy】FFT、STFTとwavelet変換で遊んでみた♬~③音声データ入力編~

昨夜の話で、やはり音声データ入力忘れていたので思い出しました。

というか、参考のサイトが見つかったので、忘れないうちに記事にしておこうと思います。


とりあえずの目標

以下のとおり、

※リンクされているものは記事にしたものであり、その記事を前提知識として書いて行くので、参照すると理解し易いと思います。

Scipy環境を作る

 ・環境の確認

不確定原理について

・FFT変換・逆変換してみる;時間軸が消える

・STFT変換・逆変換してみる;窓関数について

・wavelet変換・逆変換してみる;スペクトログラムの解釈と不確定原理

音声や地震データや株価や、。。。とにかく一次元の実時系列データに応用する

④FFTからwavelet変換まで簡単にたどってみる(上記以外のちょっと理論)

⑤二次元データに応用してみる

⑥天体観測データに応用してみる

⑦リアルタイムにスペクトログラムしてみる


今回やったこと

昨夜、お約束の以下の事項を記事にしておきます。

※wavファイル取得については、別途記事にしたいと思います

前にやったのは、RasPiで取得しましたが、ほぼ同じコードで動きました。

ただし、環境はWindowsでマイク入力というのが、ジャックからの入力で実施しました。

ということで、以下の順に記載します。

①pyaudioのインストール

②音声データ入力、書き出し

③ちょっと音声アプリ

【参考】

PyAudioの基本メモ2 音声入出力@たけし備忘録


①pyaudioのインストール

インストールしたPythonは以下のとおり

Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul  5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)] on win3

>pip install pyaudio

でうまくインストールできました。

ただし、動かし始めてから、当初音量が小さくて聞き取れず、少し試行錯誤しました。

Windows10の環境設定のサウンドの設定をいじりました。

特に、マイクをジャックからの入力にしました。

※RasPiのときはUSBコネクタで入力しました⇒その時の設定は今回はパスします


②音声データ入力、書き出し

RasPi(ubuntu)の時のアプリではまんまだと動きませんでしたが、ちょっとした変更で動きました。

# -*- coding: utf-8 -*-

#マイク0番からの入力を受ける。一定時間(RECROD_SECONDS)だけ録音し、ファイル名:入力名.wavで保存する。

import pyaudio
import sys
import time
import wave

つまり、測定条件は以下の通りでした(過去形)。

if __name__ == '__main__':

CHUNK = 1024 #1024
FORMAT = pyaudio.paInt16
CHANNELS = 1 #monoral
#サンプリングレート、マイク性能に依存
RATE = 22100
# 録音時間
RECORD_SECONDS = input('Please input recoding time>>>')
filename=input('input filename=')

p = pyaudio.PyAudio()

streamの定義は以下のとおり、

    stream = p.open(format=FORMAT,

channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)

print("* recording")

ここでint(RECORD_SECONDS)が目を引くと思いますが、最初なかなかわかりませんでしたが、文字列をintで変換しています。

※これRasPiでは動いていました。。のはず(笑)

 また、参考のように数値で与えていれば特に必要ありません。

以下のように音声を一定時間framesにため込みます。

    frames = []

for i in range(0, int(RATE / CHUNK * int(RECORD_SECONDS))):
data = stream.read(CHUNK)
frames.append(data)
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()

最後に、ため込んだframesをファイルに書き出します。

ここで、ウワンは未確認ですが、width=2は16bitを意味するそうです。

    wf = wave.open(filename+'.wav', 'wb')

wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT)) #width=2 ; 16bit
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()

ということで、めでたくWindows10でも音声など音を拾えることとなりました。


③ちょっと音声アプリ

参考に面白い例があったので、応用して以下のアプリを作ってみました。

※あくまでここではFFTやWavelet変換は使わないということで。。

以下のアプリは、音声を入力したと同時に出力するアプリです。

そして、入力から出力の間に、ここではだんだん音が大きくなるようにしています。

このアプリを動かすと最初は単に音が大きくなるが、途中から音の発生が遅れだし、かつ音が割れだして、最後はエイリアンの消滅のような壊れた音で消えます。。。

※print(s)⇒time.sleep(s/10000)とかにするとさらに遊べます。。

# -*- coding:utf-8 -*-

import pyaudio

CHUNK=1024
RATE=44100
p=pyaudio.PyAudio()

stream=p.open( format = pyaudio.paInt16,
channels = 1,
rate = RATE,
frames_per_buffer = CHUNK,
input = True,
output = True) # inputとoutputを同時にTrueにする

def audio_trans(input,s):
print(s)
ret=input*int(s/100)
return ret

s=1
while stream.is_active():
input = stream.read(CHUNK)
s += 1
input = audio_trans(input,s)
output = stream.write(input)

stream.stop_stream()
stream.close()
p.terminate()
print( "Stop Streaming")


まとめ

・Windows10で音声入力環境を構築した

・パラメータの意味が判明した

・ちょっとしたアプリを作って遊んでみた

・リアルタイムなFFT,STFT、そしてwavelet変換に一歩近づいた