From e067fc79a84bec5ef7b3d8cfb7f5422e1fb5cdd2 Mon Sep 17 00:00:00 2001 From: Jonathan Gevaryahu Date: Sun, 9 May 2010 05:53:37 +0000 Subject: [PATCH] Fix a mistake in the interpolation logic, it should now properly delay interpolation until the final cycle of each frame when INHIBIT is set. [Lord Nightmare] --- src/emu/sound/tms5220.c | 64 +++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/src/emu/sound/tms5220.c b/src/emu/sound/tms5220.c index 475fe801398..33ae22efaf0 100644 --- a/src/emu/sound/tms5220.c +++ b/src/emu/sound/tms5220.c @@ -307,6 +307,7 @@ struct _tms5220_state //UINT8 interp_period; /* TODO: the current interpolation period, counts 1,2,3,4,5,6,7,0 for divide by 8,8,8,4,4,4,2,1 */ UINT8 interp_count; /* number of samples within each sub-interpolation period, ranges from 0-24 */ + UINT8 inhibit; /* interpolation is inhibited until the DIV1 period */ //UINT8 spkslow_delay; /* delay counter for interp count, only used on tms51xx */ UINT8 sample_count; /* number of samples within the ENTIRE interpolation period, ranges from 0-199 */ UINT8 tms5220c_rate; /* only relevant for tms5220C's multi frame rate feature; is the actual 4 bit value written on a 0x2* or 0x0* command */ @@ -436,6 +437,7 @@ static void register_for_save_states(tms5220_state *tms) state_save_register_device_item(tms->device, 0, tms->previous_energy); state_save_register_device_item(tms->device, 0, tms->interp_count); + state_save_register_device_item(tms->device, 0, tms->inhibit); state_save_register_device_item(tms->device, 0, tms->sample_count); state_save_register_device_item(tms->device, 0, tms->tms5220c_rate); state_save_register_device_item(tms->device, 0, tms->pitch_count); @@ -816,8 +818,7 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size update_status_and_ints(tms); } - /* in all cases where interpolation would be inhibited, set the target - value equal to the current value. + /* in all cases where interpolation would be inhibited, set the inhibit flag; otherwise clear it. Interpolation inhibit cases: * Old frame was voiced, new is unvoiced * Old frame was silence/zero energy, new has nonzero energy @@ -825,17 +826,14 @@ 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)) - || ((OLD_FRAME_SILENCE_FLAG == 1) && (NEW_FRAME_SILENCE_FLAG == 0)) ) + || ((OLD_FRAME_SILENCE_FLAG == 1) && (NEW_FRAME_SILENCE_FLAG == 0)) ) { #ifdef DEBUG_GENERATION 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; - for (i = 0; i < tms->coeff->num_k; i++) - tms->target_k[i] = tms->current_k[i]; + tms->inhibit = 1; } else // normal frame, normal interpolation { @@ -844,16 +842,18 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size 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]; - tms->target_pitch = tms->coeff->pitchtable[tms->new_frame_pitch_idx]; - zpar = NEW_FRAME_UNVOICED_FLAG; // find out if parameters k5-k10 should be zeroed - for (i = 0; i < 4; i++) - tms->target_k[i] = tms->coeff->ktable[i][tms->new_frame_k_idx[i]]; - for (i = 4; i < tms->coeff->num_k; i++) - tms->target_k[i] = (tms->coeff->ktable[i][tms->new_frame_k_idx[i]] * (1-zpar)); + tms->inhibit = 0; } + + tms->target_energy = tms->coeff->energytable[tms->new_frame_energy_idx]; + tms->target_pitch = tms->coeff->pitchtable[tms->new_frame_pitch_idx]; + zpar = NEW_FRAME_UNVOICED_FLAG; // find out if parameters k5-k10 should be zeroed + for (i = 0; i < 4; i++) + tms->target_k[i] = tms->coeff->ktable[i][tms->new_frame_k_idx[i]]; + for (i = 4; i < tms->coeff->num_k; i++) + tms->target_k[i] = (tms->coeff->ktable[i][tms->new_frame_k_idx[i]] * (1-zpar)); + /* if TS is now 0, ramp the energy down to 0. Is this really correct to hardware? */ if ( (tms->talk_status == 0)) { @@ -870,7 +870,8 @@ 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 +#define PC_COUNT_LOAD 7 + if (interp_period == 7) tms->inhibit = 0; // disable inhibit when reaching the last interp period zpar = OLD_FRAME_UNVOICED_FLAG; #ifdef PERFECT_INTERPOLATION_HACK tms->current_energy = tms->coeff->energytable[tms->old_frame_energy_idx]; @@ -880,10 +881,10 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size for (i = 4; i < tms->coeff->num_k; i++) tms->current_k[i] = (tms->coeff->ktable[i][tms->old_frame_k_idx[i]] * (1-zpar)); // now adjust each value to be exactly correct for the 200 samples per frsme - tms->current_energy += ((tms->target_energy - tms->current_energy)*tms->sample_count)/200; - tms->current_pitch += ((tms->target_pitch - tms->current_pitch)*tms->sample_count)/200; + tms->current_energy += (((tms->target_energy - tms->current_energy)*(1-tms->inhibit))*tms->sample_count)/200; + tms->current_pitch += (((tms->target_pitch - tms->current_pitch)*(1-tms->inhibit))*tms->sample_count)/200; for (i = 0; i < tms->coeff->num_k; i++) - tms->current_k[i] += ((tms->target_k[i] - tms->current_k[i])*tms->sample_count)/200; + tms->current_k[i] += (((tms->target_k[i] - tms->current_k[i])*(1-tms->inhibit))*tms->sample_count)/200; #else switch(tms->interp_count) { @@ -895,84 +896,84 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size 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]); + tms->current_energy += (((tms->target_energy - tms->current_energy)*(1-tms->inhibit)) >> 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]); + tms->current_pitch += (((tms->target_pitch - tms->current_pitch)*(1-tms->inhibit)) >> 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]); + tms->current_k[0] += (((tms->target_k[0] - tms->current_k[0])*(1-tms->inhibit)) >> 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]); + tms->current_k[1] += (((tms->target_k[1] - tms->current_k[1])*(1-tms->inhibit)) >> 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]); + tms->current_k[2] += (((tms->target_k[2] - tms->current_k[2])*(1-tms->inhibit)) >> 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]); + tms->current_k[3] += (((tms->target_k[3] - tms->current_k[3])*(1-tms->inhibit)) >> 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->current_k[4] = (tms->coeff->ktable[4][tms->old_frame_k_idx[4]] * (1-zpar)); - tms->current_k[4] += ((tms->target_k[4] - tms->current_k[4]) >> tms->coeff->interp_coeff[interp_period]); + tms->current_k[4] += (((tms->target_k[4] - tms->current_k[4])*(1-tms->inhibit)) >> 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->current_k[5] = (tms->coeff->ktable[5][tms->old_frame_k_idx[5]] * (1-zpar)); - tms->current_k[5] += ((tms->target_k[5] - tms->current_k[5]) >> tms->coeff->interp_coeff[interp_period]); + tms->current_k[5] += (((tms->target_k[5] - tms->current_k[5])*(1-tms->inhibit)) >> 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->current_k[6] = (tms->coeff->ktable[6][tms->old_frame_k_idx[6]] * (1-zpar)); - tms->current_k[6] += ((tms->target_k[6] - tms->current_k[6]) >> tms->coeff->interp_coeff[interp_period]); + tms->current_k[6] += (((tms->target_k[6] - tms->current_k[6])*(1-tms->inhibit)) >> 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->current_k[7] = (tms->coeff->ktable[7][tms->old_frame_k_idx[7]] * (1-zpar)); - tms->current_k[7] += ((tms->target_k[7] - tms->current_k[7]) >> tms->coeff->interp_coeff[interp_period]); + tms->current_k[7] += (((tms->target_k[7] - tms->current_k[7])*(1-tms->inhibit)) >> 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->current_k[8] = (tms->coeff->ktable[8][tms->old_frame_k_idx[8]] * (1-zpar)); - tms->current_k[8] += ((tms->target_k[8] - tms->current_k[8]) >> tms->coeff->interp_coeff[interp_period]); + tms->current_k[8] += (((tms->target_k[8] - tms->current_k[8])*(1-tms->inhibit)) >> 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->current_k[9] = (tms->coeff->ktable[9][tms->old_frame_k_idx[9]] * (1-zpar)); - tms->current_k[9] += ((tms->target_k[9] - tms->current_k[9]) >> tms->coeff->interp_coeff[interp_period]); + tms->current_k[9] += (((tms->target_k[9] - tms->current_k[9])*(1-tms->inhibit)) >> tms->coeff->interp_coeff[interp_period]); break; } #endif @@ -1500,6 +1501,7 @@ static DEVICE_RESET( tms5220 ) memset(tms->target_k, 0, sizeof(tms->target_k)); /* initialize the sample generators */ + tms->inhibit = 1; tms->interp_count = tms->tms5220c_rate = tms->pitch_count = 0; tms->sample_count = reload_table[tms->tms5220c_rate&0x3]; tms->RNG = 0x1FFF;