📄 tms5220.c
字号:
current_pitch += (target_pitch - current_pitch) / interp_coeff[interp_period];
/*printf("*** Energy = %d\n",current_energy);*/
for (i = 0; i < 10; i++)
{
current_k[i] += (target_k[i] - current_k[i]) / interp_coeff[interp_period];
}
}
if (old_energy == 0)
{
/* generate silent samples here */
current_val = 0x00;
}
else if (old_pitch == 0)
{
/* generate unvoiced samples here */
randbit = (rand () % 2) * 2 - 1;
current_val = (randbit * current_energy) / 4;
}
else
{
/* generate voiced samples here */
if (pitch_count < sizeof (chirptable))
current_val = (chirptable[pitch_count] * current_energy) / 256;
else
current_val = 0x00;
}
/* Lattice filter here */
u[10] = current_val;
for (i = 9; i >= 0; i--)
{
u[i] = u[i+1] - ((current_k[i] * x[i]) / 32768);
}
for (i = 9; i >= 1; i--)
{
x[i] = x[i-1] + ((current_k[i-1] * u[i-1]) / 32768);
}
x[0] = u[0];
/* clipping, just like the chip */
if (u[0] > 511)
buffer[buf_count] = 127;
else if (u[0] < -512)
buffer[buf_count] = -128;
else
buffer[buf_count] = u[0] >> 2;
/* Update all counts */
size--;
sample_count = (sample_count + 1) % 200;
if (current_pitch != 0)
pitch_count = (pitch_count + 1) % current_pitch;
else
pitch_count = 0;
interp_count = (interp_count + 1) % 25;
buf_count++;
}
empty:
while (size > 0)
{
buffer[buf_count] = 0x00;
buf_count++;
size--;
}
}
/**********************************************************************************************
process_command -- extract a byte from the FIFO and interpret it as a command
***********************************************************************************************/
static void process_command (void)
{
unsigned char cmd;
/* if there are stray bits, ignore them */
if (bits_taken)
{
bits_taken = 0;
fifo_count--;
fifo_head = (fifo_head + 1) % FIFO_SIZE;
}
/* grab a full byte from the FIFO */
if (fifo_count > 0)
{
cmd = fifo[fifo_head] & 0x70;
fifo_count--;
fifo_head = (fifo_head + 1) % FIFO_SIZE;
/* only real command we handle now is speak external */
if (cmd == 0x60)
{
speak_external = 1;
/* according to the datasheet, this will cause an interrupt due to a BE condition */
if (!buffer_empty)
{
buffer_empty = 1;
cause_interrupt ();
}
}
}
/* update the buffer low state */
check_buffer_low ();
}
/**********************************************************************************************
extract_bits -- extract a specific number of bits from the FIFO
***********************************************************************************************/
static int extract_bits (int count)
{
int val = 0;
while (count--)
{
val = (val << 1) | ((fifo[fifo_head] >> bits_taken) & 1);
bits_taken++;
if (bits_taken >= 8)
{
fifo_count--;
fifo_head = (fifo_head + 1) % FIFO_SIZE;
bits_taken = 0;
}
}
return val;
}
/**********************************************************************************************
parse_frame -- parse a new frame's worth of data; returns 0 if not enough bits in buffer
***********************************************************************************************/
static int parse_frame (int removeit)
{
int old_head, old_taken, old_count;
int bits, indx, i, rep_flag;
/* remember previous frame */
old_energy = new_energy;
old_pitch = new_pitch;
for (i = 0; i < 10; i++)
old_k[i] = new_k[i];
/* clear out the new frame */
new_energy = 0;
new_pitch = 0;
for (i = 0; i < 10; i++)
new_k[i] = 0;
/* if the previous frame was a stop frame, don't do anything */
if (old_energy == (energytable[15] >> 6))
return 1;
/* remember the original FIFO counts, in case we don't have enough bits */
old_count = fifo_count;
old_head = fifo_head;
old_taken = bits_taken;
/* count the total number of bits available */
bits = fifo_count * 8 - bits_taken;
/* attempt to extract the energy index */
bits -= 4;
if (bits < 0)
goto ranout;
indx = extract_bits (4);
new_energy = energytable[indx] >> 6;
/* if the index is 0 or 15, we're done */
if (indx == 0 || indx == 15)
{
/* clear fifo if stop frame encountered */
if (indx == 15)
{
fifo_head = fifo_tail = fifo_count = bits_taken = 0;
removeit = 1;
}
goto done;
}
/* attempt to extract the repeat flag */
bits -= 1;
if (bits < 0)
goto ranout;
rep_flag = extract_bits (1);
/* attempt to extract the pitch */
bits -= 6;
if (bits < 0)
goto ranout;
indx = extract_bits (6);
new_pitch = pitchtable[indx] / 256;
/* if this is a repeat frame, just copy the k's */
if (rep_flag)
{
for (i = 0; i < 10; i++)
new_k[i] = old_k[i];
goto done;
}
/* if the pitch index was zero, we need 4 k's */
if (indx == 0)
{
/* attempt to extract 4 K's */
bits -= 18;
if (bits < 0)
goto ranout;
new_k[0] = k1table[extract_bits (5)];
new_k[1] = k2table[extract_bits (5)];
new_k[2] = k3table[extract_bits (4)];
new_k[3] = k4table[extract_bits (4)];
goto done;
}
/* else we need 10 K's */
bits -= 39;
if (bits < 0)
goto ranout;
new_k[0] = k1table[extract_bits (5)];
new_k[1] = k2table[extract_bits (5)];
new_k[2] = k3table[extract_bits (4)];
new_k[3] = k4table[extract_bits (4)];
new_k[4] = k5table[extract_bits (4)];
new_k[5] = k6table[extract_bits (4)];
new_k[6] = k7table[extract_bits (4)];
new_k[7] = k8table[extract_bits (3)];
new_k[8] = k9table[extract_bits (3)];
new_k[9] = k10table[extract_bits (3)];
done:
/* if we're not to remove this one, restore the FIFO */
if (!removeit)
{
fifo_count = old_count;
fifo_head = old_head;
bits_taken = old_taken;
}
/* update the buffer_low status */
check_buffer_low ();
return 1;
ranout:
/* this is an error condition; mark the buffer empty and turn off speaking */
buffer_empty = 1;
talk_status = speak_external = 0;
fifo_count = fifo_head = fifo_tail = 0;
/* generate an interrupt if necessary */
cause_interrupt ();
return 0;
}
/**********************************************************************************************
check_buffer_low -- check to see if the buffer low flag should be on or off
***********************************************************************************************/
static void check_buffer_low (void)
{
/* did we just become low? */
if (fifo_count < 8)
{
/* generate an interrupt if necessary */
if (!buffer_low)
cause_interrupt ();
buffer_low = 1;
}
/* did we just become full? */
else
{
buffer_low = 0;
}
}
/**********************************************************************************************
cause_interrupt -- generate an interrupt
***********************************************************************************************/
static void cause_interrupt (void)
{
irq_pin = 1;
if (irq_func) irq_func ();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -