Bonjour tous le monde
Soudain, j'ai commencé à jouer avec python et c'est la troisième fois, mais cette fois je jouerai également avec le fichier wav. Cette fois, nous allons effectuer une transformée de Fourier sur les données de forme d'onde lues par wav, ou les restaurer par transformée de Fourier inverse et l'écrire dans wav.
Le son est généré par la vibration de l'air (son). En outre, la vibration est constituée de vibrations superposées de fréquences multiples. Parmi ces vibrations sonores, la fréquence dominante détermine la hauteur, la magnitude de l'amplitude détermine le volume du son et les vibrations de diverses fréquences non dominantes déterminent la tonalité du son.
Comme le son contient différentes fréquences, il est difficile de l'analyser tel quel. Par conséquent, une méthode a été inventée pour exprimer le son par une simple superposition. C'est l'expansion de la classe Fourier.
f(t) = \sum_k a_k e^{\rm{i}kt}, \ \ \ \ \ e^{\rm{i}kt} = \cos(kt) + \rm{i}\sin(kt)
C'est comme ça. Je ne parlerai pas de mathématiques ici, donc si vous ne le comprenez pas, vous voudrez peut-être le rechercher dans la formule d'Euler. Maintenant, si vous connaissez $ a_k $ ici, vous pouvez approximer ce $ f (t) $. Comment devriez-vous le trouver? Utilisons une petite astuce, mais supposons d'abord que vous observiez $ f (t) $ pendant un certain temps, $ T $. Multipliez les deux côtés de l'expansion de la série précédente par $ e ^ {- \ rm {i} k't} $ et essayez d'intégrer.
\int_0^T f(t)e^{-\rm{i}k't}dt = \sum_k a_k \int_0^T e^{\rm ikt - ik't}dt
Ce sera. Si vous sélectionnez $ k $ comme $ 2n \ pi / T $ ici, l'intégration sur le côté droit ne restera que lorsque $ k = k '$.
a_k = \frac{1}{T} \int_0^T f(t)e^{-\rm ikt}dt
Ce calcul pour trouver $ a_k $ s'appelle la transformation de Fourier. En réalité, cette intégrale est approchée par calcul numérique.
Une fois que vous avez $ a_k $, l'expansion de la classe de Fourier est terminée. La génération de la forme d'une fonction d'espace réel à partir de la distribution de $ a_k $ est appelée transformation inverse de Fourier.
Eh bien, mettons de côté l'histoire théorique et effectuons le traitement proprement dit. Identique à la dernière fois Utilisez jupyter. Tout d'abord, lisez le fichier wav comme d'habitude.
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('Canal', ch)
print('Nombre total d'images', fn)
print('Temps d'échantillonnage', 1.0 * N * span / fr, 'Secondes')
origin = wr.readframes(wr.getnframes())
data = origin[:N * span * ch * width]
wr.close()
print('Longueur actuelle du tableau', len(origin))
print('Exemple de longueur de séquence: ', len(data))
Quand tu fais ça,
Canal 2
Nombre total de vues 15884224
Temps d'échantillonnage 87.07482993197279 secondes
Longueur actuelle du tableau 63536896
Exemple de longueur de séquence: 15360000
Le résultat est comme ça. La raison pour laquelle la longueur du tableau «d'origine» de lecture est quatre fois le nombre de trames semble être parce qu'une trame fait 4 octets parce qu'elle est stéréo et que la taille de l'échantillon est de 2 (16 bits). ʻOrigin` est une chaîne d'octets, donc c'est naturel. .. ..
Pour le moment, traitons les données extraites afin qu'elles puissent être facilement converties en Fourier.
#Hypothèse stéréo
X = np.frombuffer(data, dtype="int16")
left = X[::2]
right = X[1::2]
Tout d'abord, lisez les exemples de données avec int16 et divisez-les en le son entendu de la gauche et le son entendu de la droite.
Ensuite, définissez la conversion de Fourier et la conversion inverse (expansion de classe). Cette fois, nous utiliserons numpy fft. fft est une bibliothèque pour 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
La fonction «fourier» renvoie un tableau de distributions de fréquences pour chaque intervalle d'échantillonnage. La fonction ʻinverse_fourier` génère une forme d'onde dans l'espace réel basée sur la distribution de fréquence.
Cette fois, je ne ferai aucun traitement spécial, je convertis simplement la conversion de Fourier immédiatement et la conversion inverse et l'écrirai en wav.
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='-')
Commençons par le convertir en Fourier. Ensuite, la distribution de fréquence pour chaque section d'échantillon peut être obtenue. Si vous tracez la distribution à un moment approprié, vous obtiendrez le résultat suivant.
Après avoir confirmé que la distribution de fréquence est correcte, effectuons une conversion inverse.
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)
C'est un peu gênant, mais comme il s'agit d'une source sonore stéréo, le Fourier inverse de la source sonore gauche et le Fourier inverse de la source sonore droite sont mélangés.
#Exportation
outf = '/data/output/test.wav'
ww = wave.open(outf, 'w')
ww.setnchannels(ch)
ww.setsampwidth(width)
ww.setframerate(fr)
ww.writeframes(outd)
ww.close()
Alors, je vais l'écrire.
J'ai fait quelque chose qui ne semble pas contre nature, même pour moi-même sans entendre.
J'ai converti le contenu du fichier wav en Fourier et joué avec. Pour le moment, c'est comme ça cette fois.
Recommended Posts