summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Jonathan Gevaryahu <Lord-Nightmare@users.noreply.github.com>2010-05-03 21:46:54 +0000
committer Jonathan Gevaryahu <Lord-Nightmare@users.noreply.github.com>2010-05-03 21:46:54 +0000
commit8efc1abaa97736197f08047828d534fe243290f4 (patch)
tree3cb04f3a810473ccea5268b6c047b487f2be0d6d
parent9cc765cb1366d8908c0be87af7025bddcbee843f (diff)
Redid parameter interpolation and frame load logic so new frames don't immediately force all the Energy/Pitch/K values to the values of the old frame, but wait until their first interpolation to do so. This fix improves speech quality considerably. [Lord Nightmare]
-rw-r--r--src/emu/sound/tms5220.c78
1 files changed, 50 insertions, 28 deletions
diff --git a/src/emu/sound/tms5220.c b/src/emu/sound/tms5220.c
index fe1b83217ca..107b2d8b8de 100644
--- a/src/emu/sound/tms5220.c
+++ b/src/emu/sound/tms5220.c
@@ -74,7 +74,7 @@ Driver specific notes:
Progress list for drivers using old vs new interface:
starwars: uses new interface (couriersud)
-gauntlet: uses new interface (couriersud
+gauntlet: uses new interface (couriersud)
atarisy1: uses new interface (Lord Nightmare)
atarisy2: uses new interface (Lord Nightmare)
atarijsa: uses new interface (Lord Nightmare)
@@ -265,12 +265,14 @@ struct _tms5220_state
UINT8 irq_pin; /* state of the IRQ pin (output) */
/* these contain data describing the current and previous voice frames */
-#define OLD_FRAME_UNVOICED_FLAG (tms->old_frame_pitch_idx == 0) // 1 if unvoiced, 0 if voiced
+#define OLD_FRAME_SILENCE_FLAG (tms->old_frame_energy_idx == 0) // 1 if E=0, 0 otherwise.
+#define OLD_FRAME_UNVOICED_FLAG (tms->old_frame_pitch_idx == 0) // 1 if P=0 (unvoiced), 0 if voiced
UINT8 old_frame_energy_idx;
UINT8 old_frame_pitch_idx;
UINT8 old_frame_k_idx[10];
#define NEW_FRAME_STOP_FLAG (tms->new_frame_energy_idx == 0xF) // 1 if this is a stop (Energy = 0xF) frame
+#define NEW_FRAME_SILENCE_FLAG (tms->new_frame_energy_idx == 0) // ditto as above
#define NEW_FRAME_UNVOICED_FLAG (tms->new_frame_pitch_idx == 0) // ditto as above
UINT8 new_frame_energy_idx;
UINT8 new_frame_pitch_idx;
@@ -774,7 +776,7 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
if (tms->talk_status == 0)
{
#ifdef DEBUG_GENERATION
- logerror("tms5220_process: processing frame: talk status = 0 caused by stop frame or buffer empty, halting speech.\n");
+ fprintf(stderr,"tms5220_process: processing frame: talk status = 0 caused by stop frame or buffer empty, halting speech.\n");
#endif
tms->speaking_now = 0; // finally halt speech
goto empty;
@@ -787,23 +789,6 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
fprintf(stderr,"\n");
#endif
- /* Set old frame targets as starting point of new frame */
- /* If old pitch index was 0, consider the k params > 4 to be zero */
- tms->current_energy = tms->coeff->energytable[tms->old_frame_energy_idx];
- tms->current_pitch = tms->coeff->pitchtable[tms->old_frame_pitch_idx];
- for (i = 0; i < 4; i++)
- tms->current_k[i] = tms->coeff->ktable[i][tms->old_frame_k_idx[i]];
- if (tms->current_pitch == 0) // unvoiced frame, ZPAR is true
- {
- for (i = 4; i < tms->coeff->num_k; i++)
- tms->current_k[i] = 0;
- }
- else
- {
- for (i = 4; i < tms->coeff->num_k; i++)
- tms->current_k[i] = tms->coeff->ktable[i][tms->old_frame_k_idx[i]];
- }
-
/* if the new frame is a stop frame, set an interrupt and set talk status to 0 */
if (NEW_FRAME_STOP_FLAG == 1)
{
@@ -821,12 +806,12 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
*/
if ( ((OLD_FRAME_UNVOICED_FLAG == 0) && (NEW_FRAME_UNVOICED_FLAG == 1))
|| ((OLD_FRAME_UNVOICED_FLAG == 1) && (NEW_FRAME_UNVOICED_FLAG == 0))
- || ((tms->current_energy == 0) && (tms->coeff->energytable[tms->new_frame_energy_idx] != 0)) )
+ || ((OLD_FRAME_SILENCE_FLAG == 1) && (NEW_FRAME_SILENCE_FLAG == 0)) )
{
#ifdef DEBUG_GENERATION
- logerror("processing frame: interpolation inhibited\n");
- logerror("*** current Energy = %d\n",tms->current_energy);
- logerror("*** next frame Energy = %d(index: %x)\n",tms->coeff->energytable[tms->new_frame_energy_idx],tms->new_frame_energy_idx);
+ fprintf(stderr,"processing frame: interpolation inhibited\n");
+ fprintf(stderr,"*** current Energy = %d\n",tms->current_energy);
+ fprintf(stderr,"*** next frame Energy = %d(index: %x)\n",tms->coeff->energytable[tms->new_frame_energy_idx],tms->new_frame_energy_idx);
#endif
tms->target_energy = tms->current_energy;
tms->target_pitch = tms->current_pitch;
@@ -836,9 +821,9 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
else // normal frame, normal interpolation
{
#ifdef DEBUG_GENERATION
- logerror("processing frame: Normal\n");
- logerror("*** current Energy = %d\n",tms->current_energy);
- logerror("*** new (target) Energy = %d(index: %x)\n",tms->coeff->energytable[tms->new_frame_energy_idx],tms->new_frame_energy_idx);
+ fprintf(stderr,"processing frame: Normal\n");
+ fprintf(stderr,"*** current Energy = %d\n",tms->current_energy);
+ fprintf(stderr,"*** new (target) Energy = %d(index: %x)\n",tms->coeff->energytable[tms->new_frame_energy_idx],tms->new_frame_energy_idx);
#endif
tms->target_energy = tms->coeff->energytable[tms->new_frame_energy_idx];
@@ -861,7 +846,7 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
if ( (tms->talk_status == 0))
{
#ifdef DEBUG_GENERATION
- logerror("talk status is 0, forcing target energy to 0\n");
+ fprintf(stderr,"Talk status is 0, forcing target energy to 0\n");
#endif
tms->target_energy = 0;
}
@@ -873,6 +858,7 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
#else
interp_period = tms->sample_count / 25;
#endif
+#define PC_COUNT_LOAD 0
switch(tms->interp_count)
{
/* PC=X X cycle, rendering change (change for next cycle which chip is actually doing) */
@@ -881,61 +867,97 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
case 1: /* PC=0, B cycle, nothing happens (update energy) */
break;
case 2: /* PC=1, A cycle, update energy (calc pitch) */
+ if (interp_period == PC_COUNT_LOAD)
+ tms->current_energy = tms->coeff->energytable[tms->old_frame_energy_idx];
tms->current_energy += ((tms->target_energy - tms->current_energy) >> tms->coeff->interp_coeff[interp_period]);
break;
case 3: /* PC=1, B cycle, nothing happens (update pitch) */
break;
case 4: /* PC=2, A cycle, update pitch (calc K1) */
+ if (interp_period == PC_COUNT_LOAD)
+ tms->current_pitch = tms->coeff->pitchtable[tms->old_frame_pitch_idx];
tms->current_pitch += ((tms->target_pitch - tms->current_pitch) >> tms->coeff->interp_coeff[interp_period]);
break;
case 5: /* PC=2, B cycle, nothing happens (update K1) */
break;
case 6: /* PC=3, A cycle, update K1 (calc K2) */
+ if (interp_period == PC_COUNT_LOAD)
+ tms->current_k[0] = tms->coeff->ktable[0][tms->old_frame_k_idx[0]];
tms->current_k[0] += ((tms->target_k[0] - tms->current_k[0]) >> tms->coeff->interp_coeff[interp_period]);
break;
case 7: /* PC=3, B cycle, nothing happens (update K2) */
break;
case 8: /* PC=4, A cycle, update K2 (calc K3) */
+ if (interp_period == PC_COUNT_LOAD)
+ tms->current_k[1] = tms->coeff->ktable[1][tms->old_frame_k_idx[1]];
tms->current_k[1] += ((tms->target_k[1] - tms->current_k[1]) >> tms->coeff->interp_coeff[interp_period]);
break;
case 9: /* PC=4, B cycle, nothing happens (update K3) */
break;
case 10: /* PC=5, A cycle, update K3 (calc K4) */
+ if (interp_period == PC_COUNT_LOAD)
+ tms->current_k[2] = tms->coeff->ktable[2][tms->old_frame_k_idx[2]];
tms->current_k[2] += ((tms->target_k[2] - tms->current_k[2]) >> tms->coeff->interp_coeff[interp_period]);
break;
case 11: /* PC=5, B cycle, nothing happens (update K4) */
break;
case 12: /* PC=6, A cycle, update K4 (calc K5) */
+ if (interp_period == PC_COUNT_LOAD)
+ tms->current_k[3] = tms->coeff->ktable[3][tms->old_frame_k_idx[3]];
tms->current_k[3] += ((tms->target_k[3] - tms->current_k[3]) >> tms->coeff->interp_coeff[interp_period]);
break;
case 13: /* PC=6, B cycle, nothing happens (update K5) */
break;
case 14: /* PC=7, A cycle, update K5 (calc K6) */
+ if ((interp_period == PC_COUNT_LOAD) && (tms->old_frame_pitch_idx != 0)) // ZPAR clear
+ tms->current_k[4] = tms->coeff->ktable[4][tms->old_frame_k_idx[4]];
+ else if ((interp_period = PC_COUNT_LOAD) && (tms->old_frame_pitch_idx == 0)) // ZPAR set
+ tms->current_k[4] = 0;
tms->current_k[4] += ((tms->target_k[4] - tms->current_k[4]) >> tms->coeff->interp_coeff[interp_period]);
break;
case 15: /* PC=7, B cycle, nothing happens (update K6) */
break;
case 16: /* PC=8, A cycle, update K6 (calc K7) */
+ if ((interp_period == PC_COUNT_LOAD) && (tms->old_frame_pitch_idx != 0)) // ZPAR clear
+ tms->current_k[5] = tms->coeff->ktable[5][tms->old_frame_k_idx[5]];
+ else if ((interp_period = PC_COUNT_LOAD) && (tms->old_frame_pitch_idx == 0)) // ZPAR set
+ tms->current_k[5] = 0;
tms->current_k[5] += ((tms->target_k[5] - tms->current_k[5]) >> tms->coeff->interp_coeff[interp_period]);
break;
case 17: /* PC=8, B cycle, nothing happens (update K7) */
break;
case 18: /* PC=9, A cycle, update K7 (calc K8) */
+ if ((interp_period == PC_COUNT_LOAD) && (tms->old_frame_pitch_idx != 0)) // ZPAR clear
+ tms->current_k[6] = tms->coeff->ktable[6][tms->old_frame_k_idx[6]];
+ else if ((interp_period = PC_COUNT_LOAD) && (tms->old_frame_pitch_idx == 0)) // ZPAR set
+ tms->current_k[6] = 0;
tms->current_k[6] += ((tms->target_k[6] - tms->current_k[6]) >> tms->coeff->interp_coeff[interp_period]);
break;
case 19: /* PC=9, B cycle, nothing happens (update K8) */
break;
case 20: /* PC=10, A cycle, update K8 (calc K9) */
+ if ((interp_period == PC_COUNT_LOAD) && (tms->old_frame_pitch_idx != 0)) // ZPAR clear
+ tms->current_k[7] = tms->coeff->ktable[7][tms->old_frame_k_idx[7]];
+ else if ((interp_period = PC_COUNT_LOAD) && (tms->old_frame_pitch_idx == 0)) // ZPAR set
+ tms->current_k[7] = 0;
tms->current_k[7] += ((tms->target_k[7] - tms->current_k[7]) >> tms->coeff->interp_coeff[interp_period]);
break;
case 21: /* PC=10, B cycle, nothing happens (update K9) */
break;
case 22: /* PC=11, A cycle, update K9 (calc K10) */
+ if ((interp_period == PC_COUNT_LOAD) && (tms->old_frame_pitch_idx != 0)) // ZPAR clear
+ tms->current_k[8] = tms->coeff->ktable[8][tms->old_frame_k_idx[8]];
+ else if ((interp_period = PC_COUNT_LOAD) && (tms->old_frame_pitch_idx == 0)) // ZPAR set
+ tms->current_k[8] = 0;
tms->current_k[8] += ((tms->target_k[8] - tms->current_k[8]) >> tms->coeff->interp_coeff[interp_period]);
break;
case 23: /* PC=11, B cycle, nothing happens (update K10) */
break;
case 24: /* PC=12, A cycle, update K10 (do nothing) */
+ if ((interp_period == PC_COUNT_LOAD) && (tms->old_frame_pitch_idx != 0)) // ZPAR clear
+ tms->current_k[9] = tms->coeff->ktable[9][tms->old_frame_k_idx[9]];
+ else if ((interp_period = PC_COUNT_LOAD) && (tms->old_frame_pitch_idx == 0)) // ZPAR set
+ tms->current_k[9] = 0;
tms->current_k[9] += ((tms->target_k[9] - tms->current_k[9]) >> tms->coeff->interp_coeff[interp_period]);
break;
}