music/audio processing library Librosa 사용법 Tutorial
(2) Audio data representations (Spectrogram, Mel-spectogram)
librosa.load
method를 이용하여 audio file을 불러오면 waveform의 형태로 데이터를 얻게 된다.
Waveform만으로는 audio data를 분석하기에 어려움이 있다.
이번 글에서는 Audio data를 분석하고 특징을 알아낼 수 있는 representation을 librosa로 얻는 방법에 대해 소개하겠다.
Spectrogram
Spectrogram은 Short-Time Fourier Transform (STFT)를 이용한 audio의 2D 표현법이다.
STFT란, 말 그대로 짧은 시간 동안의 데이터를 Fourier Transform하는 것이다.
STFT는 window를 이용해 waveform을 frame 단위로 나누어, 각각의 frame에 DFT를 한다.
DFT된 각 frame들을 합쳐 2D 데이터로 나타내고, 이를 통해 시간에 따른 frequency의 변화를 알 수 있다.
아래 그림에서 STFT의 과정에 대해 설명하고 있다.
아래 코드를 통해 spectrogram을 추출할 수 있다.
y, sr = librosa.load(librosa.ex('trumpet'))
S = librosa.stft(y, n_fft=2048, window='hann', hop_length=512)
주요 argument는 다음과 같다.
window
: STFT에 사용할 window의 종류n_fft
: length of the windowed signal after padding with zeros. 즉, 각 frame은window_length
만큼 windowing된 후n_fft
만큼 zero-padding된다.hop_length
: number of audio samples between adjacent STFT columns. 즉 각 window center 간의 거리이다. default 값은 win_length // 4. 이 값이 작아질수록 frame의 개수는 많아지기 때문에, output의 column 개수가 많아진다. (window 하나당 frame 하나가 나온다고 생각하면 된다)
Output은 (1+n_fft
/2, n_frames) 크기의 2차원 numpy complex-valued array이다.
n_frames는 input signal의 길이와 hop_length에 의해 결정된다:
n_frames = 1 + int((len(y) - frame_length) / hop_length)
amplitude_to_db
method와 librosa.display
를 이용해 시각화할 수 있다.
amplitude_to_db
는 amplitude spectrogram을 dB-scaled spectrogram으로 바꿔주는 method이다.
($dB = 20log_{10}(\frac{amp}{amp_{ref}})$)
따라서 spectrogram의 aplituede인 np.abs(S)
를 이용해 변환한다.
D = librosa.amplitude_to_db(np.abs(S), ref=np.max)
librosa.display.specshow(D, y_axis='log', x_axis='time')
plt.colorbar(format='%+2.0f dB')
Mel spectrogram
사람의 귀는 주파수의 범위에 따른 민감도가 다르다. 보통 낮은 주파수 대역의 소리에 더 민감한데, 이를 나타낸 것이 Mel scale이다.
주파수를 mel scale로 변환하는 식은 다음과 같다.
$m=2595log_{10}(1+f/700)$
Mel spectrogram은 linear frequency의 spectogram을 mel scale로 mapping하여 low frequency는 부각하고, high frequency는 squeeze한 것이다.
audio data의 성분들도 low frequency 대역에 더 집중되어 있으므로, mel-spectrogram을 이용하면 이를 더 잘 볼 수 있다.
Librosa에서 두 가지 방법을 이용해 mel spectogram을 구할 수 있다.
첫 번째는 waveform을 이용해 바로 mel spectorgram을 구하는 것이다. 이 경우 내부에서 spectrogram을 구한 후 mel-spectrogram으로 변환한다.
y, sr = librosa.load(librosa.ex('trumpet'))
S = librosa.feature.melspectrogram(y=y, sr=sr)
두 번째는 위에서 구한 spectogram을 이용하는 것이다. Amplitude spectrogram에 제곱을 하여 power spectrum을 얻은 후, 이를 input으로 주면 된다.
D = np.abs(librosa.stft(y))**2
S = librosa.feature.melspectrogram(S=D, sr=sr)
마찬가지로 dB로 변환하여 시각화할 수 있다.
S_dB = librosa.power_to_db(S, ref=np.max)
librosa.display.specshow(S_dB, x_axis='time', y_axis='mel', sr=sr)
plt.colorbar(format='%+2.0f dB')