2017-11-05 6 views
1

저는 파이썬에서 음악 파일을 업로드하고이 파일 (피아노)의 노트를 얻을 수있는 프로그램을 만들려고합니다. 내가 Spectrogram을 만들었는데 이제 어떻게 주파수를 얻을 수 있습니까? 어떻게하면 스펙트로 그램을 고칠 수 있습니까 (스펙트로 그램의 절반에서 거울 반사가 생깁니 까?). this과 같은 것이 필요합니다. Here은 코드입니다.파이썬에서 스펙트로 그램에서 노트 (빈도 및 시간)를 얻는 방법은 무엇입니까?

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("Sound/piano2.wav") 

답변

0

당신이 기술 한 오디오 필사적 인 문제는 음악 정보 검색 (MIR) 연구 커뮤니티에서 잘 알려진 문제입니다. 그것은 해결하기 쉬운 하나가 아닌 두 개의 측면으로 구성

  • 검출 될 수 의한 고조파의 발생과 음이 주로 (C 번호로 미끄러 져 있다는 사실 하드 종종 피치 주파수 검출 C) 대신 튜닝 불일치로 인한 것입니다.

  • 비트 감지 : 오디오 퍼포먼스는 종종 정확한 시간 내에 재생되지 않으므로 실제 온셋을 찾는 것이 까다로울 수 있습니다.

유망한 신규 접근법

는,이 문제를 해결하기 위해 예컨대 깊은 신경망을 사용하는 것이다 :

불랑제-완도 우 스키, N., Bengio, Y., & 빈센트, P. (2012). Modeling temporal dependencies in high-dimensional sequences: Application to polyphonic music generation and transcription. arXiv preprint arXiv : 1206.6392.

기타 정보 :

Poliner, G. E., 엘리스, D. P., EHMANN, A. F. 고메즈, E., 필립 스트레이, S., & 옹, B. (2007). 음악 오디오의 멜로디 녹음 : 접근 및 평가. IEEE Transactions on Audio, Speech, and Language Processing, 15 (4), 1247-1256.

관련 문제