파이썬 오디오 합성

Mehvish Ashiq 2024년2월16일
  1. 파이썬 오디오 합성
  2. Python에서 추가 합성에 IPython.display 사용
  3. Python에서 가산 합성으로 다양한 기본 파형 만들기
  4. Python에서 pyaudio를 사용하여 오디오 합성 생성
파이썬 오디오 합성

오늘은 오디오 합성에 대해 알아보고 파이썬으로 소리를 생성하는 방법에 대해 알아보겠습니다.

파이썬 오디오 합성

사운드 합성 또는 오디오 합성은 사람의 목소리나 악기를 모방하는 사운드를 전자적으로(하드웨어 또는 소프트웨어 사용) 생성합니다.

합성은 주로 음악용으로, 신디사이저로 알려진 전자 장치/악기가 음악을 녹음하고 연주하는 데 사용됩니다.

이제 요점은 파이썬을 사용하여 이러한 종류의 간단한 소리, 예를 들어 사인파를 생성할 수 있습니까? 이를 위한 모듈이 있습니까? 아니면 어떻게 자체 모듈을 만들 수 있습니까?

아래에서 다양한 방법을 알아봅시다.

Python에서 추가 합성에 IPython.display 사용

  • 먼저 필요한 모듈과 라이브러리를 가져옵니다. 우리는 IPython을 가져와서 사운드 플레이어를 표시하고 numpy를 사용하여 배열 작업을 하고 matplotlib를 가져와 차트를 플로팅합니다(기본 파형을 생성하는 동안 수행할 예정임). math를 사용하여 수학 함수를 사용합니다.
    import IPython.display as ipd
    import numpy
    import math
    import matplotlib.pyplot as plt
    
  • 샘플 속도를 설정합니다. 여기에서 sample_rate22050으로 설정합니다.
    sample_rate = 22050
    
  • 사인 파형을 만듭니다.
    def makesine(frequency, duration):
        t = numpy.linspace(0, duration, math.ceil(sample_rate * duration))
        x = numpy.sin(2 * numpy.pi * frequency * t)
        return x
    

    이 단계에서 makesine() 함수를 정의합니다. 이 함수는 주파수지속 시간을 매개변수로 사용합니다. 순수한 사인 파형을 재사용하기 위해 numpy.linspace()에서 duration을 사용하고 numpy.sin() 메소드에서 frequency를 사용합니다.

    numpy.linspace()는 숫자 시퀀스를 생성하거나 균일한 간격의 숫자/샘플 w.r.t를 반환한다고 말할 수 있습니다. 간격(시작, 중지). numpy.arange()와 유사하지만 step 대신 샘플 번호(num)를 매개 변수로 사용합니다.

    여기에서 자세한 내용을 확인할 수 있습니다.

    반면 numpy.sin()은 지정된 모든 x(요소 배열)에 대한 삼각 사인을 계산합니다.

  • makesine()을 실행합니다.
    output = numpy.array(())
    y = makesine(261.63, 0.5)  # C for 0.5 seconds
    
    output = numpy.concatenate((output, y))
    y = makesine(293.66, 0.5)  # D for 0.5 seconds
    
    output = numpy.concatenate((output, y))
    y = makesine(329.63, 0.5)  # E for 0.5 seconds
    
    output = numpy.concatenate((output, y))
    ipd.Audio(output, rate=sample_rate)
    

    다음으로 makesine()을 여러 번 실행하여 지정된 주파수지속 시간으로 새 파형을 형성합니다. 그런 다음 numpy.concatenate()를 사용하여 모두 함께 배치합니다.

    아래에서 각각의 출력과 함께 작동하는 전체 소스 코드를 찾을 수 있습니다.

  • 다음은 전체 소스 코드입니다.
    import IPython.display as ipd
    import matplotlib.pyplot as plt
    import numpy
    import math
    
    sample_rate = 22050
    
    
    def makesine(frequency, duration):
        t = numpy.linspace(0, duration, math.ceil(sample_rate * duration))
        x = numpy.sin(2 * numpy.pi * frequency * t)
        return x
    
    
    output = numpy.array(())
    y = makesine(261.63, 0.5)  # C for 0.5 seconds
    
    output = numpy.concatenate((output, y))
    y = makesine(293.66, 0.5)  # D for 0.5 seconds
    
    output = numpy.concatenate((output, y))
    y = makesine(329.63, 0.5)  # E for 0.5 seconds
    
    output = numpy.concatenate((output, y))
    ipd.Audio(output, rate=sample_rate)
    

    출력:

    python 오디오 합성 - ipython display.wav

Python에서 가산 합성으로 다양한 기본 파형 만들기

기본 사인 파형으로 작업을 완료했습니다. 주파수 * i를 사용하여 정수 배수의 주파수를 사용하여 다양한 기본 파형을 실험해 봅시다. 여기서 i1의 카운터이며 매번 1씩 증가합니다.

이러한 사인파를 미리 정의된 진폭(amplist)으로 부드럽게 해야 합니다. 그런 다음 output에 누적됩니다. 그렇게 하려면 다음과 같이 addsyn()이라는 함수를 만들어야 합니다.

def addsyn(frequency, duration, amplist):
    i = 1
    t = numpy.linspace(0, duration, math.ceil(sample_rate * duration))
    output = numpy.zeros(t.size)

    for amp in amplist:
        x = numpy.multiply(makesine(frequency * i, duration), amp)
        output = output + x
        i += 1

    if numpy.max(output) > abs(numpy.min(output)):
        output = output / numpy.max(output)
    else:
        output = output / -numpy.min(output)
    return output

addsyn() 내부에서 새 output을 초기화합니다. for 루프 내에서 최대 진폭(amp)으로 사인 파형을 만듭니다. 여기서 주파수는 정수 배수입니다.

그런 다음 출력에 합산하여 output 변수에 저장합니다. 다음으로 최대 진폭이 1을 초과하지 않는지 확인하고 output을 반환합니다.

이제 다음 코드를 실행하여 하나의 고조파 사인파만 만들고 이 파형 모양을 보기 위해 0.005초만 표시하는 차트를 만들 수 있습니다.

t = numpy.linspace(0, 1, sample_rate)
sinewave = addsyn(440, 1, [1])
plt.plot(t, sinewave)
plt.xlim(0, 0.005)
ipd.Audio(sinewave, rate=sample_rate)

전체 소스 코드는 다음과 같습니다.

예제 코드:

import IPython.display as ipd
import matplotlib.pyplot as plt
import numpy
import math

sample_rate = 22050


def addsyn(frequency, duration, amplist):
    i = 1
    t = numpy.linspace(0, duration, math.ceil(sample_rate * duration))
    output = numpy.zeros(t.size)

    for amp in amplist:
        x = numpy.multiply(makesine(frequency * i, duration), amp)
        output = output + x
        i += 1

    if numpy.max(output) > abs(numpy.min(output)):
        output = output / numpy.max(output)
    else:
        output = output / -numpy.min(output)
    return output


t = numpy.linspace(0, 1, sample_rate)
sinewave = addsyn(440, 1, [1])
plt.plot(t, sinewave)
plt.xlim(0, 0.005)
ipd.Audio(sinewave, rate=sample_rate)

출력:

python 오디오 합성 - 기본 사인 파형 harmonic.wav

python 오디오 합성 - 기본 사인 파형 고조파 그래프

이제 addsyn() 함수의 다른 값을 사용하여 다른 출력을 얻을 수 있습니다. 아래의 구형파를 생성하는 또 다른 예를 참조하십시오.

예제 코드:

import IPython.display as ipd
import matplotlib.pyplot as plt
import numpy
import math

sample_rate = 22050


def addsyn(frequency, duration, amplist):
    i = 1
    t = numpy.linspace(0, duration, math.ceil(sample_rate * duration))
    output = numpy.zeros(t.size)

    for amp in amplist:
        x = numpy.multiply(makesine(frequency * i, duration), amp)
        output = output + x
        i += 1

    if numpy.max(output) > abs(numpy.min(output)):
        output = output / numpy.max(output)
    else:
        output = output / -numpy.min(output)
    return output


t = numpy.linspace(0, 1, sample_rate)
square_wave = addsyn(440, 1, [1, 0, 0.349, 0, 0.214, 0, 0.156, 0, 0.121, 0])
plt.plot(t, square_wave)
plt.xlim(0, 0.005)
ipd.Audio(square_wave, rate=sample_rate)

출력:

python 오디오 합성 - 기본 사인 파형 square.wav

python 오디오 합성 - 기본 사인 파형 사각형 그래프

Python에서 pyaudio를 사용하여 오디오 합성 생성

여기에서는 Python으로 오디오를 녹음하는 Python 모듈인 pyaudio를 사용합니다.

  • 먼저 필요한 라이브러리를 가져옵니다. 수학 함수를 수행하기 위한 math와 웨이브 생성을 위한 pyaudio입니다.
    import math  # import needed modules
    import pyaudio  # sudo apt-get install python-pyaudio
    
  • pyaudio를 초기화합니다.
    PyAudio = pyaudio.PyAudio
    
  • 변수를 초기화합니다.
    bit_rate = 16000
    frequency = 500
    length = 1
    
    bit_rate = max(bit_rate, frequency + 100)
    number_of_frames = int(bit_rate * length)
    rest_frames = number_of_frames % bit_rate
    wave_data = ""
    

    여기에서 초당 프레임 수를 나타내는 16000으로 bit_rate를 초기화했습니다. 주파수는 초당 파동(261.63=C4-note)을 나타내는 500 Hz로 설정되고 길이1로 초기화됩니다.

    그런 다음 max() 함수를 사용하여 bit_ratefrequency+100에서 최대값을 찾고 최대값을 bit_rate에 할당합니다. 그런 다음 bit_ratelength를 곱하고 int() 함수를 사용하여 int 유형으로 변환하고 number_of_frames에 할당합니다.

    다음으로 모듈로 연산자(%)를 사용하여 number_of_framesbit_rate로 나누고 나머지를 rest_frames에 할당합니다. 마지막으로 빈 문자열로 wave_data를 초기화합니다.

  • 파도를 생성합니다.
    for x in range(number_of_frames):
        wave_data = wave_data + chr(
            int(math.sin(x / ((bit_rate / frequency) / math.pi)) * 127 + 128)
        )
    
    for x in range(rest_frames):
        wave_data = wave_data + chr(128)
    

    여기에서는 웨이브를 생성하기 위해 number_of_frames까지 반복되는 두 개의 for 루프를 사용했습니다.

  • 오디오를 녹음합니다.
    p = PyAudio()
    stream = p.open(
        format=p.get_format_from_width(1), channels=1, rate=bit_rate, output=True
    )
    stream.write(wave_data)
    stream.stop_stream()
    stream.close()
    p.terminate()
    

    여기에서 PyAudio 인스턴스를 생성하고 p에 참조를 저장한 다음 해당 참조를 사용하여 오디오를 녹음할 open() 메서드를 사용하여 스트림을 엽니다. 다음으로 wave_data를 작성하고 스트림을 중지하고 닫았습니다. 마지막으로 PyAudio 인스턴스(p)도 종료합니다.

    open(), write(), stop_stream()close() 여기에 대해 자세히 읽을 수 있습니다.

  • 다음은 전체 소스 코드입니다.
    import math
    import pyaudio
    
    PyAudio = pyaudio.PyAudio
    
    bit_rate = 16000
    frequency = 500
    length = 1
    
    bit_rate = max(bit_rate, frequency + 100)
    number_of_frames = int(bit_rate * length)
    rest_frames = number_of_frames % bit_rate
    wave_data = ""
    
    for x in range(number_of_frames):
        wave_data = wave_data + chr(
            int(math.sin(x / ((bit_rate / frequency) / math.pi)) * 127 + 128)
        )
    
    for x in range(rest_frames):
        wave_data = wave_data + chr(128)
    
    p = PyAudio()
    stream = p.open(
        format=p.get_format_from_width(1), channels=1, rate=bit_rate, output=True
    )
    
    stream.write(wave_data)
    stream.stop_stream()
    stream.close()
    p.terminate()
    

    위의 코드를 실행하면 파도 소리가 들립니다. 이 웨이브를 .wav 파일에 저장하지 않는다는 점에 유의하십시오.

    .wav 파일에 저장하는 방법에 대해 알아보려면 여기를 참조하십시오.

Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook

관련 문장 - Python Audio