mirror of
https://github.com/holub/mame
synced 2025-05-25 15:25:33 +03:00
Minor updates to tms5220: simplified interpolation function case statement, made OLDP/OLDE update happen on correct cycle (subcycle may still be wrong).
This commit is contained in:
parent
6ebfe03fe2
commit
444fe77369
@ -262,7 +262,7 @@ device), PES Speech adapter (serial port connection)
|
|||||||
/* must be defined; if 0, output the waveform as if it was tapped on the speaker pin as usual, if 1, output the waveform as if it was tapped on the i/o pin (volume is much lower in the latter case) */
|
/* must be defined; if 0, output the waveform as if it was tapped on the speaker pin as usual, if 1, output the waveform as if it was tapped on the i/o pin (volume is much lower in the latter case) */
|
||||||
#define FORCE_DIGITAL 0
|
#define FORCE_DIGITAL 0
|
||||||
|
|
||||||
/* must be defined; if 1, normal speech (1xA, 1xB per interpolation step); if 0; speak as if SPKSLOW was used (2xA, 1xB per interpolation step) */
|
/* must be defined; if 1, normal speech (one A cycle, one B cycle per interpolation step); if 0; speak as if SPKSLOW was used (two A cycles, one B cycle per interpolation step) */
|
||||||
#define FORCE_SUBC_RELOAD 1
|
#define FORCE_SUBC_RELOAD 1
|
||||||
|
|
||||||
/* if defined, outputs the low 4 bits of the lattice filter to the i/o or clip logic, even though the real hardware doesn't do this */
|
/* if defined, outputs the low 4 bits of the lattice filter to the i/o or clip logic, even though the real hardware doesn't do this */
|
||||||
@ -301,7 +301,7 @@ device), PES Speech adapter (serial port connection)
|
|||||||
#undef DEBUG_IO_READY
|
#undef DEBUG_IO_READY
|
||||||
// above debugs the io ready callback
|
// above debugs the io ready callback
|
||||||
#undef DEBUG_RS_WS
|
#undef DEBUG_RS_WS
|
||||||
// above debugs the new tms5220_data_r and data_w access methods which actually respect rs and ws
|
// above debugs the tms5220_data_r and data_w access methods which actually respect rs and ws
|
||||||
|
|
||||||
#define MAX_SAMPLE_CHUNK 512
|
#define MAX_SAMPLE_CHUNK 512
|
||||||
#define FIFO_SIZE 16
|
#define FIFO_SIZE 16
|
||||||
@ -314,7 +314,7 @@ device), PES Speech adapter (serial port connection)
|
|||||||
|
|
||||||
#define TMS5220_IS_TMC0285 TMS5220_IS_5200
|
#define TMS5220_IS_TMC0285 TMS5220_IS_5200
|
||||||
|
|
||||||
static const UINT8 reload_table[4] = { 0, 2, 4, 6 }; //is the sample count reload for 5220c only; 5200 and 5220 always reload with 0
|
static const UINT8 reload_table[4] = { 0, 2, 4, 6 }; //sample count reload for 5220c only; 5200 and 5220 always reload with 0; keep in mind this is loaded on IP=0 PC=12 subcycle=1 so it immediately will increment after one sample, effectively being 1,3,5,7 as in the comments above.
|
||||||
|
|
||||||
typedef struct _tms5220_state tms5220_state;
|
typedef struct _tms5220_state tms5220_state;
|
||||||
struct _tms5220_state
|
struct _tms5220_state
|
||||||
@ -871,21 +871,22 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
|
|||||||
while ((size > 0) && tms->speaking_now)
|
while ((size > 0) && tms->speaking_now)
|
||||||
{
|
{
|
||||||
/* if it is the appropriate time to update the old energy/pitch idxes,
|
/* if it is the appropriate time to update the old energy/pitch idxes,
|
||||||
* i.e. when IP=7, do so. */
|
* i.e. when IP=7, PC=12, do so. */
|
||||||
if (tms->interp_period == 7)
|
if ((tms->interp_period == 7) && (tms->PC == 12))
|
||||||
{
|
{
|
||||||
tms->OLDE = (tms->new_frame_energy_idx == 0);
|
tms->OLDE = (tms->new_frame_energy_idx == 0);
|
||||||
tms->OLDP = (tms->new_frame_pitch_idx == 0);
|
tms->OLDP = (tms->new_frame_pitch_idx == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we're ready for a new frame, i.e. when IP=0, PC=12, Sub=1 */
|
/* if we're ready for a new frame to be applied, i.e. when IP=0, PC=12, Sub=1 */
|
||||||
|
/* (In reality, the frame was really loaded incrementally during the entire IP=0 PC=x time period, but it doesn't affect anything until IP=0 PC=12 happens) */
|
||||||
if ((tms->interp_period == 0) && (tms->PC == 12) && (tms->subcycle == 1))
|
if ((tms->interp_period == 0) && (tms->PC == 12) && (tms->subcycle == 1))
|
||||||
{
|
{
|
||||||
// HACK for regression testing, be sure to comment out before release!
|
// HACK for regression testing, be sure to comment out before release!
|
||||||
//tms->RNG = 0x1234;
|
//tms->RNG = 0x1234;
|
||||||
// end HACK
|
// end HACK
|
||||||
|
|
||||||
/* appropriately override the interp count if needed */
|
/* appropriately override the interp count if needed; this will be incremented after the frame parse! */
|
||||||
tms->interp_period = reload_table[tms->tms5220c_rate&0x3];
|
tms->interp_period = reload_table[tms->tms5220c_rate&0x3];
|
||||||
|
|
||||||
#ifdef PERFECT_INTERPOLATION_HACK
|
#ifdef PERFECT_INTERPOLATION_HACK
|
||||||
@ -966,67 +967,43 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
|
|||||||
}
|
}
|
||||||
else // Not a new frame, just interpolate the existing frame.
|
else // Not a new frame, just interpolate the existing frame.
|
||||||
{
|
{
|
||||||
if (tms->interp_period == 0) tms->inhibit = 0; // disable inhibit when reaching the last interp period
|
if (tms->interp_period == 0) tms->inhibit = 0; // disable inhibit when reaching the last interp period
|
||||||
#ifdef PERFECT_INTERPOLATION_HACK
|
#ifdef PERFECT_INTERPOLATION_HACK
|
||||||
int samples_per_frame = tms->subc_reload?200:304; // either (13 A cycles + 12 B cycles) * 8 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 8 interps for SPKSLOW
|
int samples_per_frame = tms->subc_reload?200:304; // either (13 A cycles + 12 B cycles) * 8 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 8 interps for SPKSLOW
|
||||||
int current_sample = ((tms->PC*(3-tms->subc_reload))+((tms->subc_reload?38:25)*tms->interp_period));
|
int current_sample = ((tms->PC*(3-tms->subc_reload))+((tms->subc_reload?38:25)*tms->interp_period));
|
||||||
zpar = OLD_FRAME_UNVOICED_FLAG;
|
zpar = OLD_FRAME_UNVOICED_FLAG;
|
||||||
// reset the current energy, pitch, etc to what it was at frame start
|
// reset the current energy, pitch, etc to what it was at frame start
|
||||||
tms->current_energy = tms->coeff->energytable[tms->old_frame_energy_idx];
|
tms->current_energy = tms->coeff->energytable[tms->old_frame_energy_idx];
|
||||||
tms->current_pitch = tms->coeff->pitchtable[tms->old_frame_pitch_idx];
|
tms->current_pitch = tms->coeff->pitchtable[tms->old_frame_pitch_idx];
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
tms->current_k[i] = tms->coeff->ktable[i][tms->old_frame_k_idx[i]];
|
tms->current_k[i] = tms->coeff->ktable[i][tms->old_frame_k_idx[i]];
|
||||||
for (i = 4; i < tms->coeff->num_k; i++)
|
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));
|
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 each of the samples per frsme
|
// now adjust each value to be exactly correct for each of the samples per frsme
|
||||||
tms->current_energy += (((tms->target_energy - tms->current_energy)*(1-tms->inhibit))*current_sample)/samples_per_frame;
|
tms->current_energy += (((tms->target_energy - tms->current_energy)*(1-tms->inhibit))*current_sample)/samples_per_frame;
|
||||||
tms->current_pitch += (((tms->target_pitch - tms->current_pitch)*(1-tms->inhibit))*current_sample)/samples_per_frame;
|
tms->current_pitch += (((tms->target_pitch - tms->current_pitch)*(1-tms->inhibit))*current_sample)/samples_per_frame;
|
||||||
for (i = 0; i < tms->coeff->num_k; i++)
|
for (i = 0; i < tms->coeff->num_k; i++)
|
||||||
tms->current_k[i] += (((tms->target_k[i] - tms->current_k[i])*(1-tms->inhibit))*current_sample)/samples_per_frame;
|
tms->current_k[i] += (((tms->target_k[i] - tms->current_k[i])*(1-tms->inhibit))*current_sample)/samples_per_frame;
|
||||||
#else
|
#else
|
||||||
//Updates to parameters only happen on subcycle '2' (B cycle) of PCs.
|
//Updates to parameters only happen on subcycle '2' (B cycle) of PCs.
|
||||||
if (tms->subcycle == 2)
|
if (tms->subcycle == 2)
|
||||||
{
|
|
||||||
switch(tms->PC)
|
|
||||||
{
|
{
|
||||||
case 0: /* PC = 0, B cycle, write updated energy */
|
switch(tms->PC)
|
||||||
tms->current_energy += (((tms->target_energy - tms->current_energy)*(1-tms->inhibit)) INTERP_SHIFT);
|
{
|
||||||
break;
|
case 0: /* PC = 0, B cycle, write updated energy */
|
||||||
case 1: /* PC = 1, B cycle, write updated pitch */
|
tms->current_energy += (((tms->target_energy - tms->current_energy)*(1-tms->inhibit)) INTERP_SHIFT);
|
||||||
tms->current_pitch += (((tms->target_pitch - tms->current_pitch)*(1-tms->inhibit)) INTERP_SHIFT);
|
break;
|
||||||
break;
|
case 1: /* PC = 1, B cycle, write updated pitch */
|
||||||
case 2: /* PC = 2, B cycle, write updated K1 */
|
tms->current_pitch += (((tms->target_pitch - tms->current_pitch)*(1-tms->inhibit)) INTERP_SHIFT);
|
||||||
tms->current_k[0] += (((tms->target_k[0] - tms->current_k[0])*(1-tms->inhibit)) INTERP_SHIFT);
|
break;
|
||||||
break;
|
case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11:
|
||||||
case 3: /* PC = 3, B cycle, write updated K2 */
|
/* PC = 2 thru 11, B cycle, write updated K1 thru K10 */
|
||||||
tms->current_k[1] += (((tms->target_k[1] - tms->current_k[1])*(1-tms->inhibit)) INTERP_SHIFT);
|
tms->current_k[tms->PC-2] += (((tms->target_k[tms->PC-2] - tms->current_k[tms->PC-2])*(1-tms->inhibit)) INTERP_SHIFT);
|
||||||
break;
|
break;
|
||||||
case 4: /* PC = 4, B cycle, write updated K3 */
|
case 12: /* PC = 12, do nothing */
|
||||||
tms->current_k[2] += (((tms->target_k[2] - tms->current_k[2])*(1-tms->inhibit)) INTERP_SHIFT);
|
break;
|
||||||
break;
|
}
|
||||||
case 5: /* PC = 5, B cycle, write updated K4 */
|
|
||||||
tms->current_k[3] += (((tms->target_k[3] - tms->current_k[3])*(1-tms->inhibit)) INTERP_SHIFT);
|
|
||||||
break;
|
|
||||||
case 6: /* PC = 6, B cycle, write updated K5 */
|
|
||||||
tms->current_k[4] += (((tms->target_k[4] - tms->current_k[4])*(1-tms->inhibit)) INTERP_SHIFT);
|
|
||||||
break;
|
|
||||||
case 7: /* PC = 7, B cycle, write updated K6 */
|
|
||||||
tms->current_k[5] += (((tms->target_k[5] - tms->current_k[5])*(1-tms->inhibit)) INTERP_SHIFT);
|
|
||||||
break;
|
|
||||||
case 8: /* PC = 8, B cycle, write updated K7 */
|
|
||||||
tms->current_k[6] += (((tms->target_k[6] - tms->current_k[6])*(1-tms->inhibit)) INTERP_SHIFT);
|
|
||||||
break;
|
|
||||||
case 9: /* PC = 9, B cycle, write updated K8 */
|
|
||||||
tms->current_k[7] += (((tms->target_k[7] - tms->current_k[7])*(1-tms->inhibit)) INTERP_SHIFT);
|
|
||||||
break;
|
|
||||||
case 10: /* PC = 10, B cycle, write updated K9 */
|
|
||||||
tms->current_k[8] += (((tms->target_k[8] - tms->current_k[8])*(1-tms->inhibit)) INTERP_SHIFT);
|
|
||||||
break;
|
|
||||||
case 11: /* PC = 11, B cycle, write updated K10 */
|
|
||||||
tms->current_k[9] += (((tms->target_k[9] - tms->current_k[9])*(1-tms->inhibit)) INTERP_SHIFT);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1069,7 +1046,7 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update LFSR *20* times every sample, like patent shows */
|
/* Update LFSR *20* times every sample (once per T cycle), like patent shows */
|
||||||
for (i=0; i<20; i++)
|
for (i=0; i<20; i++)
|
||||||
{
|
{
|
||||||
bitout = ((tms->RNG >> 12) & 1) ^
|
bitout = ((tms->RNG >> 12) & 1) ^
|
||||||
@ -1110,7 +1087,6 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
|
|||||||
}
|
}
|
||||||
/* Update all counts */
|
/* Update all counts */
|
||||||
|
|
||||||
size--;
|
|
||||||
tms->subcycle++;
|
tms->subcycle++;
|
||||||
if ((tms->subcycle == 2) && (tms->PC == 12))
|
if ((tms->subcycle == 2) && (tms->PC == 12))
|
||||||
{
|
{
|
||||||
@ -1127,6 +1103,7 @@ static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size
|
|||||||
tms->pitch_count++;
|
tms->pitch_count++;
|
||||||
if (tms->pitch_count >= tms->current_pitch) tms->pitch_count = 0;
|
if (tms->pitch_count >= tms->current_pitch) tms->pitch_count = 0;
|
||||||
buf_count++;
|
buf_count++;
|
||||||
|
size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
empty:
|
empty:
|
||||||
|
Loading…
Reference in New Issue
Block a user