音频信号分离 - 识别兴趣点

信息处理 信号分析 海浪 源分离
2022-02-02 17:12:04

我在这里问了这个问题:.wav 信号的音频分离,但不清楚,所以,这是我的第二次尝试:

首先,假设我有一个包含如下句子的 .wav 文件:

“我的名字是迈克尔”我想从中提取以下内容:

“我的”-> 音素 (1)

“名称”-> 音素 (2)

“是” -> 音素 (3)

“迈克尔”-> 音素 (4)

这意味着我已经获取了我的 1D 信号,并将其拆分为包含这些特定单词/音素的 2D 信号(向量),然后我可以对其进行分析和识别。因此,我想在时域而不是频域中计算它。再次澄清一下:

我接收一个包含一个句子的一维信号,将这个句子分成包含这个数据的不同部分:vect[0], vect[1],....vect[4]假设在matlab中我做了以下命令wavwrite(vect[0], ....),然后它会输出单词“My”并将所有块一起会给我完整的句子。

这是我的“现实世界问题”而不是音素,我有 bat call,每个 bat call 的长度在这个阶段是未知的。但这里是一个典型的 bat 调用示例:在这里,对于这些 bat 调用中的每一个,这些都需要与输入的信号分离并存储在一个向量中(就像上面的示例一样),然后允许我识别每个蝙蝠并对其进行分析。

这就像,样本会给我一个包含每个蝙蝠调用的 2D 向量:“Bat1”,“Bat2”......“Bat[n]” 蝙蝠被记录的时间量是未知的,或者,因此每个 bat 调用的长度是多少。

到目前为止我做了什么:

我已经获得了蝙蝠信号,对其进行了处理,并得到了以下信息(已绘制):

在此处输入图像描述

我还使用以下公式强调了信号:

rawSignal[i] = rawSignal[i] - (0.95 * rawSignal[i-1]);

然后我使用以下方法压缩了信号:

    float param = 1.0;
for(unsigned i=0; (i < rawSignal.size()); i++)
{
    int sign = getSignOf(rawSignal[i]);
    float norm = normalise_abs_value(rawSignal[i]);
    norm = 1.0 - pow(1.0 - norm, param);
    rawSignal[i] = denormalize_value(norm, sign);
}

然后给我以下输出:

在此处输入图像描述

我不清楚从这个信号中识别单个元素(“调用”)应该从哪里开始。因为,如果我使用过零和/或计算信号的总能量并因此使用阈值,那么它只会去除噪声,我会得到信号的压缩版本。

与某人交谈时,他们建议我应该尝试使用它,Cochleagram domain但是,我对此并不熟悉,并且对此可用的研究很少。

如果有人有任何建议,或者我可以使用的算法,请提出建议。

2个回答

(我对上一个问题的建议的后续),您可以使用频谱图和 ICA 来帮助:

一个类似的较短的声音文件:

import wave, struct, numpy as np, matplotlib.mlab as mlab, pylab as pl
def wavToArr(wavefile):
    w = wave.open(wavefile,"rb")
    p = w.getparams()
    s = w.readframes(p[3])
    w.close()
    sd = np.fromstring(s, np.int16)
    return sd,p

def wavToSpec(wavefile,log=False,norm=False):
    wavArr,wavParams = wavToArr(wavefile)
    print wavParams
    return  mlab.specgram(wavArr, NFFT=256,Fs=wavParams[2],detrend=detrend_mean,window=window_hanning,noverlap=128,sides='onesided',scale_by_freq=True)

wavArr,wavParams = wavToArr("bat_speech.wav")
hf = pl.figure(); ax=hf.add_subplot(1,1,1)
ax.plot(wavArr)

wav 文件数据图

现在看一下频谱图:

Pxx, freqs, bins = wavToSpec("bat_speech.wav")
Pxx += 0.0001
freqs += (len(wavArr) / wavParams[2]) / 2.
hf=pl.figure(figsize=(12,12));
ax = hf.add_subplot(2,1,1);
#plot spectrogram as decibals
hm = ax.imshow(10*np.log10(Pxx),interpolation='nearest',origin='lower',aspect='auto')
hf.colorbar(hm)
ylcnt = len(ax.get_yticklabels())
ycnt = len(freqs)
ylstep = int(ycnt / ylcnt)
ax.set_yticklabels([ int(freqs[f]) for f in xrange(0,ycnt,ylstep) ])

功率谱图(分贝)

我们可以在 8000Hz 左右剪辑它,或者不费心清理它。

现在您有了可以代理 BSS 中多个源的频率,因此您可以使用 PCA、ICA、归一化等。例如,看看您是否有一些可以隔离的组件:

from sklearn.decomposition import PCA, FastICA
ncomps = 7
# reduce dimensionality with PCA
pca = PCA(n_components=ncomps)
y = Pxx.copy().T
pc = pca.fit(y).transform(y)
# run ICA 
ica = FastICA(n_components=ncomps,random_state=42)
z = ica.fit(pc).transform(pc).T
hf = pl.figure()
for p in xrange(ncomps):
    ax = hf.add_subplot(ncomps,1,p+1)
    ax.plot(z[p])    

频谱图的ICA

或查看频谱图是否足以让您进行分割:

hf = pl.figure()
ax = hf.add_subplot(1,1,1)
ax.plot(np.sum(Pxx,axis=0))

频谱图的功率和

编辑:刚刚意识到你说你不想使用频域,但它可以帮助你隔离你可以提取的音素。无论如何,在你的 SeroWeb.wav 上运行我得到这个:

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

这似乎是一个应用特征学习思想的绝好机会。您有一个信号,假设是一小组不同呼叫的总和,每个呼叫具有不同的时间偏移量,您想仅从信号中了解呼叫的样子?

在数学中,如果你的信号是,那么假设可以表示为 其中是“基本信号”的“码本”或“字典”,指定在时间偏移处应用的编码大小为xx

x(t)=τ,α,iZαϕi(tτ)
Φ={ϕ1,,ϕk}Zϕiτα

如果这描述了您的情况,那么您可能会感兴趣 Smith & Lewicki [1] 的一篇优秀论文。基本上,他们采用的方法是应用匹配追踪 [MP; 2] 稀疏编码算法对使用卷积进行编码的“自然声音”(与正弦波或三角波等相反)的有效极长音频记录。一般来说,MP 可用于计算给定的学习方法扩展了这种编码算法他们表明,学习到的基础信号ZxΦΦΦ与猫耳蜗神经元的听觉感受野紧密匹配,就像 Olshausen & Field [3] 在视觉中著名的稀疏编码结果。

如果你已经知道(例如,你已经有你知道在中的蝙蝠呼叫的录音),那么你可以只使用 Smith & Lewicki 用来推导的 MP 变体。ΦxZ

[1] Smith, E & Lewicki, M. “高效的听觉编码”。自然,2006 年。

[2] Mallat, S & Zhang, Z. “与时频词典匹配的追求”。IEEE 信号处理汇刊,1993 年。

[3] Olshausen, B & Field, D. “通过学习自然图像的稀疏代码,出现简单细胞感受野特性。” 自然,1994 年。