Попытка получить частоты файла .wav в Python - PullRequest
0 голосов
/ 10 февраля 2019

Я знаю, что вопросы о файлах .wav в Python были почти избиты до смерти, но я крайне разочарован, потому что ни один ответ, похоже, не работает для меня.То, что я пытаюсь сделать, кажется мне относительно простым: я хочу точно знать, какие частоты есть в файле .wav в данное время.Я хочу знать, например, «от времени n миллисекунд до n + 10 миллисекунд средняя частота звука составляла x герц".Я видел людей, говорящих о преобразованиях Фурье и алгоритмах Гёртцеля, а также о различных модулях, которые я не могу понять, как добиться того, что я описал.Я пытался искать такие вещи, как «найти частоту wav-файла в python» около двадцати раз безрезультатно.Может кто-нибудь, пожалуйста, помогите мне?

Я ищу решение, подобное этому псевдокоду, или, по крайней мере, одно решение, которое будет похоже на то, к чему стремится псевдокод:

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")

Пожалуйста, предположите (как я уверен, вы можете сказать), что я идиот в математике.Это мой первый вопрос, так что будьте осторожны

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Если вы хотите обнаружить высоту звука (и кажется, что вы это делаете), то с точки зрения библиотек Python ваша лучшая ставка - aubio .Пожалуйста, обратитесь к этому примеру для реализации.

import sys
from aubio import source, pitch

win_s = 4096
hop_s = 512 

s = source(your_file, samplerate, hop_s)
samplerate = s.samplerate

tolerance = 0.8

pitch_o = pitch("yin", win_s, hop_s, samplerate)
pitch_o.set_unit("midi")
pitch_o.set_tolerance(tolerance)

pitches = []
confidences = []

total_frames = 0
while True:
    samples, read = s()
    pitch = pitch_o(samples)[0]
    pitches += [pitch]
    confidence = pitch_o.get_confidence()
    confidences += [confidence]
    total_frames += read
    if read < hop_s: break

print("Average frequency = " + str(np.array(pitches).mean()) + " hz")

Обязательно проверьте документы о методах определения высоты звука.

Я также подумал, что вас может заинтересовать оценка средней частоты и некоторых других параметров звука без использованиялюбые специальные библиотеки.Давайте просто использовать NumPy!Это должно дать вам гораздо лучшее представление о том, как можно рассчитать такие аудио функции.Он основан на specprop из seewave пакета.Проверьте документы на предмет значения вычисленных функций.

import numpy as np

def spectral_properties(y: np.ndarray, fs: int) -> dict:
    spec = np.abs(np.fft.rfft(y))
    freq = np.fft.rfftfreq(len(y), d=1 / fs)
    spec = np.abs(spec)
    amp = spec / spec.sum()
    mean = (freq * amp).sum()
    sd = np.sqrt(np.sum(amp * ((freq - mean) ** 2)))
    amp_cumsum = np.cumsum(amp)
    median = freq[len(amp_cumsum[amp_cumsum <= 0.5]) + 1]
    mode = freq[amp.argmax()]
    Q25 = freq[len(amp_cumsum[amp_cumsum <= 0.25]) + 1]
    Q75 = freq[len(amp_cumsum[amp_cumsum <= 0.75]) + 1]
    IQR = Q75 - Q25
    z = amp - amp.mean()
    w = amp.std()
    skew = ((z ** 3).sum() / (len(spec) - 1)) / w ** 3
    kurt = ((z ** 4).sum() / (len(spec) - 1)) / w ** 4

    result_d = {
        'mean': mean,
        'sd': sd,
        'median': median,
        'mode': mode,
        'Q25': Q25,
        'Q75': Q75,
        'IQR': IQR,
        'skew': skew,
        'kurt': kurt
    }

    return result_d
0 голосов
/ 10 февраля 2019

Попробуйте что-нибудь из приведенного ниже, у меня это работает с синусоидальным файлом с частотой 1234, которую я сгенерировал на этой странице.

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

отредактировано: очищено для цикланемного

...