我试图测量和计算音频设备的频率响应,只需生成输入信号,然后用扫频测量输出.

以下是我试图在伪代码中实现的:

for each frequency f in (10-20k):
    generate reference signal s with frequency f
    async play s and record result r
    determine amplitude a of r using FFT
    add tuple (f,a) to result

在Python中:

import numpy as np
from matplotlib import pyplot as plt
import sounddevice as sd
import wave
from math import log10, ceil
from scipy.fft import fft, rfft, rfftfreq, fftfreq

SAMPLE_RATE = 44100     # Hertz
DURATION = 3            # Seconds

def generate_sine_wave(freq, sample_rate, duration):
    x = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
    frequencies = x * freq
    y = np.sin((2 * np.pi) * frequencies)
    return x, y

def main():
    # info about our device
    print(sd.query_devices(device="Studio 24c"))

    # default device settings
    sd.default.device = 'Studio 24c'
    sd.default.samplerate = SAMPLE_RATE

    f_start = 10
    f_end = 20000
    samples_per_decade = 10
    ndecades = ceil(log10(f_end) - log10(f_start))
    npoints = ndecades * samples_per_decade
    freqs = np.logspace(log10(f_start), log10(f_end), num=npoints, endpoint=True, base=10)
    
    measure_duration = 0.25 # seconds
    peaks = []
    for f in freqs:
        _, y = generate_sine_wave(f, SAMPLE_RATE, measure_duration)
        rec = sd.playrec(y, SAMPLE_RATE, input_mapping=[2], output_mapping=[2])
        sd.wait()
        yf = np.fft.rfft(rec, axis=0)
        yf_abs = 1 / rec.size * np.abs(yf)
        xf = np.fft.rfftfreq(rec.size, d=1./SAMPLE_RATE)
        peaks.append(np.max(yf_abs))

    plt.xscale("log")
    plt.scatter(freqs,peaks)
    plt.grid()
    plt.show()

if __name__ == "__main__":
    main()

在测量实际设备之前,我简单地将输出信号循环到音频接口的输入端,以基本上"校准"我正在做的事情.我以为振幅在所有频率上都是相等的.然而,这就是我得到的:

enter image description here

为什么所有的振幅都是到处都是,即使产生的正弦波是相同的?在扫描测量阶段,我没有改变音频接口上的任何东西.

推荐答案

这些差异对我来说似乎相对较小(约1.0E-5分钟,1.6E-5最大).你也越来越接近你频率范围的上限22.05千赫的奈奎斯特频率,所以我想每个正弦波周期只有大约2个样本,必然会导致不准确的傅里叶变换.

我知道你正在寻找一个音频系统,其中44.1 kHz是一个常见的采样频率(例如CD),但也许可以try 将采样频率提升到500 kHz作为一个测试,看看这是否会给你更一致的速率.这会更痛苦,但你也可以try 对每个频率的n个完整周期进行采样.即,对于10 Hz,采样1秒以获得10个循环,对于1000 Hz,采样10毫秒以获得10个循环.我认为这将有助于你的基频对齐,这样你就只能得到傅立叶变换的虚部,这样你就可以做更多的苹果对苹果的比较.否则,在许多情况下,你将削减正弦波中间周期引入实傅立叶变换分量.&此外,由于您没有使用任何窗口,您将获得超出预期频率的增加频率分量.我知道你正在采取绝对值,所以这不应该使不完美的正弦波周期计数太大的问题,但也许只是try 它,而测试,看看为什么你没有得到一个更平坦的频率响应,你期望.

Python相关问答推荐

rame中不兼容的d类型

带条件计算最小值

删除任何仅包含字符(或不包含其他数字值的邮政编码)的观察

需要计算60,000个坐标之间的距离

在Mac上安装ipython

将9个3x3矩阵按特定顺序排列成9x9矩阵

优化器的运行顺序影响PyTorch中的预测

使用Python更新字典中的值

Pandas Data Wrangling/Dataframe Assignment

try 检索blob名称列表时出现错误填充错误""

LocaleError:模块keras._' tf_keras. keras没有属性__internal_'''

计算空值

Flask运行时无法在Python中打印到控制台

如何按row_id/row_number过滤数据帧

Polars Group by描述扩展

使用Python异步地持久跟踪用户输入

数据框,如果值在范围内,则获取范围和

read_csv分隔符正在创建无关的空列

设置索引值每隔17行左右更改的索引

Django抛出重复的键值违反唯一约束错误