728x90

음성 처리를 하다 보면 음성 데이터를 Down Sampling 하거나, Up sampling 할 경우가 있다.

예를 들어 보유한 데이터의 Sampling rate가 44.1kHz 인데, n_fft가 너무 크기 때문에 모든 것을 다 함축하여 Mel scale log spectrogram으로 담지 못할 경우가 있다.

이럴 때 자주 사용하는 것이 Down sampling이라고 한다.

오늘은 librosa 라이브러리를 이용하여 down sampling을 해보겠다.
우선 librosa 라이브러리를 설치해야 한다.

설치하였다고 가정하고,  함수를 하나 만들어서 진행하겠다. 함수 이름은 def down_sample이다.

def down_sample(input_wav, origin_sr, resample_sr):
    y, sr = librosa.load(input_wav, sr=origin_sr)
    resample = librosa.resample(y, sr, resample_sr)
    print("original wav sr: {}, original wav shape: {}, resample wav sr: {}, resmaple shape: {}".format(origin_sr, y.shape, resample_sr, resample.shape))

이 함수에서는 wav 파일과 기존 original sr, resample 할 sr을 받고 있다.

보유한 데이터의 음성은 16kHz이므로, original_sr = 16000, resample_sr = 8000으로 진행한다.

 

음성 처리에 있어서 librosa 라이브러리가 정말 잘 지원해주고 있다. resample을 하기 위해서는 3번째 줄의 resample = librosa.resample(y, sr, resample_sr)을 해주면 된다.

 

그 아래의 print 한 결과는 다음과 같다.

 

즉 기존의 y data는 53720이고, 그의 절반으로 하였기 때문에 26860으로 출력이 된다.

 

이렇게만 보면 이해하기가 어렵다. 아래의 코드를 활용하여 직접 그림을 그려보자.

 

    plt.figure(figsize=(10, 4)) # 10,4 크기로 그림
    plt.subplot(2, 1, 1) # 2개를 그릴건데, (총 개수, 가로, 세로) 순서로 그림
    time1 = np.linspace(0, len(y) / sr, len(y)) # 음성의 데이터를 이용하여 음성 총 길이를 구함
    plt.plot(time1, y) # 음성 flot
    plt.title('Original Wav')

    plt.subplot(2, 1, 2)
    time2 = np.linspace(0, len(resample) / resample_sr, len(resample))
    plt.plot(time2, resample)
    plt.title('Resampled Wav')

    plt.tight_layout()
    plt.savefig('compare_16k_vs_8k.png') # 저장

위의 코드에 자세히 주석을 달아놓았다. 위의 코드처럼 입력을 하면 다음의 그림을 얻을 수 있다.

 

 

코드에서 subplot은 2,1,1 -> 총 2개의 사진 중 맨 위를, 2,1,2 -> 총 2개의 사진 중 맨 아래에 그림을 그리겠다는 뜻이다.

 

육안으로 보았을 때 magnitude나 phase의 변화는 없다. 다만 자세히 들여다보면 data의 magnitude가 2개 중 1개씩 비어있다. 즉, 데이터가 총 100개면, resample 하였을 경우 (1/2로 하였기 때문에) 50개의 데이터만 남아있다. 이때, 데이터의 위치는 변화하지 않고 중간중간만 비어지는 것이다.

 

이제 음성 데이터를 저장하여 들어보겠다.

 

    sf.write('./' + '16k.wav' , y, origin_sr, format='WAV', endian='LITTLE', subtype='PCM_16')
    sf.write('./' + '8k.wav', resample, resample_sr, format='WAV', endian='LITTLE', subtype='PCM_16')

 

아래 글에 작성한 것처럼, sf.write를 사용하여 현재 directory에서 16k.wav 라고 저장하는 코드이다. 

 

실제로 음성 첨부를 하여 들어보면,

 

 

 

8kHz

 

16kHz

 

육안으로 들었을 때, 두 데이터의 차이는 크지 않다.

 

저장되는 크기는 어떨까? 예상한 것처럼, 절반으로 resampling 하였기 때문에 데이터의 크기 또한 절반으로 reduce 된다.

 

 

전체 코드는 아래와 같다.

import librosa
import numpy as np
import soundfile as sf
import matplotlib.pyplot as plt

def down_sample(input_wav, origin_sr, resample_sr):
    y, sr = librosa.load(input_wav, sr=origin_sr)
    resample = librosa.resample(y, sr, resample_sr)
    print("original wav sr: {}, original wav shape: {}, resample wav sr: {}, resmaple shape: {}".format(origin_sr, y.shape, resample_sr, resample.shape))

    plt.figure(figsize=(10, 4))
    plt.subplot(2, 1, 1)
    time1 = np.linspace(0, len(y) / sr, len(y))
    plt.plot(time1, y)
    plt.title('Original Wav')

    plt.subplot(2, 1, 2)
    time2 = np.linspace(0, len(resample) / resample_sr, len(resample))
    plt.plot(time2, resample)
    plt.title('Resampled Wav')

    plt.tight_layout()
    plt.savefig('compare_16k_vs_8k.png')

    sf.write('./' + '16k.wav' , y, origin_sr, format='WAV', endian='LITTLE', subtype='PCM_16')
    sf.write('./' + '8k.wav', resample, resample_sr, format='WAV', endian='LITTLE', subtype='PCM_16')

man_original_data = '/mnt/junewoo/workspace/transform/test_wav/man_wav1.wav'
down_sample(man_original_data, 16000, 8000)

 

728x90

+ Recent posts