TTS, STT와 같은 모델은 음성 데이터를 다루는 인공지능 모델입니다. 음성 데이터를 처리하려면 음성 데이터에 대한 지식이 필요합니다. 음성 데이터를 처리하기 위해 공부하고 정리했던 기본 지식들을 정리해보고자 합니다.
1. 기본 용어
2. 푸리에 변환
3. STFT
4. Mel-scale
5. 음성 전처리하기
1. 기본 용어
1-1. 샘플링 레이트 (Sampling rate)
디지털 오디오 신호는 결국 일련의 숫자 배열과 같은 형태입니다. 음성의 형태에 따라 어느 시간대에 어떤 신호값을 갖느냐가 소리를 결정하는 것이죠.
샘플링 레이트는 이 음성의 신호값들을 1초에 몇 개씩 기록할 것인지를 나타내는 단위입니다. 만약 샘플링 레이트가 22,050Hz다. 라고 한다면 1초에 22,050개의 신호값을 기록한다는 뜻입니다.
1-2. 샘플 심도 (Sample Depth, Sample Precision, Sample size)
샘플 심도는 이 음성 신호를 얼마나 자세하게 기록할 것인가를 뜻합니다. 예를 들면 3.141592... 라는 신호값이 있을 때, 이를 3.14까지만 기록한 경우와 3.141592까지 기록한 경우, 둘 중에 후자의 경우가 샘플 심도가 더 높다라고 할 수 있을 겁니다. 샘플 심도는 bit단위를 이용해 기록하는데, 만약 16비트 음성이라면 각 신호값들을 16비트($-2^8~2^8$)의 숫자를 이용해 신호값을 기록한다는 것입니다. 비트가 클수록 음성을 더 원본과 가깝게 잘 보존한 것이겠죠.
1-3. 비트 레이트 (bit rate, bps(bit ber second))
비트 레이트는 기록된 음성 신호에 대하여 1초에 몇 개의 비트값이 사용되는지를 나타냅니다. 쉽게 말하면 이 음성 파일의 용량을 측정하는 것과 같다고 볼 수 있습니다.
비트 레이트는 {샘플링 레이트}x{샘플 심도}로 계산할 수 있습니다. 만약 44,100Hz에 16비트, 모노채널을 사용하는 음성파일이 있다면 이 음성 파일의 비트 레이트는 44,100x16x1=705k(bps)가 되는 것입니다.
2. 푸리에 변환 (Fourier Transform)
음성 파일마다 다르겠지만, 대부분 음성 파일에는 서로 다른 소리들이 섞여서 기록될 겁니다. 만약 서로 다른 두 개의 소리가 함께 녹음되었다고 생각해 봅시다.
그러면 위와 같이 2개의 음성 파형이 합쳐진 새로운 음성 파형의 형태로 소리가 기록될 겁니다. 문제는, 새롭게 합쳐진 음성 파형만 보고 음성A와 음성B가 각각 원래 어떤 파형을 가지는지를 파악하기가 어렵다는 것입니다.
푸리에 변환은 이렇게 합성된 음성을 다시 개별의 음성 파형들로 분리하는 기술입니다. 간단하게 살펴 보자면, 만약 위의 그래프를 퓨리에 변환을 수행하면 아래와 같은 모습을 갖게 됩니다.
보면 그래프의 특정 부분이 툭툭 튀어나온 것을 확인할 수 있는데, 이는 합성되기 전의 음성 신호를 각각 푸리에 변환한 결과와 같습니다.
그래서 이 그래프의 튀어나온 부분을 다시 역 푸리에 변환을 하면 각자 원래의 신호를 복원할 수 있는 식으로 활용이 되고 있습니다. 푸리에 변환의 자세한 원리는 다음 유튜브를 보는 것을 추천드립니다. (https://youtu.be/Mc9PHZ3H36M)
3. STFT
푸리에 변환을 통해서 여러 소리가 섞인 음성으로부터 소리를 분리할 수 있게 되었습니다. 하지만 위의 그래프를 보면 알 수 있듯이, 서로 다른 음성이 존재한다는 것은 알 수 있지만 어느 음성이 어느 시간에 발생했는지를 알기는 어렵습니다. 만약 사람 A가 앞의 5초동안 말하고, 사람 B가 뒤의 5초 동안 말했다면, 음성 전체를 푸리에 변환했을 때 사람 A와 B가 말을 했다는 것은 알 수 있지만, 누가 언제 얼마나 말했는지는 알 수가 없습니다.
STFT(Short Time Fourier Transform)은 이를 파악하기 위해 음성을 여러 구간으로 나눠 각 구간마다 푸리에 변환을 수행합니다. 간격을 조밀하게 잡을수록 어느 시간대에 누가 말을 했는지를 더 자세히 파악할 수 있게 되겠죠? 그러나 간격을 조밀하게 잡을수록, 바꿔 말하면 전체 신호의 일부만 사용하기 때문에 음성의 해상도가 떨어진다는 문제가 발생합니다. 즉, 음성의 해상도와 푸리에를 적용할 구간의 크기(window의 크기)는 서로 반비례 관계입니다. 하지만 간격을 작게 가져가면서좋은 해상도를 가져갈 수 있다면 제일 좋겠죠. 그래서 구간을 서로 겹치도록 하여 STFT를 적용하게 됩니다.
위와 같이 overlap을 적용할 경우, window의 크기를 크게 가져가 해상도를 챙기면서도, 간격을 조밀하게 가져가 음성 정보를 더 얻을 수 있게 됩니다.
해상도를 늘리는 방법은 overlap 외에 zero-padding도 있습니다. 음성 신호에 임의의 신호값(0)을 추가하여 길이를 늘려 해상도를 늘리는 방법입니다.
파이썬에서는 librosa를 통해 stft를 구현할 수 있습니다.
librosa.stft(y, *, n_fft=2048, hop_length=None, win_length=None, window='hann')
y는 stft를 적용하려는 음성 신호를 나타냅니다. win_length는 stft를 적용할 window 크기를 말하며, hop_length는 겹치는 영역의 크기를 말합니다. n_fft는 zero-padding의 범위를 포함한 window 크기를 말합니다. 따라서 win_length보다 작아서는 안되겠죠.
4. Mel-Scale
개는 사람보다 더 높은 주파수의 소리를 들을 수 있다고 하죠. 이처럼 세상에는 사람이 들을 수 없는 주파수의 소리도 존재합니다. 그렇지만 만약 사람의 말소리를 대상으로 하는 인공지능을 만든다면 이런 주파수까지 고려할 필요는 없겠죠. 사람은 1000hz까지의 소리에는 매우 민감하지만 그 이상의 주파수로 갈수록 차이를 잘 느끼지 못하게 된다고 합니다. Mel-scale은 이렇게 사람이 민감한 주파수의 소리는 확대하고, 민감하지 않은 주파수의 소리는 축소하는 스케일링을 말합니다.
5. 음성 전처리하기
지금까지 음성 처리 방법들과 관련하여 알아봤습니다. 이번엔 논문의 정보를 따라 데이터를 직접 전처리해 보도록 하겠습니다. Tacotron2 논문을 보고 전처리를 해보겠습니다.
"As in Tacotron, mel spectrograms are computed through a short time Fourier transform (STFT) using a 50ms frame size, 12.5ms frame hop, and a Hann window function."
논문에는 STFT를 사용하며, window 크기로 50ms, 겹치는 간격(frame hop)으로 12.5ms로 설정했으며, Hann window function을 사용했다고 되어 있습니다. 이를 따라 librosa를 사용해 오디오를 전처리해보면 다음과 같이 쓸 수 있습니다.
import librsoa
audio, sr = librosa.load("example.wav")
stft = librosa.stft(
audio,
n_fft=int(sr*0.05),
hop_length=int(sr*0.0125),
window='hann'
)
오디오의 길이는 (샘플레이트 * 시간)으로 나타납니다. 50ms 길이의 window 역시, sr*50(ms)로 나타낼 수 있습니다. 50ms는 0.05초이므로 n_fft의 크기는 sr*0.05로 나타낼 수 있습니다. 이와 마찬가지로 hop_length 역시 sr*12.5(ms) = sr*0.0125로 쓸 수 있습니다.
"We transform the STFT magnitude to the mel scale using an 80 channel mel filterbank spanning 125Hz to 7.6kHz, followed by log dynamic range compression."
STFT 신호는 mel 스케일링을 거치는데, 80채널의 mel filterbank를 사용하여, 125Hz부터 7.6kHz의 범위를 스케일링 합니다. 그리고 이는 log compression을 거칩니다.
D = np.abs(stft)**2
S = librosa.feature.melspectrogram(
S=D,
sr=sr,
n_mels=80,
fmin=125,
fmax=7600
)
S = np.log10(S)
plt.imshow(S)
np.abs(stft)**2는 librosa의 melspectrogram 문서에 따라 쓴 것입니다. 그 뒤에 melspectrogram을 적용하는데, n_mels에 mel filterbank의 채널 수를, fmin과 fmax에 각각 최소~최대 주파수(hz)를 씁니다. 그 뒤에 log를 씌우면 우리가 많이 본 스펙트로그램의 형태를 볼 수 있게 됩니다.
이상으로 음성파일의 전처리 방식에 필요한 기본적인 배경지식을 알아봤습니다. 음성파일 전처리 연구에 참고가 되면 좋겠습니다. 감사합니다.
'딥러닝 관련 이것저것' 카테고리의 다른 글
3가지 유형의 Positional Embedding 총정리 (0) | 2025.02.04 |
---|