web-dev-qa-db-fra.com

Essayer d'obtenir les fréquences d'un fichier .wav en Python

Je sais que les questions sur les fichiers .wav dans Python ont été presque battues à mort, mais je suis extrêmement frustré car personne ne semble travailler pour moi. Ce que j'essaie de faire me semble relativement simple: je veux savoir exactement quelles fréquences il y a dans un fichier .wav à des moments donnés. Je veux savoir, par exemple, "à partir du moment n millisecondes à n + 1 millisecondes, la fréquence moyenne du son était de x hertz ". J'ai vu des gens parler des transformées de Fourier et des algorithmes de Goertzel, ainsi que de divers modules, que je ne peux pas sembler pour comprendre comment faire ce que j'ai décrit. J'ai essayé de chercher des choses comme "trouver la fréquence d'un fichier wav en python" environ vingt fois en vain. Quelqu'un peut-il m'aider?

Ce que je recherche, c'est une solution comme ce pseudocode, ou au moins une qui fera quelque chose comme ce que le pseudocode veut dire:

import some_module_that_can_help_me_do_this as freq

file = 'output.wav'
start_time = 1000  # Start 1000 milliseconds into the file
end_time = 1010  # End 10 milliseconds thereafter

print("Average frequency = " + str(freq.average(start_time, end_time)) + " hz")

S'il vous plaît, supposez (comme je suis sûr que vous pouvez le dire) que je suis un idiot en mathématiques. Ceci est ma première question ici, alors soyez doux

J'ai ressenti la frustration des OP - il ne devrait pas être si difficile de trouver comment obtenir les valeurs du spectrogramme au lieu de voir l'image du spectrogramme si quelqu'un a besoin de:

#!/usr/bin/env python

import librosa
import sys
import numpy as np
import matplotlib.pyplot as plt
import librosa.display

np.set_printoptions(threshold=sys.maxsize)

filename = 'filename.wav'
Fs = 44100
clip, sample_rate = librosa.load(filename, sr=Fs)

n_fft = 1024  # frame length 
start = 0 

hop_length=512

#commented out code to display Spectrogram
X = librosa.stft(clip, n_fft=n_fft, hop_length=hop_length)
#Xdb = librosa.amplitude_to_db(abs(X))
#plt.figure(figsize=(14, 5))
#librosa.display.specshow(Xdb, sr=Fs, x_axis='time', y_axis='hz') 
#If to pring log of frequencies  
#librosa.display.specshow(Xdb, sr=Fs, x_axis='time', y_axis='log')
#plt.colorbar()

#librosa.display.waveplot(clip, sr=Fs)
#plt.show()

#now print all values 

t_samples = np.arange(clip.shape[0]) / Fs
t_frames = np.arange(X.shape[1]) * hop_length / Fs
#f_hertz = np.arange(N / 2 + 1) * Fs / N       # Works only when N is even
f_hertz = np.fft.rfftfreq(n_fft, 1 / Fs)         # Works also when N is odd

#example
print('Time (seconds) of last sample:', t_samples[-1])
print('Time (seconds) of last frame: ', t_frames[-1])
print('Frequency (Hz) of last bin:   ', f_hertz[-1])

print('Time (seconds) :', len(t_samples))

#prints array of time frames 
print('Time of frames (seconds) : ', t_frames)
#prints array of frequency bins
print('Frequency (Hz) : ', f_hertz)

print('Number of frames : ', len(t_frames))
print('Number of bins : ', len(f_hertz))

#This code is working to printout frame by frame intensity of each frequency
#on top line gives freq bins
curLine = 'Bins,'
for b in range(1, len(f_hertz)):
    curLine += str(f_hertz[b]) + ','
print(curLine)

curLine = ''
for f in range(1, len(t_frames)):
    curLine = str(t_frames[f]) + ','
    for b in range(1, len(f_hertz)): #for each frame, we get list of bin values printed
        curLine += str("%.02f" % np.abs(X[b, f])) + ','
        #remove format of the float for full details if needed
        #curLine += str(np.abs(X[b, f])) + ','
        #print other useful info like phase of frequency bin b at frame f.
        #curLine += str("%.02f" % np.angle(X[b, f])) + ',' 
    print(curLine)
1
Deepak Garud

Essayez quelque chose le long ci-dessous, cela a fonctionné pour moi avec un fichier d'onde sinusoïdale avec une fréquence de 1234 que j'ai générée à partir de cette page.

from scipy.io import wavfile

def freq(file, start_time, end_time):
    sample_rate, data = wavfile.read(file)
    start_point = int(sample_rate * start_time / 1000)
    end_point = int(sample_rate * end_time / 1000)
    length = (end_time - start_time) / 1000
    counter = 0
    for i in range(start_point, end_point):
        if data[i] < 0 and data[i+1] > 0:
            counter += 1
    return counter/length    

freq("sin.wav", 1000 ,2100)
1231.8181818181818

édité: nettoyé pour la boucle un peu

0
vitalious