summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Lord-Nightmare <Lord-Nightmare@users.noreply.github.com>2015-08-28 03:43:30 -0400
committer Lord-Nightmare <Lord-Nightmare@users.noreply.github.com>2015-08-28 03:43:30 -0400
commit017ebde24e06e7799fc0e8453321a725ee71f780 (patch)
tree96ab9dacec70c5809938998260c3b1dfbd66c6c6 /src
parent66b36b336f1d8a5a40d93aec365ae8acfa2211df (diff)
TMS5110: Purge process() of gotos to hopefully make the compiler's optimizer happier. [Lord Nightmare]
Diffstat (limited to 'src')
-rw-r--r--src/emu/sound/tms5110.c470
1 files changed, 229 insertions, 241 deletions
diff --git a/src/emu/sound/tms5110.c b/src/emu/sound/tms5110.c
index 154dd0fc047..0ff39a00fed 100644
--- a/src/emu/sound/tms5110.c
+++ b/src/emu/sound/tms5110.c
@@ -350,290 +350,278 @@ void tms5110_device::process(INT16 *buffer, unsigned int size)
int i, bitout;
INT32 this_sample;
- /* if we're not speaking, fill with nothingness */
- if (!m_TALKD)
- goto empty;
-
-render:
/* loop until the buffer is full or we've stopped speaking */
- while ((size > 0) && m_TALKD)
+ while (size > 0)
{
-
- /* 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 ((m_IP == 0) && (m_PC == 12) && (m_subcycle == 1))
+ if(m_TALKD) // speaking
{
- // HACK for regression testing, be sure to comment out before release!
- //m_RNG = 0x1234;
- // end HACK
+ /* 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 ((m_IP == 0) && (m_PC == 12) && (m_subcycle == 1))
+ {
+ // HACK for regression testing, be sure to comment out before release!
+ //m_RNG = 0x1234;
+ // end HACK
#ifdef PERFECT_INTERPOLATION_HACK
- /* remember previous frame energy, pitch, and coefficients */
- m_old_frame_energy_idx = m_new_frame_energy_idx;
- m_old_frame_pitch_idx = m_new_frame_pitch_idx;
- for (i = 0; i < m_coeff->num_k; i++)
- m_old_frame_k_idx[i] = m_new_frame_k_idx[i];
+ /* remember previous frame energy, pitch, and coefficients */
+ m_old_frame_energy_idx = m_new_frame_energy_idx;
+ m_old_frame_pitch_idx = m_new_frame_pitch_idx;
+ for (i = 0; i < m_coeff->num_k; i++)
+ m_old_frame_k_idx[i] = m_new_frame_k_idx[i];
#endif
- /* Parse a new frame into the new_target_energy, new_target_pitch and new_target_k[] */
- parse_frame();
+ /* Parse a new frame into the new_target_energy, new_target_pitch and new_target_k[] */
+ parse_frame();
- // if the new frame is unvoiced (or silenced via ZPAR), be sure to zero out the k5-k10 parameters
- // NOTE: this is probably the bug the tms5100/tmc0280 has, pre-rev D, I think.
- // GUESS: Pre-rev D versions start zeroing k5-k10 immediately upon new frame load regardless of interpolation inhibit
- // I.e. ZPAR = /TALKD || (PC>5&&P=0)
- // GUESS: D and later versions only start or stop zeroing k5-k10 at the IP7->IP0 transition AFTER the frame
- // I.e. ZPAR = /TALKD || (PC>5&&OLDP)
+ // if the new frame is unvoiced (or silenced via ZPAR), be sure to zero out the k5-k10 parameters
+ // NOTE: this is probably the bug the tms5100/tmc0280 has, pre-rev D, I think.
+ // GUESS: Pre-rev D versions start zeroing k5-k10 immediately upon new frame load regardless of interpolation inhibit
+ // I.e. ZPAR = /TALKD || (PC>5&&P=0)
+ // GUESS: D and later versions only start or stop zeroing k5-k10 at the IP7->IP0 transition AFTER the frame
+ // I.e. ZPAR = /TALKD || (PC>5&&OLDP)
#ifdef PERFECT_INTERPOLATION_HACK
- m_old_uv_zpar = m_uv_zpar;
- m_old_zpar = m_zpar; // unset old zpar on new frame
+ m_old_uv_zpar = m_uv_zpar;
+ m_old_zpar = m_zpar; // unset old zpar on new frame
#endif
- m_zpar = 0;
- //m_uv_zpar = (OLD_FRAME_UNVOICED_FLAG||m_zpar); // GUESS: fixed version in tmc0280d/tms5100a/cd280x/tms5110
- m_uv_zpar = (NEW_FRAME_UNVOICED_FLAG||m_zpar); // GUESS: buggy version in tmc0280/tms5100
+ m_zpar = 0;
+ //m_uv_zpar = (OLD_FRAME_UNVOICED_FLAG||m_zpar); // GUESS: fixed version in tmc0280d/tms5100a/cd280x/tms5110
+ m_uv_zpar = (NEW_FRAME_UNVOICED_FLAG||m_zpar); // GUESS: buggy version in tmc0280/tms5100
- /* if the new frame is a stop frame, unset both TALK and SPEN (via TCON). TALKD remains active while the energy is ramping to 0. */
- if (NEW_FRAME_STOP_FLAG == 1)
- {
- m_TALK = m_SPEN = 0;
- }
+ /* if the new frame is a stop frame, unset both TALK and SPEN (via TCON). TALKD remains active while the energy is ramping to 0. */
+ if (NEW_FRAME_STOP_FLAG == 1)
+ {
+ m_TALK = m_SPEN = 0;
+ }
- /* 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
- * Old frame was unvoiced, new is voiced (note this is the case on the patent but may not be correct on the real final chip)
- */
- if ( ((OLD_FRAME_UNVOICED_FLAG == 0) && (NEW_FRAME_UNVOICED_FLAG == 1))
- || ((OLD_FRAME_UNVOICED_FLAG == 1) && (NEW_FRAME_UNVOICED_FLAG == 0)) /* this line needs further investigation, starwars tie fighters may sound better without it */
- || ((OLD_FRAME_SILENCE_FLAG == 1) && (NEW_FRAME_SILENCE_FLAG == 0)) )
- m_inhibit = 1;
- else // normal frame, normal interpolation
- m_inhibit = 0;
+ /* 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
+ * Old frame was unvoiced, new is voiced (note this is the case on the patent but may not be correct on the real final chip)
+ */
+ if ( ((OLD_FRAME_UNVOICED_FLAG == 0) && (NEW_FRAME_UNVOICED_FLAG == 1))
+ || ((OLD_FRAME_UNVOICED_FLAG == 1) && (NEW_FRAME_UNVOICED_FLAG == 0)) /* this line needs further investigation, starwars tie fighters may sound better without it */
+ || ((OLD_FRAME_SILENCE_FLAG == 1) && (NEW_FRAME_SILENCE_FLAG == 0)) )
+ m_inhibit = 1;
+ else // normal frame, normal interpolation
+ m_inhibit = 0;
#ifdef DEBUG_GENERATION
- /* Debug info for current parsed frame */
- fprintf(stderr, "OLDE: %d; OLDP: %d; ", m_OLDE, m_OLDP);
- fprintf(stderr,"Processing new frame: ");
- if (m_inhibit == 0)
- fprintf(stderr, "Normal Frame\n");
- else
- fprintf(stderr,"Interpolation Inhibited\n");
- fprintf(stderr,"*** current Energy, Pitch and Ks = %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",m_current_energy, m_current_pitch, m_current_k[0], m_current_k[1], m_current_k[2], m_current_k[3], m_current_k[4], m_current_k[5], m_current_k[6], m_current_k[7], m_current_k[8], m_current_k[9]);
- fprintf(stderr,"*** target Energy(idx), Pitch, and Ks = %04d(%x),%04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",
- (m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar)),
- m_new_frame_energy_idx,
- (m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar)),
- (m_coeff->ktable[0][m_new_frame_k_idx[0]] * (1-m_zpar)),
- (m_coeff->ktable[1][m_new_frame_k_idx[1]] * (1-m_zpar)),
- (m_coeff->ktable[2][m_new_frame_k_idx[2]] * (1-m_zpar)),
- (m_coeff->ktable[3][m_new_frame_k_idx[3]] * (1-m_zpar)),
- (m_coeff->ktable[4][m_new_frame_k_idx[4]] * (1-m_uv_zpar)),
- (m_coeff->ktable[5][m_new_frame_k_idx[5]] * (1-m_uv_zpar)),
- (m_coeff->ktable[6][m_new_frame_k_idx[6]] * (1-m_uv_zpar)),
- (m_coeff->ktable[7][m_new_frame_k_idx[7]] * (1-m_uv_zpar)),
- (m_coeff->ktable[8][m_new_frame_k_idx[8]] * (1-m_uv_zpar)),
- (m_coeff->ktable[9][m_new_frame_k_idx[9]] * (1-m_uv_zpar)) );
+ /* Debug info for current parsed frame */
+ fprintf(stderr, "OLDE: %d; OLDP: %d; ", m_OLDE, m_OLDP);
+ fprintf(stderr,"Processing new frame: ");
+ if (m_inhibit == 0)
+ fprintf(stderr, "Normal Frame\n");
+ else
+ fprintf(stderr,"Interpolation Inhibited\n");
+ fprintf(stderr,"*** current Energy, Pitch and Ks = %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",m_current_energy, m_current_pitch, m_current_k[0], m_current_k[1], m_current_k[2], m_current_k[3], m_current_k[4], m_current_k[5], m_current_k[6], m_current_k[7], m_current_k[8], m_current_k[9]);
+ fprintf(stderr,"*** target Energy(idx), Pitch, and Ks = %04d(%x),%04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",
+ (m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar)),
+ m_new_frame_energy_idx,
+ (m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar)),
+ (m_coeff->ktable[0][m_new_frame_k_idx[0]] * (1-m_zpar)),
+ (m_coeff->ktable[1][m_new_frame_k_idx[1]] * (1-m_zpar)),
+ (m_coeff->ktable[2][m_new_frame_k_idx[2]] * (1-m_zpar)),
+ (m_coeff->ktable[3][m_new_frame_k_idx[3]] * (1-m_zpar)),
+ (m_coeff->ktable[4][m_new_frame_k_idx[4]] * (1-m_uv_zpar)),
+ (m_coeff->ktable[5][m_new_frame_k_idx[5]] * (1-m_uv_zpar)),
+ (m_coeff->ktable[6][m_new_frame_k_idx[6]] * (1-m_uv_zpar)),
+ (m_coeff->ktable[7][m_new_frame_k_idx[7]] * (1-m_uv_zpar)),
+ (m_coeff->ktable[8][m_new_frame_k_idx[8]] * (1-m_uv_zpar)),
+ (m_coeff->ktable[9][m_new_frame_k_idx[9]] * (1-m_uv_zpar)) );
#endif
- }
- else // Not a new frame, just interpolate the existing frame.
- {
- int inhibit_state = ((m_inhibit==1)&&(m_IP != 0)); // disable inhibit when reaching the last interp period, but don't overwrite the m_inhibit value
-#ifdef PERFECT_INTERPOLATION_HACK
- int samples_per_frame = m_subc_reload?175:266; // either (13 A cycles + 12 B cycles) * 7 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 7 interps for SPKSLOW
- //int samples_per_frame = m_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 = (m_subcycle - m_subc_reload)+(m_PC*(3-m_subc_reload))+((m_subc_reload?25:38)*((m_IP-1)&7));
- //fprintf(stderr, "CS: %03d", current_sample);
- // reset the current energy, pitch, etc to what it was at frame start
- m_current_energy = (m_coeff->energytable[m_old_frame_energy_idx] * (1-m_old_zpar));
- m_current_pitch = (m_coeff->pitchtable[m_old_frame_pitch_idx] * (1-m_old_zpar));
- for (i = 0; i < m_coeff->num_k; i++)
- m_current_k[i] = (m_coeff->ktable[i][m_old_frame_k_idx[i]] * (1-((i<4)?m_old_zpar:m_old_uv_zpar)));
- // now adjust each value to be exactly correct for each of the samples per frame
- if (m_IP != 0) // if we're still interpolating...
- {
- m_current_energy = (m_current_energy + (((m_coeff->energytable[m_new_frame_energy_idx] - m_current_energy)*(1-inhibit_state))*current_sample)/samples_per_frame)*(1-m_zpar);
- m_current_pitch = (m_current_pitch + (((m_coeff->pitchtable[m_new_frame_pitch_idx] - m_current_pitch)*(1-inhibit_state))*current_sample)/samples_per_frame)*(1-m_zpar);
- for (i = 0; i < m_coeff->num_k; i++)
- m_current_k[i] = (m_current_k[i] + (((m_coeff->ktable[i][m_new_frame_k_idx[i]] - m_current_k[i])*(1-inhibit_state))*current_sample)/samples_per_frame)*(1-((i<4)?m_zpar:m_uv_zpar));
}
- else // we're done, play this frame for 1/8 frame.
+ else // Not a new frame, just interpolate the existing frame.
{
- m_current_energy = (m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar));
- m_current_pitch = (m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar));
+ int inhibit_state = ((m_inhibit==1)&&(m_IP != 0)); // disable inhibit when reaching the last interp period, but don't overwrite the m_inhibit value
+#ifdef PERFECT_INTERPOLATION_HACK
+ int samples_per_frame = m_subc_reload?175:266; // either (13 A cycles + 12 B cycles) * 7 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 7 interps for SPKSLOW
+ //int samples_per_frame = m_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 = (m_subcycle - m_subc_reload)+(m_PC*(3-m_subc_reload))+((m_subc_reload?25:38)*((m_IP-1)&7));
+ //fprintf(stderr, "CS: %03d", current_sample);
+ // reset the current energy, pitch, etc to what it was at frame start
+ m_current_energy = (m_coeff->energytable[m_old_frame_energy_idx] * (1-m_old_zpar));
+ m_current_pitch = (m_coeff->pitchtable[m_old_frame_pitch_idx] * (1-m_old_zpar));
for (i = 0; i < m_coeff->num_k; i++)
- m_current_k[i] = (m_coeff->ktable[i][m_new_frame_k_idx[i]] * (1-((i<4)?m_zpar:m_uv_zpar)));
- }
+ m_current_k[i] = (m_coeff->ktable[i][m_old_frame_k_idx[i]] * (1-((i<4)?m_old_zpar:m_old_uv_zpar)));
+ // now adjust each value to be exactly correct for each of the samples per frame
+ if (m_IP != 0) // if we're still interpolating...
+ {
+ m_current_energy = (m_current_energy + (((m_coeff->energytable[m_new_frame_energy_idx] - m_current_energy)*(1-inhibit_state))*current_sample)/samples_per_frame)*(1-m_zpar);
+ m_current_pitch = (m_current_pitch + (((m_coeff->pitchtable[m_new_frame_pitch_idx] - m_current_pitch)*(1-inhibit_state))*current_sample)/samples_per_frame)*(1-m_zpar);
+ for (i = 0; i < m_coeff->num_k; i++)
+ m_current_k[i] = (m_current_k[i] + (((m_coeff->ktable[i][m_new_frame_k_idx[i]] - m_current_k[i])*(1-inhibit_state))*current_sample)/samples_per_frame)*(1-((i<4)?m_zpar:m_uv_zpar));
+ }
+ else // we're done, play this frame for 1/8 frame.
+ {
+ m_current_energy = (m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar));
+ m_current_pitch = (m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar));
+ for (i = 0; i < m_coeff->num_k; i++)
+ m_current_k[i] = (m_coeff->ktable[i][m_new_frame_k_idx[i]] * (1-((i<4)?m_zpar:m_uv_zpar)));
+ }
#else
- //Updates to parameters only happen on subcycle '2' (B cycle) of PCs.
- if (m_subcycle == 2)
- {
- switch(m_PC)
+ //Updates to parameters only happen on subcycle '2' (B cycle) of PCs.
+ if (m_subcycle == 2)
{
- case 0: /* PC = 0, B cycle, write updated energy */
- m_current_energy = (m_current_energy + (((m_coeff->energytable[m_new_frame_energy_idx] - m_current_energy)*(1-inhibit_state)) INTERP_SHIFT))*(1-m_zpar);
- break;
- case 1: /* PC = 1, B cycle, write updated pitch */
- m_current_pitch = (m_current_pitch + (((m_coeff->pitchtable[m_new_frame_pitch_idx] - m_current_pitch)*(1-inhibit_state)) INTERP_SHIFT))*(1-m_zpar);
- break;
- case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11:
- /* PC = 2 through 11, B cycle, write updated K1 through K10 */
- m_current_k[m_PC-2] = (m_current_k[m_PC-2] + (((m_coeff->ktable[m_PC-2][m_new_frame_k_idx[m_PC-2]] - m_current_k[m_PC-2])*(1-inhibit_state)) INTERP_SHIFT))*(((m_PC-2)>4)?(1-m_uv_zpar):(1-m_zpar));
- break;
- case 12: /* PC = 12 */
- /* we should NEVER reach this point, PC=12 doesn't have a subcycle 2 */
- break;
+ switch(m_PC)
+ {
+ case 0: /* PC = 0, B cycle, write updated energy */
+ m_current_energy = (m_current_energy + (((m_coeff->energytable[m_new_frame_energy_idx] - m_current_energy)*(1-inhibit_state)) INTERP_SHIFT))*(1-m_zpar);
+ break;
+ case 1: /* PC = 1, B cycle, write updated pitch */
+ m_current_pitch = (m_current_pitch + (((m_coeff->pitchtable[m_new_frame_pitch_idx] - m_current_pitch)*(1-inhibit_state)) INTERP_SHIFT))*(1-m_zpar);
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11:
+ /* PC = 2 through 11, B cycle, write updated K1 through K10 */
+ m_current_k[m_PC-2] = (m_current_k[m_PC-2] + (((m_coeff->ktable[m_PC-2][m_new_frame_k_idx[m_PC-2]] - m_current_k[m_PC-2])*(1-inhibit_state)) INTERP_SHIFT))*(((m_PC-2)>4)?(1-m_uv_zpar):(1-m_zpar));
+ break;
+ case 12: /* PC = 12 */
+ /* we should NEVER reach this point, PC=12 doesn't have a subcycle 2 */
+ break;
+ }
}
- }
#endif
- }
+ }
- // calculate the output
- if (OLD_FRAME_UNVOICED_FLAG == 1)
- {
- // generate unvoiced samples here
- if (m_RNG & 1)
- m_excitation_data = ~0x3F; /* according to the patent it is (either + or -) half of the maximum value in the chirp table, so either 01000000(0x40) or 11000000(0xC0)*/
- else
- m_excitation_data = 0x40;
- }
- else /* (OLD_FRAME_UNVOICED_FLAG == 0) */
- {
- // generate voiced samples here
- /* US patent 4331836 Figure 14B shows, and logic would hold, that a pitch based chirp
- * function has a chirp/peak and then a long chain of zeroes.
- * The last entry of the chirp rom is at address 0b110011 (51d), the 52nd sample,
- * and if the address reaches that point the ADDRESS incrementer is
- * disabled, forcing all samples beyond 51d to be == 51d
- */
- if (m_pitch_count >= 51)
- m_excitation_data = (INT8)m_coeff->chirptable[51];
- else /*m_pitch_count < 51*/
- m_excitation_data = (INT8)m_coeff->chirptable[m_pitch_count];
- }
+ // calculate the output
+ if (OLD_FRAME_UNVOICED_FLAG == 1)
+ {
+ // generate unvoiced samples here
+ if (m_RNG & 1)
+ m_excitation_data = ~0x3F; /* according to the patent it is (either + or -) half of the maximum value in the chirp table, so either 01000000(0x40) or 11000000(0xC0)*/
+ else
+ m_excitation_data = 0x40;
+ }
+ else /* (OLD_FRAME_UNVOICED_FLAG == 0) */
+ {
+ // generate voiced samples here
+ /* US patent 4331836 Figure 14B shows, and logic would hold, that a pitch based chirp
+ * function has a chirp/peak and then a long chain of zeroes.
+ * The last entry of the chirp rom is at address 0b110011 (51d), the 52nd sample,
+ * and if the address reaches that point the ADDRESS incrementer is
+ * disabled, forcing all samples beyond 51d to be == 51d
+ */
+ if (m_pitch_count >= 51)
+ m_excitation_data = (INT8)m_coeff->chirptable[51];
+ else /*m_pitch_count < 51*/
+ m_excitation_data = (INT8)m_coeff->chirptable[m_pitch_count];
+ }
- // Update LFSR *20* times every sample (once per T cycle), like patent shows
- for (i=0; i<20; i++)
- {
- bitout = ((m_RNG >> 12) & 1) ^
- ((m_RNG >> 3) & 1) ^
- ((m_RNG >> 2) & 1) ^
- ((m_RNG >> 0) & 1);
- m_RNG <<= 1;
- m_RNG |= bitout;
- }
- this_sample = lattice_filter(); /* execute lattice filter */
+ // Update LFSR *20* times every sample (once per T cycle), like patent shows
+ for (i=0; i<20; i++)
+ {
+ bitout = ((m_RNG >> 12) & 1) ^
+ ((m_RNG >> 3) & 1) ^
+ ((m_RNG >> 2) & 1) ^
+ ((m_RNG >> 0) & 1);
+ m_RNG <<= 1;
+ m_RNG |= bitout;
+ }
+ this_sample = lattice_filter(); /* execute lattice filter */
#ifdef DEBUG_GENERATION_VERBOSE
- //fprintf(stderr,"C:%01d; ",m_subcycle);
- fprintf(stderr,"IP:%01d PC:%02d X:%04d E:%03d P:%03d Pc:%03d ",m_IP, m_PC, m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
- //fprintf(stderr,"X:%04d E:%03d P:%03d Pc:%03d ", m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
- for (i=0; i<10; i++)
- fprintf(stderr,"K%d:%04d ", i+1, m_current_k[i]);
- fprintf(stderr,"Out:%06d ", this_sample);
+ //fprintf(stderr,"C:%01d; ",m_subcycle);
+ fprintf(stderr,"IP:%01d PC:%02d X:%04d E:%03d P:%03d Pc:%03d ",m_IP, m_PC, m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
+ //fprintf(stderr,"X:%04d E:%03d P:%03d Pc:%03d ", m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
+ for (i=0; i<10; i++)
+ fprintf(stderr,"K%d:%04d ", i+1, m_current_k[i]);
+ fprintf(stderr,"Out:%06d ", this_sample);
//#ifdef PERFECT_INTERPOLATION_HACK
-// fprintf(stderr,"%d%d%d%d",m_old_zpar,m_zpar,m_old_uv_zpar,m_uv_zpar);
+// fprintf(stderr,"%d%d%d%d",m_old_zpar,m_zpar,m_old_uv_zpar,m_uv_zpar);
//#else
-// fprintf(stderr,"x%dx%d",m_zpar,m_uv_zpar);
+// fprintf(stderr,"x%dx%d",m_zpar,m_uv_zpar);
//#endif
- fprintf(stderr,"\n");
+ fprintf(stderr,"\n");
#endif
- /* next, force result to 14 bits (since its possible that the addition at the final (k1) stage of the lattice overflowed) */
- while (this_sample > 16383) this_sample -= 32768;
- while (this_sample < -16384) this_sample += 32768;
- if (m_digital_select == 0) // analog SPK pin output is only 8 bits, with clipping
- buffer[buf_count] = clip_analog(this_sample);
- else // digital I/O pin output is 12 bits
- {
+ /* next, force result to 14 bits (since its possible that the addition at the final (k1) stage of the lattice overflowed) */
+ while (this_sample > 16383) this_sample -= 32768;
+ while (this_sample < -16384) this_sample += 32768;
+ if (m_digital_select == 0) // analog SPK pin output is only 8 bits, with clipping
+ buffer[buf_count] = clip_analog(this_sample);
+ else // digital I/O pin output is 12 bits
+ {
#ifdef ALLOW_4_LSB
- // input: ssss ssss ssss ssss ssnn nnnn nnnn nnnn
- // N taps: ^ = 0x2000;
- // output: ssss ssss ssss ssss snnn nnnn nnnn nnnN
- buffer[buf_count] = (this_sample<<1)|((this_sample&0x2000)>>13);
+ // input: ssss ssss ssss ssss ssnn nnnn nnnn nnnn
+ // N taps: ^ = 0x2000;
+ // output: ssss ssss ssss ssss snnn nnnn nnnn nnnN
+ buffer[buf_count] = (this_sample<<1)|((this_sample&0x2000)>>13);
#else
- this_sample &= ~0xF;
- // input: ssss ssss ssss ssss ssnn nnnn nnnn 0000
- // N taps: ^^ ^^^ = 0x3E00;
- // output: ssss ssss ssss ssss snnn nnnn nnnN NNNN
- buffer[buf_count] = (this_sample<<1)|((this_sample&0x3E00)>>9);
+ this_sample &= ~0xF;
+ // input: ssss ssss ssss ssss ssnn nnnn nnnn 0000
+ // N taps: ^^ ^^^ = 0x3E00;
+ // output: ssss ssss ssss ssss snnn nnnn nnnN NNNN
+ buffer[buf_count] = (this_sample<<1)|((this_sample&0x3E00)>>9);
#endif
- }
- // Update all counts
+ }
+ // Update all counts
- m_subcycle++;
- if ((m_subcycle == 2) && (m_PC == 12)) // RESETF3
- {
- /* Circuit 412 in the patent acts a reset, resetting the pitch counter to 0
- * if INHIBIT was true during the most recent frame transition.
- * The exact time this occurs is betwen IP=7, PC=12 sub=0, T=t12
- * and m_IP = 0, PC=0 sub=0, T=t12, a period of exactly 20 cycles,
- * which overlaps the time OLDE and OLDP are updated at IP=7 PC=12 T17
- * (and hence INHIBIT itself 2 t-cycles later). We do it here because it is
- * convenient and should make no difference in output.
- */
- if ((m_IP == 7)&&(m_inhibit==1)) m_pitch_zero = 1;
- if ((m_IP == 0)&&(m_pitch_zero==1)) m_pitch_zero = 0;
- if (m_IP == 7) // RESETL4
+ m_subcycle++;
+ if ((m_subcycle == 2) && (m_PC == 12)) // RESETF3
{
- // Latch OLDE and OLDP
- OLD_FRAME_SILENCE_FLAG = NEW_FRAME_SILENCE_FLAG; // m_OLDE
- OLD_FRAME_UNVOICED_FLAG = NEW_FRAME_UNVOICED_FLAG; // m_OLDP
- /* if TALK was clear last frame, halt speech now, since TALKD (latched from TALK on new frame) just went inactive. */
+ /* Circuit 412 in the patent acts a reset, resetting the pitch counter to 0
+ * if INHIBIT was true during the most recent frame transition.
+ * The exact time this occurs is betwen IP=7, PC=12 sub=0, T=t12
+ * and m_IP = 0, PC=0 sub=0, T=t12, a period of exactly 20 cycles,
+ * which overlaps the time OLDE and OLDP are updated at IP=7 PC=12 T17
+ * (and hence INHIBIT itself 2 t-cycles later). We do it here because it is
+ * convenient and should make no difference in output.
+ */
+ if ((m_IP == 7)&&(m_inhibit==1)) m_pitch_zero = 1;
+ if ((m_IP == 0)&&(m_pitch_zero==1)) m_pitch_zero = 0;
+ if (m_IP == 7) // RESETL4
+ {
+ // Latch OLDE and OLDP
+ OLD_FRAME_SILENCE_FLAG = NEW_FRAME_SILENCE_FLAG; // m_OLDE
+ OLD_FRAME_UNVOICED_FLAG = NEW_FRAME_UNVOICED_FLAG; // m_OLDP
+ /* if TALK was clear last frame, halt speech now, since TALKD (latched from TALK on new frame) just went inactive. */
#ifdef DEBUG_GENERATION
- if (m_TALK == 0)
- fprintf(stderr,"tms5110_process: processing frame: TALKD = 0 caused by stop frame or buffer empty, halting speech.\n");
+ if (m_TALK == 0)
+ fprintf(stderr,"tms5110_process: processing frame: TALKD = 0 caused by stop frame or buffer empty, halting speech.\n");
#endif
- m_TALKD = m_TALK; // TALKD is latched from TALK
- m_TALK = m_SPEN; // TALK is latched from SPEN
+ m_TALKD = m_TALK; // TALKD is latched from TALK
+ m_TALK = m_SPEN; // TALK is latched from SPEN
+ }
+ m_subcycle = m_subc_reload;
+ m_PC = 0;
+ m_IP++;
+ m_IP&=0x7;
}
- m_subcycle = m_subc_reload;
- m_PC = 0;
- m_IP++;
- m_IP&=0x7;
- }
- else if (m_subcycle == 3)
- {
- m_subcycle = m_subc_reload;
- m_PC++;
- }
- m_pitch_count++;
- if ((m_pitch_count >= m_current_pitch)||(m_pitch_zero == 1)) m_pitch_count = 0;
- m_pitch_count &= 0x1FF;
- buf_count++;
- size--;
- }
-
-empty:
-
-#ifdef VERBOSE
- fprintf(stderr,"empty called with size of %d; IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", size, m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD);
-#endif
- while (size > 0)
- {
- m_subcycle++;
- if ((m_subcycle == 2) && (m_PC == 12)) // RESETF3
- {
- if (m_IP == 7) // RESETL4
+ else if (m_subcycle == 3)
{
- m_TALKD = m_TALK; // TALKD is latched from TALK
- m_TALK = m_SPEN; // TALK is latched from SPEN
+ m_subcycle = m_subc_reload;
+ m_PC++;
}
- m_subcycle = m_subc_reload;
- m_PC = 0;
- m_IP++;
- m_IP&=0x7;
- if (m_TALKD) goto render;
+ m_pitch_count++;
+ if ((m_pitch_count >= m_current_pitch)||(m_pitch_zero == 1)) m_pitch_count = 0;
+ m_pitch_count &= 0x1FF;
}
- else if (m_subcycle == 3)
+ else // m_TALKD == 0
{
- m_subcycle = m_subc_reload;
- m_PC++;
+ m_subcycle++;
+ if ((m_subcycle == 2) && (m_PC == 12)) // RESETF3
+ {
+ if (m_IP == 7) // RESETL4
+ {
+ m_TALKD = m_TALK; // TALKD is latched from TALK
+ m_TALK = m_SPEN; // TALK is latched from SPEN
+ }
+ m_subcycle = m_subc_reload;
+ m_PC = 0;
+ m_IP++;
+ m_IP&=0x7;
+ }
+ else if (m_subcycle == 3)
+ {
+ m_subcycle = m_subc_reload;
+ m_PC++;
+ }
+ buffer[buf_count] = -1; /* should be just -1; actual chip outputs -1 every idle sample; (cf note in data sheet, p 10, table 4) */
}
- buffer[buf_count] = -1; /* should be just -1; actual chip outputs -1 every idle sample; (cf note in data sheet, p 10, table 4) */
- buf_count++;
- size--;
+ buf_count++;
+ size--;
}
}