如何绘制一个wav文件

时间:2013-09-04 22:52:16

标签: python audio matplotlib

我刚刚读了一个带有scipy的wav文件,现在我想使用matplotlib制作文件的图,在“y scale”上我希望看​​到aplitude和“x scale”我希望看到帧数! 任何帮助我该怎么办? 谢谢!

from scipy.io.wavfile import read
import numpy as np
from numpy import*
import matplotlib.pyplot as plt
a=read("C:/Users/Martinez/Desktop/impulso.wav")
print a

8 个答案:

答案 0 :(得分:55)

您可以调用wave lib来读取音频文件。

要绘制波形,请使用matplotlib中的“plot”功能

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


#If Stereo
if spf.getnchannels() == 2:
    print 'Just mono files'
    sys.exit(0)

plt.figure(1)
plt.title('Signal Wave...')
plt.plot(signal)
plt.show()

您将拥有类似:enter image description here

的内容

要以秒为单位绘制x轴,你需要获得帧率并除以信号的大小,你可以使用numpy的linspace函数创建一个与音频文件大小线性间隔的时间向量,最后你可以再次使用情节,如plt.plot(Time,signal)

import matplotlib.pyplot as plt
import numpy as np
import wave
import sys


spf = wave.open('Animal_cut.wav','r')

#Extract Raw Audio from Wav File
signal = spf.readframes(-1)
signal = np.fromstring(signal, 'Int16')
fs = spf.getframerate()

#If Stereo
if spf.getnchannels() == 2:
    print 'Just mono files'
    sys.exit(0)


Time=np.linspace(0, len(signal)/fs, num=len(signal))

plt.figure(1)
plt.title('Signal Wave...')
plt.plot(Time,signal)
plt.show()

以秒为单位的新绘图x轴:

enter image description here

答案 1 :(得分:16)

或者,如果您想使用SciPy,您还可以执行以下操作:

from scipy.io.wavfile import read
import matplotlib.pyplot as plt

# read audio samples
input_data = read("Sample.wav")
audio = input_data[1]
# plot the first 1024 samples
plt.plot(audio[0:1024])
# label the axes
plt.ylabel("Amplitude")
plt.xlabel("Time")
# set the title  
plt.title("Sample Wav")
# display the plot
plt.show()

答案 2 :(得分:7)

根据@ederwander的答案,这里还有一个版本也可以处理立体声输入

import matplotlib.pyplot as plt
import numpy as np
import wave

file = 'test.wav'

with wave.open(file,'r') as wav_file:
    #Extract Raw Audio from Wav File
    signal = wav_file.readframes(-1)
    signal = np.fromstring(signal, 'Int16')

    #Split the data into channels 
    channels = [[] for channel in range(wav_file.getnchannels())]
    for index, datum in enumerate(signal):
        channels[index%len(channels)].append(datum)

    #Get time from indices
    fs = wav_file.getframerate()
    Time=np.linspace(0, len(signal)/len(channels)/fs, num=len(signal)/len(channels))

    #Plot
    plt.figure(1)
    plt.title('Signal Wave...')
    for channel in channels:
        plt.plot(Time,channel)
    plt.show()

enter image description here

答案 3 :(得分:3)

只是一个观察(我不能添加评论)。

您将收到以下消息:

  

DeprecationWarning:不推荐使用数字样式代码   导致将来出错。

不要将np.fromstring与二进制文件一起使用。它不是signal = np.fromstring(signal, 'Int16'),而是首选使用signal = np.frombuffer(signal, dtype='int16')

答案 4 :(得分:2)

这是绘制信号波文件和信号频谱的代码

import wave    
from scipy import signal    
import numpy as np    
import matplotlib.pyplot as plt    
signal_wave = wave.open('voice.wav', 'r')    
sample_frequency = 16000    
data = np.fromstring(signal_wave.readframes(sample_frequency), dtype=np.int16)    
sig = signal_wave.readframes(-1)    
sig = np.fromstring(sig, 'Int16')

用于wave文件

sig = sig[:]

对于wave文件的某些段

sig = sig[25000:32000]    
left, right = data[0::2], da[1::2]    
lf, rf = abs(np.fft.rfft(left)), abs(np.fft.rfft(right))

绘制信号波文件的波和频谱

plt.figure(1)    
a = plt.subplot(211)    
a.set_xlabel('time [s]')    
a.set_ylabel('sample value [-]')    
plt.plot(sig)    
c = plt.subplot(212)    
Pxx, freqs, bins, im = c.specgram(sig, NFFT=1024, Fs=16000, noverlap=900)    
c.set_xlabel('Time')    
c.set_ylabel('Frequency')    
plt.show()

wave signal and spectrogram of the signal

答案 5 :(得分:1)

这是处理单声道/立体声和8位/ 16位PCM的版本。

{{1}}

答案 6 :(得分:0)

我想我可以对此发表评论,但是在@ederwander和@TimSC的回答略有基础上,我想做些更精致的事情(如详细说明),并在美学上令人愉悦。下面的代码创建了我认为是立体声或单声道文件的非常不错的波形(我不需要标题,因此我只是将其注释掉,也不需要show方法-只需要保存图像文件)

这是渲染立体声音的示例: enter image description here

代码,以及我提到的区别:

1

答案 7 :(得分:0)

我想出了一个更灵活,更高效的解决方案:

  • 下采样用于每秒实现两次采样。这是通过计算每个窗口的绝对值的平均值来实现的。结果看起来像来自SoundCloud等流媒体网站的波形。
  • 支持多渠道(感谢@Alter)
  • 每个操作都使用Numpy,比循环遍历数组要好得多。
  • 文件被批量处理以支持非常大的文件。
import matplotlib.pyplot as plt
import numpy as np
import wave
import math

file = 'audiofile.wav'

with wave.open(file,'r') as wav_file:
    num_channels = wav_file.getnchannels()
    frame_rate = wav_file.getframerate()
    downsample = math.ceil(frame_rate * num_channels / 2) # Get two samples per second!

    process_chunk_size = 600000 - (600000 % frame_rate)

    signal = None
    waveform = np.array([])

    while signal is None or signal.size > 0:
        signal = np.frombuffer(wav_file.readframes(process_chunk_size), dtype='int16')

        # Take mean of absolute values per 0.5 seconds
        sub_waveform = np.nanmean(
            np.pad(np.absolute(signal), (0, ((downsample - (signal.size % downsample)) % downsample)), mode='constant', constant_values=np.NaN).reshape(-1, downsample),
            axis=1
        )

        waveform = np.concatenate((waveform, sub_waveform))

    #Plot
    plt.figure(1)
    plt.title('Waveform')
    plt.plot(waveform)
    plt.show()