Derzeit scheint es keine freie Software zu geben, die das Audiospektrum (Wellenform im Frequenzbereich, der sich gemäß den üblichen Geräuschen schleimig bewegt) auf einem Mac verwenden kann. Machen wir also unsere eigene mit Python und spielen wir damit.
(Für Windows scheint es, dass Sie dies mit der kostenlosen Software AviUtl tun können.)
Ich habe eine Datei im ** WAV-Format **, mit der ich eine Sprachwellenform erstellen möchte. (In meinem Fall ist es die Ausgabedatei des Songs, den ich in GarageBand eingegeben habe.) Ich möchte dies in ein Videoformat konvertieren, aber es ist etwas langweilig für ein Video, bei dem nur Audio in einem Standbild fließt.
Daher besteht der Zweck dieser Zeit darin, ein ** Audiospektrum ** zu erstellen, das sich entsprechend dem von Ihnen erstellten Song bewegt, sodass es mehr oder weniger als Video aussieht.
Sie können so etwas machen ↓ https://www.youtube.com/watch?v=JPE54SlF6H0 Pokemon Sword Shield Kampf! Beat [8-Bit-Tonquellenanordnung]](http://img.youtube.com/vi/JPE54SlF6H0/0.jpg)](http://www.youtube.com/watch?v=JPE54SlF6H0)
OS:macOS High Sierra 10.13.6 Sprache: Python 3.7.4
Andere als die Standardbibliothek,
Erfordert die Installation. Grundsätzlich denke ich, dass pip (pip3) in Ordnung ist. Ich werde es schreiben, damit auch diejenigen, die nur NumPy verstehen, es lesen können (weil ich es bin).
Dies ist ein Beispielcode, der nur hellblaue Wellen auf einem rosa Hintergrund bewegt. Wenn Sie eine Tonquelle mit dem Namen "sample.wav" in derselben Ebene wie das Programm vorbereiten, können Sie sie vorerst verschieben. Mono-Stereo ist ziemlich grob, aber beide werden unterstützt. [Kostenlose Tonquelle wie diese](https://on-jin.com/sound/listshow.php?pagename=ta&title=%E3%82%B3%E3%83%B3%E3%83%88%E3%81 % AE% E3% 82% AA% E3% 83% 8102% EF% BC% 88% E3% 83% 81% E3% 83% A3% E3% 83% B3% E3% 83% 81% E3% 83% A3 % E3% 83% B3% EF% BC% 89 & jann =% E3% 81% 9D% E3% 81% AE% E4% BB% 96% E9% 9F% B3 & bunr =% E3% 83% 90% E3% 83% A9 % E3% 82% A8% E3% 83% 86% E3% 82% A3 & Kate =% E3% 81% 9D% E3% 81% AE% E4% BB% 96) Sie können auch spielen.
Nachdem ich das Ganze gepostet habe, möchte ich genauer hinsehen.
SampleAudioVisualizer.py
#!/usr/bin/env python3
import wave
import sys
import pygame
from pygame.locals import *
import scipy.fftpack as spfft
import soundfile as sf
import pyaudio
import numpy as np
# --------------------------------------------------------------------
#Parameter
# --------------------
fn = "sample.wav"
#zur Berechnung
CHUNK = 1024 #Ausgabe zum Streamen in Stücken mit Pyaudio(Ich weiß nicht warum 1024)
start = 0 #Startposition der Probenahme
N = 1024 #Anzahl der FFT-Proben
SHIFT = 1024 #Anzahl der Abtastwerte zum Verschieben der Fensterfunktion
hammingWindow = np.hamming(N) #Fensterfunktion
# --------------------
#Zum Zeichnen
SCREEN_SIZE = (854, 480) #Bildschirmgröße
rectangle_list = []
# --------------------
#Grundeinstellungen des Pygame-Bildschirms
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE)
pygame.display.set_caption("Pygame Audio Visualizer")
# --------------------------------------------------------------------
#Neuzeichnungsfunktion wird später beim Abspielen der WAV-Datei neu gezeichnet()Funktion zum Aufrufen
def play_wav_file(filename):
try:
wf = wave.open(filename, "r")
except FileNotFoundError: #Wenn die Datei nicht existiert
print("[Error 404] No such file or directory: " + filename)
return 0
#Stream öffnen
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
#Audio abspielen
data = wf.readframes(CHUNK)
while data != '':
stream.write(data)
data = wf.readframes(CHUNK)
redraw()
stream.close()
p.terminate()
# --------------------------------------------------------------------
#Wiederholen Sie "Zeichnen mit FFT".
def redraw():
global start
global screen
global rectangle_list
# --------------------
#Berechnen Sie das Amplitudenspektrum, indem Sie FFT auf den Block des Zielabtastpunkts anwenden
windowedData = hammingWindow * x[start:start + N] #Datenblock mit Fensterfunktion
X = spfft.fft(windowedData) # FFT
amplitudeSpectrum = [np.sqrt(c.real ** 2 + c.imag ** 2)
for c in X] #Schwingungsspektrum
# --------------------
#Zeichnen im Pygame
screen.fill((240, 128, 128)) #Initialisieren Sie mit Ihrer Lieblingsfarbe
rectangle_list.clear() #Quadratische Listeninitialisierung
#Spektralzeichnung Beim Ausführen und Anpassen von Zahlenwerten
for i in range(86):
rectangle_list.append(pygame.draw.line(screen, (102, 205, 170), (1+i * 10, 350 + amplitudeSpectrum[i] * 1),
(1+i * 10, 350 - amplitudeSpectrum[i] * 1), 4))
pygame.display.update(rectangle_list) #Update anzeigen
start += SHIFT #Verschieben Sie den Bereich, um die Fensterfunktion anzuwenden
if start + N > nframes:
sys.exit()
for event in pygame.event.get(): #Verarbeitung beenden
if event.type == QUIT:
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
sys.exit()
# --------------------------------------------------------------------
if __name__ == "__main__":
# --------------------
#Holen Sie sich WAV-Daten
data, fs = sf.read(fn) #Die Form der Daten ist(Anzahl der Frames x Anzahl der Kanäle)
if data.ndim == 1:
x = data #Wenn es monaural ist, verwenden Sie es so wie es ist
if data.ndim == 2:
x = data[:, 0] #Wenn es Stereo ist, werde ich mich nur auf den L-Kanal konzentrieren(Ändern Sie für R 0 in 1)
nframes = x.size #Holen Sie sich die Anzahl der Frames(Wird als Endbedingung beim Verschieben der Fensterfunktion in FFT verwendet)
# --------------------
#Starten Sie die Wiedergabe und das Zeichnen
play_wav_file(fn)
# --------------------------------------------------------------------
Der Datenteil im WAV-Format sind Zeitreihendaten, die Toninformationen für jede ** 1 / fs ** Sekunde enthalten (fs: Abtastfrequenz [Hz]).
(Ergänzung) Um das Abrufen eines Bildes zu vereinfachen, [Kostenlose Tonquelle](https://on-jin.com/sound/listshow.php?pagename=ta&title=%E3%82%B3%E3%83] % B3% E3% 83% 88% E3% 81% AE% E3% 82% AA% E3% 83% 8102% EF% BC% 88% E3% 83% 81% E3% 83% A3% E3% 83% B3 % E3% 83% 81% E3% 83% A3% E3% 83% B3% EF% BC% 89 & Garn =% E3% 81% 9D% E3% 81% AE% E4% BB% 96% E9% 9F% B3 & bunr = % E3% 83% 90% E3% 83% A9% E3% 82% A8% E3% 83% 86% E3% 82% A3 & Kate =% E3% 81% 9D% E3% 81% AE% E4% BB% 96) Zeichnen wir die Daten von. (Da diese Tonquelle Stereo ist, nehme ich nur den L-Kanal) So können Sie sehen, dass diese Daten (Array) Wellen enthalten, die Werte von -1 bis +1 annehmen. Die horizontale Achse ist der Index des Arrays. Da die Information von "1 / fs" Sekunden (in diesem Beispiel übrigens "fs = 44,1 [kHz]") für jedes Element ausgedrückt wird, ist es die "Wellenform auf der Zeitachse". ..
Es ist möglicherweise einfacher zu sagen, dass Sie in Sekunden konvertieren können, indem Sie die horizontale Achse dieses Diagramms mit "1/44100" multiplizieren.
Das Audiospektrum hingegen ist ein sich ständig ändernder Graph im Frequenzbereich. ** Daten im Zeitbereich können im Frequenzbereich durch Durchführen einer Fourier-Transformation ** angezeigt werden. Es scheint also, dass wir fortfahren werden, während wir die Fourier-Transformation gut nutzen.
Deshalb,
Es scheint gut zu sein, die Verarbeitung durchzuführen. Es ist ein Bild, das häufig die Sprachwiedergabe und Fourier-Konvertierung in Echtzeit wiederholt.
Ich versuche übrigens, WAV-Datenpunkte zu verarbeiten, indem ich 1024 um 1024 als "Kurzzeitdaten" verschiebe, aber es muss nicht separat 1024 sein. Wenn Sie es jedoch zu klein machen, dauert das Zeichnen länger als das Spielen, sodass das Verhalten seltsam ist. Wenn Sie es zu groß machen, wird die Zeichnung langsam aktualisiert und die Glätte geht verloren. Seien Sie also vorsichtig.
Dieser Teil der Hauptroutine.
Auszug
import soundfile as sf
fn = "sample.wav"
# (Abkürzung)
# --------------------------------------------------------------------
if __name__ == "__main__":
# --------------------
#Holen Sie sich WAV-Daten
data, fs = sf.read(fn) #Die Form der Daten ist(Anzahl der Frames x Anzahl der Kanäle)
if data.ndim == 1:
x = data #Wenn es monaural ist, verwenden Sie es so wie es ist
if data.ndim == 2:
x = data[:, 0] #Wenn es Stereo ist, werde ich mich nur auf den L-Kanal konzentrieren(Ändern Sie für R 0 in 1)
nframes = x.size #Holen Sie sich die Anzahl der Frames(Es wird als Endbedingung beim Verschieben der Fensterfunktion in der später beschriebenen FFT verwendet.)
# --------------------
# (Abkürzung)
Sie können PySoundFile verwenden, um WAV-Dateien gut zu handhaben. Ich konnte die Daten und ihre Länge mit der Methode "read ()" abrufen. (Referenz: Wav-Dateivorgang in Python)
Definieren Sie eine Funktion namens "play_wav_file ()", die in den Stream schreibt und das Audio in Einheiten von "CHUNK" wiedergibt. Das Modul verwendet Wave und PyAudio.
(Referenz: [Python] Wav-Datei mit Pyaudio abspielen)
Im Grunde ist es der Artikel, auf den ich mich bezog, aber ich habe eine selbst erstellte Funktion namens "redraw ()" in den Schleifenprozess des Schreibens in den Stream und des Lesens der nächsten Daten eingefügt. (Zum Anzeigen des Audiospektrums gleichzeitig mit der Wiedergabe)
Auszug
import wave
import pyaudio
# --------------------------------------------------------------------
#Parameter
# --------------------
#zur Berechnung
CHUNK = 1024 #Ausgabe zum Streamen in Stücken mit Pyaudio(Ich weiß nicht warum 1024)
# ~Unterlassung~
# --------------------------------------------------------------------
#Neuzeichnungsfunktion wird später beim Abspielen der WAV-Datei neu gezeichnet()Funktion zum Aufrufen
def play_wav_file(filename):
try:
wf = wave.open(filename, "r")
except FileNotFoundError: #Wenn die Datei nicht existiert
print("[Error 404] No such file or directory: " + filename)
return 0
#Stream öffnen
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
#Audio abspielen
data = wf.readframes(CHUNK)
while data != '':
stream.write(data)
data = wf.readframes(CHUNK)
redraw() #Es ist eine Funktion zum Neuzeichnen. Ich werde es später machen.
stream.close()
p.terminate()
# ~Unterlassung~
Dieser Artikel (Kurzzeit-Fourier-Transformation - Ein Durchbruch bei der künstlichen Intelligenz) ist sehr einfach zu verstehen und hilfreich.
Da wir zum Zeitpunkt der Audiowiedergabe früher "CHUNK = 1024" eingestellt haben, haben wir auch die Anzahl der Zielabtastwerte N, die einer Hochgeschwindigkeits-Fourier-Transformation (im Folgenden als FFT bezeichnet) unterzogen werden sollen, auf 1024 eingestellt.
Wenden Sie nach dem Extrahieren von 1024 Daten aus den gesamten Daten die ** Fensterfunktion ** an und führen Sie dann die FFT aus, anstatt die FFT so wie sie ist auszuführen. Es ist eine theoretische Geschichte geworden, aber die Seite Grund für die Verwendung der Fensterfunktion - Logical Arts Research Institute wurde im vorherigen Artikel vorgestellt. Es ist leicht verständlich organisiert, schauen Sie also bitte vorbei, wenn Sie interessiert sind.
Hier verwenden wir das Hauptfenster ** summen ** (np.hamming ()
). Durch Anwenden werden die Kanten glatt verbunden und die ausgeschnittene Probe wird zu einer periodischen Funktion.
Auszug
import sys
import scipy.fftpack as spfft
import numpy as np
# --------------------------------------------------------------------
#Parameter
# --------------------
#zur Berechnung
CHUNK = 1024 #Ausgabe zum Streamen in Stücken mit Pyaudio(Ich weiß nicht warum 1024)
start = 0 #Startposition der Probenahme
N = 1024 #Anzahl der FFT-Proben
SHIFT = 1024 #Anzahl der Abtastwerte zum Verschieben der Fensterfunktion
hammingWindow = np.hamming(N) #Fensterfunktion
# ~Unterlassung~
# --------------------------------------------------------------------
#Wiederholen Sie "Zeichnen mit FFT". Hier werden wir nur den Prozess der Anwendung von FFT betrachten.
def redraw():
global start
# ~Unterlassung~
# --------------------
#Berechnen Sie das Amplitudenspektrum, indem Sie FFT auf den Block des Zielabtastpunkts anwenden
windowedData = hammingWindow * x[start:start + N] #Datenblock mit Fensterfunktion
# (↑ Liste x[]Ist dieser Artikel 3-Es sind die in 1 extrahierten WAV-Daten.)
X = spfft.fft(windowedData) # FFT
amplitudeSpectrum = [np.sqrt(c.real ** 2 + c.imag ** 2)
for c in X] #Schwingungsspektrum
# --------------------
#Hier ist der Zeichenprozess in Pygame(Hier weggelassen)
start += SHIFT #Verschieben Sie den Bereich, um die Fensterfunktion anzuwenden
if start + N > nframes:
sys.exit() #Gehen Sie zum Ende der WAV-Datei und beenden Sie das Programm, wenn die Fensterfunktion nicht mehr angewendet werden kann
#Hier ist die Endbedingung für PyGame(Hier weggelassen)
# --------------------------------------------------------------------
# ~Unterlassung~
Was Sie tun, ist einfach, N Datenelemente abzutasten, eine Fensterfunktion anzuwenden, um eine FFT durchzuführen, das Amplitudenspektrum zu berechnen, das Abtastziel um UMSCHALT zu verschieben und sich auf den nächsten Aufruf vorzubereiten. Ich werde. Jetzt müssen Sie nur noch das berechnete Amplitudenspektrum mit ** PyGame ** zeichnen.
Ich werde mit diesem Artikel spielen (Visualizer für Anfänger mit Python).
Auszug
import pygame
from pygame.locals import *
# --------------------------------------------------------------------
#Parameter
# --------------------
# ~Unterlassung~
# --------------------
#Zum Zeichnen
SCREEN_SIZE = (854, 480) #Bildschirmgröße
rectangle_list = []
# --------------------
#Grundeinstellungen des Pygame-Bildschirms
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE)
pygame.display.set_caption("Pygame Audio Visualizer")
# --------------------------------------------------------------------
#Wiederholen Sie "Zeichnen mit FFT".
def redraw():
# ~Unterlassung~
global screen
global rectangle_list
# --------------------
#Magnitudenspektrum durch Anwenden von FFT auf den Block von Zielabtastpunkten(amplitudeSpectrum)Verarbeitung zur Berechnung(Kürzung)
# --------------------
#Zeichnen im Pygame
screen.fill((240, 128, 128)) #Initialisieren Sie mit Ihrer Lieblingsfarbe
rectangle_list.clear() #Quadratische Listeninitialisierung
#Spektralzeichnung Beim Ausführen und Anpassen von Zahlenwerten
for i in range(86):
rectangle_list.append(pygame.draw.line(screen, (102, 205, 170), (1+i * 10, 350 + amplitudeSpectrum[i] * 1),
(1+i * 10, 350 - amplitudeSpectrum[i] * 1), 4))
pygame.display.update(rectangle_list) #Update anzeigen
# ~Unterlassung~
for event in pygame.event.get(): #Verarbeitung beenden
if event.type == QUIT:
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
sys.exit()
# --------------------------------------------------------------------
# ~Unterlassung~
Das Problem ist, wie die Wellen angezeigt werden. Wenn Sie jedoch beispielsweise "pygame.draw.line" verwenden, können Sie die Wellen auf die gleiche Weise wie ein Histogramm mit mehreren geraden Linien ausdrücken. Ich denke, dass Arrangements hier so gut funktionieren werden, wie Sie möchten. Die Methoden von PyGame sind in hier organisiert. Es scheint, dass pygame.draw.line
so verwendet wird.
pygame.draw.line Zeichnen Sie ein gerades Liniensegment.
pygame.draw.line(Surface, color, start_pos, end_pos, width=1): return Rect Zeichnen Sie eine gerade Linie auf die Oberfläche. Es gibt keine spezielle Dekoration an beiden Enden der Linie und es wird eine quadratische Form, die der Dicke der Linie entspricht.
Bestimmen Sie als Beispiel für den Zeichnungsfluss im Voraus die Größe des PyGame-Fensters, initialisieren Sie es und dann
pygame.Rect
) basierend auf dem berechneten Amplitudenspektrum und behalten Sie es in der Liste.pygame.display.update ()
Ist es so Bereiten wir auch den Beendigungsprozess vor, wenn das PyGame-Fenster mit der Taste × gelöscht oder die Esc-Taste gedrückt wird.
(Übrigens ist die Anzeigegröße auf 854 * 480 eingestellt, um dem Seitenverhältnis von YouTube zu entsprechen, und der Bereich für die Schleife ist auf 86 eingestellt, wenn der Abstand zwischen den Quadraten (geraden Linien), die die diesmal erzeugten Wellen darstellen, 87 beträgt. Es ist, weil es nach den Augen vom Bildschirm verschwindet. Die Beschreibung hier ist nicht sehr klug ... Es tut mir leid. Wenn Sie spielen, während Sie die Zahlen entsprechend ändern, können Sie das Verhalten meiner Meinung nach irgendwie erfassen. )
Im Beispielcode bewegen sich nur Wellen in der Hintergrundfarbe. Sie können jedoch auch Bilder von Zeichen und Logos wie das Eröffnungs-GIF einfügen. (Referenz: Einführung in Pygame mit Python 3: Kapitel 1) Einfache Ausführung von "Surface.blit ()" in "redraw ()" Ich denke, es kann implementiert werden.
Auch dieses Mal habe ich mein Bestes getan, um ein Video zu erstellen, indem ich den erstellten Bildschirm aufzeichnete, aber es scheint, dass einige Leute Dinge tun, wie den Bildschirm von PyGame in ein Video zu schreiben. [PyGame] AVI-Export & Screenshot des Bildschirms
Ich habe Python in College-Klassen nur so weit berührt, dass ich mit Beispielcode gespielt habe, aber es ist interessant, weil es verschiedene nützliche Bibliotheken gibt. Es mag viele Orte gegeben haben, an denen ich nicht wusste, wie es geht, aber ich hoffe, ich kann es nach und nach studieren.
Danke für deine harte Arbeit!
Recommended Posts