오늘은 소리나 음원, 음악 데이터에서 STFT나 Chroma 분석을 수행하는데 편한 librosa를 소개하고, 이를 이용해서 소리 데이터에서 특성을 추출하는 기초에 대한 이야기를 해보려고 합니다. 먼저 STFT에 대해서는 얼마전에 이야기를 했었는데요.
위 글에서 FFT와 STFT에 대한 이야기를 했었습니다. 저 글에서는 scipy와 numpy를 사용했는데요. 이번에는 소리 데이터 분석에 유용한 도구인 librosa를 가지고 이야기를 해보도록 하겠습니다.
import librosa.display, librosa
import IPython.display
import warnings
import numpy as np
warnings.simplefilter("ignore")
def sin_wave(amp, freq, time):
return amp * np.sin(2*np.pi*freq*time)
먼저 필요 모듈들을 import하고 정현파를 만드는 함수 sin_wave를 간단히 만들어 두겠습니다.
일단 도, 미, 솔을 만들어 보겠습니다. 각 주파수는 위 표에 나와있습니다.
sr = 22*1000.
ts = 1/sr
time = np.arange(0, 1, ts)
DO = sin_wave(1, 261.6256, time)
MI = sin_wave(1, 329.6276, time)
SOL = sin_wave(1, 391.9954, time)
그래서 1초로 하고, 샘플링 주파수는 22kHz로 해서 간단하게 도, 미, 솔 파형을 만들어 봤습니다.
import matplotlib.pyplot as plt
plt.figure(figsize=(12,5))
plt.plot(time, DO, label="DO", color='red')
plt.plot(time, MI, label="MI", color='blue')
plt.plot(time, SOL, label="SOL", color='green')
plt.xlim((0, 0.01))
plt.legend(); plt.grid(); plt.show()
위 코드로 0.01초 부분까지만 확인해보면~
이렇게 잘 만들어 졌음을 알 수 있습니다.
IPython 모듈의 diplay.Audio를 Jupyter에서 이용하면 바로 음원을 들어 볼 수 있습니다. 오늘 글에 포함된 소리들은 모두 이 글 하단의 영상에서 들으실 수 있습니다.
sample_concat = np.concatenate((DO, MI, SOL))
그래놓고 1초짜리 도 미 솔을 이어붙여서 3초짜리로 만들었습니다.
import matplotlib.pyplot as plt
def draw_wave(sample_sounds):
plt.figure(figsize=(12,6))
librosa.display.waveshow(sample_sounds, alpha=0.2)
plt.xlabel("Time (s)"); plt.ylabel("Amplitude")
plt.title("Waveform"); plt.show()
이제 미리 시간축에서 음원의 파형을 그려주는 함수를 하나 만들어 두겠습니다.
도, 미, 솔을 이어 붙은 음원의 파형입니다.
def get_stft(sample_sounds):
return librosa.stft(sample_sounds)
이제 librosa가 제공하는 stft 결과값을 얻어오는 함수도 간단히 하나 만들구요~ 이 함수의 각종 옵션은
이렇습니다.
n_fft는 윈도우의 길이, 그리고 hop length는 얼마나 겹칠 것인지를 설정합니다. 디폴트가 잘 지정되어 있어서 그냥 데이터만 주어도 됩니다.
import numpy as np
def draw_stft(sample_sounds, ylim=(None, None)):
plt.figure(figsize=(12,6))
librosa.display.specshow(np.abs(get_stft(sample_sounds)),
y_axis='hz', x_axis='s')
plt.ylim(ylim); plt.grid(); plt.show()
그리고 stft 결과를 받아와서 그려주는 것도 함수로 하나 만들어 두겠습니다.
먼저 도, 미, 솔을 이어 붙인 음원에 대한 STFT의 결과를 그렸습니다. 잘되네요^^
이제 CHROMA 분석을 해보겠습니다. 위 주파수 분석 결과에 12음계를 y라벨로 사용한다고 생각하시면 됩니다.
def get_chroma(sample_sounds, sr):
return librosa.feature.chroma_stft(S=np.abs(get_stft(sample_sounds)),
sr=sr)
STFT 분석 결과를 가지고 chroma_stft 함수를 이용하면 chroma 결과를 얻을 수 있습니다. 이 함수를 만들고,
def draw_chroma(sample_sounds, sr):
plt.figure(figsize=(12,6))
librosa.display.specshow(get_chroma(sample_sounds, sr),
y_axis='chroma', x_axis='time')
plt.grid(); plt.show()
그것을 이용해서 chroma 결과를 그려주는 것도 함수로 만들어 두겠습니다.
아까 만들어둔 도, 미, 솔을 그린 것입니다.
도, 미, 솔 이어 붙인것도 도, 미, 솔 잘 찾아주네요 ㅋㅋ
sum_samples = sum([DO, MI, SOL])
이제 도, 미, 솔을 그냥 더해버리겠습니다.~
STFT 결과도 잘 나오고
Chroma 결과도 잘 나오네요~
화음을 한 번 들어보는 겁니다. 이건 영상에서 확인해주세요~
위 세 개의 음원은 제가 매우 관심있게 함께 하는 회사의 음악 담당이신 분이 만들어 주신 음원입니다.^^. 이자리를 빌어 감사를 표합니다.~
piano, sr = librosa.core.load('./melody_sample/piano.wav')
일단 피아노 음원을 읽고~
이렇게 생겼군요~
STFT 결과는 저렇습니다~
CHROMA로 분석해서 보면 저렇습니다.
flute, sr = librosa.core.load('./melody_sample/flute.wav')
guitar, sr = librosa.core.load('./melody_sample/guitar.wav')
sum_inst = sum([piano*2, guitar, flute*1.2])
다른 두개도 다 읽어서~ 더해버렸습니다.^^
재미난 결과를 볼 수 있습니다.
어떤가요. 음원이나 소리를 분석할 때 STFT는 꽤 좋고, librosa를 이용하시면 편하게 사용할 수 있습니다. 특히 음원일때는 chroma 분석도 괜찮구요.
'Theory > DataScience' 카테고리의 다른 글
Selenium 처음 시작해 보기 (10) | 2021.09.30 |
---|---|
Jupyter Notebook을 원격으로 접속하기 (7) | 2021.04.08 |
Python scikit learn의 Label Encoder와 MinMax, Standard, Robust Scaler 이해하기 (6) | 2021.04.05 |
Box Plot의 기초 (6) | 2021.03.24 |
Colab에서 KoNLPy와 WordCloud 설정하기 (4) | 2021.01.15 |
한글 형태소 분석기 KoNLPy 사용을 위한 환경 설정 해보기 (8) | 2020.12.23 |
네이버 검색 결과를 API를 이용해서 쉽게 받아보자 (6) | 2020.10.13 |