[creative technology강의] #1 오디오 합성

Jude's Sound Lab·2022년 6월 15일
0

Note for late 2022

목록 보기
1/11

호도법과 관련해서는 아래글을 참고
https://blog.naver.com/PostView.naver?blogId=welcomelady&logNo=222409978578&parentCategoryNo=&categoryNo=26&viewDate=&isShowPopularPosts=true&from=search

헷갈릴때는 이 비례만 기억하자
360 : 2 x pi x r = 1rad : r

Sine Wave


코드 구현

sine wave 그리기

np.sin에는 radian을 넣어주어야 한다. 더 정확히는 파동이 몇번의 주기를 지났는지 혹은 파동을 그리는 원형 운동이 몇 바퀴를 회전했는지를 넣어주어야 한다. 이를 period라고 부를 수 있다. period는 frequency * time이다.

frequency = 440 # 주파수를 Hz단위로 표현
amplitude = 0.5 # Digital audio signal을 표현할 때 최대 최소 값이 [-1, 1]
duration = 3 # 길이를 초로 표현(sec)
sample_rate = 16000 # (samples/sec)

# 3초에 대항하는 샘플의 수가 얼마인지를 계산
total_number_of_samples = duration * sample_rate
# 48000개의 샘플
time_frame = np.arange(total_number_of_samples)
# time_frame을 second 단위로 변환
time_frame_in_sec = time_frame / sample_rate
# sin파 = sin(각속도 * time)
sine_wave = np.sin(2 * np.pi * (frequency * time_frame_in_sec)) * amplitude
# Frequency (period / sec) * time (sec) = period
# 즉 주어진 시간 동안 몇번 주기를 반복했는지 (몇 바퀴 회전하였는지)
# 한바퀴 회전을 각(radian)으로 표현하면 2*pi

plt.plot(sine_wave[:100])

soundfile

soundfile은 wave 파일로 만들어준 파형을 저장을 해준다. 이를 librosa를 통해 불러오면 해상도를 default Hz인 22050으로 다시 자르게 된다. 그렇게 되면 이미지처럼 음파도 열화가 되는걸까?

import soundfile as sf
sf.write('clipping.wav', data=sine_wave, samplerate=sample_rate)
sine_wave_load, sr_load = librosa.load('clipping.wav')
print(sine_wave_load.shape, sr_load)
# (66150,) 22050
ipd.display(ipd.Audio(sine_wave_load, rate=sr_load))
plt.plot(sine_wave_load[:100])

소리의 합성

def make_sine_wave(freq, amp, dur, sr=16000):
  '''
  입력 : Frequency, Amplitude, Duration, sample rate
  출력 : 1D array
  '''
  total_number_of_samples = dur * sr
  time_frame = np.arange(total_number_of_samples)
  time_frame_in_sec = time_frame / sr
  sine_wave = np.sin(2 * np.pi * (freq * time_frame_in_sec)) * amp

  return sine_wave
  
fund = make_sine_wave(220, 0.8, 3)
harmonic_1 = make_sine_wave(220 * 2, 0.5, 3)
harmonic_2 = make_sine_wave(220 * 4, 0.5, 3)

combine = fund + harmonic_1 + harmonic_2
plt.plot(combine[:200])
ipd.Audio(combine, rate=sample_rate)

import random

num_harmonics = 10
fund_frequency = 220
fund = make_sine_wave(fund_frequency, 1, 3)
for i in range(2,50):
  harmonics = make_sine_wave(fund_frequency * i, random.random()/i, 3)
  fund += harmonics

plt.plot(fund[:300])
ipd.Audio(fund, rate=sample_rate)

클래스로 만들어보기

class Oscilator:
  def __init__(self, frequency, amplitude=1, sample_rate=16000):
    self.frequency = frequency
    self.amplitude = amplitude
    self.sample_rate = 16000

  def generate(self, duration):
    return make_sine_wave(self.frequency, self.amplitude, duration, sr=self.sample_rate)

  def generate_with_harmonics(self, duration): # class method의 첫번째 인풋은 self
    fund = make_sine_wave(self.frequency, self.amplitude, duration)
    for i in range(2,50):
      harmonics = make_sine_wave(self.frequency * i, self.calculate_harmonics_amplitude(i), duration)
      fund += harmonics
    return fund
  
  def calculate_harmonics_amplitude(self, i):
    return self.amplitude

oscil_a = Oscilator(440)
print(oscil_a.frequency)

output = oscil_a.generate_with_harmonics(5)
ipd.display(ipd.Audio(oscil_a.generate(5), rate=oscil_a.sample_rate))
plt.plot(output[:100])

class RandomOscil(Oscilator):
  def __init__(self, freq, amp, sr):
    # 부모 클래스의 init을 진행하는 코드
    super().__init__(freq, amp, sr)
  
  def calculate_harmonics_amplitude(self, i):
    return random.random() * self.amplitude / i

rand_oscil = RandomOscil(440, 0.3, 16000)
print(rand_oscil.frequency)
output = rand_oscil.generate_with_harmonics(4)
plt.plot(output[:100])
ipd.Audio(output, rate=rand_oscil.sample_rate)

class SawOscil(Oscilator):
  def __init__(self, freq, amp, sr):
    super().__init__(freq, amp, sr)
  
  def calculate_harmonics_amplitude(self, i):
    return self.amplitude / i

saw_oscil = SawOscil(440, 0.3, 16000)
print(saw_oscil.frequency)
output = saw_oscil.generate_with_harmonics(4)
plt.plot(output[:100])
ipd.Audio(output, rate = saw_oscil.sample_rate)

profile
chords & code // harmony with structure

0개의 댓글