C 给定一个音频流,查找门砰然关上的时间(声压级计算?)

C 给定一个音频流,查找门砰然关上的时间(声压级计算?),c,algorithm,audio,signal-processing,C,Algorithm,Audio,Signal Processing,与拍门探测器不同(“拍上!拍下!拍上!拍下,拍下,拍下!拍下”)我需要在门关闭时检测。这是在车辆中,比房间或家庭门更容易: 听着: 看: 它是以16位4khz的频率采样,我希望避免大量处理或存储样本 当您使用audacity或其他波形工具查看它时,它非常独特,并且几乎总是由于车内声压的增加而剪辑-即使车窗和其他车门打开时: 听着: 看: 我希望有一个相对简单的算法,可以读取4kHz、8位的读数,并跟踪“稳态”。当算法检测到声级显著增加时,它将标记该点 你的想法是什么 您将如何检测此事件 有

与拍门探测器不同(“拍上!拍下!拍上!拍下,拍下,拍下!拍下”)我需要在门关闭时检测。这是在车辆中,比房间或家庭门更容易:

听着:

看:

它是以16位4khz的频率采样,我希望避免大量处理或存储样本

当您使用audacity或其他波形工具查看它时,它非常独特,并且几乎总是由于车内声压的增加而剪辑-即使车窗和其他车门打开时:

听着:

看:

我希望有一个相对简单的算法,可以读取4kHz、8位的读数,并跟踪“稳态”。当算法检测到声级显著增加时,它将标记该点

  • 你的想法是什么
  • 您将如何检测此事件
  • 有声压级计算的代码示例可能会有所帮助吗
  • 我可以不频繁地采样(1kHz或更慢的频率)吗
更新:玩Octave(开源数值分析-类似于Matlab),看看均方根是否能满足我的需要(结果与SPL非常相似)

更新2:在简单的情况下,计算RMS会发现门很容易关上:

现在,我只需要看看困难的情况(收音机打开,高温/空气打开,等等)。CFAR看起来真的很有趣——我知道我将不得不使用一种自适应算法,CFAR当然符合要求


-亚当

也许你应该试着检测气压的显著瞬间上升,这应该标志着门关上了。您可以将其与此波形和声级分析相结合,这些都可能给您带来更好的结果。

我可以想象,频率和振幅也会因车辆而异。确定这一点的最佳方法是在思域和大型SUV上取样。也许您可以让用户在“学习”模式下关门,以获得振幅和频率特征。然后,您可以在使用模式下使用它进行比较


你也可以考虑用以消除与门关闭无关的背景噪声。

< P>查看源音频文件的截图,一个简单的检测声音电平变化的方法是做一个样本来找出特定时间的波的“能量”。 粗略的算法是:

  • 将样品分成若干部分
  • 计算每个部分的能量
  • 取上一个窗口和当前窗口之间的能量比
  • 如果比率超过某个阈值,则确定有突然的大噪音
  • 伪代码

    samples = load_audio_samples()     // Array containing audio samples
    WINDOW_SIZE = 1000                 // Sample window of 1000 samples (example)
    
    for (i = 0; i < samples.length; i += WINDOW_SIZE):
        // Perform a numerical integration of the current window using simple
        // addition of current sample to a sum.
        for (j = 0; j < WINDOW_SIZE; j++):
            energy += samples[i+j]
    
        // Take ratio of energies of last window and current window, and see
        // if there is a big difference in the energies. If so, there is a
        // sudden loud noise.
        if (energy / last_energy > THRESHOLD):
            sudden_sound_detected()
    
        last_energy = energy
        energy = 0;
    
    samples=load\u audio\u samples()//包含音频样本的数组
    窗口大小=1000//1000个样本的样本窗口(示例)
    对于(i=0;i阈值):
    检测到突然的声音()
    最后的能量=能量
    能量=0;
    
    我应该添加一条免责声明,说明我没有尝试过此操作。

    这种方法应该可以在不首先记录所有样品的情况下进行。只要存在一定长度的缓冲区(
    WINDOW\u SIZE
    ),就可以执行数值积分来计算声音部分的能量。但是,这确实意味着,根据
    窗口大小的长度
    ,处理过程会有延迟。确定一段声音的合适长度是另一个问题

    如何划分为多个部分

    在第一个音频文件中,似乎关门声音的持续时间为0.25秒,因此用于数值积分的窗口最多应为该值的一半,甚至更类似 十分之一,因此可以注意到静音和突如其来的声音之间的差异,即使窗口在静音部分和噪音部分之间重叠

    例如,如果集成窗口为0.5秒,第一个窗口覆盖0.25秒的静音和0.25秒的关门,第二个窗口覆盖0.25秒的关门和0.25秒的静音,则两段声音的噪音水平可能相同,因此,不触发声音检测。我想有一个较短的窗口可以在某种程度上缓解这个问题

    然而,如果窗口太短,则意味着声音的上升可能无法完全适应一个窗口,并且相邻部分之间的能量差异可能很小,这可能会导致声音丢失

    我相信对于要检测的声音,
    窗口大小
    阈值
    都必须根据经验确定

    为了确定此算法需要在内存中保留多少样本,假设
    窗口大小
    为关门声音的1/10,约为0.025秒。在4 kHz的采样率下,即100个样本。这似乎不是太大的内存需求。使用16位样本,即200字节

    优点/缺点

    这种方法的优点是,如果数据不正确,可以使用简单的整数算法进行处理
    %% Test Script (Matlab)
    clear
    hold all %keep plots open
    dt=.001
    
    %% Van driver door
    data = wavread('van_driver_door_closing.wav');
    
    %Frequency analysis
    NFFT = 2^nextpow2(length(data));
    Y = fft(data(:,2), NFFT)/length(data);
    freq = (1/dt)/2*linspace(0,1,NFFT/2);
    spectral = [freq'  2*abs(Y(1:NFFT/2))];
    
    plot(spectral(:,1),spectral(:,2))
    
    %% Repeat for van sliding door
    data = wavread('van_driverdoorclosing.wav');
    
    %Frequency analysis
    NFFT = 2^nextpow2(length(data));
    Y = fft(data(:,2), NFFT)/length(data);
    freq = (1/dt)/2*linspace(0,1,NFFT/2);
    spectral = [freq'  2*abs(Y(1:NFFT/2))];
    
    plot(spectral(:,1),spectral(:,2))