声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 1664|回复: 0

[模式识别] 用功率谱来识别声音怎么做啊?

[复制链接]
发表于 2008-5-10 09:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
我用matlab,得到一个声音的功率谱,如下,想用来识别,但是不知道里面怎么提取出特征参数,得到功率谱怎么做识别的。
很急啊,还有不到十天就要交论文初稿了。


/////////////////////////matlab命令:

>> [a,b]=myrecord('1','2',11025,2);  %b是经过归一化和端点检测后的声音数据
>> [pxx,f]=mypsd(b);  %pxx得到功率谱
>> subplot(211);
>> plot(b);
>> xlabel('声音数据');
>> subplot(212);
>> plot(pxx);
>> xlabel('功率谱');


///////////////////////////myrecord函数:

function [ newWav, valueWav ] = myrecord( filename1, filename2, fs, sec)
%  录音并提取可用的声音部分。
%  newWav:目标声音的数据;filename:要存储的文件名
%  录音部分
channels = 1;
newWav = wavrecord(sec*fs,fs,channels,'double');
%  端点检测部分
valueWav =  newWav / max(abs(newWav));  %各个采样点的幅度归一化到1
%%  常数设置
FrameLen = 240;
FrameInc = 80;
amp1 = 10;  %确定进入声音段的最低能量门限
zcr1 = 10;  %确定进入声音段的过零率
amp2 = 2;  %可能处在声音段时的最低能量门限
zcr2 = 5;  %可能处在声音段时的过零率
delta = 0.02;  %检测过零率时用到的阈值
minsilence = 3;  %能表示处于静音段的最少持续静音帧数
minlen = 4;  %能表示处于声音段的最少持续声音帧数
status = 0;  %检查时用到的状态记号,0表示静音,1表示可能处于声音段,2表示正处于声音片段,3表示声音结束
count = 0;  %持续声音段的总帧数
silence = 0;  %持续静音段的总帧数
%%  计算过零率
tmp1 = enframe(valueWav(1:length(valueWav)-1), FrameLen, FrameInc);
tmp2 = enframe(valueWav(2:length(valueWav)) , FrameLen, FrameInc);
signs = (tmp1.*tmp2)<0;  %两点的符号不一样,即穿过零
diffs = (tmp1 -tmp2)>delta;  %两点之间的差值超过阈值
zcr = sum(signs.*diffs, 2);  %检测上面两个条件都符合
%%  计算短时能量,过程是先预加重,然后分帧,再计算幅值绝对值的和
amp = sum(abs(enframe(filter([1 -0.9375], 1, valueWav), FrameLen, FrameInc)), 2);
%%  调整能量门限
amp1 = min(amp1, max(amp)/4);  %用于确定是声音帧
amp2 = min(amp2, max(amp)/8);  %用于确定超过静音帧门限
%%  开始端点检测
startFrame = 0;
endFrame = 0;
status = 0;
for n=1:length(zcr)  %一帧一帧检查
    switch status
    case {0,1}
        if amp(n) > amp1 | zcr(n) > zcr1  %确定进入声音段
            startFrame = max(n-count-1,1);  %得到声音开始的第一帧
            status = 2;
            silence = 0;
            count = count + 1;
        elseif amp(n) > amp2 | zcr(n) > zcr2  %可能处于声音段
            status = 1;
            count = count + 1;
        else  %处在静音状态
            status = 0;
            count = 0;
        end
    case 2,
        if amp(n) > amp2 | zcr(n) > zcr2  %保持在声音段
            count = count + 1;
        else  %声音将要结束,因为没有维持能量或过零率
            silence = silence+1;
            if silence < minsilence  %静音不够长,声音还没有结束
                count = count + 1;
            elseif count < minlen % 声音不够长,认为之前检测到的是噪声(特别是当噪声的过零率或短时能量很高时,这个检测可以减少误判)
                status = 0;
                silence = 0;
                count = 0;
            else  %声音结束
                status = 3;
            end
        end
    case 3,
        break;
    end
end
count = count-silence/2;
endFrame = startFrame + count -1;  %得到声音结束帧
%  声音数据存储部分
valueWav = valueWav(startFrame*FrameInc : endFrame*FrameInc, : );
wavwrite(newWav, filename1);
wavwrite(valueWav,filename2);


/////////////////////////////mypsd函数:

function [ pxx, f ] = mypsd( wavData )
%  用周期图法得到功率谱
%  pxx:结果功率谱图;wavData:声音数据
nfft=1024;
fs=22050;
window=hamming(length(wavData));
[pxx,f]=periodogram(wavData,window,nfft,fs);


/////////////////////////最后帖图是用一个陶瓷杯子的杯盖敲杯身的结果图

用一个陶瓷杯子的杯盖敲杯身的结果图

用一个陶瓷杯子的杯盖敲杯身的结果图
回复
分享到:

使用道具 举报

您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-5-21 14:56 , Processed in 0.051208 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表