使用python过滤WAV文件 [英] Filtering a wav file using python

查看:159
本文介绍了使用python过滤WAV文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我最近成功构建了一个系统,该系统将完全使用python记录,绘制和播放音频wav文件.现在,我尝试在录制和开始绘制文件并将其输出到扬声器之间进行一些过滤和音频混合.但是,我不知道从哪里开始.现在,我要读取一个初始wav文件,应用一个低通滤波器,然后将新过滤的数据重新打包到一个新的wav文件中.这是我记录初始数据后用来绘制初始数据的代码.

So i recently successfully built a system which will record, plot, and playback an audio wav file entirely with python. Now, I'm trying to put some filtering and audio mixing in between the when i record and when i start plotting and outputting the file to the speakers. However, i have no idea where to start. Right now I'm to read in a the intial wav file, apply a low pass filter, and then re-pack the newly filtered data into a new wav file. Here is the code i used to plot the initial data once i recorded it.

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)

这是一些我用来生成单一音调的测试音频文件的代码:

And here is some code i used to generate a test audio file of a single tone:

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()

我不太确定如何应用所说的音频过滤器并重新包装它.您将提供的任何帮助和/或建议将不胜感激.

I'm not really sure how to apply said audio filter and repack it, though. Any help and/or advice you could offer would be greatly appreciated.

推荐答案

第一步:您需要哪种音频滤波器?

选择已过滤的频段

  • 低通滤波器:从音频信号中去除最高频率
  • >
  • 高通滤波器:从音频信号中去除最低频率
  • >
  • 带通滤波器:从音频信号中去除最高和最低频率
  • First step : What kind of audio filter do you need ?

    Choose the filtered band

    • Low-pass Filter : remove highest frequency from your audio signal
    • High-pass Filter : remove lowest frequencies from your audio signal
    • Band-pass Filter : remove both highest and lowest frequencies from your audio signal
    • 对于以下步骤,我假设您需要低通滤波器.

      For the following steps, i assume you need a Low-pass Filter.

      截止频率是您的信号将被衰减-3dB的频率.

      The Cutoff frequency is the frequency where your signal will be attenuated by -3dB.

      您的示例信号为440Hz,所以我们选择 400Hz的截止频率 .然后,低通400Hz滤波器会衰减440Hz信号(超过-3dB).

      Your example signal is 440Hz, so let's choose a Cutoff frequency of 400Hz. Then your 440Hz-signal is attenuated (more than -3dB), by the Low-pass 400Hz filter.

      根据其他stackoverflow答案

      滤波器设计超出了堆栈溢出的范围-这是DSP 问题,而不是编程问题.过滤器的设计涵盖了 DSP教科书-转到您的资料库.我喜欢Proakis和Manolakis' 数字信号处理. (Ifeachor和Jervis的数字信号 处理也不错.)

      Filter design is beyond the scope of Stack Overflow - that's a DSP problem, not a programming problem. Filter design is covered by any DSP textbook - go to your library. I like Proakis and Manolakis' Digital Signal Processing. (Ifeachor and Jervis' Digital Signal Processing isn't bad either.)

      举个简单的例子,我建议使用移动平均值过滤器(用于简单的低通滤波器).

      To go inside a simple example, I suggest to use a moving average filter (for a simple low-pass filter).

      请参见移动平均值

      从数学上讲,移动平均是卷积的一种,因此可以看作信号处理中使用的低通滤波器的一个例子

      Mathematically, a moving average is a type of convolution and so it can be viewed as an example of a low-pass filter used in signal processing

      此移动平均低通滤波器是基本的滤波器,非常易于使用和理解.

      This Moving average Low-pass Filter is a basic filter, and it is quite easy to use and to understand.

      移动平均值的参数是窗口长度.

      移动平均值窗口长度与这里

      The relationship between moving average window length and Cutoff frequency needs little bit mathematics and is explained here

      代码将是

      import math
      
      sampleRate = 11025.0 
      cutOffFrequency = 400.0
      freqRatio = cutOffFrequency / sampleRate
      
      N = int(math.sqrt(0.196201 + freqRatio**2) / freqRatio)
      

      因此,在此示例中,窗口长度将为 12

      So, in the example, the window length will be 12

      请参见关于如何在python中创建移动平均值的具体讨论

      来自 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)
      

      使用lfilter

      或者,按照 dpwilson 的建议,我们也可以使用lfilter

      Using lfilter

      Alternatively, as suggested by dpwilson, we can also use 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()
      

      这篇关于使用python过滤WAV文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆