diff options
Diffstat (limited to 'src/emu/sound/votrax.c')
-rw-r--r-- | src/emu/sound/votrax.c | 382 |
1 files changed, 191 insertions, 191 deletions
diff --git a/src/emu/sound/votrax.c b/src/emu/sound/votrax.c index b25ad8ef8ae..83e06859da1 100644 --- a/src/emu/sound/votrax.c +++ b/src/emu/sound/votrax.c @@ -95,21 +95,21 @@ const char *const votrax_sc01_device::s_phoneme_table[64] = // it is only an approximation const double votrax_sc01_device::s_glottal_wave[16] = { - 0, - 16.0/22.0, - -22.0/22.0, - -17.0/22.0, - -15.0/22.0, - -10.0/22.0, - -7.0/22.0, + 0, + 16.0/22.0, + -22.0/22.0, + -17.0/22.0, + -15.0/22.0, + -10.0/22.0, + -7.0/22.0, -4.0/22.0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0 }; @@ -161,14 +161,14 @@ WRITE8_MEMBER( votrax_sc01_device::write ) // only 6 bits matter m_phoneme = data & 0x3f; const UINT8 *rom = m_rom + (m_phoneme << 3); -mame_printf_debug("%s: STROBE %s (F1=%X F2=%X FC=%X F3=%X F2Q=%X VA=%X FA=%X CL=%X CLD=%X VD=%X PAC=%X PH=%02X)\n", +mame_printf_debug("%s: STROBE %s (F1=%X F2=%X FC=%X F3=%X F2Q=%X VA=%X FA=%X CL=%X CLD=%X VD=%X PAC=%X PH=%02X)\n", machine().time().as_string(3), s_phoneme_table[m_phoneme], rom[0] >> 4, rom[1] >> 4, rom[2] >> 4, rom[3] >> 4, rom[4] >> 4, rom[5] >> 4, rom[6] >> 4, rom[3] & 0xf, rom[4] & 0xf, rom[5] & 0xf, rom[6] & 0xf, rom[7]); - + // the STROBE signal resets the phoneme counter m_counter_84 = 0xf; - + // not in the schematics, but necessary to fully reset the request latch m_latch_92 = 0; @@ -179,8 +179,8 @@ mame_printf_debug("%s: STROBE %s (F1=%X F2=%X FC=%X F3=%X F2Q=%X VA=%X FA=%X CL= //------------------------------------------------- -// inflection_w - handle a write to the -// inflection bits +// inflection_w - handle a write to the +// inflection bits //------------------------------------------------- WRITE8_MEMBER( votrax_sc01_device::inflection_w ) @@ -189,7 +189,7 @@ WRITE8_MEMBER( votrax_sc01_device::inflection_w ) data &= 3; if (m_inflection == data) return; - + // append an inflection marker m_stream->update(); m_inflection = data; @@ -202,83 +202,83 @@ WRITE8_MEMBER( votrax_sc01_device::inflection_w ) //************************************************************************** //------------------------------------------------- -// update_subphoneme_clock_period - re-compute the -// period of the sub-phoneme clock, as a multiple +// update_subphoneme_clock_period - re-compute the +// period of the sub-phoneme clock, as a multiple // of the master clock //------------------------------------------------- void votrax_sc01_device::update_subphoneme_clock_period() { assert(m_latch_80 < 128); - + /* - The sub-phoneme timing circuit is based off the switching capacitor - technique described in the Votrax patent. Replacing the capacitor - ladder with [Rx] representing the effective resistance, the circuit - becomes essentially a pair of op-amps: - - VM - | i1 - [R1] - | Vc - +----------------------+ - | +---|C1|---+ | - [R2] | | | |\ - |Vb i2 | |\ | +--++\ - +--[Rx]--+----+-\ | | > - | | >--+-----+-/ - [R3] +----++/ Vc |/ - |i3 | |/ - +--------+ Va - | - [R4] - | - 0 - - We have two op-amps, the left used as a standard amplifier, the right - one as a comparator. The circuit triggers when the two inputs of the - right op-amp are equal. - - The left part of the circuit (before C1) is simply a current injector. - It's all made of resistors, there's no modulated input, so everything - is going to be constant. If you don't know about op-amps used as - amplifiers, you just need to know that it forces its two inputs to - have the same voltage while not sending or providing any current - through there (only though its output in fact). - - In the schema, the injected current is i2. Basic equations apply: - Va = R4.i3 - Vb = Va + R3.i3 - Vb = Va + Rx.i2 - Vc = Vb + R2.i1 - VM = Vc + R1.i1 - i1 = i2 + i3 - - And the tipping happens when the voltage on the right of C1 reaches - Vc, so: - Vc = Va + i2.T/C1 - - (i2 being a constant, the integration is kinda easy) - - Some maths later: - R3.i3 = Rx.i2 -> i3 = Rx/R3.i2 - i1 = (1+Rx/R3).i2 - Va + (Rx + R2 + R2.Rx/R3).i2 = Va + T/C1.i2 - T = C1*(Rx*(1+R2/R3) + R2) - - Which isn't, interestingly though not surprisingly, dependant on Vm, - R1 or R4. And you have to round it to the next multiple of - 0.2ms+0.1ms due to the clocking on p2 and its offset to p1 (charging - only happens on p1 active), and add one p1/p2 cycle (0.2ms) for the - discharge. - - So now you have your base clock, which you have to multiply by 16 to - get the phoneme length. - - r2 = 9e3 - r3 = 1e3 - c1 = 1000e-12 - rx = 1/(5KHz * cx) + The sub-phoneme timing circuit is based off the switching capacitor + technique described in the Votrax patent. Replacing the capacitor + ladder with [Rx] representing the effective resistance, the circuit + becomes essentially a pair of op-amps: + + VM + | i1 + [R1] + | Vc + +----------------------+ + | +---|C1|---+ | + [R2] | | | |\ + |Vb i2 | |\ | +--++\ + +--[Rx]--+----+-\ | | > + | | >--+-----+-/ + [R3] +----++/ Vc |/ + |i3 | |/ + +--------+ Va + | + [R4] + | + 0 + + We have two op-amps, the left used as a standard amplifier, the right + one as a comparator. The circuit triggers when the two inputs of the + right op-amp are equal. + + The left part of the circuit (before C1) is simply a current injector. + It's all made of resistors, there's no modulated input, so everything + is going to be constant. If you don't know about op-amps used as + amplifiers, you just need to know that it forces its two inputs to + have the same voltage while not sending or providing any current + through there (only though its output in fact). + + In the schema, the injected current is i2. Basic equations apply: + Va = R4.i3 + Vb = Va + R3.i3 + Vb = Va + Rx.i2 + Vc = Vb + R2.i1 + VM = Vc + R1.i1 + i1 = i2 + i3 + + And the tipping happens when the voltage on the right of C1 reaches + Vc, so: + Vc = Va + i2.T/C1 + + (i2 being a constant, the integration is kinda easy) + + Some maths later: + R3.i3 = Rx.i2 -> i3 = Rx/R3.i2 + i1 = (1+Rx/R3).i2 + Va + (Rx + R2 + R2.Rx/R3).i2 = Va + T/C1.i2 + T = C1*(Rx*(1+R2/R3) + R2) + + Which isn't, interestingly though not surprisingly, dependant on Vm, + R1 or R4. And you have to round it to the next multiple of + 0.2ms+0.1ms due to the clocking on p2 and its offset to p1 (charging + only happens on p1 active), and add one p1/p2 cycle (0.2ms) for the + discharge. + + So now you have your base clock, which you have to multiply by 16 to + get the phoneme length. + + r2 = 9e3 + r3 = 1e3 + c1 = 1000e-12 + rx = 1/(5KHz * cx) */ // determine total capacitance @@ -290,7 +290,7 @@ void votrax_sc01_device::update_subphoneme_clock_period() if ((m_latch_80 & 0x10) != 0) cx += 86e-12; if ((m_latch_80 & 0x20) != 0) cx += 173e-12; if ((m_latch_80 & 0x40) != 0) cx += 345e-12; - + // apply the equation above to determine charging time // note that the 5kHz listed above for P1 is for a nominal master // clock frequency of 1.28MHz, meaning it is master clock / 128 @@ -298,7 +298,7 @@ void votrax_sc01_device::update_subphoneme_clock_period() double p1_frequency = double(m_master_clock_freq) / double(1 << (P_CLOCK_BIT + 2)); double rx = 1.0 / (p1_frequency * cx); double period = 1000e-12 * (rx * (1.0 + 9e3 / 1e3) + 9e3); - + // convert to master clock cycles and round up m_subphoneme_period = UINT32(ceil(period * double(m_master_clock_freq))); } @@ -489,9 +489,9 @@ void votrax_sc01_device::filter_s_to_z(const double *k, double fs, double *a, do double fpeak = sqrt(fabs(k[0]*k[1]-k[2]))/(2*M_PI*k[2]); double zc = 2*M_PI*fpeak/tan(M_PI*fpeak/fs); - double m0 = zc*k[0]; - double m1 = zc*k[1]; - double m2 = zc*zc*k[2]; + double m0 = zc*k[0]; + double m1 = zc*k[1]; + double m2 = zc*zc*k[2]; a[0] = 1+m0; a[1] = 3+m0; @@ -578,7 +578,7 @@ if (LOG_TIMING | LOG_LOWPARAM | LOG_GLOTTAL | LOG_TRANSITION) // update master clock m_master_clock ^= 1; - + // on the falling edge of the master clock, advance the 10-bit counter at 34 UINT8 old_latch_72 = m_latch_72; if (m_master_clock == 0) @@ -590,41 +590,41 @@ if (LOG_TIMING | LOG_LOWPARAM | LOG_GLOTTAL | LOG_TRANSITION) } // derive beta 1 clock: - // set if m_latch_70.0 == 1 - // reset if m_latch_70.0 == 0 -// UINT8 old_beta1 = m_beta1; + // set if m_latch_70.0 == 1 + // reset if m_latch_70.0 == 0 +// UINT8 old_beta1 = m_beta1; m_beta1 = BIT(m_latch_70, 0); // derive p2 clock: - // set if (m_counter_34.P_CLOCK_BIT & clock) == 1 - // reset if (m_counter_34.P_CLOCK_BIT == 0) + // set if (m_counter_34.P_CLOCK_BIT & clock) == 1 + // reset if (m_counter_34.P_CLOCK_BIT == 0) UINT8 old_p2 = m_p2; if (BIT(m_counter_34, P_CLOCK_BIT) & m_master_clock) m_p2 = 1; else if (!BIT(m_counter_34, P_CLOCK_BIT)) m_p2 = 0; - + // derive p1 clock: - // set if (!m_counter_34.P_CLOCK_BIT & clock) == 1 - // reset if (m_counter_34.P_CLOCK_BIT == 1) -// UINT8 old_p1 = m_p1; + // set if (!m_counter_34.P_CLOCK_BIT & clock) == 1 + // reset if (m_counter_34.P_CLOCK_BIT == 1) +// UINT8 old_p1 = m_p1; if (BIT(~m_counter_34, P_CLOCK_BIT) & m_master_clock) m_p1 = 1; else if (BIT(m_counter_34, P_CLOCK_BIT)) m_p1 = 0; - + // derive phi2 clock: - // set if (m_counter_34.PHI_CLOCK_BIT & clock) == 1 - // reset if (m_counter_34.PHI_CLOCK_BIT == 0) + // set if (m_counter_34.PHI_CLOCK_BIT & clock) == 1 + // reset if (m_counter_34.PHI_CLOCK_BIT == 0) UINT8 old_phi2 = m_phi2; if (BIT(m_counter_34, PHI_CLOCK_BIT) & m_master_clock) m_phi2 = 1; else if (!BIT(m_counter_34, PHI_CLOCK_BIT)) m_phi2 = 0; - + // derive phi1 clock: - // set if (!m_counter_34.PHI_CLOCK_BIT & clock) == 1 - // reset if (m_counter_34.PHI_CLOCK_BIT == 1) + // set if (!m_counter_34.PHI_CLOCK_BIT & clock) == 1 + // reset if (m_counter_34.PHI_CLOCK_BIT == 1) UINT8 old_phi1 = m_phi1; if (BIT(~m_counter_34, PHI_CLOCK_BIT) & m_master_clock) m_phi1 = 1; @@ -632,31 +632,31 @@ if (LOG_TIMING | LOG_LOWPARAM | LOG_GLOTTAL | LOG_TRANSITION) m_phi1 = 0; // derive alternate phi2 clock: - // set if (m_counter_34.PHI_CLOCK_BIT & clock) == 1 - // reset if (m_counter_34.PHI_CLOCK_BIT == 0) + // set if (m_counter_34.PHI_CLOCK_BIT & clock) == 1 + // reset if (m_counter_34.PHI_CLOCK_BIT == 0) UINT8 old_phi2_20 = m_phi2_20; if (BIT(m_counter_34, PHI_CLOCK_BIT + 2) & m_master_clock) m_phi2_20 = 1; else if (!BIT(m_counter_34, PHI_CLOCK_BIT + 2)) m_phi2_20 = 0; - + // derive alternate phi1 clock: - // set if (!m_counter_34.PHI_CLOCK_BIT & clock) == 1 - // reset if (m_counter_34.PHI_CLOCK_BIT == 1) -// UINT8 old_phi1_20 = m_phi1_20; + // set if (!m_counter_34.PHI_CLOCK_BIT & clock) == 1 + // reset if (m_counter_34.PHI_CLOCK_BIT == 1) +// UINT8 old_phi1_20 = m_phi1_20; if (BIT(~m_counter_34, PHI_CLOCK_BIT + 2) & m_master_clock) m_phi1_20 = 1; else if (BIT(m_counter_34, PHI_CLOCK_BIT + 2)) m_phi1_20 = 0; // determine rising edges of each clock of interest -// UINT8 beta1_rising = (old_beta1 ^ m_beta1) & m_beta1; +// UINT8 beta1_rising = (old_beta1 ^ m_beta1) & m_beta1; UINT8 p2_rising = (old_p2 ^ m_p2) & m_p2; -// UINT8 p1_rising = (old_p1 ^ m_p1) & m_p1; +// UINT8 p1_rising = (old_p1 ^ m_p1) & m_p1; UINT8 phi2_rising = (old_phi2 ^ m_phi2) & m_phi2; UINT8 phi1_rising = (old_phi1 ^ m_phi1) & m_phi1; UINT8 phi2_20_rising = (old_phi2_20 ^ m_phi2_20) & m_phi2_20; -// UINT8 phi1_20_rising = (old_phi1_20 ^ m_phi1_20) & m_phi1_20; +// UINT8 phi1_20_rising = (old_phi1_20 ^ m_phi1_20) & m_phi1_20; UINT8 a0_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 0); UINT8 a2_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 2); UINT8 _125k_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 3); @@ -673,7 +673,7 @@ if (LOG_TIMING | LOG_LOWPARAM | LOG_GLOTTAL | LOG_TRANSITION) UINT8 old_clock_88 = m_clock_88; m_clock_88 = !m_latch_42; //!(m_latch_42 | m_phi1); -- figure 7 seems to be wrong here UINT8 clock_88_rising = (old_clock_88 ^ m_clock_88) & m_clock_88; - + // the A/R line holds the counter in reset except during phoneme processing, // when it is clocked on the rising edge of the subphoneme timer clock if (m_internal_request != CLEAR_LINE) @@ -683,11 +683,11 @@ if (LOG_TIMING | LOG_LOWPARAM | LOG_GLOTTAL | LOG_TRANSITION) m_counter_84 = (m_counter_84 - 1) & 0x0f; mame_printf_debug("counter=%d\n", m_counter_84); } - + // clock the zero count latch if (p2_rising) m_latch_92 = ((m_counter_84 == 0) | (m_latch_92 << 1)) & 3; - + // once both bits are set, the request line goes high if (m_latch_92 == 3) { @@ -708,15 +708,15 @@ mame_printf_debug("counter=%d\n", m_counter_84); UINT8 romdata = m_rom[(m_phoneme << 3) | ((m_counter_34 >> 4) & 7)]; // update the ROM data; ROM format is (upper nibble/lower nibble) - // +00 = F1 parameter / 0 - // +01 = F2 parameter / 0 - // +02 = FC parameter / 0 - // +03 = F3 parameter / CL - // +04 = F2Q Parameter / CLD - // +05 = VA Parameter / VD - // +06 = FA Parameter / PAC - // +07 = Phoneme timing (full 7 bits) - + // +00 = F1 parameter / 0 + // +01 = F2 parameter / 0 + // +02 = FC parameter / 0 + // +03 = F3 parameter / CL + // +04 = F2Q Parameter / CLD + // +05 = VA Parameter / VD + // +06 = FA Parameter / PAC + // +07 = Phoneme timing (full 7 bits) + // latch a new value from ROM on phi2 UINT8 a = m_latch_72 & 7; UINT8 romdata_swapped; @@ -728,26 +728,26 @@ mame_printf_debug("counter=%d\n", m_counter_84); case 3: m_srff_132 = m_srff_114 & BIT(~romdata, 3); break; - + // update CLD case 4: romdata_swapped = (BIT(romdata, 0) << 3) | (BIT(romdata, 1) << 2) | (BIT(romdata, 2) << 1) | (BIT(romdata, 3) << 0); if (m_counter_84 != 0 && romdata_swapped == (m_counter_84 ^ 0xf)) m_srff_114 = 1; break; - + // update VD case 5: romdata_swapped = (BIT(romdata, 0) << 3) | (BIT(romdata, 1) << 2) | (BIT(romdata, 2) << 1) | (BIT(romdata, 3) << 0); if (m_counter_84 != 0 && romdata_swapped == (m_counter_84 ^ 0xf)) m_srff_112 = 1; break; - + // update FF == PAC & (VA | FA) case 6: m_srff_142 = BIT(romdata, 3); break; - + // update PH case 7: if (m_latch_80 != (romdata & 0x7f)) @@ -762,7 +762,7 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); break; } } - + //============================================== // // Glottal circuit (patent figure 6) @@ -787,7 +787,7 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); m_counter_224 = (m_counter_224 + 1) & 0xf; } } - + // clock remaining glottal counters (220, 222, 236) on rising edge of phi2 if (phi2_20_rising) { @@ -800,7 +800,7 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); else m_counter_220 = (m_counter_220 + 1) & 0xf; } - + // counter 222 is always enabled if (1) { @@ -810,12 +810,12 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); else m_counter_222 = (m_counter_222 + 1) & 0xf; } - + // counter 236 is always enabled if (1) { m_counter_236 = (m_counter_236 + 1) & 0xf; - + // rising edge of Q1 from counter 236 clocks counter 234 if ((m_counter_236 & 0x3) == 0x2) { @@ -825,36 +825,36 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); } } } - + // update FGATE state if (counter_220_tc) m_fgate = 0; if (counter_224_tc) m_fgate = 1; - + // apply asynchronous clear to counters 234/236 if (counter_220_tc && m_phi1_20) m_counter_236 = m_counter_234 = 0; - + // derive glottal circuit output signals #if !TEMP_HACKS UINT8 old_glottal_sync = m_glottal_sync; #endif m_glottal_sync = (m_counter_234 == 0); glottal_out = s_glottal_wave[m_counter_234]; - + //============================================== // // Transition circuit (patent figure 3a/3b) // //============================================== - + // divide 1.25k clock by 2 (lower-left of 46) UINT8 old_0625_clock = m_0625_clock; if (_125k_rising) m_0625_clock = !m_0625_clock; UINT8 _0625_rising = (old_0625_clock ^ m_0625_clock) & m_0625_clock; - + // update counter above if (_0625_rising) { @@ -863,7 +863,7 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); else m_counter_46 = (m_counter_46 + 1) & 0xf; } - + // and then the latch to the right if (a2_rising) m_latch_46 = (BIT(m_counter_46, 1) << 0) | @@ -885,21 +885,21 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); if (!(m_srff_142 & !((m_fa == 0) & (m_va == 0))) && (m_latch_46 & 0x3) == 0x3) ram_write = 1; break; - + case 5: if ((m_latch_46 & 0xc) == 0xc && m_srff_112) ram_write = 1; break; - + case 6: if ((m_latch_46 & 0xc) == 0xc && m_srff_114) ram_write = 1; break; } - + // gate on the phi2 clock (OR gate @ 172) ram_write &= m_phi2; - + // write the transitioned values to RAM if requested // (note we consolidate the serial addition and clocking steps here) if (ram_write) @@ -907,7 +907,7 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); UINT8 old = (m_latch_168 << 4) | m_latch_170; m_ram[a] = old - (old >> 3) + ((romdata & 0xf0) >> 3); } - + // latch some parameter values on rising edge of phi2 if (phi2_rising) { @@ -916,17 +916,17 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); case 2: m_fc = m_latch_168; break; - + case 5: m_va = m_latch_168; break; - + case 6: m_fa = m_latch_168; break; } } - + // latch remaining parameter values on rising edge of (phi2 & glottal sync) #if TEMP_HACKS if (phi2_rising) @@ -940,20 +940,20 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); case 0: m_f1 = m_latch_168; break; - + case 1: m_f2 = (m_latch_168 << 1) | (m_latch_170 >> 3); break; - + case 3: m_f3 = m_latch_168; break; - + case 4: m_f2q = m_latch_168; break; } - + // latch value from RAM on rising edge of phi1 if (phi1_rising) { @@ -966,13 +966,13 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); // Noise generator circuit (patent figure 8) // //============================================== - + // nose is clocked by the NOR of /FA and P1 UINT8 old_noise_clock = m_noise_clock; m_noise_clock = !((m_fa == 0) | m_p1); UINT8 noise_clock_rising = (old_noise_clock ^ m_noise_clock) & m_noise_clock; UINT8 noise_clock_falling = (old_noise_clock ^ m_noise_clock) & old_noise_clock; - + // falling edge clocks the shift register if (noise_clock_falling) { @@ -981,20 +981,20 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); // XOR'ed input goes into d4, which shifts in to d2, then d3, then d1 // thus the full 18-bit value is effectively // - // d4 = (m_shift_252 >> 0) & 0x1f; - // d2 = (m_shift_252 >> 5) & 0x1f; - // d3 = (m_shift_252 >> 10) & 0xf; - // d1 = (m_shift_252 >> 14) & 0xf; + // d4 = (m_shift_252 >> 0) & 0x1f; + // d2 = (m_shift_252 >> 5) & 0x1f; + // d3 = (m_shift_252 >> 10) & 0xf; + // d1 = (m_shift_252 >> 14) & 0xf; // // input at the low end is ((d1+4 ^ d2+5) ^ (d4+4 ^ d4+5)) ^ !(counter2 | counter3) // output is tapped at d3+4 UINT32 old_shift = m_shift_252; m_shift_252 <<= 1; - m_shift_252 |= ((BIT(old_shift, 17) ^ BIT(old_shift, 9)) ^ (BIT(old_shift, 3) ^ BIT(old_shift, 4))) ^ + m_shift_252 |= ((BIT(old_shift, 17) ^ BIT(old_shift, 9)) ^ (BIT(old_shift, 3) ^ BIT(old_shift, 4))) ^ ((m_counter_250 & 0xc) == 0); } - + // rising edge clocks the counter if (noise_clock_rising) { @@ -1004,7 +1004,7 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); else m_counter_250 = (m_counter_250 + 1) & 0xf; } - + // compute final noise out signal noise_out_digital = !(BIT(m_shift_252, 13) & (m_fgate | (m_va == 0))); } @@ -1132,9 +1132,9 @@ mame_printf_debug("[PH=%02X]\n", m_latch_80); double s4_out = apply_filter(m_s4i_hist, m_s4_hist, a, b); shift_hist(s4_out, m_s4_hist, 4); - + // TODO: apply closure circuit (undocumented) - + // output the current result *dest++ = INT16(s4_out * 4000); } @@ -1168,24 +1168,24 @@ void votrax_sc01_device::device_start() m_stream = stream_alloc(0, 1, m_master_clock_freq / 16); m_phoneme_timer = timer_alloc(); m_rom = subregion("phoneme")->base(); - + // reset inputs m_inflection = 0; m_phoneme = 0x3f; - + // reset outputs m_request_func.resolve(m_request_cb, *this); m_request_state = ASSERT_LINE; m_internal_request = ASSERT_LINE; - + // save inputs save_item(NAME(m_inflection)); save_item(NAME(m_phoneme)); - + // save outputs save_item(NAME(m_request_state)); save_item(NAME(m_internal_request)); - + // save timing circuit save_item(NAME(m_master_clock_freq)); save_item(NAME(m_master_clock)); @@ -1203,14 +1203,14 @@ void votrax_sc01_device::device_start() save_item(NAME(m_latch_42)); save_item(NAME(m_counter_84)); save_item(NAME(m_latch_92)); - + // save low parameter clocking save_item(NAME(m_srff_132)); save_item(NAME(m_srff_114)); save_item(NAME(m_srff_112)); save_item(NAME(m_srff_142)); save_item(NAME(m_latch_80)); - + // save glottal circuit save_item(NAME(m_counter_220)); save_item(NAME(m_counter_222)); @@ -1234,7 +1234,7 @@ void votrax_sc01_device::device_start() save_item(NAME(m_f2q)); save_item(NAME(m_va)); save_item(NAME(m_fa)); - + // save noise generator circuit save_item(NAME(m_noise_clock)); save_item(NAME(m_shift_252)); @@ -1263,11 +1263,11 @@ void votrax_sc01_device::device_reset() { // set the initial state m_stream->update(); - + // reset inputs m_phoneme = 0x3f; m_request_func(m_internal_request = m_request_state = ASSERT_LINE); - + // reset timing circuit m_master_clock = 0; m_counter_34 = 0; @@ -1284,7 +1284,7 @@ void votrax_sc01_device::device_reset() m_latch_42 = 0; m_counter_84 = 0; m_latch_92 = 0; - + // reset low parameter clocking m_srff_132 = 0; m_srff_114 = 0; @@ -1292,7 +1292,7 @@ void votrax_sc01_device::device_reset() m_srff_142 = 0; m_latch_80 = 50; update_subphoneme_clock_period(); - + // reset glottal circuit m_counter_220 = 0; m_counter_222 = 0; @@ -1301,7 +1301,7 @@ void votrax_sc01_device::device_reset() m_counter_236 = 0; m_fgate = 0; m_glottal_sync = 0; - + // reset transition circuit m_0625_clock = 0; m_counter_46 = 0; @@ -1316,7 +1316,7 @@ void votrax_sc01_device::device_reset() m_f2q = 0; m_va = 0; m_fa = 0; - + // reset noise circuit m_noise_clock = 0; m_shift_252 = 0; @@ -1339,7 +1339,7 @@ void votrax_sc01_device::device_reset() //------------------------------------------------- // device_clock_changed - handle dynamic clock -// changes by altering our output frequency +// changes by altering our output frequency //------------------------------------------------- void votrax_sc01_device::device_clock_changed() @@ -1354,10 +1354,10 @@ void votrax_sc01_device::device_clock_changed() m_stream->update(); m_stream->set_sample_rate(newfreq / 16); } - + // determine how many clock ticks remained on the phoneme timer UINT64 remaining = m_phoneme_timer->remaining().as_ticks(m_master_clock_freq); - + // recompute the master clock m_master_clock_freq = newfreq; @@ -1376,11 +1376,11 @@ void votrax_sc01_device::device_timer(emu_timer &timer, device_timer_id id, int { // force a stream update m_stream->update(); - + // if we're requesting more data, no need for timing if (m_request_state == ASSERT_LINE) return; - + // if we're supposed to have fired, do it now if (m_internal_request == ASSERT_LINE) { @@ -1397,7 +1397,7 @@ mame_printf_debug("%s: REQUEST\n", timer.machine().time().as_string(3)); clocks_until_request += m_subphoneme_period - m_subphoneme_count; clocks_until_request += m_subphoneme_period * (m_counter_84 - 1); } - + // plus 1/2 clocks_until_request = MAX(clocks_until_request, (1 << P_CLOCK_BIT) / 2); timer.adjust(attotime::from_ticks(clocks_until_request, m_master_clock_freq)); |