?? ssynth.dsp
字號:
.module/boot=3/boot=4 lpc_sync_synth;
{ SSYNTH.DSP - synthesizes lpc speech on a pitch syncronious boundry.
INPUT:
i1 -> (negative) reflection coefficient (k[]'s)
l1 = 0
i2 -> output (speech) buffer
l2 = 0
ax1 = pitch period
mx1 = gain
OUTPUT:
Ouput buffer filled
FUNCTIONS CALLED:
noise_rand (random number generator)
DESCRIPTION:
clear_filter: clears delay line, initializes variables
(no arguments required)
synthesis : updates the frame delay line -> new -> old ->
then synthesises a frame of speech, based on interpolated
parameters (cur_) from the last frame (old_) and the latest (new_).
When a frame is considered voiced the filter is excited with an
impuls on a pitchsyncronous boundry. When a frame is unvoiced, the
filter is excited whith random noise. Before input to the filter
the excitation is scaled to an appropriate value depending on
voiced/unvoiced status and the gain. The lattice filter is
taken from the apps handbook.
In order to interpolate the parameter a DELAY OF ONE
FRAME is introduced!
}
{ include constant definitions }
#include "lpc.h";
.entry synthesis, clear_filter;
.external noise_rand;
.var/pm/ram/circ e_back[N]; {delay line}
.var/dm/ram lo_noise_seed,hi_noise_seed;
.var/pm/ram new_k[N];
.var/dm/ram new_gain;
.var/dm/ram new_pitch;
.var/pm/ram old_k[N];
.var/dm/ram old_gain;
.var/dm/ram old_pitch;
.var/dm/ram/circ cur_k[N];
.var/dm/ram cur_gain;
.var/dm/ram cur_pitch;
.var/dm/ram pif_cnt; {Place In Frame - cntr}
.var/dm/ram pp_cnt; {pitch period - cntr}
.var/dm/ram first_time;
{clear filter and return}
clear_filter:
{clear the filter}
i4 = ^e_back; l4 = 0;
ar = 0;
cntr = N;
do clear_loop until ce;
clear_loop: pm(i4,m5) = ar;
{initialize seed value for random nr generation}
ax0 = 0;
dm(lo_noise_seed) = ax0;
dm(hi_noise_seed) = ax0;
ax0 = 1;
dm(first_time) = ax0; {first_time = TRUE}
rts;
{generate one frame of data and output to speech buffer}
synthesis:
ax0 = dm(first_time);
ar = pass ax0;
if eq jump not_first;
{copy parm's to new} {first_time = TRUE}
dm(new_pitch) = ax1;
dm(new_gain) = mx1;
i6 = ^new_k; l6 = 0;
cntr = N;
do move_to_new until ce;
ax0 = dm(i1,m1);
move_to_new: pm(i6,m5) = ax0;
{start of by interpolating}
ax0 = 1;
dm(pp_cnt) = ax0;
{don't do this anymore}
ax0 = 0;
dm(first_time) = ax0;
jump done;
not_first: {first_time = FALSE}
{move parm's from old to new and update new}
ax0 = dm(new_pitch);
mx0 = dm(new_gain);
dm(new_pitch) = ax1;
dm(new_gain) = mx1;
dm(old_pitch) = ax0;
dm(old_gain) = mx0;
i6 = ^new_k; l6 = 0;
i5 = ^old_k; l5 = 0;
cntr = N;
do move_to_old until ce;
ay0 = pm(i6,m4), ax0 = dm(i1,m1);
pm(i5,m5) = ay0;
move_to_old: pm(i6,m5) = ax0;
{setup for lattice filter}
i0 = ^cur_k; l0 = N;
i4 = ^e_back; l4 = N;
m2 = -1;
m6 = 3;
m7 = -2;
{setup pitch_period cntr, in temp var (=af)}
ax0 = dm(pp_cnt);
af = pass ax0;
{synthesize a whole frame}
cntr = FRAME_LENGTH;
ax0 = 0;
dm(pif_cnt) = ax0;
do frame_loop until ce;
my0 = 0; {excitation default to 0}
af = af - 1;
if gt jump not_pitch_time;
{time to interpolate}
{calculate interpolation factor = pif_cnt/(FRAME_LENGTH - 1)}
mx0 = dm(pif_cnt);
my0 = INTERP_FACTOR; {= 1/(FRAME_LENGHT - 1) shift -1}
mr = mx0 * my0 (ss); {product is in 17.15 format}
my1 = mr0; {get 1.15 format}
{calc interpolated gain}
ax0 = dm(new_gain);
ay0 = dm(old_gain);
ar = ax0 - ay0; {new - old}
mr = ar * my1 (ss); {(new-old)*int_factor}
ar = mr1 + ay0; { + old}
dm(cur_gain) = ar;
{test for transition between voiced/unvoiced and unvoiced/voiced}
ay0 = dm(old_pitch);
ar = pass ay0;
if eq jump old_unv;
ax0 = dm(new_pitch);
ar = pass ax0;
if eq jump new_unv;
{voiced - voiced}
{calc interpolated pitch}
ar = ax0 - ay0; {new - old}
mr = ar * my1 (ss); {(new-old)*int_factor}
ar = mr1 + ay0; { + old}
dm(cur_pitch) = ar;
{"interpolate" k's}
i1 = ^cur_k; l1 = 0;
i5 = ^old_k; l5 = 0;
cntr = N;
do interpolate_k until ce;
ay0 = pm(i5,m5);
interpolate_k: dm(i1,m1) = ay0;
new_unv:
{reinitialize pitch cntr}
ar = dm(cur_pitch);
af = pass ar;
{set my0 = excitation impuls, in case of voiced frame}
{multiply excitation by gain*(pitch/FRAME_LENGTH)}
mx1 = ONE_OVER_FRAMEL; { = 1/FRAME_LENGTH}
my1 = dm(cur_pitch);
mr = mx1 * my1 (ss); {pitch/FRAME_LENGTH, result in 16.16 format}
my1 = dm(cur_gain);
mr = mr0 * my1 (ss); {gain*pitch/FRAME_LENGTH}
my1 = 0x7fff; {impuls}
mr = mr1 * my1 (ss);
my0 = mr1;
jump not_pitch_time;
old_unv: {unvoiced - *}
ax0 = 1; {set the pitch_period cntr to a apropriate spacing}
af = pass ax0;
ax0 = 0;
dm(cur_pitch) = ax0; {set voiced state to unvoiced}
{copy old_k to cur_k}
i1 = ^cur_k; l1 = 0;
i5 = ^old_k; l5 = 0;
cntr = N;
do move_to_cur until ce;
ay0 = pm(i5,m5);
move_to_cur: dm(i1,m1) = ay0;
not_pitch_time:
{calculate driving sample if noised}
ax0 = dm(cur_pitch);
ar = pass ax0; {check for voiced/unvoiced}
if ne jump voiced;
sr1 = dm(hi_noise_seed); {noised, old_pitch = 0}
sr0 = dm(lo_noise_seed);
call noise_rand; {random: 16 bit nr}
dm(hi_noise_seed) = sr1;
dm(lo_noise_seed) = sr0;
ar = abs sr1;
sr = ashift ar by -3 (hi);
my1 = dm(cur_gain); {multiply by gain}
mr = sr1 * my1 (ss);
my0 = mr1; {my0 = excitation}
jump do_filter;
voiced:
do_filter:
{do allpole lattice filter (from apps book)}
cntr = N - 1;
mr = 0;
mr1 = my0;
mx0 = dm(i0,m1), my0 = pm(i4,m5);
mr = mr - mx0*my0 (ss), mx0 = dm(i0,m1), my0 = pm(i4,m5);
do dataloop until ce;
mr = mr - mx0*my0 (ss);
my1 = mr1, mr = 0;
mr1 = my0;
mr = mr + mx0*my1 (ss), mx0 = dm(i0,m1), my0 = pm(i4,m7);
pm(i4,m6) = mr1, mr = 0;
dataloop: mr1 = my1;
my0 = pm(i4,m7), mx0 = dm(i0,m2);
dm(i2,m1) = my1; {store synthesized sample}
pm(i4,m5) = mr1; {store newest value in delay line}
{increment place_in_frame cntr}
ay0 = dm(pif_cnt);
ar = ay0 + 1;
frame_loop: dm(pif_cnt) = ar;
{store pitch_period cntr for next iteration}
ar = pass af;
dm(pp_cnt) = ar;
done:
l4 = 0;
rts;
.endmod;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -