コードをコピーし、読者の開発環境で貼り付けてご使用ください。
目次
- 2-4 2音を鳴らすwavファイルを作る
- 2-6 平均律、純正律のドミソの和音を聞き比べる
- 2-7 周波数の近い2音を鳴らしてうなりを確認する
- 2-8 プッシュボタンを使わずに電話をかけられるか
- 2-10 wavファイルのパラメータを読み取る
- 2-11 matplotlibモジュールでグラフを描く
- 3-1 wavファイルで、サウンドデータの符号を一斉に反転する
- 3-2-1 クリッピングされたデータでグラフを描く
- 3ー2-2 wavファイルでクリッピングする
- 3-3 逆再生する、ドレミファソラシドを鳴らす
- 3-4 変声機の原理を確認する
- 4-5 SciPyのFFT、IFFTを使ったわかりやすい例(1)
- 4-6 SciPyのFFT、IFFTを使ったわかりやすい例(2)
- 4-7 SciPyのFFT、IFFTを使ったわかりやすい例(3)
- 4-8 SciPyのFFT、IFFTを使ったわかりやすい例(4)
- 5-1 ノイズ入りのサウンドからノイズを消す
- 5-2 ノイズ入りの信号から周波数成分を見つける
- 5-3 肉声を電話の声に変換する
- 5ー4 FFTは信用できるのか
- 5-5 Pythonでリアルタイムに動くグラフを描く
- 5-6 変化する周波数成分を表示する
- 6-1 離散フーリエ係数の値を変える際の注意点
- 6-2 最も基本的なイコライザを作る
2-4 2音を鳴らすwavファイルを作る
#================== #waveファイルを作る。左は440Hz、右は700Hzで10秒間。 # import sys import wave import numpy as np import datetime dt = datetime.datetime.now() print('▼▼▼▼ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) pi = np.pi fs = 44100 #サンプリング周波数 s = 10 #10秒の長さのwaveファイルを作る #s秒分のサウンドデータを作るには、fs*sフレームが必要。 N = fs * s #フレーム数(左右で1フレーム) t = np.arange(0, s, 1/fs) #横軸 #sin(2π*□*t) の周波数は□の部分。16ビットで録音するので、 #-32768~32767がデータの範囲。だから-15000~15000の範囲の #大きさの音を作ることにした。 ldata = 15000 * np.sin(2*pi*440*t) #440Hz rdata = 15000 * np.sin(2*pi*700*t) #700Hz sounddata = np.zeros(N * 2, dtype= "int16") #左右のデータ分が必要 sounddata[0::2] = ldata sounddata[1::2] = rdata writewave = wave.Wave_write("keshitene.wav") #保存先ファイル #setparamの引数は #(nchannels, sampwidth, framerate, nframes, comptype, compname) #先頭から順にステレオ、サンプルのサイズ2バイト、 #サンプリング周波数fs、フレーム数N。 writewave.setparams((2, 2, fs, N, 'NONE', 'NONE')) writewave.writeframes(sounddata) #編集したサウンドデータを保存 writewave.close() dt = datetime.datetime.now() print('▲▲▲▲ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) sys.exit() #==================
2-6 平均律、純正律のドミソの和音を聞き比べる
#================== #wavファイルを作る。ドミソの和音。 # import sys import numpy as np import wave pi = np.pi fs = 22050 #サンプリング周波数 s = 20 #20秒の長さのwaveファイルを作る #s秒分のサウンドデータを作るには、fs*sフレームが必要。 N = fs * s #フレーム数 t = np.arange(0, s, 1/fs) #横軸 #sin(2π*□*t) の周波数は□の部分。16ビットで録音するので、 #-32768~32767がデータの範囲であることに注意。 #この範囲の外に出ると音が潰れる。 do = 523.3 #ドの音の周波数 r12 = 2 ** (1/12) #2の12乗根(≒1.059463094) #-------------- # A # #純正律でドミソ #ldata = 10000 * np.sin(2*pi*do*t) + 10000 * np.sin(2*pi*do*5/4*t) #rdata = 10000 * np.sin(2*pi*do*3/2*t) #-------------- # B # #平均律でドミソ ldata = 10000 * np.sin(2*pi*do*t) + 10000 * np.sin(2*pi*do*(r12**4)*t) rdata = 10000 * np.sin(2*pi*do*(r12**7)*t) #-------------- sounddata = np.zeros(N * 2, dtype= "int16") #左右のデータ分が必要 sounddata[0::2] = ldata sounddata[1::2] = rdata writewave = wave.Wave_write("keshitene.wav") #保存先ファイル #setparamの引数は #(nchannels, sampwidth, framerate, nframes, comptype, compname) #先頭から順にステレオ、サンプルのサイズ2バイト、 #サンプリング周波数fs、フレーム数N。 writewave.setparams((2, 2, fs, N, 'NONE', 'NONE')) writewave.writeframes(sounddata) #編集したサウンドデータを保存 writewave.close() sys.exit() #==================
2-7 周波数の近い2音を鳴らしてうなりを確認する
#================== import sys import numpy as np import wave pi = np.pi fs = 22050 #サンプリング周波数 s = 20 #20秒の長さのwavファイルを作る #s秒分のサウンドデータを作るには、fs*sフレームが必要。 N = fs * s #フレーム数 t = np.arange(0, s, 1/fs) #横軸 #sin(2π*□*t) の周波数は□の部分。16ビットで録音するので、 #-32768~32767がデータの範囲であることに注意。 #この範囲の外に出ると音が潰れる。 do = 523.3 #ドの音の周波数 r12 = 2 ** (1/12) #2の12乗根 #-------------- ldata = 15000 * np.sin(2*pi*do*5/4*t) #左スピーカー。純正律でミ rdata = 15000 * np.sin(2*pi*do*(r12**4)*t) #右スピーカー。平均律でミ #-------------- sounddata = np.zeros(N * 2, dtype= "int16") #左右のデータ分が必要 sounddata[0::2] = ldata sounddata[1::2] = rdata writewave = wave.Wave_write("keshitene.wav") #保存先ファイル #setparamの引数は #(nchannels, sampwidth, framerate, nframes, comptype, compname) #先頭から順にステレオ、サンプルのサイズ2バイト、 #サンプリング周波数fs、フレーム数N。 writewave.setparams((2, 2, fs, N, 'NONE', 'NONE')) writewave.writeframes(sounddata) #編集したサウンドデータを保存 writewave.close() sys.exit() #==================
2-8 プッシュボタンを使わずに電話をかけられるか
#================== #wavファイルを作る。1をプッシュ # import sys import numpy as np import wave pi = np.pi fs = 22050 #サンプリング周波数 s = 20 #20秒の長さのwavファイルを作る #s秒分のサウンドデータを作るには、fs*sフレームが必要。 N = fs * s #フレーム数 t = np.arange(0, s, 1/fs) #横軸 #sin(2π*□*t) の周波数は□の部分。16ビットで録音するので、 #-32768~32767がデータの範囲であることに注意。 #この範囲の外に出ると音が潰れる。 #---------------------- #1……697Hz、1209Hz #7……852Hz、1209Hz # #697の部分を852に書き換えると「7」になる ldata = 15000 * np.sin(2*pi*697*t) rdata = 15000 * np.sin(2*pi*1209*t) #1209は1,7で共通 #---------------------- sounddata = np.zeros(N * 2, dtype= "int16") #左右のデータ分が必要 sounddata[0::2] = ldata sounddata[1::2] = rdata writewave = wave.Wave_write("keshitene.wav") #保存先ファイル #setparamの引数は #(nchannels, sampwidth, framerate, nframes, comptype, compname) #先頭から順にステレオ、サンプルのサイズ2バイト、 #サンプリング周波数fs、フレーム数N。 writewave.setparams((2, 2, fs, N, 'NONE', 'NONE')) writewave.writeframes(sounddata) #編集したサウンドデータを保存 writewave.close() sys.exit() #==================
2-10 wavファイルのパラメータを読み取る
#================== import sys import datetime import wave dt = datetime.datetime.now() print('▼▼▼▼ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) wavefile= wave.open("C:\\Users\\xxxx\\Desktop\\sound\\'yyyy.wav","rb") print('■parameter = ', wavefile.getparams()) print('■framerate = ', wavefile.getframerate()) wavefile.close() dt = datetime.datetime.now() print('▲▲▲▲ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) sys.exit() #==================
2-11 matplotlibモジュールでグラフを描く
1本目
#================== #グラフを描画する import numpy as np import matplotlib.pyplot as plt t = np.arange(0, 1, 0.2) y = t * t plt.plot(y) plt.show() #==================
2本目
#================== import numpy as np import matplotlib.pyplot as plt t = np.arange(0, 1, 0.2) y = t * t plt.plot(t, y) plt.show() #==================
3本目
#================== import numpy as np import matplotlib.pyplot as plt pi = np.pi #円周率、π N = 100 #1秒でデータ100個 t = np.arange(0, 1, 1/N) #時刻0以上1秒未満、1/N秒刻みの時刻の配列 #A y = np.sin(2*pi*4*t) #周波数は4Hz #B #y = np.sin(2*pi*4*t)+2*np.sin(2*pi*10*t) #周波数は4Hz,10Hz plt.plot(t, y) #波形を描画 plt.show() #==================
3-1 wavファイルで、サウンドデータの符号を一斉に反転する
#================== import sys import numpy as np import wave wavefile = wave.open("BGM.wav", "rb") buf = wavefile.readframes(wavefile.getnframes())#サウンドデータ部分の読み取り buf = np.frombuffer(buf, dtype= "int16")#16bit符号付き整数に変換 params = wavefile.getparams() wavefile.close() print(params) if params.sampwidth != 2: sys.exit() #16ビットで記録していなければ終了 sounddata = buf.copy() #サウンドデータの操作用バッファ print(sounddata) sounddata = -sounddata #サウンドデータの符号を一斉に反転 print(sounddata) #サウンドデータを見てみる writewave = wave.Wave_write("keshitene.wav") #保存先ファイル writewave.setparams(wavefile.getparams()) #保存先にパラメータをセット writewave.writeframes(sounddata) #編集したサウンドデータを保存 writewave.close() sys.exit() #==================
3-2-1 クリッピングされたデータでグラフを描く
#================== import numpy as np import matplotlib.pyplot as plt pi = np.pi #円周率、π N = 1000 #1秒でデータ1000個 t = np.arange(0, 1, 1/N) #0以上1秒未満、1/N秒刻みの時刻の配列 y = np.sin(2*pi*2*t) #周波数は2Hz y[y < -0.8] = -0.8 y[y > 0.8] = 0.8 plt.ylim(-1, 1) plt.plot(t, y) #波形を描画 plt.show() #==================
3ー2-2 wavファイルでクリッピングする
#================== #クリッピング # import sys import wave import numpy as np import datetime #------------------------------------------------- dt = datetime.datetime.now() print('▼▼▼▼ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) wavefile = wave.open("C:\\Users\\xxxx\\Desktop\\BGM.wav","rb") params = wavefile.getparams() if params.sampwidth != 2: wavefile.close() sys.exit() #16ビットで記録していなければ終了 nframes = params.nframes #フレーム数の取得 buf = wavefile.readframes(nframes) #サウンドデータの読み取り buf = np.frombuffer(buf, dtype= "int16") #16bit符号付き整数に変換 wavefile.close() bufcopy = buf.copy() lim = 1000 bufcopy[bufcopy > lim] = lim bufcopy[bufcopy < -lim] = -lim writewave = wave.Wave_write("C:\\Users\\xxxx\\Desktop\\keshitene.wav") writewave.setparams(params) #元のwavファイルと同じパラメータをセット writewave.writeframes(bufcopy) #編集したサウンドデータを保存 writewave.close() dt = datetime.datetime.now() print('▲▲▲▲ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) sys.exit() #==================
3-3 逆再生する、ドレミファソラシドを鳴らす
逆再生する
#================== #逆再生 # import sys import wave import numpy as np import datetime dt = datetime.datetime.now() print('▼▼▼▼ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) wavefile = wave.open("C:\\Users\\xxxx\\Desktop\\keshitene.wav","rb") params = wavefile.getparams() nframes = params.nframes #フレーム数の取得 if (params.sampwidth != 2): wavefile.close() sys.exit() #16ビットで記録していなければ終了 buf = wavefile.readframes(nframes) #サウンドデータの読み取り buf = np.frombuffer(buf, dtype= "int16") #16bit符号付き整数に変換 wavefile.close() buf1 = np.zeros(buf.size, dtype = "int16") for i in range(buf.size): #bufの内容を逆転してbuf1へ格納 buf1[i] = buf[buf.size - i - 1] writewave= wave.Wave_write("C:\\Users\\xxxx\\Desktop\\keshitene.wav") writewave.setparams(params) writewave.writeframes(buf1) #編集したサウンドデータを保存 writewave.close() # dt = datetime.datetime.now() print('▲▲▲▲ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) sys.exit() #==================
ドレミファソラシドを鳴らす
#================== #wavファイルを作る。ドレミファソラシド # import sys import numpy as np import wave import datetime dt = datetime.datetime.now() print('▼▼▼▼ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) pi = np.pi fs = 22050 #サンプリング周波数 s = 0.5 #s秒分のサウンドデータを作るには、fs*sフレームが必要。 N = int(fs * s) #フレーム数 t = np.arange(0, s, 1/fs) #横軸 do = 523.3 #ドの音の周波数 x = do r12 = 2 ** (1/12) #2の12乗根(≒1.059463094) #-------------- #平均律でドレミファソラシド ldata = 15000 * np.sin(2*pi*x*t) #ド x = x * r12 * r12 ldata = np.concatenate([ldata, 15000 * np.sin(2*pi*x*t)]) #レ x = x * r12 * r12 ldata = np.concatenate([ldata, 15000 * np.sin(2*pi*x*t)]) #ミ x = x * r12 ldata = np.concatenate([ldata, 15000 * np.sin(2*pi*x*t)]) #ファ x = x * r12 * r12 ldata = np.concatenate([ldata, 15000 * np.sin(2*pi*x*t)]) #ソ x = x * r12 * r12 ldata = np.concatenate([ldata, 15000 * np.sin(2*pi*x*t)]) #ラ x = x * r12 * r12 ldata = np.concatenate([ldata, 15000 * np.sin(2*pi*x*t)]) #シ x = x * r12 ldata = np.concatenate([ldata, 15000 * np.sin(2*pi*x*t)]) #ド rdata = ldata sounddata = np.zeros(int(N*2*8), dtype= "int16") sounddata[0::2] = ldata sounddata[1::2] = rdata writewave= wave.Wave_write("C:\\Users\\xxxx\\Desktop\\keshitene.wav") #保存先ファイル #setparamの引数は #(nchannels, sampwidth, framerate, nframes, comptype, compname) #先頭から順にステレオ、サンプルのサイズ2バイト、 #サンプリング周波数fs、フレーム数N。 writewave.setparams((2, 2, fs, N, 'NONE', 'NONE')) writewave.writeframes(sounddata) #編集したサウンドデータを保存 writewave.close() dt = datetime.datetime.now() print('▲▲▲▲ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) sys.exit() #==================
3-4 変声機の原理を確認する
#================== #左のスピーカーからA-Bが流れ、右から Bが流れるwavファイル import sys import numpy as np import scipy as sp from scipy.fftpack import fft import wave import datetime dt = datetime.datetime.now() print('▼▼▼▼ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) #音楽A wavefile = wave.open("C:\\Users\\xxxx\\Desktop\\音楽A.wav","rb") #こちらの方が長い曲 params = wavefile.getparams() if (params.sampwidth != 2) or (params.nchannels != 2): wavefile.close() sys.exit() #16ビットで記録していないか、ステレオでなければ終了 #サウンドデータ部分の読み取り buf = wavefile.readframes(wavefile.getnframes()) buf = np.frombuffer(buf, dtype= "int16")#16bit符号付き整数に変換 print(wavefile.getparams()) wavefile.close() sdata = buf.copy() ldata = sdata[0::2] #左のデータ rdata = sdata[1::2] #右のデータ #音楽B #こちらの方が短い曲 wavefile1 = wave.open("C:\\Users\\xxxx\\Desktop\\音楽B.wav","rb") params = wavefile1.getparams() if (params.sampwidth != 2) or (params.nchannels != 2): wavefile1.close() sys.exit() #16ビットで記録していないか、ステレオでなければ終了 #サウンドデータ部分の読み取り buf = wavefile1.readframes(wavefile1.getnframes()) buf = np.frombuffer(buf, dtype= "int16")#16bit符号付き整数に変換 print(wavefile1.getparams()) wavefile1.close() sdata1 = buf.copy() ldata1 = sdata1[0::2] #左のデータ rdata1 = sdata1[1::2] #右のデータ soundLen = rdata1.size #短い方の曲の長さ #2つの曲(A,B)ともステレオの右のデータだけを使う #rdataにはA-B、ldataにはBを入れる rdata[:soundLen] = rdata[:soundLen]//2 - rdata1//2 #A-B を入れる ldata[:soundLen] = rdata1//2 #B を入れる sdata[0::2] = ldata sdata[1::2] = rdata writewave = wave.Wave_write("C:\\Users\\xxxx\\Desktop\\keshitene.wav") writewave.setparams(wavefile.getparams()) #保存先にパラメータをセット writewave.writeframes(sdata) #編集したサウンドデータを保存 writewave.close() dt = datetime.datetime.now() print('▲▲▲▲ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) sys.exit() #==================
4-5 SciPyのFFT、IFFTを使ったわかりやすい例(1)
#================== import numpy as np import scipy as sp from scipy.fftpack import fft import matplotlib.pyplot as plt pi = np.pi fs = 600 #サンプリング周波数 N = 200 #サンプル数 t = np.arange(0, N/fs, 1/fs) #1/fs秒刻みの時刻の配列 y = np.sin(2*pi*30*t)+2*np.sin(2*pi*45*t) #周波数は30Hz,45Hz plt.ylim(-4, 4) #描画するy軸の範囲をセット plt.plot(t, y) #元の波形を描画 plt.show() #yf[k]には第k次高調波のフーリエ係数が入る yf = sp.fftpack.fft(y[:N]) plt.plot(np.abs(yf)) #含まれる周波数成分を描画 plt.show() yf[10] = 0 #第10次高調波をカット yf[N-10] = 0 #第10次高調波をカット yif = sp.fftpack.ifft(yf[:N]).real plt.ylim(-4, 4) plt.plot(t, yif) plt.show() #==================
4-6 SciPyのFFT、IFFTを使ったわかりやすい例(2)
#================== import numpy as np import scipy as sp from scipy.fftpack import fft import matplotlib.pyplot as plt # fs = 600 t = np.arange(0, 6, 1/fs) y= np.sin(2*np.pi*50*t)+2*np.sin(2*np.pi*80*t)+3*np.sin(2*np.pi*100*t) yf = sp.fftpack.fft(y[:300]) plt.plot(np.abs(yf)) plt.show() #==================
4-7 SciPyのFFT、IFFTを使ったわかりやすい例(3)
#================== import numpy as np import scipy as sp from scipy.fftpack import fft import matplotlib.pyplot as plt pi = np.pi fs = 100 #サンプリング周波数 N = fs #サンプル数はfsとする t = np.arange(0, 1, 1/fs) #1/fs秒刻みの時刻の配列。基本周期T = 1。 y = np.sin(2*pi*4*t)+2*np.sin(2*pi*10*t) #周波数は4Hz,10Hz plt.plot(t, y) #元の波形を描画 plt.show() #yf[k]には第k次高調波のフーリエ係数が入る yf = sp.fftpack.fft(y[:N]) plt.plot(np.abs(yf)) #含まれる周波数成分を描画 plt.show() yif = sp.fftpack.ifft(yf[:N]).real #ifftで元の波形に戻してみる plt.plot(t, yif) #戻ったか、確認。最初と同じグラフのはず plt.show() yf[10] = 0 #第10次高調波をカット yf[N-10] = 0 #第10次高調波をカット #t = np.arange(0, 1, 1/fs) #1/fs秒刻みの時刻の配列。基本周期T = 1。 yif = sp.fftpack.ifft(yf[:N]).real plt.plot(t, yif) plt.show() yf1 = sp.fftpack.fft(yif[:N]) #10次はカットしてある plt.plot(np.abs(yf1)) #周波数成分を調べる plt.show() #==================
4-8 SciPyのFFT、IFFTを使ったわかりやすい例(4)
#================== import numpy as np import scipy as sp from scipy.fftpack import fft import matplotlib.pyplot as plt pi = np.pi #周期T = 3秒。基本周波数=1/3Hz。 fs = 40 #サンプリング周波数。データ1個で1/40秒。 N = 120 #データ数は3/(1/40)=120 #tは1/40秒刻みの時刻の配列。1/40秒ごとに3秒間、サンプリング t = np.arange(0, 3, 1/40) tt = np.arange(0, 120) #要素は0から1刻みで119まで y = np.sin(2*pi*4*t)+2*np.sin(2*pi*10*t) #周波数は4Hz,10Hz plt.plot(t, y) #元の波形を描画 plt.show() #yf[k]には第k次高調波のフーリエ係数が入る yf = sp.fftpack.fft(y[:N]) #配列 tt には0,1,2,……, 119 が入っている #yf[k]には第k次高調波(周波数はk/3 Hz)の成分が入るので、 #横軸の目盛りを= tt / 3.0 とすれば周波数が表示される plt.plot(tt / 3.0, np.abs(yf)) #含まれる周波数成分を描画 plt.show() #==================
5-1 ノイズ入りのサウンドからノイズを消す
1本目
#================== #ノイズ入りのwavファイルを作る。左は440Hz、右は700Hzで10秒間。 # import scipy as sp import sys import numpy as np import wave from scipy.fftpack import fft import matplotlib.pyplot as plt pi = np.pi fs = 44100 #サンプリング周波数 s = 10 #10秒の長さのwavファイルを作る #s秒分のサウンドデータを作るには、fs*sフレームが必要。 N = fs * s #フレーム数(左右ひと組で1フレーム) t = np.arange(0, s, 1/fs) #横軸の配列を作る #sin(2π*□*t) の周波数は□の部分。16ビットで録音するので、 #-32768~32767がデータの範囲。だから-15000~15000の範囲の #大きさの音を作ることにした。 # #440Hzの音+ノイズ ldata = 15000 * np.sin(2*pi*440*t) + 2500 *np.random.randn(t.size) #700Hzの音+ノイズ rdata = 15000 * np.sin(2*pi*700*t) + 2500 * np.random.randn(t.size) #配列のサイズは左、右のサイズの和 sounddata = np.zeros(N * 2, dtype = "int16") sounddata[0::2] = ldata sounddata[1::2] = rdata writewave = wave.Wave_write("keshitene.wav") #保存先ファイル #setparamの引数は #(nchannels, sampwidth, framerate, nframes, comptype, compname) #先頭から順にステレオ、サンプルのサイズ2バイト、 #サンプリング周波数fs、フレーム数N。 writewave.setparams((2, 2, fs, N, 'NONE', 'NONE')) writewave.writeframes(sounddata) #編集したサウンドデータを保存 writewave.close() sys.exit() #==================
2本目
#================== #ノイズ入りのwavファイルを作る。左は440Hz、右は700Hzで10秒間。 # import scipy as sp import sys import numpy as np import wave from scipy.fftpack import fft import matplotlib.pyplot as plt pi = np.pi fs = 44100 #サンプリング周波数 s = 10 #10秒の長さのwavファイルを作る #s秒分のサウンドデータを作るには、fs*sフレームが必要。 N = fs * s #フレーム数 t = np.arange(0, s, 1/fs) #横軸の配列を作る #sin(2π*□*t) の周波数は□の部分。16ビットで録音するので、 #-32768~32767がデータの範囲。だから-15000~15000の範囲の #大きさの音を作ることにした。 #440Hzの音+ノイズ ldata = 15000 * np.sin(2*pi*440*t) + 2500 *np.random.randn(t.size) #700Hzの音+ノイズ rdata = 15000 * np.sin(2*pi*700*t) + 2500 * np.random.randn(t.size) #■■■ yf = sp.fftpack.fft(ldata[:N]) plt.plot(abs(yf)) plt.show() #■■■ #配列のサイズは左、右のサイズの和 sounddata = np.zeros(N * 2, dtype = "int16") sounddata[0::2] = ldata sounddata[1::2] = rdata writewave = wave.Wave_write("keshitene.wav") #保存先ファイル #setparamの引数は #(nchannels, sampwidth, framerate, nframes, comptype, compname) #先頭から順にステレオ、サンプルのサイズ2バイト、 #サンプリング周波数fs、フレーム数N。 writewave.setparams((2, 2, fs, N, 'NONE', 'NONE')) writewave.writeframes(sounddata) #編集したサウンドデータを保存 writewave.close() sys.exit() #==================
3本目
#================== #ノイズ入りのwavファイルを作る。左は440Hz、右は700Hzで10秒間。 # import scipy as sp import sys import numpy as np import wave from scipy.fftpack import fft import matplotlib.pyplot as plt pi = np.pi fs = 44100 #サンプリング周波数 s = 10 #10秒の長さのwavファイルを作る #s秒分のサウンドデータを作るには、fs*sフレームが必要。 N = fs * s #フレーム数 t = np.arange(0, s, 1/fs) #横軸の配列を作る #sin(2π*□*t) の周波数は□の部分。16ビットで録音するので、 #-32768~32767がデータの範囲。だから-15000~15000の範囲の #大きさの音を作ることにした。 #440Hzの音+ノイズ ldata = 15000 * np.sin(2*pi*440*t) + 2500 *np.random.randn(t.size) #700Hzの音+ノイズ rdata = 15000 * np.sin(2*pi*700*t) + 2500 * np.random.randn(t.size) #■■■ yf = sp.fftpack.fft(ldata[:N]) yf[abs(yf) < 7500000] = 0 #yfの絶対値が750万未満のデータは0に ldata = sp.fftpack.ifft(yf[:N]).real yf = sp.fftpack.fft(rdata[:N]) yf[abs(yf) < 7500000] = 0 #yfの絶対値が750万未満のデータは0に rdata = sp.fftpack.ifft(yf[:N]).real #■■■ #配列のサイズは左、右のサイズの和 sounddata = np.zeros(N * 2, dtype = "int16") sounddata[0::2] = ldata sounddata[1::2] = rdata writewave = wave.Wave_write("keshitene.wav") #保存先ファイル #setparamの引数は #(nchannels, sampwidth, framerate, nframes, comptype, compname) #先頭から順にステレオ、サンプルのサイズ2バイト、 #サンプリング周波数fs、フレーム数N。 writewave.setparams((2, 2, fs, N, 'NONE', 'NONE')) writewave.writeframes(sounddata) #編集したサウンドデータを保存 writewave.close() sys.exit() #==================
5-2 ノイズ入りの信号から周波数成分を見つける
#================== import sys import numpy as np import scipy as sp from scipy.fftpack import fft import matplotlib.pyplot as plt pi = np.pi fs = 1000 #サンプリング周波数 N = fs * 4 #サンプル数 t = np.arange(0, 4, 1/fs) #1/fs秒刻みの時刻の配列(4秒間) #100Hz,440Hz の信号にノイズを混ぜる y=np.sin(2*pi*100*t)+1.5*np.sin(2*pi*440*t)+3* np.random.randn(t.size) plt.plot(t, y) #元の波形を描画 plt.show() #yf[k]には第k次高調波のフーリエ係数が入る yf = sp.fftpack.fft(y[:N]) #得られる最大の周波数成分は fs = 1000ヘルツ。 #つまりFFTの結果のグラフの右端は fs = 1000ヘルツの成分。 plt.plot(np.abs(yf)) #含まれる周波数成分を描画 plt.show() sys.exit() #==================
5-3 肉声を電話の声に変換する
#================== import sys import numpy as np import scipy as sp from scipy.fftpack import fft import wave N = 8192 #FFTするサイズ。2の13乗。 # #-------------------------------- #サウンドデータの高域成分をカットする関数 # #databuf: サウンドデータの入ったバッファ #num1: 第num1次高調波から第num2高調波までを残して消す def editsound(databuf, num1, num2): databuf1 = np.zeros(databuf.size) for i in range(int(databuf.size / N)): #databufの先頭から順にNデータずつ処理 databuf2 = databuf[N * i: N * (i+1)] #Nデータを取り出す yf = sp.fftpack.fft(databuf2) for j in range(1, num1): yf[j] = 0 #低周波成分を0に yf[N - j] = 0 for j in range(num2+1, int(N/2)): yf[j] = 0 #高周波成分を0に yf[N - j] = 0 #ifftの結果は複素数。もとが実データなので結果の虚数部分は0。 #コピー先は複素数の配列ではないので実数部分だけをコピーする。 databuf1[N * i: N * (i+1)] = sp.fftpack.ifft(yf).real return databuf1 #-------------------------------- #メインルーチン wavefile = wave.open("人の声.wav","rb") #サウンドデータ部分の読み取り buf = wavefile.readframes(wavefile.getnframes()) buf = np.frombuffer(buf, dtype= "int16") #16bit符号付き整数に変換 params = wavefile.getparams() wavefile.close() print(params) if (params.sampwidth != 2) or (params.nchannels != 2): sys.exit() #16ビットで記録していないか、ステレオでなければ終了 sounddata = buf.copy() #サウンドデータ用バッファ sounddata[0::2] = editsound(sounddata[0::2], 56, 631) #左の音を編集 sounddata[1::2] = editsound(sounddata[1::2], 56, 631) #右の音を編集 writewave = wave.Wave_write("電話の声.wav") #保存先ファイル名 writewave.setparams(wavefile.getparams()) #同じパラメータをセット writewave.writeframes(sounddata) #編集したデータをファイルへ保存 writewave.close() sys.exit() #==================
5ー4 FFTは信用できるのか
#================== import sys import numpy as np import scipy as sp from scipy.fftpack import fft import matplotlib.pyplot as plt print("▼") pi = np.pi fs = 200 #サンプリング周波数 N = 600 #サンプル数 t = np.arange(0, N/fs, 1/fs) #1/fs秒刻みの時刻の配列 y = np.sin(2*pi*40*t)+2*np.sin(2*pi*90*t) #yf[k]には第k次高調波のフーリエ係数が入る yf = sp.fftpack.fft(y[:N]) plt.plot(np.abs(yf)) #含まれる周波数成分を描画 plt.show() print("▲") sys.exit() #==================
5-5 Pythonでリアルタイムに動くグラフを描く
#================== #リアルタイムにグラフを描画 # import sys import numpy as np import matplotlib.pyplot as plt pi = np.pi t = np.arange(0, 3, 1/40) #横軸 for i in range(1,1000): plt.ylim(-5, 5) #y軸の最小値、最大値をセット y = 3*np.sin(2*pi*4*t+0.3*i) plt.plot(t, y) #波形を描画 plt.pause(0.1) #pyplot.show()では1回描画して止まってしまう plt.clf() #今描いたグラフを消す sys.exit() #==================
5-6 変化する周波数成分を表示する
#================== #リアルタイムに周波数成分を描画 # import sys import numpy as np import scipy as sp from scipy.fftpack import fft import matplotlib.pyplot as plt pi = np.pi N = 120 #データ数は3/(1/40)=120 # t は1/40秒刻み、0秒以上3秒未満の時刻の配列。 #周期T = 3秒。基本周波数=1/3Hz。サンプリング周波数は40Hz t = np.arange(0, 3, 1/40) for i in range(1,100): y = np.sin(2*pi*(1/3*30)*t) + np.sin(2*pi*(1/3*10 + 0.1*i)*t) yf = sp.fftpack.fft(y[:N]) #yf[k]には第k次高調波のフーリエ係数が入る plt.plot(np.abs(yf)) #含まれる周波数成分を描画 plt.pause(0.1) plt.clf() sys.exit() #==================
6-1 離散フーリエ係数の値を変える際の注意点
1本目
#================== import sys import numpy as np import scipy as sp from scipy.fftpack import fft y = [10, 20, 30, 40, 50, 60, 70, 80] yf = sp.fftpack.fft(y) #yf[k]には第k次高調波のフーリエ係数が入る for i in range(8): print("■yf", i, yf[i]) yif = sp.fftpack.ifft(yf) for i in range(8): print("■■yif", i, yif[i]) sys.exit() #==================
2本目
#================== import sys import numpy as np import scipy as sp from scipy.fftpack import fft y = [10, 20, 30, 40, 50, 60, 70, 80] yf = sp.fftpack.fft(y) #yf[k]には第k次高調波のフーリエ係数が入る for i in range(8): print("■yf", i, yf[i]) yf[1] = 3-4j yf[7] = 3+4j #yf[1]の共役複素数 yf[2] = 6j yf[6] = -6j #yf[2]の共役複素数 yif = sp.fftpack.ifft(yf) for i in range(8): print("■■yif", i, yif[i]) sys.exit() #==================
3本目
#================== import sys import numpy as np import scipy as sp from scipy.fftpack import fft y = [10, 20, 30, 40, 50, 60, 70, 80] yf = sp.fftpack.fft(y) #yf[k]には第k次高調波のフーリエ係数が入る for i in range(8): print("■yf", i, yf[i]) yf[1] = 3-4j yf[7] = 5 #yf[1]の共役複素数ではない yf[2] = 6j yf[6] = 1+3j #yf[2]の共役複素数ではない yif = sp.fftpack.ifft(yf) for i in range(8): print("■■yif", i, yif[i]) sys.exit() #==================
6-2 最も基本的なイコライザを作る
#================== import sys import numpy as np import scipy as sp from scipy.fftpack import fft import wave import datetime N = 22050 #FFTするサイズ #-------------------------------- #サウンドデータの、指定した周波数成分をrate倍する # #databuf: サウンドデータの入ったバッファ #num1~num2次高調波の成分をrate倍にする。maxはN/2-1 def editSound(databuf, num1, num2, rate): databuf1 = np.zeros(databuf.size) for i in range(int(databuf.size / N)): #Nデータずつ処理 yf = sp.fftpack.fft(databuf[N * i: N * (i+1)]) for j in range(num1, num2+1): yf[j] = yf[j] * rate #周波数成分をrate倍に yf[N - j] = yf[N - j] * rate #ifftの結果は複素数。もとが実データなので結果の虚数部分は0。 #だがコピー先は実数の配列ではないので実数部分だけをコピーする。 databuf1[N * i: N * (i+1)] = sp.fftpack.ifft(yf).real return databuf1 #-------------------------------- wavefile = wave.open("C:\\Users\\xxxx\\Desktop\\BGM.wav","rb") #サウンドデータ部分の読み取り buf = wavefile.readframes(wavefile.getnframes()) buf = np.frombuffer(buf, dtype= "int16") #16bit符号付き整数に変換 params = wavefile.getparams() wavefile.close() print(params) if (params.sampwidth != 2) or (params.nchannels != 2): sys.exit() #16ビットで記録していないか、ステレオでなければ終了 sounddata = buf.copy() #サウンドデータ用バッファ #高音を編集 sounddata[0::2] = editSound(sounddata[0::2], 500, 5000, 0) #左を編集 sounddata[1::2] = editSound(sounddata[1::2], 500, 5000, 0) #右を編集 #低音を編集 sounddata[0::2] = editSound(sounddata[0::2], 1, 499, 1.2) #左を編集 sounddata[1::2] = editSound(sounddata[1::2], 1, 499, 1.2) #右を編集 #保存先 writewave = wave.Wave_write("C:\\Users\\xxxx\\Desktop\\keshitene.wav") #保存先ファイルに元と同じパラメータをセット writewave.setparams(wavefile.getparams()) writewave.writeframes(sounddata) #編集したサウンドデータを保存 writewave.close() dt = datetime.datetime.now() print('▲▲▲▲ {}:{}:{}'.format(dt.hour, dt.minute, dt.second)) sys.exit() #==================