본문 바로가기

Programming Language/Python

Librosa python library로 음성파일 분석하기

Librosa는 python에서 많이 쓰이는 음성 파일 분석 프로그램이다.

Librosa를 쓰기 위해선 반드시 ffmpeg의 설치 여부를 확인해야 한다.

그렇지 않으면 음성 파일을 로드하는 과정에서 에러가 발생할 것이다.


1. 음성 파일 load


1
2
3
4
5
6
7
8
9
10
11
12
13
14
import librosa
import librosa.display
import IPython.display
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.font_manager as fm
 
%matplotlib inline
 
audio_path = 'data/1_0000_trim.wav'
y, sr = librosa.load(audio_path)
ori_sent = '그는 괜찮은 척 하려고 애쓰는 것 같았다'
 
cs


2. 음성 파일 load 확인

1
2
IPython.display.Audio(data=y, rate=sr)
 
cs

 


1
2
3
4
= librosa.amplitude_to_db(librosa.stft(y[:1024]), ref=np.max)
 
plt.plot(D.flatten())
plt.show()
cs



이 떄, x축은 시간 (ms)이고, y축은 dB 단위이다.

dB는 max값을 기준으로 상대적인 값의 변화로 표현된다.


3, mel-frequency cepstral coeeicients (MFCC)


Librosa는 MFCC를 매우 쉽게 수행할 수 있다.

음성 데이터를 더 잘 분석하기 위해, MFCC를 수행한 후, amplitude를 log scale로 변환하도록 하겠다.


1
2
3
4
5
6
7
8
9
10
= librosa.feature.melspectrogram(y, sr=sr, n_mels=128)
 
log_S = librosa.logamplitude(S, ref_power=np.max)
plt.figure(figsize=(124))
librosa.display.specshow(log_S, sr=sr, x_axis='time', y_axis='mel')
plt.title('mel power spectrogram')
plt.colorbar(format='%+02.0f dB')
plt.tight_layout()
plt.show()
 
cs




매우 간단하게 책에서나 보던 이쁜 그림이 나왔다.


4. Normalization


값의 범위가 -80-0이면 다루기가 쉽지 않으니, normalization을 수행할 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
min_level_db = -100
 
def _normalize(S):
    return np.clip((S - min_level_db) / -min_level_db, 01)


norm_S = _normalize(log_S)
 
plt.figure(figsize=(124))
librosa.display.specshow(norm_S, sr=sr, x_axis='time', y_axis='mel')
plt.title('norm mel power spectrogram')
plt.colorbar(format='%+0.1f dB')
plt.tight_layout()
plt.show()
cs






이제 음성 데이터를 '이미지'처럼 다룰 수 있도록 0-1로의 값으로 표현할 수 있게 되었다.



5. 음성 데이터 자르기



난 자소 단위로 음성 데이터를 자르기를 원하니, 먼저 입력 문장을 자소 단위로 쪼게보도록 하겠다.

라이브러리는 hgtk를 사용했는데, 가장 간편하고 빠른 것 같다.


1
2
3
4
5
import hgtk
 
jamo_sent = hgtk.text.decompose(ori_sent)
jamo_sent = jamo_sent.replace('ᴥ''')
print(jamo_sent)
cs


ㄱㅡㄴㅡㄴ ㄱㅙㄴㅊㅏㄶㅇㅡㄴ ㅊㅓㄱ ㅎㅏㄹㅕㄱㅗ ㅇㅐㅆㅡㄴㅡㄴ ㄱㅓㅅ ㄱㅏㅌㅇㅏㅆㄷㅏ

이제 자소 개수만큼 음성 데이터를 잘라보자.

1
2
3
char_frame_num = int(time_frame_num / len(jamo_sent)) #가로 사이즈
print(char_frame_num)
print(time_frame_num)
cs
2
140

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mpl.rc('font', family="NanumBarunGothic")
plt.figure(figsize=(20150))
jamo_sent_size = len(jamo_sent)
for i in range(0, jamo_sent_size):
    plt.subplot(jamo_sent_size, 5, i+1)
    start_position = (i * char_frame_num) - 1
    end_position = ((i+1* char_frame_num) + 1
    if(start_position < 0):
        start_position = 0
        end_position = end_position + 1
    if(end_position > time_frame_num):
        start_position = start_position - (end_position - time_frame_num)
        end_position = time_frame_num
    window = norm_S[0:mel_freq_num, start_position:end_position]
    plt.pcolor(window, cmap='jet')
    plt.title(str(jamo_sent[i]))
    plt.colorbar()
cs




이쁘게 잘 나온다 ^^