Python-Audiosynthese

Mehvish Ashiq 16 Februar 2024
  1. Python-Audiosynthese
  2. Verwenden Sie IPython.display für Additive Synthesis in Python
  3. Erstellen Sie verschiedene grundlegende Wellenformen mit additiver Synthese in Python
  4. Verwenden Sie pyaudio, um Audiosynthese in Python zu generieren
Python-Audiosynthese

Heute lernen wir etwas über Audiosynthese und wie wir mit Python Ton erzeugen können.

Python-Audiosynthese

Tonsynthese oder Audiosynthese erzeugt elektronisch Ton (unter Verwendung von Hardware oder Software), der die menschliche Stimme oder Musikinstrumente nachahmt.

Die Synthese ist hauptsächlich für Musik gedacht, bei der ein elektronisches Gerät/Instrument, das als Synthesizer bekannt ist, zum Aufnehmen und Aufführen von Musik verwendet wird.

Der Punkt ist nun, können wir Python verwenden, um diese Art von einfachen Klängen zu erzeugen, zum Beispiel Sinuswellen? Haben wir dafür ein Modul oder wie können wir unser eigenes erstellen?

Lassen Sie uns die verschiedenen Möglichkeiten unten lernen.

Verwenden Sie IPython.display für Additive Synthesis in Python

  • Zuerst importieren wir die notwendigen Module und Bibliotheken. Wir importieren IPython, um den Soundplayer anzuzeigen, numpy für die Arbeit mit Arrays, matplotlib zum Zeichnen von Diagrammen (wir werden dies tun, während wir grundlegende Wellenformen erzeugen) und math, um mathematische Funktionen zu verwenden.
    import IPython.display as ipd
    import numpy
    import math
    import matplotlib.pyplot as plt
    
  • Stellen Sie die Abtastrate ein. Hier setzen wir die sample_rate mit 22050.
    sample_rate = 22050
    
  • Machen Sie die Sinuswellenform.
    def makesine(frequency, duration):
        t = numpy.linspace(0, duration, math.ceil(sample_rate * duration))
        x = numpy.sin(2 * numpy.pi * frequency * t)
        return x
    

    In diesem Schritt definieren wir eine Funktion makesine(), die Frequenz und Dauer als Parameter nimmt. Wir verwenden duration in numpy.linspace() und frequency in numpy.sin()-Methoden, um reine Sinuswellenformen wiederzuverwenden.

    Beachten Sie, dass numpy.linspace() numerische Sequenzen erstellt, oder wir können sagen, dass es Zahlen/Samples mit gleichen Abständen bzgl. Intervall (Start, Stop). Es ist ähnlich wie numpy.arange(), nimmt aber anstelle von step eine Sample-Nummer (num) als Parameter.

    Mehr dazu finden Sie hier.

    Andererseits berechnet numpy.sin() den trigonometrischen Sinus für alle angegebenen x (ein Array von Elementen).

  • Führen Sie makesine() aus.
    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)
    

    Als nächstes führen wir makesine() mehrmals aus, um eine neue Wellenform mit der angegebenen Frequenz und Dauer zu bilden. Danach verwenden wir numpy.concatenate(), um sie alle zusammen zu platzieren.

    Den vollständigen funktionierenden Quellcode finden Sie unten mit der jeweiligen Ausgabe.

  • Hier ist der komplette Quellcode.
    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)
    

    AUSGANG:

    Python-Audiosynthese - ipython display.wav

Erstellen Sie verschiedene grundlegende Wellenformen mit additiver Synthese in Python

Wir sind mit der grundlegenden Sinuswellenform fertig. Lassen Sie uns mit verschiedenen grundlegenden Wellenformen mit Frequenzen bei ganzzahligen Vielfachen experimentieren, indem wir Frequenz * i verwenden; hier ist i der Zähler von 1 und erhöht jedes Mal um 1.

Wir müssen diese Sinuswellen zu vordefinierten Amplituden (amplist) weicher machen, die dann im output gestapelt werden. Um dies zu erreichen, müssen wir eine Funktion namens addsyn() wie folgt erstellen:

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

Innerhalb des addsyn() initialisieren wir einen neuen output. Innerhalb der for-Schleife erzeugen wir die Sinuswellenform mit maximaler Amplitude (amp); Frequenz ist hier ein ganzzahliges Vielfaches.

Dann summieren wir es zur Ausgabe und speichern es in der Variable output. Als nächstes stellen wir sicher, dass die maximale Amplitude 1 nicht überschreitet und geben die Ausgabe zurück.

Jetzt können wir den folgenden Code ausführen, um nur eine harmonische Sinuswelle zu erzeugen, und ein Diagramm dafür erstellen, das nur 0.005 Sekunden anzeigt, um diese Wellenformform zu sehen.

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)

Der vollständige Quellcode würde wie folgt aussehen.

Beispielcode:

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)

AUSGANG:

Python-Audiosynthese - Grundlegende Sinuswellenform harmonisch.wav

Python-Audiosynthese - grundlegendes Sinuswellenform-Oberwellendiagramm

Jetzt können wir mit verschiedenen Werten der Funktion addsyn() herumspielen, um unterschiedliche Ausgaben zu erhalten. Sehen Sie sich unten ein weiteres Beispiel zum Erstellen einer Rechteckwelle an.

Beispielcode:

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)

AUSGANG:

Python-Audiosynthese - Grundlegende Sinuswellenform quadratisch.wav

Python-Audiosynthese - Grundlegendes Sinuswellenform-Quadratdiagramm

Verwenden Sie pyaudio, um Audiosynthese in Python zu generieren

Hier verwenden wir pyaudio, ein Python-Modul, das Audio mit Python aufzeichnet.

  • Zuerst importieren wir die notwendigen Bibliotheken: math zum Ausführen mathematischer Funktionen und pyaudio zum Erzeugen von Wellen.
    import math  # import needed modules
    import pyaudio  # sudo apt-get install python-pyaudio
    
  • Initialisieren Sie pyaudio.
    PyAudio = pyaudio.PyAudio
    
  • Variablen initialisieren.
    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 = ""
    

    Hier haben wir die bit_rate mit 16000 initialisiert, was die Anzahl der Bilder pro Sekunde anzeigt. Die Frequenz ist auf 500 Hz eingestellt, was die Wellen pro Sekunde bezeichnet (261.63=C4-Ton), während die Länge mit 1 initialisiert ist.

    Danach verwenden wir die Funktion max(), um das Maximum aus bit_rate und frequency+100 zu finden und weisen bit_rate den maximalen Wert zu. Dann multiplizieren wir bit_rate und length, wandeln es mit der Funktion int() in den Typ int um und weisen es number_of_frames zu.

    Als nächstes verwenden wir den Modulo-Operator (%), um number_of_frames durch bit_rate zu dividieren und den Rest rest_frames zuzuweisen. Abschließend initialisieren wir wave_data mit einem leeren String.

  • Wellen erzeugen.
    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)
    

    Hier haben wir zwei for-Schleifen verwendet, die bis zur number_of_frames iterieren, um Wellen zu erzeugen.

  • Ton aufnehmen.
    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()
    

    Hier haben wir eine Instanz von PyAudio erstellt, die Referenz in p gespeichert und diese Referenz verwendet, um einen Stream mit der Methode open() zu öffnen, der Audio aufzeichnet. Als nächstes schrieben wir wave_data, stoppten den Stream und schlossen ihn. Beenden Sie abschließend auch die PyAudio-Instanz (p).

    Über open(), write(), stop_stream() und close() können Sie hier im Detail nachlesen.

  • Hier ist der komplette Quellcode.
    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()
    

    Sobald wir den obigen Code ausführen, können wir eine Welle hören. Beachten Sie, dass wir diese Wave nicht in einer .wav-Datei speichern.

    Sie können hier lesen, um mehr über das Speichern in einer .wav-Datei zu erfahren.

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

Verwandter Artikel - Python Audio