zhco2004 发表于 2008-5-10 09:47

用功率谱来识别声音怎么做啊?

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


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

>> =myrecord('1','2',11025,2);%b是经过归一化和端点检测后的声音数据
>> =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, 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));
=periodogram(wavData,window,nfft,fs);


/////////////////////////最后帖图是用一个陶瓷杯子的杯盖敲杯身的结果图
页: [1]
查看完整版本: 用功率谱来识别声音怎么做啊?