Previous 199869 Revisions Next

r40502 Friday 28th August, 2015 at 07:43:30 UTC by Jonathan Gevaryahu
TMS5110: Purge process() of gotos to hopefully make the compiler's optimizer happier. [Lord Nightmare]
[src/emu/sound]tms5110.c

trunk/src/emu/sound/tms5110.c
r249013r249014
350350   int i, bitout;
351351   INT32 this_sample;
352352
353   /* if we're not speaking, fill with nothingness */
354   if (!m_TALKD)
355      goto empty;
356
357render:
358353   /* loop until the buffer is full or we've stopped speaking */
359   while ((size > 0) && m_TALKD)
354   while (size > 0)
360355   {
361
362      /* if we're ready for a new frame to be applied, i.e. when IP=0, PC=12, Sub=1
363       * (In reality, the frame was really loaded incrementally during the entire IP=0
364       * PC=x time period, but it doesn't affect anything until IP=0 PC=12 happens)
365       */
366      if ((m_IP == 0) && (m_PC == 12) && (m_subcycle == 1))
356      if(m_TALKD) // speaking
367357      {
368         // HACK for regression testing, be sure to comment out before release!
369         //m_RNG = 0x1234;
370         // end HACK
358         /* if we're ready for a new frame to be applied, i.e. when IP=0, PC=12, Sub=1
359          * (In reality, the frame was really loaded incrementally during the entire IP=0
360          * PC=x time period, but it doesn't affect anything until IP=0 PC=12 happens)
361          */
362         if ((m_IP == 0) && (m_PC == 12) && (m_subcycle == 1))
363         {
364            // HACK for regression testing, be sure to comment out before release!
365            //m_RNG = 0x1234;
366            // end HACK
371367
372368#ifdef PERFECT_INTERPOLATION_HACK
373         /* remember previous frame energy, pitch, and coefficients */
374         m_old_frame_energy_idx = m_new_frame_energy_idx;
375         m_old_frame_pitch_idx = m_new_frame_pitch_idx;
376         for (i = 0; i < m_coeff->num_k; i++)
377            m_old_frame_k_idx[i] = m_new_frame_k_idx[i];
369            /* remember previous frame energy, pitch, and coefficients */
370            m_old_frame_energy_idx = m_new_frame_energy_idx;
371            m_old_frame_pitch_idx = m_new_frame_pitch_idx;
372            for (i = 0; i < m_coeff->num_k; i++)
373               m_old_frame_k_idx[i] = m_new_frame_k_idx[i];
378374#endif
379375
380         /* Parse a new frame into the new_target_energy, new_target_pitch and new_target_k[] */
381         parse_frame();
376            /* Parse a new frame into the new_target_energy, new_target_pitch and new_target_k[] */
377            parse_frame();
382378
383         // if the new frame is unvoiced (or silenced via ZPAR), be sure to zero out the k5-k10 parameters
384         // NOTE: this is probably the bug the tms5100/tmc0280 has, pre-rev D, I think.
385         // GUESS: Pre-rev D versions start zeroing k5-k10 immediately upon new frame load regardless of interpolation inhibit
386         // I.e. ZPAR = /TALKD || (PC>5&&P=0)
387         // GUESS: D and later versions only start or stop zeroing k5-k10 at the IP7->IP0 transition AFTER the frame
388         // I.e. ZPAR = /TALKD || (PC>5&&OLDP)
379            // if the new frame is unvoiced (or silenced via ZPAR), be sure to zero out the k5-k10 parameters
380            // NOTE: this is probably the bug the tms5100/tmc0280 has, pre-rev D, I think.
381            // GUESS: Pre-rev D versions start zeroing k5-k10 immediately upon new frame load regardless of interpolation inhibit
382            // I.e. ZPAR = /TALKD || (PC>5&&P=0)
383            // GUESS: D and later versions only start or stop zeroing k5-k10 at the IP7->IP0 transition AFTER the frame
384            // I.e. ZPAR = /TALKD || (PC>5&&OLDP)
389385#ifdef PERFECT_INTERPOLATION_HACK
390         m_old_uv_zpar = m_uv_zpar;
391         m_old_zpar = m_zpar; // unset old zpar on new frame
386            m_old_uv_zpar = m_uv_zpar;
387            m_old_zpar = m_zpar; // unset old zpar on new frame
392388#endif
393         m_zpar = 0;
394         //m_uv_zpar = (OLD_FRAME_UNVOICED_FLAG||m_zpar); // GUESS: fixed version in tmc0280d/tms5100a/cd280x/tms5110
395         m_uv_zpar = (NEW_FRAME_UNVOICED_FLAG||m_zpar); // GUESS: buggy version in tmc0280/tms5100
389            m_zpar = 0;
390            //m_uv_zpar = (OLD_FRAME_UNVOICED_FLAG||m_zpar); // GUESS: fixed version in tmc0280d/tms5100a/cd280x/tms5110
391            m_uv_zpar = (NEW_FRAME_UNVOICED_FLAG||m_zpar); // GUESS: buggy version in tmc0280/tms5100
396392
397         /* 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. */
398         if (NEW_FRAME_STOP_FLAG == 1)
399         {
400            m_TALK = m_SPEN = 0;
401         }
393            /* 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. */
394            if (NEW_FRAME_STOP_FLAG == 1)
395            {
396               m_TALK = m_SPEN = 0;
397            }
402398
403         /* in all cases where interpolation would be inhibited, set the inhibit flag; otherwise clear it.
404            Interpolation inhibit cases:
405          * Old frame was voiced, new is unvoiced
406          * Old frame was silence/zero energy, new has nonzero energy
407          * 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)
408          */
409         if ( ((OLD_FRAME_UNVOICED_FLAG == 0) && (NEW_FRAME_UNVOICED_FLAG == 1))
410            || ((OLD_FRAME_UNVOICED_FLAG == 1) && (NEW_FRAME_UNVOICED_FLAG == 0)) /* this line needs further investigation, starwars tie fighters may sound better without it */
411            || ((OLD_FRAME_SILENCE_FLAG == 1) && (NEW_FRAME_SILENCE_FLAG == 0)) )
412            m_inhibit = 1;
413         else // normal frame, normal interpolation
414            m_inhibit = 0;
399            /* in all cases where interpolation would be inhibited, set the inhibit flag; otherwise clear it.
400               Interpolation inhibit cases:
401             * Old frame was voiced, new is unvoiced
402             * Old frame was silence/zero energy, new has nonzero energy
403             * 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)
404             */
405            if ( ((OLD_FRAME_UNVOICED_FLAG == 0) && (NEW_FRAME_UNVOICED_FLAG == 1))
406               || ((OLD_FRAME_UNVOICED_FLAG == 1) && (NEW_FRAME_UNVOICED_FLAG == 0)) /* this line needs further investigation, starwars tie fighters may sound better without it */
407               || ((OLD_FRAME_SILENCE_FLAG == 1) && (NEW_FRAME_SILENCE_FLAG == 0)) )
408               m_inhibit = 1;
409            else // normal frame, normal interpolation
410               m_inhibit = 0;
415411
416412#ifdef DEBUG_GENERATION
417         /* Debug info for current parsed frame */
418         fprintf(stderr, "OLDE: %d; OLDP: %d; ", m_OLDE, m_OLDP);
419         fprintf(stderr,"Processing new frame: ");
420         if (m_inhibit == 0)
421            fprintf(stderr, "Normal Frame\n");
422         else
423            fprintf(stderr,"Interpolation Inhibited\n");
424         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]);
425         fprintf(stderr,"*** target Energy(idx), Pitch, and Ks = %04d(%x),%04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",
426            (m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar)),
427            m_new_frame_energy_idx,
428            (m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar)),
429            (m_coeff->ktable[0][m_new_frame_k_idx[0]] * (1-m_zpar)),
430            (m_coeff->ktable[1][m_new_frame_k_idx[1]] * (1-m_zpar)),
431            (m_coeff->ktable[2][m_new_frame_k_idx[2]] * (1-m_zpar)),
432            (m_coeff->ktable[3][m_new_frame_k_idx[3]] * (1-m_zpar)),
433            (m_coeff->ktable[4][m_new_frame_k_idx[4]] * (1-m_uv_zpar)),
434            (m_coeff->ktable[5][m_new_frame_k_idx[5]] * (1-m_uv_zpar)),
435            (m_coeff->ktable[6][m_new_frame_k_idx[6]] * (1-m_uv_zpar)),
436            (m_coeff->ktable[7][m_new_frame_k_idx[7]] * (1-m_uv_zpar)),
437            (m_coeff->ktable[8][m_new_frame_k_idx[8]] * (1-m_uv_zpar)),
438            (m_coeff->ktable[9][m_new_frame_k_idx[9]] * (1-m_uv_zpar)) );
413            /* Debug info for current parsed frame */
414            fprintf(stderr, "OLDE: %d; OLDP: %d; ", m_OLDE, m_OLDP);
415            fprintf(stderr,"Processing new frame: ");
416            if (m_inhibit == 0)
417               fprintf(stderr, "Normal Frame\n");
418            else
419               fprintf(stderr,"Interpolation Inhibited\n");
420            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]);
421            fprintf(stderr,"*** target Energy(idx), Pitch, and Ks = %04d(%x),%04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",
422               (m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar)),
423               m_new_frame_energy_idx,
424               (m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar)),
425               (m_coeff->ktable[0][m_new_frame_k_idx[0]] * (1-m_zpar)),
426               (m_coeff->ktable[1][m_new_frame_k_idx[1]] * (1-m_zpar)),
427               (m_coeff->ktable[2][m_new_frame_k_idx[2]] * (1-m_zpar)),
428               (m_coeff->ktable[3][m_new_frame_k_idx[3]] * (1-m_zpar)),
429               (m_coeff->ktable[4][m_new_frame_k_idx[4]] * (1-m_uv_zpar)),
430               (m_coeff->ktable[5][m_new_frame_k_idx[5]] * (1-m_uv_zpar)),
431               (m_coeff->ktable[6][m_new_frame_k_idx[6]] * (1-m_uv_zpar)),
432               (m_coeff->ktable[7][m_new_frame_k_idx[7]] * (1-m_uv_zpar)),
433               (m_coeff->ktable[8][m_new_frame_k_idx[8]] * (1-m_uv_zpar)),
434               (m_coeff->ktable[9][m_new_frame_k_idx[9]] * (1-m_uv_zpar)) );
439435#endif
440436
441      }
442      else // Not a new frame, just interpolate the existing frame.
443      {
444         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
445#ifdef PERFECT_INTERPOLATION_HACK
446         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
447         //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
448         int current_sample = (m_subcycle - m_subc_reload)+(m_PC*(3-m_subc_reload))+((m_subc_reload?25:38)*((m_IP-1)&7));
449         //fprintf(stderr, "CS: %03d", current_sample);
450         // reset the current energy, pitch, etc to what it was at frame start
451         m_current_energy = (m_coeff->energytable[m_old_frame_energy_idx] * (1-m_old_zpar));
452         m_current_pitch = (m_coeff->pitchtable[m_old_frame_pitch_idx] * (1-m_old_zpar));
453         for (i = 0; i < m_coeff->num_k; i++)
454            m_current_k[i] = (m_coeff->ktable[i][m_old_frame_k_idx[i]] * (1-((i<4)?m_old_zpar:m_old_uv_zpar)));
455         // now adjust each value to be exactly correct for each of the samples per frame
456         if (m_IP != 0) // if we're still interpolating...
457         {
458            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);
459            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);
460            for (i = 0; i < m_coeff->num_k; i++)
461               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));
462437         }
463         else // we're done, play this frame for 1/8 frame.
438         else // Not a new frame, just interpolate the existing frame.
464439         {
465            m_current_energy = (m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar));
466            m_current_pitch = (m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar));
440            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
441#ifdef PERFECT_INTERPOLATION_HACK
442            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
443            //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
444            int current_sample = (m_subcycle - m_subc_reload)+(m_PC*(3-m_subc_reload))+((m_subc_reload?25:38)*((m_IP-1)&7));
445            //fprintf(stderr, "CS: %03d", current_sample);
446            // reset the current energy, pitch, etc to what it was at frame start
447            m_current_energy = (m_coeff->energytable[m_old_frame_energy_idx] * (1-m_old_zpar));
448            m_current_pitch = (m_coeff->pitchtable[m_old_frame_pitch_idx] * (1-m_old_zpar));
467449            for (i = 0; i < m_coeff->num_k; i++)
468               m_current_k[i] = (m_coeff->ktable[i][m_new_frame_k_idx[i]] * (1-((i<4)?m_zpar:m_uv_zpar)));
469         }
450               m_current_k[i] = (m_coeff->ktable[i][m_old_frame_k_idx[i]] * (1-((i<4)?m_old_zpar:m_old_uv_zpar)));
451            // now adjust each value to be exactly correct for each of the samples per frame
452            if (m_IP != 0) // if we're still interpolating...
453            {
454               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);
455               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);
456               for (i = 0; i < m_coeff->num_k; i++)
457                  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));
458            }
459            else // we're done, play this frame for 1/8 frame.
460            {
461               m_current_energy = (m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar));
462               m_current_pitch = (m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar));
463               for (i = 0; i < m_coeff->num_k; i++)
464                  m_current_k[i] = (m_coeff->ktable[i][m_new_frame_k_idx[i]] * (1-((i<4)?m_zpar:m_uv_zpar)));
465            }
470466#else
471         //Updates to parameters only happen on subcycle '2' (B cycle) of PCs.
472         if (m_subcycle == 2)
473         {
474            switch(m_PC)
467            //Updates to parameters only happen on subcycle '2' (B cycle) of PCs.
468            if (m_subcycle == 2)
475469            {
476               case 0: /* PC = 0, B cycle, write updated energy */
477               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);
478               break;
479               case 1: /* PC = 1, B cycle, write updated pitch */
480               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);
481               break;
482               case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11:
483               /* PC = 2 through 11, B cycle, write updated K1 through K10 */
484               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));
485               break;
486               case 12: /* PC = 12 */
487               /* we should NEVER reach this point, PC=12 doesn't have a subcycle 2 */
488               break;
470               switch(m_PC)
471               {
472                  case 0: /* PC = 0, B cycle, write updated energy */
473                  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);
474                  break;
475                  case 1: /* PC = 1, B cycle, write updated pitch */
476                  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);
477                  break;
478                  case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11:
479                  /* PC = 2 through 11, B cycle, write updated K1 through K10 */
480                  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));
481                  break;
482                  case 12: /* PC = 12 */
483                  /* we should NEVER reach this point, PC=12 doesn't have a subcycle 2 */
484                  break;
485               }
489486            }
490         }
491487#endif
492      }
488         }
493489
494      // calculate the output
495      if (OLD_FRAME_UNVOICED_FLAG == 1)
496      {
497         // generate unvoiced samples here
498         if (m_RNG & 1)
499            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)*/
500         else
501            m_excitation_data = 0x40;
502      }
503      else /* (OLD_FRAME_UNVOICED_FLAG == 0) */
504      {
505         // generate voiced samples here
506         /* US patent 4331836 Figure 14B shows, and logic would hold, that a pitch based chirp
507          * function has a chirp/peak and then a long chain of zeroes.
508          * The last entry of the chirp rom is at address 0b110011 (51d), the 52nd sample,
509          * and if the address reaches that point the ADDRESS incrementer is
510          * disabled, forcing all samples beyond 51d to be == 51d
511          */
512         if (m_pitch_count >= 51)
513            m_excitation_data = (INT8)m_coeff->chirptable[51];
514         else /*m_pitch_count < 51*/
515            m_excitation_data = (INT8)m_coeff->chirptable[m_pitch_count];
516      }
490         // calculate the output
491         if (OLD_FRAME_UNVOICED_FLAG == 1)
492         {
493            // generate unvoiced samples here
494            if (m_RNG & 1)
495               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)*/
496            else
497               m_excitation_data = 0x40;
498         }
499         else /* (OLD_FRAME_UNVOICED_FLAG == 0) */
500         {
501            // generate voiced samples here
502            /* US patent 4331836 Figure 14B shows, and logic would hold, that a pitch based chirp
503             * function has a chirp/peak and then a long chain of zeroes.
504             * The last entry of the chirp rom is at address 0b110011 (51d), the 52nd sample,
505             * and if the address reaches that point the ADDRESS incrementer is
506             * disabled, forcing all samples beyond 51d to be == 51d
507             */
508            if (m_pitch_count >= 51)
509               m_excitation_data = (INT8)m_coeff->chirptable[51];
510            else /*m_pitch_count < 51*/
511               m_excitation_data = (INT8)m_coeff->chirptable[m_pitch_count];
512         }
517513
518      // Update LFSR *20* times every sample (once per T cycle), like patent shows
519   for (i=0; i<20; i++)
520   {
521      bitout = ((m_RNG >> 12) & 1) ^
522            ((m_RNG >>  3) & 1) ^
523            ((m_RNG >>  2) & 1) ^
524            ((m_RNG >>  0) & 1);
525      m_RNG <<= 1;
526      m_RNG |= bitout;
527   }
528      this_sample = lattice_filter(); /* execute lattice filter */
514         // Update LFSR *20* times every sample (once per T cycle), like patent shows
515         for (i=0; i<20; i++)
516         {
517            bitout = ((m_RNG >> 12) & 1) ^
518                  ((m_RNG >>  3) & 1) ^
519                  ((m_RNG >>  2) & 1) ^
520                  ((m_RNG >>  0) & 1);
521            m_RNG <<= 1;
522            m_RNG |= bitout;
523         }
524         this_sample = lattice_filter(); /* execute lattice filter */
529525#ifdef DEBUG_GENERATION_VERBOSE
530      //fprintf(stderr,"C:%01d; ",m_subcycle);
531      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);
532      //fprintf(stderr,"X:%04d E:%03d P:%03d Pc:%03d ", m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
533      for (i=0; i<10; i++)
534         fprintf(stderr,"K%d:%04d ", i+1, m_current_k[i]);
535      fprintf(stderr,"Out:%06d ", this_sample);
526         //fprintf(stderr,"C:%01d; ",m_subcycle);
527         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);
528         //fprintf(stderr,"X:%04d E:%03d P:%03d Pc:%03d ", m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
529         for (i=0; i<10; i++)
530            fprintf(stderr,"K%d:%04d ", i+1, m_current_k[i]);
531         fprintf(stderr,"Out:%06d ", this_sample);
536532//#ifdef PERFECT_INTERPOLATION_HACK
537//      fprintf(stderr,"%d%d%d%d",m_old_zpar,m_zpar,m_old_uv_zpar,m_uv_zpar);
533//         fprintf(stderr,"%d%d%d%d",m_old_zpar,m_zpar,m_old_uv_zpar,m_uv_zpar);
538534//#else
539//      fprintf(stderr,"x%dx%d",m_zpar,m_uv_zpar);
535//         fprintf(stderr,"x%dx%d",m_zpar,m_uv_zpar);
540536//#endif
541      fprintf(stderr,"\n");
537         fprintf(stderr,"\n");
542538#endif
543      /* next, force result to 14 bits (since its possible that the addition at the final (k1) stage of the lattice overflowed) */
544      while (this_sample > 16383) this_sample -= 32768;
545      while (this_sample < -16384) this_sample += 32768;
546      if (m_digital_select == 0) // analog SPK pin output is only 8 bits, with clipping
547         buffer[buf_count] = clip_analog(this_sample);
548      else // digital I/O pin output is 12 bits
549      {
539         /* next, force result to 14 bits (since its possible that the addition at the final (k1) stage of the lattice overflowed) */
540         while (this_sample > 16383) this_sample -= 32768;
541         while (this_sample < -16384) this_sample += 32768;
542         if (m_digital_select == 0) // analog SPK pin output is only 8 bits, with clipping
543            buffer[buf_count] = clip_analog(this_sample);
544         else // digital I/O pin output is 12 bits
545         {
550546#ifdef ALLOW_4_LSB
551         // input:  ssss ssss ssss ssss ssnn nnnn nnnn nnnn
552         // N taps:                       ^                 = 0x2000;
553         // output: ssss ssss ssss ssss snnn nnnn nnnn nnnN
554         buffer[buf_count] = (this_sample<<1)|((this_sample&0x2000)>>13);
547            // input:  ssss ssss ssss ssss ssnn nnnn nnnn nnnn
548            // N taps:                       ^                 = 0x2000;
549            // output: ssss ssss ssss ssss snnn nnnn nnnn nnnN
550            buffer[buf_count] = (this_sample<<1)|((this_sample&0x2000)>>13);
555551#else
556         this_sample &= ~0xF;
557         // input:  ssss ssss ssss ssss ssnn nnnn nnnn 0000
558         // N taps:                       ^^ ^^^            = 0x3E00;
559         // output: ssss ssss ssss ssss snnn nnnn nnnN NNNN
560         buffer[buf_count] = (this_sample<<1)|((this_sample&0x3E00)>>9);
552            this_sample &= ~0xF;
553            // input:  ssss ssss ssss ssss ssnn nnnn nnnn 0000
554            // N taps:                       ^^ ^^^            = 0x3E00;
555            // output: ssss ssss ssss ssss snnn nnnn nnnN NNNN
556            buffer[buf_count] = (this_sample<<1)|((this_sample&0x3E00)>>9);
561557#endif
562      }
563      // Update all counts
558         }
559         // Update all counts
564560
565      m_subcycle++;
566      if ((m_subcycle == 2) && (m_PC == 12)) // RESETF3
567      {
568         /* Circuit 412 in the patent acts a reset, resetting the pitch counter to 0
569          * if INHIBIT was true during the most recent frame transition.
570          * The exact time this occurs is betwen IP=7, PC=12 sub=0, T=t12
571          * and m_IP = 0, PC=0 sub=0, T=t12, a period of exactly 20 cycles,
572          * which overlaps the time OLDE and OLDP are updated at IP=7 PC=12 T17
573          * (and hence INHIBIT itself 2 t-cycles later). We do it here because it is
574          * convenient and should make no difference in output.
575          */
576         if ((m_IP == 7)&&(m_inhibit==1)) m_pitch_zero = 1;
577         if ((m_IP == 0)&&(m_pitch_zero==1)) m_pitch_zero = 0;
578         if (m_IP == 7) // RESETL4
561         m_subcycle++;
562         if ((m_subcycle == 2) && (m_PC == 12)) // RESETF3
579563         {
580            // Latch OLDE and OLDP
581            OLD_FRAME_SILENCE_FLAG = NEW_FRAME_SILENCE_FLAG; // m_OLDE
582            OLD_FRAME_UNVOICED_FLAG = NEW_FRAME_UNVOICED_FLAG; // m_OLDP
583            /* if TALK was clear last frame, halt speech now, since TALKD (latched from TALK on new frame) just went inactive. */
564            /* Circuit 412 in the patent acts a reset, resetting the pitch counter to 0
565             * if INHIBIT was true during the most recent frame transition.
566             * The exact time this occurs is betwen IP=7, PC=12 sub=0, T=t12
567             * and m_IP = 0, PC=0 sub=0, T=t12, a period of exactly 20 cycles,
568             * which overlaps the time OLDE and OLDP are updated at IP=7 PC=12 T17
569             * (and hence INHIBIT itself 2 t-cycles later). We do it here because it is
570             * convenient and should make no difference in output.
571             */
572            if ((m_IP == 7)&&(m_inhibit==1)) m_pitch_zero = 1;
573            if ((m_IP == 0)&&(m_pitch_zero==1)) m_pitch_zero = 0;
574            if (m_IP == 7) // RESETL4
575            {
576               // Latch OLDE and OLDP
577               OLD_FRAME_SILENCE_FLAG = NEW_FRAME_SILENCE_FLAG; // m_OLDE
578               OLD_FRAME_UNVOICED_FLAG = NEW_FRAME_UNVOICED_FLAG; // m_OLDP
579               /* if TALK was clear last frame, halt speech now, since TALKD (latched from TALK on new frame) just went inactive. */
584580#ifdef DEBUG_GENERATION
585            if (m_TALK == 0)
586               fprintf(stderr,"tms5110_process: processing frame: TALKD = 0 caused by stop frame or buffer empty, halting speech.\n");
581               if (m_TALK == 0)
582                  fprintf(stderr,"tms5110_process: processing frame: TALKD = 0 caused by stop frame or buffer empty, halting speech.\n");
587583#endif
588            m_TALKD = m_TALK; // TALKD is latched from TALK
589            m_TALK = m_SPEN; // TALK is latched from SPEN
584               m_TALKD = m_TALK; // TALKD is latched from TALK
585               m_TALK = m_SPEN; // TALK is latched from SPEN
586            }
587            m_subcycle = m_subc_reload;
588            m_PC = 0;
589            m_IP++;
590            m_IP&=0x7;
590591         }
591         m_subcycle = m_subc_reload;
592         m_PC = 0;
593         m_IP++;
594         m_IP&=0x7;
592         else if (m_subcycle == 3)
593         {
594            m_subcycle = m_subc_reload;
595            m_PC++;
596         }
597         m_pitch_count++;
598         if ((m_pitch_count >= m_current_pitch)||(m_pitch_zero == 1)) m_pitch_count = 0;
599         m_pitch_count &= 0x1FF;
595600      }
596      else if (m_subcycle == 3)
601      else // m_TALKD == 0
597602      {
598         m_subcycle = m_subc_reload;
599         m_PC++;
600      }
601      m_pitch_count++;
602      if ((m_pitch_count >= m_current_pitch)||(m_pitch_zero == 1)) m_pitch_count = 0;
603      m_pitch_count &= 0x1FF;
604      buf_count++;
605      size--;
606   }
607
608empty:
609
610#ifdef VERBOSE
611   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);
612#endif
613   while (size > 0)
614   {
615      m_subcycle++;
616      if ((m_subcycle == 2) && (m_PC == 12)) // RESETF3
617      {
618         if (m_IP == 7) // RESETL4
603         m_subcycle++;
604         if ((m_subcycle == 2) && (m_PC == 12)) // RESETF3
619605         {
620            m_TALKD = m_TALK; // TALKD is latched from TALK
621            m_TALK = m_SPEN; // TALK is latched from SPEN
606            if (m_IP == 7) // RESETL4
607            {
608               m_TALKD = m_TALK; // TALKD is latched from TALK
609               m_TALK = m_SPEN; // TALK is latched from SPEN
610            }
611            m_subcycle = m_subc_reload;
612            m_PC = 0;
613            m_IP++;
614            m_IP&=0x7;
622615         }
623         m_subcycle = m_subc_reload;
624         m_PC = 0;
625         m_IP++;
626         m_IP&=0x7;
627         if (m_TALKD) goto render;
616         else if (m_subcycle == 3)
617         {
618            m_subcycle = m_subc_reload;
619            m_PC++;
620         }
621         buffer[buf_count] = -1; /* should be just -1; actual chip outputs -1 every idle sample; (cf note in data sheet, p 10, table 4) */
628622      }
629      else if (m_subcycle == 3)
630      {
631         m_subcycle = m_subc_reload;
632         m_PC++;
633      }
634      buffer[buf_count] = -1; /* should be just -1; actual chip outputs -1 every idle sample; (cf note in data sheet, p 10, table 4) */
635      buf_count++;
636      size--;
623   buf_count++;
624   size--;
637625   }
638626}
639627


Previous 199869 Revisions Next


© 1997-2024 The MAME Team