Hallo zusammen
Plötzlich habe ich angefangen mit Python zu spielen und dies ist das dritte Mal, aber dieses Mal werde ich auch mit der WAV-Datei spielen. Dieses Mal führen wir eine Fourier-Konvertierung der von wav gelesenen Wellenformdaten durch oder stellen sie durch inverse Fourier-Konvertierung wieder her und schreiben sie in wav.
Schall wird durch die Schwingung von Luft (Schall) erzeugt. Darüber hinaus besteht die Schwingung aus überlappenden Schwingungen mehrerer Frequenzen. Unter solchen Schallschwingungen bestimmt die dominante Frequenz die Tonhöhe, die Größe der Amplitude bestimmt die Lautstärke des Schalls und die Schwingungen verschiedener nicht dominanter Frequenzen bestimmen den Ton des Schalls.
Da der Ton verschiedene Frequenzen enthält, ist es schwierig, ihn so zu analysieren, wie er ist. Daher wurde ein Verfahren erfunden, um den Klang durch eine einfache Überlagerung auszudrücken. Dies ist die Erweiterung der Fourier-Klasse.
f(t) = \sum_k a_k e^{\rm{i}kt}, \ \ \ \ \ e^{\rm{i}kt} = \cos(kt) + \rm{i}\sin(kt)
Es ist so. Ich werde hier nicht über Mathematik sprechen. Wenn Sie es also nicht verstehen, möchten Sie es vielleicht in Eulers Formel nachschlagen. Wenn Sie hier $ a_k $ kennen, können Sie dieses $ f (t) $ approximieren. Wie sollten Sie das finden? Verwenden wir einen kleinen Trick, aber nehmen wir zunächst an, Sie beobachten $ f (t) $ für eine bestimmte Zeit, $ T $. Multiplizieren Sie beide Seiten der vorherigen Serienerweiterung mit $ e ^ {- \ rm {i} k't} $ und versuchen Sie zu integrieren.
\int_0^T f(t)e^{-\rm{i}k't}dt = \sum_k a_k \int_0^T e^{\rm ikt - ik't}dt
Es wird sein. Wenn Sie hier $ k $ als $ 2n \ pi / T $ auswählen, bleibt die Integration auf der rechten Seite nur erhalten, wenn $ k = k '$.
a_k = \frac{1}{T} \int_0^T f(t)e^{-\rm ikt}dt
Diese Berechnung zum Finden von $ a_k $ wird als Fourier-Transformation bezeichnet. In der Realität wird dieses Integral durch numerische Berechnung angenähert.
Sobald Sie $ a_k $ haben, ist die Erweiterung der Fourier-Klasse abgeschlossen. Das Erzeugen der Form einer Realraumfunktion aus der Verteilung von $ a_k $ wird als Fourier-Inverse-Transformation bezeichnet.
Lassen Sie uns die theoretische Geschichte beiseite legen und die eigentliche Verarbeitung durchführen. Wie beim letzten Mal Verwenden Sie Jupyter. Lesen Sie zuerst die WAV-Datei wie gewohnt.
import wave
import struct
from scipy import fromstring, int16
import numpy as np
from pylab import *
%matplotlib inline
wavfile = '/data/input/test.wav'
wr = wave.open(wavfile, "rb")
ch = wr.getnchannels()
width = wr.getsampwidth()
fr = wr.getframerate()
fn = wr.getnframes()
N = 256
span = 15000
print('Kanal', ch)
print('Gesamtzahl der Frames', fn)
print('Beispielzeit', 1.0 * N * span / fr, 'Sekunden')
origin = wr.readframes(wr.getnframes())
data = origin[:N * span * ch * width]
wr.close()
print('Aktuelle Arraylänge', len(origin))
print('Länge der Probensequenz: ', len(data))
Wenn Sie dies tun,
Kanal 2
Gesamtzahl der Frames 15884224
Abtastzeit 87.07482993197279 Sekunden
Aktuelle Array-Länge 63536896
Länge der Probensequenz: 15360000
Das Ergebnis ist so. Der Grund, warum die Länge des gelesenen "Ursprungs" -Arrays das Vierfache der Anzahl von Frames beträgt, scheint darin zu liegen, dass ein Frame 4 Bytes groß ist, weil es Stereo ist und die Abtastgröße 2 (16 Bit) beträgt. Es ist natürlich, weil "Ursprung" eine Byte-Zeichenfolge ist. .. ..
Lassen Sie uns vorerst die extrahierten Daten so verarbeiten, dass sie leicht in Fourier konvertiert werden können.
#Stereo-Annahme
X = np.frombuffer(data, dtype="int16")
left = X[::2]
right = X[1::2]
Lesen Sie zuerst die Beispieldaten mit int16 und teilen Sie sie in den von links zu hörenden und den von rechts zu hörenden Ton auf.
Definieren Sie als Nächstes die Fourier-Konvertierung und die inverse Konvertierung (Klassenerweiterung). Dieses Mal werden wir numpy fft verwenden. fft ist eine Bibliothek für FFT (Fast Discrete Fourier Transform).
def fourier (x, n, w):
K = []
for i in range(0, w-2):
sample = x[i * n:( i + 1) * n]
partial = np.fft.fft(sample)
K.append(partial)
return K
def inverse_fourier (k):
ret = []
for sample in k:
inv = np.fft.ifft(sample)
ret.extend(inv.real)
print (len(sample))
return ret
Die Funktion "Fourier" gibt für jedes Abtastintervall ein Array von Häufigkeitsverteilungen zurück. Die Funktion "inverse_fourier" erzeugt eine Wellenform im realen Raum basierend auf der Häufigkeitsverteilung.
Dieses Mal werde ich keine spezielle Verarbeitung durchführen, sondern nur die Fourier-Konvertierung sofort konvertieren und die Konvertierung rückgängig machen und in wav schreiben.
Kl = fourier(left, N, span)
Kr = fourier(right, N, span)
freqlist = np.fft.fftfreq(N, d=1/fr)
amp = [np.sqrt(c.real ** 2 + c.imag ** 2) for c in Kl[2500]]
plot(freqlist, amp, marker= 'o', linestyle='-')
axis([0, fr / 2 , 0, 100000])
amp = [np.sqrt(c.real ** 2 + c.imag ** 2) for c in Kr[2500]]
plot(freqlist, amp, marker= 'o', linestyle='-')
Lassen Sie es uns zunächst in Fourier konvertieren. Dann kann die Häufigkeitsverteilung für jeden Probenabschnitt erhalten werden. Wenn Sie die Verteilung zu einem geeigneten Zeitpunkt zeichnen, erhalten Sie das folgende Ergebnis.
Nachdem Sie bestätigt haben, dass die Häufigkeitsverteilung korrekt ist, führen wir eine inverse Konvertierung durch.
def combine_wav (left, right):
ret = []
number = len(right) if len(left) > len(right) else len(left)
for i in range(0, number -1):
data = [int(left[i]), int(right[i])]
ret.extend(data)
return ret
left_dash = inverse_fourier(Kl)
right_dash = inverse_fourier(Kr)
raw_data = combine_wav(left_dash, right_dash)
outd = struct.pack("h" * len(raw_data), *raw_data)
Es ist ein wenig nervig, aber da es sich um eine Stereo-Tonquelle handelt, werden der umgekehrte Fourier der linken Tonquelle und der umgekehrte Fourier der rechten Tonquelle gemischt.
#Export
outf = '/data/output/test.wav'
ww = wave.open(outf, 'w')
ww.setnchannels(ch)
ww.setsampwidth(width)
ww.setframerate(fr)
ww.writeframes(outd)
ww.close()
Also werde ich es aufschreiben.
Ich habe etwas gemacht, das sich selbst für mich selbst ohne Gehör nicht unnatürlich anfühlt.
Ich habe den Inhalt der WAV-Datei in Fourier konvertiert und damit gespielt. Diesmal ist es vorerst so.