?? pitch.dsp
字號:
.module/boot=3/boot=4 pitch_detection;
{ PITCH.DSP - extracts the pitch period, and makes a
voiced/unvoiced decision.
INPUT:
i0 -> k[N]
l0 = 0
i6 -> autocor_speech[FRAME_LENGTH]
l6 = 0
OUTPUT:
si = pitch (= 0 if unvoiced)
CONST:
PITCH_DETECT_LENGTH = part of frame used for pitch detection
starting at 3 msec.
mSEC_3 = sample to start pitch detection at
FUNCIOTNS CALLED:
None
DESCRIPTION:
The k's are autoscaled, and then autocorrelated. The new values are
correlated with the autocorrelated speech R[]. The resulting sequence
is searched for the largest peak in the interval
mSEC_3 ..... mSEC_3+PITCH_DETECT_LENGTH
Depending on the relative size of the peak (to re[0]), a decision of
voiced/unvoiced is made. In case of voiced the location is equal to
the pitch period.
}
{Include constant definition}
#include "lpc.h"
.entry detect_pitch;
.external overflow;
.var/dm rk[N]; {autocorrelation of k[]}
{.var/pm re[FRAME_LENGTH];} {cross correlation of R[] and rk[]}
.var/dm k_dm[N]; {scratch copy's of k}
.var/dm p2_k;
.var/dm p2_autocor_speech;
.var/dm zero_crossings; {in re[]}
detect_pitch:
{store pointers for later use}
dm(p2_k) = i0;
dm(p2_autocor_speech) = i6;
{autoscale befored autocorrelation}
{detect largest value in k's}
{i0 = ^k; l0 = 0;}
cntr = N;
sb = -16;
do max_k until ce;
si = dm(i0,m1);
max_k: sb = expadj si;
{adjust k input: normalize to largest and then right shift
to |P_K_SHIFT|.(16-|P_K_SHIFT|) format (done in one shift).
At the same time copy to pm for correlation}
i0 = dm(p2_k); l0 = 0;
i1 = ^k_dm; l1 = 0;
cntr = N;
ax0 = sb;
ay0 = P_K_SHIFT; {scale down to avoid overflow (worst case)}
ar = ay0 - ax0;
se = ar;
do adj_k until ce;
si = dm(i0,m1);
sr = ashift si (hi);
adj_k: dm(i1,m1) = sr1;
{calculate autocorrelation of k[], rk[i] = sum_of k[j]*k[i+j]}
i5 = ^k_dm; l5 = 0; {k[i+j]}
i2 = N; l2 = 0; {innerloop counter 'refill'}
i1 = ^rk; l1 = 0;
m2 = -1;
cntr = N;
do corr_loop until ce;
i0 = ^k_dm; l0 = 0; {k[j]}
i4 = i5; l4 = 0;
cntr = i2;
mr=0, my0 = dm(i4,m5);
mx0=dm(i0,m1);
do cor_data_loop until ce;
mr=mr+mx0*my0(ss),my0=dm(i4,m5);
cor_data_loop: mx0=dm(i0,m1);
if mv call overflow;
mx0 = dm(i2,m2);
my0 = dm(i5,m5); {(innerloop cnt'er)--, i++}
corr_loop: dm(i1,m1) = mr1;
{shift down R[] (autocor_speech) to |P_R_SHIFT|.(16-|P_R_SHIFT|) format}
cntr = FRAME_LENGTH;
{i6 = ^autocor_speech; l6 = 0;}
do shft_ac until ce;
si = pm(i6,m4);
sr = ashift si by P_R_SHIFT (hi);
shft_ac: pm(i6,m5) = sr1;
{Setup rk[] and R[] (autocor_speech) for correlation.
Only calculate the necessary correlation coefficients, equivalent
to the 0-15 ms portion of the frame (samples 0-120 (out of 160),
re(0) is necesary for later voiced/unvoiced calc}
{ re[i] = sum_of(rk[j]*R[i+j]) }
i5 = dm(p2_autocor_speech); l5 = 0; {R[i+j]}
i2 = N; l2 = 0;
i6 = dm(p2_autocor_speech); l6 = 0;
ay0 = 0; {last 'sign' for zerocrossing count}
af = pass ay0; {zerocrossing counter}
cntr = PITCH_DETECT_LENGTH + mSEC_3; {0-15 msec}
{correlate rk's and R's}
do cor_loop until ce;
i0 = ^rk; l0 = 0; {rk[j]}
i4 = i5; l4 = 0;
cntr=i2;
mr=0, my0=pm(i4,m5), mx0=dm(i0,m1);
do cor_inner_loop until ce;
cor_inner_loop: mr=mr+mx0*my0(ss),my0=pm(i4,m5),mx0=dm(i0,m1);
ar = mr1 xor ay0; {test for sign switch = zerocrossing}
if ge jump no_crossing;
af = af + 1; {inc zerocrossing counter}
ay0 = mr1; {store new sign}
no_crossing:
modify(i5,m5); {i++}
cor_loop: pm(i6,m5) = mr1;
ar = pass af;
i5 = ar; {zerocrossing count}
{find the largest peak in range 3-15 msec. The index of the largest
peak is equal to the pitch period. At the same time count the
nr of zerocrossings in re[]}
si = 0; {store for pitch of max peak}
ay1 = 0; {store for value of max peak}
i6 = dm(p2_autocor_speech); l6 = 0;
ax0 = pm(i6,m4); {save re(0) for voiced/unvoiced check}
m7 = mSEC_3;
modify(i6,m7); {-> re(mSEC_3)}
i2 = mSEC_3; l2 = 0; {pitch counter}
cntr = PITCH_DETECT_LENGTH;
do find_max_peak until ce;
ax1 = pm(i6,m5); {re[j]}
ar = ax1 - ay1; {re[j] > max?}
if le jump not_bigger;
ay1 = ax1; {new max value}
si = i2; {corresponding pitch value}
not_bigger:
nop;
find_max_peak: modify(i2,m1); {(pitch period cnt'er)++}
{Check for voiced/unvoiced excitation. If unvoiced set pitch = 0}
{ax0 = re(0)}
{ay1 = MSW of peakvalue}
ay0 = 0000; {LSB of peakvalue}
divide(ax0,ay1); {ay0 = re[peak]/re[0]}
ax0 = i5; {nr of zerocrossings in re[]}
ay1 = 70;
ar = ax0 - ay1; {i5>treshold => unvoiced}
if ge jump not_voiced;
ax1 = 0x1999; {= 0.20}
ar = ay0 - ax1; {re(j)/re(0) - 0.20}
if lt jump not_voiced;
ax1 = 0x2666; {= 0.30}
ar = ay0 - ax1; {re(j)/re(0) - 0.30}
if gt jump frame_voiced;
ay1 = 60;
ar = ax0 - ay1; {i5>treshold => unvoiced}
if lt jump frame_voiced;
not_voiced:
si = 0; {unvoiced => pitch period = 0}
i0 = dm(p2_k); l0 = 0; {zero out k5 - k10 for unvoiced speech}
m3 = 4;
modify(i0,m3);
ax0 = 0;
cntr = 6;
do zero_ks until ce;
zero_ks: dm(i0,m1) = ax0;
frame_voiced:
rts;
.endmod;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -