2017-02-28 51 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