2017-02-28 69 views
0

有谁知道我怎样才能将声音文件分割成帧,然后可以将其转换为numpy阵列,详细说明帧中特定的声音频率?从声音文件中获取帧

例如,使用cv2,我可以将电影剪辑分割成多个帧,然后将其存储为图像库。这段代码很好地完成了这项工作,以至于我可以很容易地获得每幅图像的颜色直方图。

filepath1 = input('Please enter the filepath for where the frames should be saved: ') 

name = input('Please enter the name of the clip: ') 

ret, frame = clip.read() 
count = 0 
ret == True 
while ret: 
    ret, frame = clip.read() 
    cv2.imwrite(os.path.join(filepath1,name+'%d.png'%count), frame) 
    count += 1 

但我似乎无法为声音文件找到任何相当简单的东西;有没有人有任何建议如何(或如果)它可以完成?

+0

只是可以肯定 - 你** **不希望从一个声音文件创建图像的序列,对不对? – kazemakase

+0

呃,是的。因为如果我从一个声音文件中查找一系列图像,我会遇到比这里发布的更大的问题。我只是通过类比来使用电影的例子;我想要一个相当于电影画面的声音文件。 – Lodore66

回答

1

严格来说,电影帧的声音文件相当于音频样本。这只是每个频道的一个价值,所以我不确定这是否是您真正想要的。我最想要达到的目标是分析文件频率内容随时间的变化。可能你想看看spectrogram?在这种情况下,从www.frank-zalkow.de获取的以下脚本可能正是您想要的,或者至少为您提供一些如何开始的想法。 enter image description here

#!/usr/bin/env python 
#coding: utf-8 
""" This work is licensed under a Creative Commons Attribution 3.0 Unported License. 
    Frank Zalkow, 2012-2013 """ 

import numpy as np 
from matplotlib import pyplot as plt 
import scipy.io.wavfile as wav 
from numpy.lib import stride_tricks 

""" short time fourier transform of audio signal """ 
def stft(sig, frameSize, overlapFac=0.5, window=np.hanning): 
    win = window(frameSize) 
    hopSize = int(frameSize - np.floor(overlapFac * frameSize)) 

    # zeros at beginning (thus center of 1st window should be for sample nr. 0) 
    samples = np.append(np.zeros(np.floor(frameSize/2.0)), sig)  
    # cols for windowing 
    cols = np.ceil((len(samples) - frameSize)/float(hopSize)) + 1 
    # zeros at end (thus samples can be fully covered by frames) 
    samples = np.append(samples, np.zeros(frameSize)) 

    frames = stride_tricks.as_strided(samples, shape=(cols, frameSize), strides=(samples.strides[0]*hopSize, samples.strides[0])).copy() 
    frames *= win 

    return np.fft.rfft(frames)  

""" scale frequency axis logarithmically """  
def logscale_spec(spec, sr=44100, factor=20.): 
    timebins, freqbins = np.shape(spec) 

    scale = np.linspace(0, 1, freqbins) ** factor 
    scale *= (freqbins-1)/max(scale) 
    scale = np.unique(np.round(scale)) 

    # create spectrogram with new freq bins 
    newspec = np.complex128(np.zeros([timebins, len(scale)])) 
    for i in range(0, len(scale)): 
     if i == len(scale)-1: 
      newspec[:,i] = np.sum(spec[:,scale[i]:], axis=1) 
     else:   
      newspec[:,i] = np.sum(spec[:,scale[i]:scale[i+1]], axis=1) 

    # list center freq of bins 
    allfreqs = np.abs(np.fft.fftfreq(freqbins*2, 1./sr)[:freqbins+1]) 
    freqs = [] 
    for i in range(0, len(scale)): 
     if i == len(scale)-1: 
      freqs += [np.mean(allfreqs[scale[i]:])] 
     else: 
      freqs += [np.mean(allfreqs[scale[i]:scale[i+1]])] 

    return newspec, freqs 

""" plot spectrogram""" 
def plotstft(audiopath, binsize=2**10, plotpath=None, colormap="jet"): 
    samplerate, samples = wav.read(audiopath) 
    s = stft(samples, binsize) 

    sshow, freq = logscale_spec(s, factor=1.0, sr=samplerate) 
    ims = 20.*np.log10(np.abs(sshow)/10e-6) # amplitude to decibel 

    timebins, freqbins = np.shape(ims) 

    plt.figure(figsize=(15, 7.5)) 
    plt.imshow(np.transpose(ims), origin="lower", aspect="auto", cmap=colormap, interpolation="none") 
    plt.colorbar() 

    plt.xlabel("time (s)") 
    plt.ylabel("frequency (hz)") 
    plt.xlim([0, timebins-1]) 
    plt.ylim([0, freqbins]) 

    xlocs = np.float32(np.linspace(0, timebins-1, 5)) 
    plt.xticks(xlocs, ["%.02f" % l for l in ((xlocs*len(samples)/timebins)+(0.5*binsize))/samplerate]) 
    ylocs = np.int16(np.round(np.linspace(0, freqbins-1, 10))) 
    plt.yticks(ylocs, ["%.02f" % freq[i] for i in ylocs]) 

    if plotpath: 
     plt.savefig(plotpath, bbox_inches="tight") 
    else: 
     plt.show() 

    plt.clf() 

plotstft("my_audio_file.wav") 
+1

但是,请注意,频谱图仅适用于较长的音频记录,但不适用于单一时间索引。 OP可能想要做的是为每个帧提取一小段音频,然后对其进行FFT,从而得到该帧所产生的频谱。然后可以绘制频谱或将其保存到文件中。这[博客文章](http://www.cbcity.de/die-fft-mit-python-einfach-erklaert)描述了这项任务所需要的大部分内容(不介意德语的第一段)。 – Schmuddi

+1

@Schmuddi这是正确的。 *为每一帧提取一小段音频,然后对其进行FFT处理,从而得到该帧所得到的频谱*正是在频谱图中发生的情况。基本上,所得图像中的每个柱是音频“拉伸”的FFT/PSD。 – kazemakase

+0

谢谢大家;所有这些答案都是有用的,并且都提供了有价值的(和互补的)做我感兴趣的方式。现在,最好开始与他们合作! – Lodore66