愛林

[Python/ML] 음성 데이터 분석(Sound Processing) - (1) 본문

Data Science/Machine Learning

[Python/ML] 음성 데이터 분석(Sound Processing) - (1)

愛林 2022. 12. 19. 16:39
반응형

음성 데이터 분석 (Sound Processing)


소리는 공기를 구성하는 입자들이 진동하며 만들어내는 현상이다.

정확하게 정의하자면,

 

어떠한 물체 또는 매질(Object)의 진동으로 인해 공기 입자들이 밀고 당겨지는 반복적인 과정(Oscilation)에서 생긴 파동(Wave)

 

이 진동으로 생긴 파동, 즉 음파가 우리의 귀를 때려 귀청을 울리면 그것이 우리가 듣는 소리가 된다.

공기의 진동을 측정할 때의 양적 기준을 음압(Sound Pressure) 라고 한다.

이 음압의 변화를 기록한 시계열 데이터를 우리는 사운드 데이터(Sound Data) 라고 한다.

 

이 음압의 변화를 나타낸 데이터 중 가장 간단한 형태가 사인 함수(Sine function) 이다.

sin 함수는 3가지 특징을 가진다.

  • 진폭(Ampulitude) A : 위, 아래로 움직이는 폭. 소리의 크기가 된다.
  • 주파수(Frequency) ω 또는 f  : 진동속도. 주파수가 높을수록 빠르게 진동한다. 소리의 높낮이로 인식되며, 주파수가 높을수록 음이 높다.
  • 위상(Phase)  ϕ : 사인함수의 시작지점. 위상만큼 출발이 늦어진다. 위상의 차이는 소리의 시간차이다.

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=nslee21&logNo=221794532239

 

Asin(ωt−ϕ)

sin 함수는 위와 같이 표시된다. 

또는 ω 를 2πf 로 표현하여 이렇게 표현하기도 한다.

 

Asin(2πft−ϕ)

 

t는 시간을 나타내고 보통은 초(second) 단위로 나타낸다.

주파수 ω는 초당 진동의 횟수를 나타낸다.

ω=2πf

 

1회전의 각도가 2π = 360 이므로 초당 라디안을 나타내지만,

이 값을 2π로 나누어 Hz 단위를 쓰기도 한다.

1초에 1번 진동하는 것이 Hz이다.

위의 식에서 f 는 Hz 단위의 주파수이다. 

 

코드를 통해서 sin 함수를 표현해보자면,

t = np.linspace(0, 1, 100)

plt.plot(t, 1 * np.sin(2 * np.pi * t + 0), ls="-", label=r"$\sin\left(2\pi{t}\right)$ 주파수 1Hz. 진폭 1, 위상 0")
plt.plot(t, 2 * np.sin(2 * np.pi * t + 0), ls="--", label=r"$2\sin\left(2\pi{t}\right)$ 진폭이 2로 커진 경우 ")
plt.plot(t, 1 * np.sin(3 * np.pi * t + 0), ls=":", label=r"$\sin\left(3\pi{t}\right)$ 주파수가 1.5Hz로 커진 경우")
plt.plot(t, 1 * np.sin(2 * np.pi * t - 0.3), ls="-.", label=r"$\sin\left(2\pi{t} - 0.3\right)$ 위상이 늦춰진 경우")
plt.ylim(-2.2, 3)
plt.xticks(np.linspace(0, 1, 5))
plt.legend()
plt.title(r"$A\sin\left(\omega{t}+\phi\right)$")
plt.show()

 

이 주파수 f 의 역수를 주기 T라고 한다. 주기는 1번의 진동에 필요한 시간을 뜻한다.

또는

이런 주파수는 사람에게 음의 높이(tone) 으로 인식된다.

사인파처럼 주파수가 일정한 음압 시계열은 사람에게 음높이가 일정한 '삐-" 정도로 들린다.

그래서 하나의 사인파로 이루어진 소리는 싱글톤(Single Tone) 이라고 한다.

def single_tone(frequecy, sampling_rate=44100, duration=1):
    # frequency: 주파수
    # sampling_rate: 초당 샘플링 데이터 수. 디폴트 44100
    # duration: 지속 시간. 단위 초. 디폴트 1초
    t = np.linspace(0, duration, int(sampling_rate))
    y = np.sin(2 * np.pi * frequecy * t)
    return y

y = single_tone(400)

plt.plot(y[:400])
plt.show()

 

Jupyter Notebook 환경에서는 다음과 같이 사운드 데이터를 표시할 수 있다.

 

from IPython.display import Audio, display

display(Audio(y, rate=44100))

이런 식으로 아이콘이 표시되면서 소리를 들을 수 있다.

삐 - 한다. wav파일이라 넣기가 쉽지 않아서 그냥 캡쳐해서 생긴 것만 넣었다 ..

 

이 음계에서 기준이 되는 가온다(middle C) 음은 261.62Hz의 싱글 톤이다.

반음(semitone, half tone, half step) 이 올라갈 때마다 2^1/12 만큼 주파수가 올라가고, 12반음. 1옥타브가 올라가면 

주파수는 2배가 된다.

 

다음 코드는 가온다로부터 한 옥타브의 음에 대해서 계산한 주파수이다.

notes = 'C,C#,D,D#,E,F,F#,G,G#,A,A#,B,C'.split(',')
freqs = 261.62 * 2**(np.arange(0, len(notes)) / 12.)
notes = list(zip(notes, freqs))
notes
[('C', 261.62),
 ('C#', 277.17673474627884),
 ('D', 293.6585210786982),
 ('D#', 311.1203654270119),
 ('E', 329.6205450734967),
 ('F', 349.2208026479644),
 ('F#', 369.98655218804913),
 ('G', 391.9870974524774),
 ('G#', 415.29586321592035),
 ('A', 439.9906403173536),
 ('A#', 466.1538452797511),
 ('B', 493.8727953675693),
 ('C', 523.24)]

각자의 주파수를 계산해주었다.

octave = np.hstack([single_tone(f) for f in freqs])
display(Audio(octave, rate=44100))

옥타브가 점점 올라가는 것을 확인했다.

 

이렇게 복수의 싱글톤을 더해서 한 번에 소리를 내면 화음이 된다.

예를 들어서 도(C) 미(E) 솔(G) 3도 화음은 다음과 같다.

tone_C = single_tone(261.62)
tone_E = single_tone(329.62)
tone_G = single_tone(392)
harmony = tone_C + tone_E + tone_G

plt.plot(harmony[:10000])
plt.show()

display(Audio(harmony, rate=44100))

화음이 울리는 것을 확인할 수 있다.

 

우리는 Python 에서 음향 데이터를 다룰 때 wave 형식의 파일을 사용하게 되는데, 

wave 파일은 음압 시계열 데이터를 저장하는 가장 기본적인 파일 형식으로 .wav 확장자로 표시된다.

wave 파일은 보통 초당 44100번 음압을 측정하고 -32768 ~ 32767 (2^15) 까지의 2Byte 숫자로 기록한다.

 

파이썬에서 wave 파일을 쓰거나 읽기 위해서는 scipy 패키지의 io.wavfile 서브패키지에서 제공하는

read , write 명령어를 사용해야 한다.

 

# 초당 샘플링 데이터 수 
sampling_rate = 44100
scipy.io.wavfile.write("octave.wav", sampling_rate, octave)

sr, y_read = scipy.io.wavfile.read("octave.wav")
# sr == sampling_rate

plt.plot(y_read[40000:50000])
plt.show()

아까 만든 octave 로 octave.wav 파일을 write 를 사용해 만들어주고,

read를 통해 읽어주었다.

실행시키니 위와 같은 그래프가 나왔다.

Audio(y_read, rate =sr)

아까 그 octave 파일과 같은 음성이 만들어진다.

 

전화는 DTMF(Dual-tone multi-frequency) 방식이라는 두 싱글톤 조합의 음향 신호로 전화번호를 입력받는다.

이를 사용하여 나의 전화번호를 호출해보았다.

tone_0 = single_tone(1336) + single_tone(941)
tone_1 = single_tone(1209) + single_tone(697)
tone_6 = single_tone(1477) + single_tone(770)
tone_3 = single_tone(1477) + single_tone(697)
notes = list(zip(tone_0 , tone_1, tone_0, tone_6, tone_3, tone_0, tone_1))
harmony = tone_0 + tone_1 + tone_0 + tone_6 + tone_3 + tone_0 + tone_1

plt.plot(harmony[:10000])
plt.show()

display(Audio(harmony, rate = 44100))

신기한 음이 출력이 되었다.

 

 

 

참고


https://datascienceschool.net/03%20machine%20learning/03.03.01%20%EC%82%AC%EC%9A%B4%EB%93%9C%20%ED%94%84%EB%A1%9C%EC%84%B8%EC%8B%B1%20%EA%B8%B0%EC%B4%88.html

 

사운드 프로세싱 기초 — 데이터 사이언스 스쿨

.ipynb .pdf to have style consistency -->

datascienceschool.net

 

https://lucaseo.github.io/posts/2020-12-13-understanding-audio-data-sound-waveform-adc/

 

[KR] ML/DL을 위한 소리 데이터 이해하기(1) - Waveform, ADC

1. 소리 데이터란 소리는 다음 과정에서 생산된 것을 의미합니다. (1) 어떠한 물체 또는 매질(object)의 진동(vibration)으로 인해 공기 입자들이 밀고 당겨지는 반복적인 과정(oscilation)에서 생긴 파동(

lucaseo.github.io

 

https://hyongdoc.tistory.com/401

 

[Python 음성 데이터 분석] Librosa 라이브러리를 이용한 주파수 분석

이번 포스팅에서는 지난 포스팅에 이어, 실제로 파이썬을 이용해 어떻게 음성 데이터를 불러오고 가공하는지에 대해 알아보겠습니다. Librosa 라이브러리 만든이 칭찬해~~ 파이썬은 배워두면 참

hyongdoc.tistory.com

 

Comments