Python-Audiosynthese
- Python-Audiosynthese
-
Verwenden Sie
IPython.display
für Additive Synthesis in Python - Erstellen Sie verschiedene grundlegende Wellenformen mit additiver Synthese in Python
-
Verwenden Sie
pyaudio
, um Audiosynthese in Python zu generieren
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) undmath
, 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
mit22050
.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()
, dieFrequenz
undDauer
als Parameter nimmt. Wir verwendenduration
innumpy.linspace()
undfrequency
innumpy.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 wienumpy.arange()
, nimmt aber anstelle vonstep
eine Sample-Nummer (num
) als Parameter.Mehr dazu finden Sie hier.
Andererseits berechnet
numpy.sin()
den trigonometrischen Sinus für alle angegebenenx
(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 angegebenenFrequenz
undDauer
zu bilden. Danach verwenden wirnumpy.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:
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
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
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 undpyaudio
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
mit16000
initialisiert, was die Anzahl der Bilder pro Sekunde anzeigt. DieFrequenz
ist auf500
Hz eingestellt, was die Wellen pro Sekunde bezeichnet (261.63=C4-Ton
), während dieLänge
mit1
initialisiert ist.Danach verwenden wir die Funktion
max()
, um das Maximum ausbit_rate
undfrequency+100
zu finden und weisenbit_rate
den maximalen Wert zu. Dann multiplizieren wirbit_rate
undlength
, wandeln es mit der Funktionint()
in den Typint
um und weisen esnumber_of_frames
zu.Als nächstes verwenden wir den Modulo-Operator (
%
), umnumber_of_frames
durchbit_rate
zu dividieren und den Restrest_frames
zuzuweisen. Abschließend initialisieren wirwave_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 zurnumber_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 inp
gespeichert und diese Referenz verwendet, um einen Stream mit der Methodeopen()
zu öffnen, der Audio aufzeichnet. Als nächstes schrieben wirwave_data
, stoppten den Stream und schlossen ihn. Beenden Sie abschließend auch diePyAudio
-Instanz (p
).Über
open()
,write()
,stop_stream()
undclose()
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.