だから私は最近、完全にpythonでオーディオwavファイルを記録、プロット、再生するシステムを構築することに成功しました。今、私はいくつかのフィルタリングとオーディオのミキシングを、録音したときと、ファイルをプロットしてスピーカーに出力し始めたときの間に入れようとしています。ただし、どこから始めればよいかわかりません。ここで、最初のwavファイルを読み込み、ローパスフィルターを適用して、新しくフィルター処理されたデータを新しいwavファイルに再パックします。これは、記録した初期データをプロットするために使用したコードです。
import matplotlib.pyplot as plt
import numpy as np
import wave
import sys
spf = wave.open('wavfile.wav','r')
#Extract Raw Audio from Wav File
signal = spf.readframes(-1)
signal = np.fromstring(signal, 'Int16')
plt.figure(1)
plt.title('Signal Wave...')
plt.plot(signal)
そして、ここに私がシングルトーンのテストオーディオファイルを生成するために使用したいくつかのコードがあります:
import numpy as np
import wave
import struct
freq = 440.0
data_size = 40000
fname = "High_A.wav"
frate = 11025.0
amp = 64000.0
sine_list_x = []
for x in range(data_size):
sine_list_x.append(np.sin(2*np.pi*freq*(x/frate)))
wav_file = wave.open(fname, "w")
nchannels = 1
sampwidth = 2
framerate = int(frate)
nframes = data_size
comptype = "NONE"
compname = "not compressed"
wav_file.setparams((nchannels, sampwidth, framerate, nframes,
comptype, compname))
for s in sine_list_x:
wav_file.writeframes(struct.pack('h', int(s*amp/2)))
wav_file.close()
ただし、上記のオーディオフィルターを適用して再パックする方法はわかりません。あなたが提供できるどんな助けや助言も大いに感謝されます。
次の手順では、ローパスフィルターが必要であると想定しています。
カットオフ周波数 は、信号が-3dB減衰する周波数です。
例の信号は440Hzなので、 カットオフ周波数400Hzを選択します。次に、440Hz信号は、ローパス400Hzフィルターによって減衰されます(-3dB以上)。
この他のスタックオーバーフローの答え によると
フィルターの設計はスタックオーバーフローの範囲を超えています-これはDSPの問題であり、プログラミングの問題ではありません。フィルターの設計はDSPの教科書でカバーされています-ライブラリにアクセスしてください。私はProakisとManolakisのデジタル信号処理が好きです。 (IfeachorとJervisのデジタル信号処理も悪くありません。)
簡単な例に入るには、移動平均フィルター(簡単なローパスフィルターの場合)を使用することをお勧めします。
参照 移動平均
数学的には、移動平均は畳み込みの一種であるため、信号処理で使用されるローパスフィルターの例と見なすことができます。
この移動平均ローパスフィルターは基本的なフィルターであり、非常に使いやすく、理解しやすくなっています。
移動平均のパラメーターは、ウィンドウの長さです。
移動平均 ウィンドウの長さと カットオフ周波数 の間の関係は少し数学を必要とし、説明 ここ
コードは
import math
sampleRate = 11025.0
cutOffFrequency = 400.0
freqRatio = (cutOffFrequency/sampleRate)
N = int(math.sqrt(0.196196 + freqRatio**2)/freqRatio)
したがって、この例では、ウィンドウの長さは11になります。
Alleo からの解は
def running_mean(x, windowSize):
cumsum = numpy.cumsum(numpy.insert(x, 0, 0))
return (cumsum[windowSize:] - cumsum[:-windowSize]) / windowSize
filtered = running_mean(signal, N)
または、 dpwilson で提案されているように、lfilterを使用することもできます。
win = numpy.ones(N)
win *= 1.0/N
filtered = scipy.signal.lfilter(win, [1], signal).astype(channels.dtype)
import matplotlib.pyplot as plt
import numpy as np
import wave
import sys
import math
import contextlib
fname = 'test.wav'
outname = 'filtered.wav'
cutOffFrequency = 400.0
# from http://stackoverflow.com/questions/13728392/moving-average-or-running-mean
def running_mean(x, windowSize):
cumsum = np.cumsum(np.insert(x, 0, 0))
return (cumsum[windowSize:] - cumsum[:-windowSize]) / windowSize
# from http://stackoverflow.com/questions/2226853/interpreting-wav-data/2227174#2227174
def interpret_wav(raw_bytes, n_frames, n_channels, sample_width, interleaved = True):
if sample_width == 1:
dtype = np.uint8 # unsigned char
Elif sample_width == 2:
dtype = np.int16 # signed 2-byte short
else:
raise ValueError("Only supports 8 and 16 bit audio formats.")
channels = np.fromstring(raw_bytes, dtype=dtype)
if interleaved:
# channels are interleaved, i.e. sample N of channel M follows sample N of channel M-1 in raw data
channels.shape = (n_frames, n_channels)
channels = channels.T
else:
# channels are not interleaved. All samples from channel M occur before all samples from channel M-1
channels.shape = (n_channels, n_frames)
return channels
with contextlib.closing(wave.open(fname,'rb')) as spf:
sampleRate = spf.getframerate()
ampWidth = spf.getsampwidth()
nChannels = spf.getnchannels()
nFrames = spf.getnframes()
# Extract Raw Audio from multi-channel Wav File
signal = spf.readframes(nFrames*nChannels)
spf.close()
channels = interpret_wav(signal, nFrames, nChannels, ampWidth, True)
# get window size
# from http://dsp.stackexchange.com/questions/9966/what-is-the-cut-off-frequency-of-a-moving-average-filter
freqRatio = (cutOffFrequency/sampleRate)
N = int(math.sqrt(0.196196 + freqRatio**2)/freqRatio)
# Use moviung average (only on first channel)
filtered = running_mean(channels[0], N).astype(channels.dtype)
wav_file = wave.open(outname, "w")
wav_file.setparams((1, ampWidth, sampleRate, nFrames, spf.getcomptype(), spf.getcompname()))
wav_file.writeframes(filtered.tobytes('C'))
wav_file.close()
sox library
は静的ノイズ除去に使用できます。
私は this Gist を見つけました。これには例としていくつかの便利なコマンドがあります