2017-05-14 2 views
2

기타로 연주 된 B3 음의 피치를 감지하려고합니다. 오디오는 here입니다. 당신이 볼 수 있듯이 spectrogram단일 기타 음을위한 고조파 스펙트럼 파이톤

, 기본 피치는 B3 노트에 해당하는 250Hz에서 관한 것이라고 볼 수 있습니다 :

은 스펙트로 그램이다.

또한 고조파가 많아서 here에서 HPS를 사용하기로했습니다. 나는 피치를 검출하는이 코드를 사용하고 있습니다 :

def freq_from_hps(signal, fs): 
    """Estimate frequency using harmonic product spectrum 
    Low frequency noise piles up and overwhelms the desired peaks 
    """ 
    N = len(signal) 
    signal -= mean(signal) # Remove DC offset 

    # Compute Fourier transform of windowed signal 
    windowed = signal * kaiser(N, 100) 

    # Get spectrum 
    X = log(abs(rfft(windowed))) 

    # Downsample sum logs of spectra instead of multiplying 
    hps = copy(X) 
    for h in arange(2, 9): # TODO: choose a smarter upper limit 
     dec = decimate(X, h) 
     hps[:len(dec)] += dec 

    # Find the peak and interpolate to get a more accurate peak 
    i_peak = argmax(hps[:len(dec)]) 
    i_interp = parabolic(hps, i_peak)[0] 

    # Convert to equivalent frequency 
    return fs * i_interp/N # Hz 

내 샘플링 속도는 그러나 40000입니다 대신 250Hz에서 (B3 노트)에 가까운 결과, 내가 0.66Hz를 얻고을 얻는. 이것이 어떻게 가능한지?

같은 레포에서 자동 상관법을 사용해 보았지만 10000Hz와 같은 나쁜 결과가 나옵니다.

대답 덕분에 신호의 저주파수를 제거하기 위해 필터를 적용해야한다는 것을 이해합니다. 어떻게해야합니까? 이를 수행하는 방법이 여러 가지가 있으며 권장되는 방법은 무엇입니까?

상태 업데이트 : 대답에 의해 제안 된

하이 패스 필터가 작동된다. 내 오디오 신호에 응답 기능을 적용하면 약 245Hz가 올바르게 표시됩니다. 그러나 전체 신호를 필터링하고 싶습니다. 노트가 신호 중간에 있거나 신호에 두 개 이상의 노트가 포함되어있을 수 있습니다 (솔루션의 시작 감지는 알고 있지만 왜 이것이 작동하지 않는지 궁금합니다). 그래서 filtered_audio을 반환하는 코드를 편집했습니다.

노이즈가 올바르게 제거 되었더라도 문제가 발생합니다 (스크린 샷 참조). 결과적으로 0.05가됩니다.

spectrogram

+0

당신이 루프백을 수행 한 또 다른 알려진 주파수 소스를 가지고 : 여기

이 작업을 수행하는 코드는?- 다른 사람들은 OS, 드라이버에 따라 원하는 샘플 속도를 얻는 데 어려움을 겪었습니다. – f5r5e5d

+0

피치 알고리즘이 스펙트로 그램을 보지 못하기 때문에 전체 클립의 피치를 계산하려고하면 말도 안됩니다. 스펙트로 그램은 시간 경과에 따른 파워 스펙트럼을 나타내지 만 알고리즘은 전체 신호의 평균 파워 스펙트럼에서만 작동합니다. 필자가 의미하는 바를 알기 위해서는 전체 신호의 스펙트럼을보고 단지 노트의 스펙트럼 (0-1 초)과 비교하십시오. 클립에서 여러 음표의 가능성을 해결하려면 새로운 질문을해야한다고 생각합니다. – Michael

+0

감사합니다. 당신 말이 맞습니다. 나는 신호를 여러 개의 신호 (모든 음을 연주 할 때마다 10-15 프레임 중 하나의 세그먼트)로 분할 한 다음 각 신호에 대해 HPS를 수행해야한다고 생각했습니다. 논리적 인 접근이라고 생각하십니까? – pk1914

답변

1

은 스펙트로 그램의 고조파 사이의 거리를 바탕으로, 나는 피치가 약 150 ~ 200 Hz의 것으로 추정 것입니다. 그렇다면 왜 피치 검출 알고리즘이 스펙트로 그램에서 눈으로 볼 수있는 피치를 감지하지 못합니까? 몇 가지 추측이 있습니다 :

메모는 몇 초 동안 만 지속됩니다. 처음에는 고조파가 10 개 이상인 아름다운 하모닉 스택이 있습니다! 이들은 빠르게 사라지며 5 초 후에도 보이지 않습니다. 전체 신호의 음조를 추정하려는 경우 5-12 초 사이의 사운드의 "피치"로 인해 예상치가 오염되었을 수 있습니다. 처음 1-2 초 동안 만 피치를 계산 해보십시오.

저주파 노이즈가 너무 많습니다. 스펙트로 그램에서 0과 64Hz 사이의 많은 전력을 볼 수 있습니다. 이것은 고조파의 일부가 아니므로 고역 통과 필터으로 제거 할 수 있습니다. 사운드 카드/오디오 인터페이스 또는 함께

import numpy as np 
from scipy.io import wavfile 
from scipy import signal 
import matplotlib.pyplot as plt 

from frequency_estimator import freq_from_hps 
# downloaded from https://github.com/endolith/waveform-analyzer/ 

filename = 'Vocaroo_s1KZzNZLtg3c.wav' 
# downloaded from http://vocaroo.com/i/s1KZzNZLtg3c 

# Parameters 
time_start = 0 # seconds 
time_end = 1 # seconds 
filter_stop_freq = 70 # Hz 
filter_pass_freq = 100 # Hz 
filter_order = 1001 

# Load data 
fs, audio = wavfile.read(filename) 
audio = audio.astype(float) 

# High-pass filter 
nyquist_rate = fs/2. 
desired = (0, 0, 1, 1) 
bands = (0, filter_stop_freq, filter_pass_freq, nyquist_rate) 
filter_coefs = signal.firls(filter_order, bands, desired, nyq=nyquist_rate) 

# Examine our high pass filter 
w, h = signal.freqz(filter_coefs) 
f = w/2/np.pi * fs # convert radians/sample to cycles/second 
plt.plot(f, 20 * np.log10(abs(h)), 'b') 
plt.ylabel('Amplitude [dB]', color='b') 
plt.xlabel('Frequency [Hz]') 
plt.xlim((0, 300)) 

# Apply high-pass filter 
filtered_audio = signal.filtfilt(filter_coefs, [1], audio) 

# Only analyze the audio between time_start and time_end 
time_seconds = np.arange(filtered_audio.size, dtype=float)/fs 
audio_to_analyze = filtered_audio[(time_seconds >= time_start) & 
            (time_seconds <= time_end)] 

fundamental_frequency = freq_from_hps(audio_to_analyze, fs) 
print 'Fundamental frequency is {} Hz'.format(fundamental_frequency) 
+0

업데이트 된 질문을 참조하십시오. 오디오 파일을 추가하고 스펙트로 그램을 수정하고 질문을 재구성했습니다. – pk1914

+0

멋지다. 따라 서 계단을 설명해 주시겠습니까? 'filter_stop_freq '아래의 모든 항목이 삭제 되었습니까? 나는이 변수의 대부분을 실제로 사용하는 것을 이해하지 못합니다. – pk1914

+0

나는 그것을 여기에서 설명하기가 쉽지 않다는 것을 이해한다. 그래서 참고 문헌은 훌륭 할 것이다! :) – pk1914