~ubuntu-branches/debian/sid/mame/sid

« back to all changes in this revision

Viewing changes to src/emu/sound/votrax.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Emmanuel Kasper, Jordi Mallach
  • Date: 2012-06-05 20:02:23 UTC
  • mfrom: (0.3.1) (0.1.4)
  • Revision ID: package-import@ubuntu.com-20120605200223-gnlpogjrg6oqe9md
Tags: 0.146-1
[ Emmanuel Kasper ]
* New upstream release
* Drop patch to fix man pages section and patches to link with flac 
  and jpeg system lib: all this has been pushed upstream by Cesare Falco
* Add DM-Upload-Allowed: yes field.

[ Jordi Mallach ]
* Create a "gnu" TARGETOS stanza that defines NO_AFFINITY_NP.
* Stop setting TARGETOS to "unix" in d/rules. It should be autodetected,
  and set to the appropriate value.
* mame_manpage_section.patch: Change mame's manpage section to 6 (games),
  in the TH declaration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**************************************************************************
2
 
 
3
 
    Votrax SC-01 Emulator
4
 
 
5
 
    Mike@Dissfulfils.co.uk
6
 
 
7
 
**************************************************************************
8
 
 
9
 
DEVICE_START(votrax)- Start emulation, load samples from Votrax subdirectory
10
 
votrax_w         - Write data to votrax port
11
 
votrax_status_r  - Return busy status (-1 = busy)
12
 
 
13
 
If you need to alter the base frequency (i.e. Qbert) then just alter
14
 
the variable VotraxBaseFrequency, this is defaulted to 8000
15
 
 
16
 
**************************************************************************/
 
1
/***************************************************************************
 
2
 
 
3
    votrax.c
 
4
 
 
5
    Simple VOTRAX SC-01 simulator based on sample fragments.
 
6
 
 
7
****************************************************************************
 
8
 
 
9
    Copyright Aaron Giles
 
10
    All rights reserved.
 
11
 
 
12
    Redistribution and use in source and binary forms, with or without
 
13
    modification, are permitted provided that the following conditions are
 
14
    met:
 
15
 
 
16
        * Redistributions of source code must retain the above copyright
 
17
          notice, this list of conditions and the following disclaimer.
 
18
        * Redistributions in binary form must reproduce the above copyright
 
19
          notice, this list of conditions and the following disclaimer in
 
20
          the documentation and/or other materials provided with the
 
21
          distribution.
 
22
        * Neither the name 'MAME' nor the names of its contributors may be
 
23
          used to endorse or promote products derived from this software
 
24
          without specific prior written permission.
 
25
 
 
26
    THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
 
27
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
28
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
29
    DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
 
30
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
31
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
32
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
33
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
34
    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 
35
    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
36
    POSSIBILITY OF SUCH DAMAGE.
 
37
 
 
38
***************************************************************************/
17
39
 
18
40
#include "emu.h"
19
 
#include "samples.h"
20
41
#include "votrax.h"
21
42
 
22
43
 
23
 
typedef struct _votrax_state votrax_state;
24
 
struct _votrax_state
25
 
{
26
 
        device_t *device;
27
 
        int             stream;
28
 
        int             frequency;              /* Some games (Qbert) change this */
29
 
        int     volume;
30
 
        sound_stream *  channel;
31
 
 
32
 
        loaded_sample *sample;
33
 
        UINT32          pos;
34
 
        UINT32          frac;
35
 
        UINT32          step;
36
 
 
37
 
        loaded_samples *samples;
38
 
};
39
 
 
40
 
INLINE votrax_state *get_safe_token(device_t *device)
41
 
{
42
 
        assert(device != NULL);
43
 
        assert(device->type() == VOTRAX);
44
 
        return (votrax_state *)downcast<legacy_device_base *>(device)->token();
45
 
}
46
 
 
47
 
#define FRAC_BITS               24
48
 
#define FRAC_ONE                (1 << FRAC_BITS)
49
 
#define FRAC_MASK               (FRAC_ONE - 1)
50
 
 
51
 
 
52
 
/****************************************************************************
53
 
 * 64 Phonemes - currently 1 sample per phoneme, will be combined sometime!
54
 
 ****************************************************************************/
55
 
 
56
 
static const char *const VotraxTable[65] =
57
 
{
58
 
 "EH3","EH2","EH1","PA0","DT" ,"A1" ,"A2" ,"ZH",
59
 
 "AH2","I3" ,"I2" ,"I1" ,"M"  ,"N"  ,"B"  ,"V",
60
 
 "CH" ,"SH" ,"Z"  ,"AW1","NG" ,"AH1","OO1","OO",
61
 
 "L"  ,"K"  ,"J"  ,"H"  ,"G"  ,"F"  ,"D"  ,"S",
62
 
 "A"  ,"AY" ,"Y1" ,"UH3","AH" ,"P"  ,"O"  ,"I",
63
 
 "U"  ,"Y"  ,"T"  ,"R"  ,"E"  ,"W"  ,"AE" ,"AE1",
64
 
 "AW2","UH2","UH1","UH" ,"O2" ,"O1" ,"IU" ,"U1",
65
 
 "THV","TH" ,"ER" ,"EH" ,"E1" ,"AW" ,"PA1","STOP",
66
 
 0
67
 
};
68
 
 
69
 
static STREAM_UPDATE( votrax_update_sound )
70
 
{
71
 
        votrax_state *info = (votrax_state*) param;
72
 
        stream_sample_t *buffer = outputs[0];
73
 
 
74
 
        if (info->sample)
75
 
        {
76
 
                /* load some info locally */
77
 
                UINT32 pos = info->pos;
78
 
                UINT32 frac = info->frac;
79
 
                UINT32 step = info->step;
80
 
                UINT32 length = info->sample->length;
81
 
                INT16 *sample = info->sample->data;
82
 
 
83
 
                while (length--)
84
 
                {
85
 
                        /* do a linear interp on the sample */
86
 
                        INT32 sample1 = sample[pos];
87
 
                        INT32 sample2 = sample[(pos + 1) % length];
88
 
                        INT32 fracmult = frac >> (FRAC_BITS - 14);
89
 
                        *buffer++ = ((0x4000 - fracmult) * sample1 + fracmult * sample2) >> 14;
90
 
 
91
 
                        /* advance */
92
 
                        frac += step;
93
 
                        pos += frac >> FRAC_BITS;
94
 
                        frac = frac & ((1 << FRAC_BITS) - 1);
95
 
 
96
 
                        /* handle looping/ending */
97
 
                        if (pos >= length)
98
 
                        {
99
 
                                info->sample = NULL;
100
 
                                break;
101
 
                        }
102
 
                }
103
 
 
104
 
                /* push position back out */
105
 
                info->pos = pos;
106
 
                info->frac = frac;
107
 
        }
108
 
}
109
 
 
110
 
 
111
 
static DEVICE_START( votrax )
112
 
{
113
 
        votrax_state *votrax = get_safe_token(device);
114
 
 
115
 
        votrax->device = device;
116
 
        votrax->samples = readsamples(device->machine(),VotraxTable,"votrax");
117
 
        votrax->frequency = 8000;
118
 
        votrax->volume = 230;
119
 
 
120
 
        votrax->channel = device->machine().sound().stream_alloc(*device, 0, 1, device->machine().sample_rate(), votrax, votrax_update_sound);
121
 
 
122
 
        votrax->sample = NULL;
123
 
        votrax->step = 0;
124
 
}
125
 
 
126
 
 
127
 
WRITE8_DEVICE_HANDLER( votrax_w )
128
 
{
129
 
        votrax_state *info = get_safe_token(device);
130
 
        int Phoneme,Intonation;
131
 
 
132
 
        info->channel->update();
133
 
 
134
 
    Phoneme = data & 0x3F;
135
 
    Intonation = data >> 6;
136
 
 
137
 
        logerror("Speech : %s at intonation %d\n",VotraxTable[Phoneme],Intonation);
138
 
 
139
 
    if(Phoneme==63)
140
 
        info->sample = NULL;
141
 
 
142
 
    if(info->samples->sample[Phoneme].data)
143
 
        {
144
 
                info->sample = &info->samples->sample[Phoneme];
145
 
                info->pos = 0;
146
 
                info->frac = 0;
147
 
                info->step = ((INT64)(info->sample->frequency + (256*Intonation)) << FRAC_BITS) / info->device->machine().sample_rate();
148
 
                info->channel->set_output_gain(0, (info->volume + (8*Intonation)*100/255) / 100.0);
149
 
        }
150
 
}
151
 
 
152
 
int votrax_status_r(device_t *device)
153
 
{
154
 
        votrax_state *info = get_safe_token(device);
155
 
        info->channel->update();
156
 
    return (info->sample != NULL);
157
 
}
158
 
 
159
 
 
160
 
 
161
 
/**************************************************************************
162
 
 * Generic get_info
163
 
 **************************************************************************/
164
 
 
165
 
DEVICE_GET_INFO( votrax )
166
 
{
167
 
        switch (state)
168
 
        {
169
 
                /* --- the following bits of info are returned as 64-bit signed integers --- */
170
 
                case DEVINFO_INT_TOKEN_BYTES:                                   info->i = sizeof(votrax_state);                         break;
171
 
 
172
 
                /* --- the following bits of info are returned as pointers to data or functions --- */
173
 
                case DEVINFO_FCT_START:                                                 info->start = DEVICE_START_NAME( votrax );                      break;
174
 
                case DEVINFO_FCT_STOP:                                                  /* Nothing */                                                                   break;
175
 
                case DEVINFO_FCT_RESET:                                                 /* Nothing */                                                                   break;
176
 
 
177
 
                /* --- the following bits of info are returned as NULL-terminated strings --- */
178
 
                case DEVINFO_STR_NAME:                                                  strcpy(info->s, "Votrax SC-01");                                break;
179
 
                case DEVINFO_STR_FAMILY:                                        strcpy(info->s, "Votrax speech");                               break;
180
 
                case DEVINFO_STR_VERSION:                                       strcpy(info->s, "1.0");                                                 break;
181
 
                case DEVINFO_STR_SOURCE_FILE:                                           strcpy(info->s, __FILE__);                                              break;
182
 
                case DEVINFO_STR_CREDITS:                                       strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
183
 
        }
184
 
}
185
 
 
186
 
 
187
 
DEFINE_LEGACY_SOUND_DEVICE(VOTRAX, votrax);
 
44
//**************************************************************************
 
45
//  DEBUGGING
 
46
//**************************************************************************
 
47
 
 
48
#define TEMP_HACKS              (1)
 
49
 
 
50
#define LOG_TIMING              (0)
 
51
#define LOG_LOWPARAM    (0)
 
52
#define LOG_GLOTTAL             (0)
 
53
#define LOG_TRANSITION  (0)
 
54
 
 
55
 
 
56
 
 
57
//**************************************************************************
 
58
//  CONSTANTS
 
59
//**************************************************************************
 
60
 
 
61
// note that according to the patent timing circuit, p1/p2 and phi1/phi2
 
62
// run 4x faster than all references in the patent text
 
63
const UINT32 P_CLOCK_BIT = 5;           // 5 according to timing diagram
 
64
const UINT32 PHI_CLOCK_BIT = 3;         // 3 according to timing diagram
 
65
 
 
66
 
 
67
 
 
68
//**************************************************************************
 
69
//  GLOBAL VARIABLES
 
70
//**************************************************************************
 
71
 
 
72
// device type definition
 
73
const device_type VOTRAX_SC01 = &device_creator<votrax_sc01_device>;
 
74
 
 
75
// ROM definition for the Votrax phoneme ROM
 
76
ROM_START( votrax_sc01 )
 
77
        ROM_REGION( 0x200, "phoneme", 0 )
 
78
        ROM_LOAD( "sc01.bin", 0x0000, 0x200, CRC(0353dd6c) SHA1(00e8e497b96a10bd9f4d7e559433c3c209b0d3a8) )
 
79
ROM_END
 
80
 
 
81
// textual phoneme names for debugging
 
82
const char *const votrax_sc01_device::s_phoneme_table[64] =
 
83
{
 
84
        "EH3",  "EH2",  "EH1",  "PA0",  "DT",   "A1",   "A2",   "ZH",
 
85
        "AH2",  "I3",   "I2",   "I1",   "M",    "N",    "B",    "V",
 
86
        "CH",   "SH",   "Z",    "AW1",  "NG",   "AH1",  "OO1",  "OO",
 
87
        "L",    "K",    "J",    "H",    "G",    "F",    "D",    "S",
 
88
        "A",    "AY",   "Y1",   "UH3",  "AH",   "P",    "O",    "I",
 
89
        "U",    "Y",    "T",    "R",    "E",    "W",    "AE",   "AE1",
 
90
        "AW2",  "UH2",  "UH1",  "UH",   "O2",   "O1",   "IU",   "U1",
 
91
        "THV",  "TH",   "ER",   "EH",   "E1",   "AW",   "PA1",  "STOP"
 
92
};
 
93
 
 
94
// this waveform is derived from measuring fig. 10 in the patent
 
95
// it is only an approximation
 
96
const double votrax_sc01_device::s_glottal_wave[16] =
 
97
{
 
98
        0,
 
99
        16.0/22.0,
 
100
        -22.0/22.0,
 
101
        -17.0/22.0,
 
102
        -15.0/22.0,
 
103
        -10.0/22.0,
 
104
        -7.0/22.0,
 
105
        -4.0/22.0,
 
106
        0,
 
107
        0,
 
108
        0,
 
109
        0,
 
110
        0,
 
111
        0,
 
112
        0,
 
113
        0
 
114
};
 
115
 
 
116
 
 
117
 
 
118
//**************************************************************************
 
119
//  LIVE DEVICE
 
120
//**************************************************************************
 
121
 
 
122
//-------------------------------------------------
 
123
//  votrax_sc01_device - constructor
 
124
//-------------------------------------------------
 
125
 
 
126
votrax_sc01_device::votrax_sc01_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
 
127
        : device_t(mconfig, VOTRAX_SC01, "Votrax SC-01", "votrax", tag, owner, clock),
 
128
          device_sound_interface(mconfig, *this),
 
129
          m_stream(NULL),
 
130
          m_phoneme_timer(NULL)
 
131
{
 
132
}
 
133
 
 
134
 
 
135
//-------------------------------------------------
 
136
//  static_set_interface - configuration helper
 
137
//  to set the interface
 
138
//-------------------------------------------------
 
139
 
 
140
void votrax_sc01_device::static_set_interface(device_t &device, const votrax_sc01_interface &interface)
 
141
{
 
142
        votrax_sc01_device &votrax = downcast<votrax_sc01_device &>(device);
 
143
        static_cast<votrax_sc01_interface &>(votrax) = interface;
 
144
}
 
145
 
 
146
 
 
147
 
 
148
//**************************************************************************
 
149
//  READ/WRITE HANDLERS
 
150
//**************************************************************************
 
151
 
 
152
//-------------------------------------------------
 
153
//  write - handle a write to the control register
 
154
//-------------------------------------------------
 
155
 
 
156
WRITE8_MEMBER( votrax_sc01_device::write )
 
157
{
 
158
        // flush out anything currently processing
 
159
        m_stream->update();
 
160
 
 
161
        // only 6 bits matter
 
162
        m_phoneme = data & 0x3f;
 
163
const UINT8 *rom = m_rom + (m_phoneme << 3);
 
164
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",
 
165
                machine().time().as_string(3), s_phoneme_table[m_phoneme],
 
166
                rom[0] >> 4, rom[1] >> 4, rom[2] >> 4, rom[3] >> 4, rom[4] >> 4, rom[5] >> 4, rom[6] >> 4,
 
167
                rom[3] & 0xf, rom[4] & 0xf, rom[5] & 0xf, rom[6] & 0xf, rom[7]);
 
168
 
 
169
        // the STROBE signal resets the phoneme counter
 
170
        m_counter_84 = 0xf;
 
171
 
 
172
        // not in the schematics, but necessary to fully reset the request latch
 
173
        m_latch_92 = 0;
 
174
 
 
175
        // clear the request signal
 
176
        m_request_func(m_request_state = m_internal_request = CLEAR_LINE);
 
177
        m_phoneme_timer->adjust(attotime::zero);
 
178
}
 
179
 
 
180
 
 
181
//-------------------------------------------------
 
182
//  inflection_w - handle a write to the
 
183
//  inflection bits
 
184
//-------------------------------------------------
 
185
 
 
186
WRITE8_MEMBER( votrax_sc01_device::inflection_w )
 
187
{
 
188
        // only 2 bits matter
 
189
        data &= 3;
 
190
        if (m_inflection == data)
 
191
                return;
 
192
 
 
193
        // append an inflection marker
 
194
        m_stream->update();
 
195
        m_inflection = data;
 
196
}
 
197
 
 
198
 
 
199
 
 
200
//**************************************************************************
 
201
//  CORE LOGIC
 
202
//**************************************************************************
 
203
 
 
204
//-------------------------------------------------
 
205
//  update_subphoneme_clock_period - re-compute the
 
206
//  period of the sub-phoneme clock, as a multiple
 
207
//  of the master clock
 
208
//-------------------------------------------------
 
209
 
 
210
void votrax_sc01_device::update_subphoneme_clock_period()
 
211
{
 
212
        assert(m_latch_80 < 128);
 
213
 
 
214
/*
 
215
    The sub-phoneme timing circuit is based off the switching capacitor
 
216
    technique described in the Votrax patent. Replacing the capacitor
 
217
    ladder with [Rx] representing the effective resistance, the circuit
 
218
    becomes essentially a pair of op-amps:
 
219
 
 
220
         VM
 
221
         | i1
 
222
        [R1]
 
223
         |                       Vc
 
224
         +----------------------+
 
225
         |        +---|C1|---+  |
 
226
        [R2]      |          |  |  |\
 
227
         |Vb i2   |    |\    |  +--++\
 
228
         +--[Rx]--+----+-\   |     |  >
 
229
         |             |  >--+-----+-/
 
230
        [R3]      +----++/   Vc    |/
 
231
         |i3      |    |/
 
232
         +--------+ Va
 
233
         |
 
234
        [R4]
 
235
         |
 
236
         0
 
237
 
 
238
    We have two op-amps, the left used as a standard amplifier, the right
 
239
    one as a comparator.  The circuit triggers when the two inputs of the
 
240
    right op-amp are equal.
 
241
 
 
242
    The left part of the circuit (before C1) is simply a current injector.
 
243
    It's all made of resistors, there's no modulated input, so everything
 
244
    is going to be constant.  If you don't know about op-amps used as
 
245
    amplifiers, you just need to know that it forces its two inputs to
 
246
    have the same voltage while not sending or providing any current
 
247
    through there (only though its output in fact).
 
248
 
 
249
    In the schema, the injected current is i2.  Basic equations apply:
 
250
      Va = R4.i3
 
251
      Vb = Va + R3.i3
 
252
      Vb = Va + Rx.i2
 
253
      Vc = Vb + R2.i1
 
254
      VM = Vc + R1.i1
 
255
      i1 = i2 + i3
 
256
 
 
257
    And the tipping happens when the voltage on the right of C1 reaches
 
258
    Vc, so:
 
259
      Vc = Va + i2.T/C1
 
260
 
 
261
    (i2 being a constant, the integration is kinda easy)
 
262
 
 
263
    Some maths later:
 
264
      R3.i3 = Rx.i2 -> i3 = Rx/R3.i2
 
265
      i1 = (1+Rx/R3).i2
 
266
      Va + (Rx + R2 + R2.Rx/R3).i2 = Va + T/C1.i2
 
267
      T = C1*(Rx*(1+R2/R3) + R2)
 
268
 
 
269
    Which isn't, interestingly though not surprisingly, dependant on Vm,
 
270
    R1 or R4.  And you have to round it to the next multiple of
 
271
    0.2ms+0.1ms due to the clocking on p2 and its offset to p1 (charging
 
272
    only happens on p1 active), and add one p1/p2 cycle (0.2ms) for the
 
273
    discharge.
 
274
 
 
275
    So now you have your base clock, which you have to multiply by 16 to
 
276
    get the phoneme length.
 
277
 
 
278
    r2 = 9e3
 
279
    r3 = 1e3
 
280
    c1 = 1000e-12
 
281
    rx = 1/(5KHz * cx)
 
282
*/
 
283
 
 
284
        // determine total capacitance
 
285
        double cx = 0;
 
286
        if ((m_latch_80 & 0x01) != 0) cx += 5e-12;
 
287
        if ((m_latch_80 & 0x02) != 0) cx += 11e-12;
 
288
        if ((m_latch_80 & 0x04) != 0) cx += 21e-12;
 
289
        if ((m_latch_80 & 0x08) != 0) cx += 43e-12;
 
290
        if ((m_latch_80 & 0x10) != 0) cx += 86e-12;
 
291
        if ((m_latch_80 & 0x20) != 0) cx += 173e-12;
 
292
        if ((m_latch_80 & 0x40) != 0) cx += 345e-12;
 
293
 
 
294
        // apply the equation above to determine charging time
 
295
        // note that the 5kHz listed above for P1 is for a nominal master
 
296
        // clock frequency of 1.28MHz, meaning it is master clock / 128
 
297
        // which should be the P1 clock but appears to be a bit different
 
298
        double p1_frequency = double(m_master_clock_freq) / double(1 << (P_CLOCK_BIT + 2));
 
299
        double rx = 1.0 / (p1_frequency * cx);
 
300
        double period = 1000e-12 * (rx * (1.0 + 9e3 / 1e3) + 9e3);
 
301
 
 
302
        // convert to master clock cycles and round up
 
303
        m_subphoneme_period = UINT32(ceil(period * double(m_master_clock_freq)));
 
304
}
 
305
 
 
306
//-------------------------------------------------
 
307
//  bits_to_caps - compute the final capacity from
 
308
//  a grid of bit-selected caps
 
309
//-------------------------------------------------
 
310
 
 
311
double votrax_sc01_device::bits_to_caps(UINT32 value, int caps_count, const double *caps_values)
 
312
{
 
313
        double sum = 0;
 
314
        for(int i=0; i<caps_count; i++)
 
315
                if(value & (1<<i))
 
316
                        sum += caps_values[i];
 
317
        return sum;
 
318
}
 
319
 
 
320
/*
 
321
  Playing with analog filters, or where all the magic filter formulas are coming from.
 
322
 
 
323
  First you start with an analog circuit, for instance this one:
 
324
 
 
325
  |                     +--[R2]--+
 
326
  |                     |        |
 
327
  |                     +--|C2|--+<V1     +--|C3|--+
 
328
  |                     |        |        |        |
 
329
  |  Vi   +--[R1]--+    |  |\    |        |  |\    |
 
330
  |  -----+        +----+--+-\   |        +--+-\   |
 
331
  |       +--|C1|--+       |  >--+--[Rx]--+  |  >--+----- Vo
 
332
  |                |     0-++/             0-++/   |
 
333
  |                |       |/    +--[R0]--+  |/    |
 
334
  |                |             |        |        |
 
335
  |                |             |    /|  |        |
 
336
  |                |             |   /-+--+--[R0]--+
 
337
  |                +--[R4]-------+--<  |
 
338
  |                            V2^   \++-0
 
339
  |                                   \|
 
340
 
 
341
  You need to determine the transfer function H(s) of the circuit, which is
 
342
  defined as the ratio Vo/Vi.  To do that, you use some properties:
 
343
 
 
344
  - The intensity through an element is equal to the voltage
 
345
    difference through the element divided by the impedence
 
346
 
 
347
  - The impedence of a resistance is equal to its resistance
 
348
 
 
349
  - The impedence of a capacitor is 1/(s*C) where C is its capacitance
 
350
 
 
351
  - The impedence of elements in series is the sum of the impedences
 
352
 
 
353
  - The impedence of elements in parallel is the inverse of the sum of
 
354
    the inverses
 
355
 
 
356
  - The sum of all intensities flowing into a node is 0 (there's no
 
357
    charge accumulation in a wire)
 
358
 
 
359
  - An operational amplifier in looped mode is an interesting beast:
 
360
    the intensity at its two inputs is always 0, and the voltage is
 
361
    forced identical between the inputs.  In our case, since the '+'
 
362
    inputs are all tied to ground, that means that the '-' inputs are at
 
363
    voltage 0, intensity 0.
 
364
 
 
365
  From here we can build some equations.  Noting:
 
366
  X1 = 1/(1/R1 + s*C1)
 
367
  X2 = 1/(1/R2 + s*C2)
 
368
  X3 = 1/(s*C3)
 
369
 
 
370
  Then computing the intensity flow at each '-' input we have:
 
371
  Vi/X1 + V2/R4 + V1/X2 = 0
 
372
  V2/R0 + Vo/R0 = 0
 
373
  V1/Rx + Vo/X3 = 0
 
374
 
 
375
  Wrangling the equations, one eventually gets:
 
376
  |                            1 + s * C1*R1
 
377
  | Vo/Vi = H(s) = (R4/R1) * -------------------------------------------
 
378
  |                            1 + s * C3*Rx*R4/R2 + s^2 * C2*C3*Rx*R4
 
379
 
 
380
  To check the mathematics between the 's' stuff, check "Laplace
 
381
  transform".  In short, it's a nice way of manipulating derivatives
 
382
  and integrals without having to manipulate derivatives and
 
383
  integrals.
 
384
 
 
385
  With that transfer function, we first can compute what happens to
 
386
  every frequency in the input signal.  You just compute H(2i*pi*f)
 
387
  where f is the frequency, which will give you a complex number
 
388
  representing the amplitude and phase effect.  To get the usual dB
 
389
  curves, compute 20*log10(abs(v))).
 
390
 
 
391
  Now, once you have an analog transfer function, you can build a
 
392
  digital filter from it using what is called the bilinear transform.
 
393
 
 
394
  In our case, we have an analog filter with the transfer function:
 
395
  |                 1 + k[0]*s
 
396
  |        H(s) = -------------------------
 
397
  |                 1 + k[1]*s + k[2]*s^2
 
398
 
 
399
  We can always reintroduce the global multipler later, and it's 1 in
 
400
  most of our cases anyway.
 
401
 
 
402
  The we pose:
 
403
  |                    z-1
 
404
  |        s(z) = zc * ---
 
405
  |                    z+1
 
406
 
 
407
  where zc = 2*pi*fr/tan(pi*fr/fs)
 
408
  with fs = sampling frequency
 
409
  and fr = most interesting frequency
 
410
 
 
411
  Then we rewrite H in function of negative integer powers of z.
 
412
 
 
413
  Noting m0 = zc*k[0], m1 = zc*k[1], m2=zc*zc*k[2],
 
414
 
 
415
  a little equation wrangling then gives:
 
416
 
 
417
  |                 (1+m0)    + (3+m0)   *z^-1 + (3-m0)   *z^-2 +    (1-m0)*z^-3
 
418
  |        H(z) = ----------------------------------------------------------------
 
419
  |                 (1+m1+m2) + (3+m1-m2)*z^-1 + (3-m1-m2)*z^-2 + (1-m1+m2)*z^-3
 
420
 
 
421
  That beast in the digital transfer function, of which you can
 
422
  extract response curves by posing z = exp(2*i*pi*f/fs).
 
423
 
 
424
  Note that the bilinear transform is an approximation, and H(z(f)) =
 
425
  H(s(f)) only at frequency fr.  And the shape of the filter will be
 
426
  better respected around fr.  If you look at the curves of the
 
427
  filters we're interested in, the frequency:
 
428
  fr = sqrt(abs(k[0]*k[1]-k[2]))/(2*pi*k[2])
 
429
 
 
430
  which is a (good) approximation of the filter peak position is a
 
431
  good choice.
 
432
 
 
433
  Note that terminology wise, the "standard" bilinear transform is
 
434
  with fr = fs/2, and using a different fr is called "pre-warping".
 
435
 
 
436
  So now we have a digital transfer function of the generic form:
 
437
 
 
438
  |                 a[0] + a[1]*z^-1 + a[2]*z^-2 + a[3]*z^-3
 
439
  |        H(z) = --------------------------------------------
 
440
  |                 b[0] + b[1]*z^-1 + b[2]*z^-2 + b[3]*z^-3
 
441
 
 
442
  The magic then is that the powers of z represent time in samples.
 
443
  Noting x the input stream and y the output stream, you have:
 
444
  H(z) = y(z)/x(z)
 
445
 
 
446
  or in other words:
 
447
  y*b[0]*z^0 + y*b[1]*z^-1 + y*b[2]*z^-2 + y*b[3]*z^-3 = x*a[0]*z^0 + x*a[1]*z^-1 + x*a[2]*z^-2 + x*a[3]*z^-3
 
448
 
 
449
  i.e.
 
450
 
 
451
  y*z^0 = (x*a[0]*z^0 + x*a[1]*z^-1 + x*a[2]*z^-2 + x*a[3]*z^-3 - y*b[1]*z^-1 - y*b[2]*z^-2 - y*b[3]*z^-3) / b[0]
 
452
 
 
453
  and powers of z being time in samples,
 
454
 
 
455
  y[0] = (x[0]*a[0] + x[-1]*a[1] + x[-2]*a[2] + x[-3]*a[3] - y[-1]*b[1] - y[-2]*b[2] - y[-3]*b[3]) / b[0]
 
456
 
 
457
  So you have a filter you can apply.  Note that this is why you want
 
458
  negative powers of z.  Positive powers would mean looking into the
 
459
  future (which is possible in some cases, in particular with x, and
 
460
  has some very interesting properties, but is not very useful in
 
461
  analog circuit simulation).
 
462
 
 
463
  Note that if you have multiple inputs, all this stuff is linear.
 
464
  Or, in other words, you just have to split it in multiple circuits
 
465
  with only one input connected each time and sum the results.  It
 
466
  will be correct.
 
467
 
 
468
  Also, since we're in practice in a dynamic system, for an amplifying
 
469
  filter (i.e. where things like r4/r1 is not 1), it's better to
 
470
  proceed in two steps:
 
471
 
 
472
  - amplify the input by the current value of the coefficient, and
 
473
    historize it
 
474
  - apply the now non-amplifying filter to the historized amplified
 
475
    input
 
476
 
 
477
  That way reduces the probability of the output boucing all over the
 
478
  place.
 
479
 
 
480
*/
 
481
 
 
482
 
 
483
//-------------------------------------------------------------
 
484
//  filter_s_to_z - analog to digital filter transformation
 
485
//-------------------------------------------------------------
 
486
 
 
487
void votrax_sc01_device::filter_s_to_z(const double *k, double fs, double *a, double *b)
 
488
{
 
489
        double fpeak = sqrt(fabs(k[0]*k[1]-k[2]))/(2*M_PI*k[2]);
 
490
        double zc = 2*M_PI*fpeak/tan(M_PI*fpeak/fs);
 
491
 
 
492
        double m0 = zc*k[0];
 
493
        double m1 = zc*k[1];
 
494
        double m2 = zc*zc*k[2];
 
495
 
 
496
        a[0] = 1+m0;
 
497
        a[1] = 3+m0;
 
498
        a[2] = 3-m0;
 
499
        a[3] = 1-m0;
 
500
        b[0] = 1+m1+m2;
 
501
        b[1] = 3+m1-m2;
 
502
        b[2] = 3-m1-m2;
 
503
        b[3] = 1-m1+m2;
 
504
}
 
505
 
 
506
 
 
507
//-------------------------------------------------------------
 
508
//  apply_filter - apply the digital filter (before output
 
509
//                 shifting, so y[0] is one step in the past)
 
510
//-------------------------------------------------------------
 
511
double votrax_sc01_device::apply_filter(const double *x, const double *y, const double *a, const double *b)
 
512
{
 
513
        return (x[0]*a[0] + x[1]*a[1] + x[2]*a[2] + x[3]*a[3] - y[0]*b[1] - y[1]*b[2] - y[2]*b[3]) / b[0];
 
514
}
 
515
 
 
516
 
 
517
//-------------------------------------------------------------
 
518
//  shift_hist - shift a value in an output history
 
519
//-------------------------------------------------------------
 
520
 
 
521
void votrax_sc01_device::shift_hist(double val, double *hist_array, int hist_size)
 
522
{
 
523
        for(int i = 0; i < hist_size-1; i++)
 
524
                hist_array[hist_size-1-i] = hist_array[hist_size-2-i];
 
525
        hist_array[0] = val;
 
526
}
 
527
 
 
528
 
 
529
//-------------------------------------------------
 
530
//  sound_stream_update - handle update requests
 
531
//  for our sound stream
 
532
//-------------------------------------------------
 
533
 
 
534
void votrax_sc01_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
 
535
{
 
536
        // determine how many master half-clocks per sample
 
537
        int half_clocks_per_sample = (m_master_clock_freq * 2) / stream.sample_rate();
 
538
 
 
539
        // iterate over clocks (samples)
 
540
        stream_sample_t *dest = outputs[0];
 
541
        while (samples--)
 
542
        {
 
543
                // run the digital logic at the master clock rate
 
544
                double glottal_out = 0;
 
545
                UINT8 noise_out_digital = 0;
 
546
                for (int curclock = 0; curclock < half_clocks_per_sample; curclock++)
 
547
                {
 
548
if (LOG_TIMING | LOG_LOWPARAM | LOG_GLOTTAL | LOG_TRANSITION)
 
549
{
 
550
        if (m_counter_34 % 32 == 0 && m_master_clock == 0)
 
551
        {
 
552
        if (LOG_TIMING)
 
553
                mame_printf_debug("MCLK C034 L070 L072 BET1  P1   P2  PHI1 PHI2 PH1' PH2' SUBC C088 C084 L092 IIRQ ");
 
554
        if (LOG_LOWPARAM)
 
555
                mame_printf_debug("F132 F114 F112 F142 L080 ");
 
556
        if (LOG_GLOTTAL)
 
557
                mame_printf_debug("C220 C222 C224 C234 C236 FGAT GLSY ");
 
558
        if (LOG_TRANSITION)
 
559
                mame_printf_debug("0625 C046 L046 A0-2 L168 L170  FC   VA   FA   F1   F2   F3   F2Q ");
 
560
        mame_printf_debug("\n");
 
561
        }
 
562
        if (LOG_TIMING)
 
563
                mame_printf_debug("%4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X ", m_master_clock, m_counter_34, m_latch_70, m_latch_72, m_beta1, m_p1, m_p2, m_phi1, m_phi2, m_phi1_20, m_phi2_20, m_subphoneme_count, m_clock_88, m_counter_84, m_latch_92, m_internal_request);
 
564
        if (LOG_LOWPARAM)
 
565
                mame_printf_debug("%4X %4X %4X %4X %4X ", m_srff_132, m_srff_114, m_srff_112, m_srff_142, m_latch_80);
 
566
        if (LOG_GLOTTAL)
 
567
                mame_printf_debug("%4X %4X %4X %4X %4X %4X %4X ", m_counter_220, m_counter_222, m_counter_224, m_counter_234, m_counter_236, m_fgate, m_glottal_sync);
 
568
        if (LOG_TRANSITION)
 
569
                mame_printf_debug("%4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X ", m_0625_clock, m_counter_46, m_latch_46, m_latch_72 & 7, m_latch_168, m_latch_170, m_fc, m_va, m_fa, m_f1, m_f2, m_f3, m_f2q);
 
570
        mame_printf_debug("\n");
 
571
}
 
572
 
 
573
                        //==============================================
 
574
                        //
 
575
                        // Timing circuit (patent figure 2a)
 
576
                        //
 
577
                        //==============================================
 
578
 
 
579
                        // update master clock
 
580
                        m_master_clock ^= 1;
 
581
 
 
582
                        // on the falling edge of the master clock, advance the 10-bit counter at 34
 
583
                        UINT8 old_latch_72 = m_latch_72;
 
584
                        if (m_master_clock == 0)
 
585
                                m_counter_34 = (m_counter_34 + 1) & 0x3ff;
 
586
                        else
 
587
                        {
 
588
                                m_latch_70 = m_counter_34 & 0xf;
 
589
                                m_latch_72 = ((m_counter_34 >> 4) & 7) | ((m_counter_34 >> 6) & 8);
 
590
                        }
 
591
 
 
592
                        // derive beta 1 clock:
 
593
                        //  set if m_latch_70.0 == 1
 
594
                        //  reset if m_latch_70.0 == 0
 
595
//          UINT8 old_beta1 = m_beta1;
 
596
                        m_beta1 = BIT(m_latch_70, 0);
 
597
 
 
598
                        // derive p2 clock:
 
599
                        //  set if (m_counter_34.P_CLOCK_BIT & clock) == 1
 
600
                        //  reset if (m_counter_34.P_CLOCK_BIT == 0)
 
601
                        UINT8 old_p2 = m_p2;
 
602
                        if (BIT(m_counter_34, P_CLOCK_BIT) & m_master_clock)
 
603
                                m_p2 = 1;
 
604
                        else if (!BIT(m_counter_34, P_CLOCK_BIT))
 
605
                                m_p2 = 0;
 
606
 
 
607
                        // derive p1 clock:
 
608
                        //  set if (!m_counter_34.P_CLOCK_BIT & clock) == 1
 
609
                        //  reset if (m_counter_34.P_CLOCK_BIT == 1)
 
610
//          UINT8 old_p1 = m_p1;
 
611
                        if (BIT(~m_counter_34, P_CLOCK_BIT) & m_master_clock)
 
612
                                m_p1 = 1;
 
613
                        else if (BIT(m_counter_34, P_CLOCK_BIT))
 
614
                                m_p1 = 0;
 
615
 
 
616
                        // derive phi2 clock:
 
617
                        //  set if (m_counter_34.PHI_CLOCK_BIT & clock) == 1
 
618
                        //  reset if (m_counter_34.PHI_CLOCK_BIT == 0)
 
619
                        UINT8 old_phi2 = m_phi2;
 
620
                        if (BIT(m_counter_34, PHI_CLOCK_BIT) & m_master_clock)
 
621
                                m_phi2 = 1;
 
622
                        else if (!BIT(m_counter_34, PHI_CLOCK_BIT))
 
623
                                m_phi2 = 0;
 
624
 
 
625
                        // derive phi1 clock:
 
626
                        //  set if (!m_counter_34.PHI_CLOCK_BIT & clock) == 1
 
627
                        //  reset if (m_counter_34.PHI_CLOCK_BIT == 1)
 
628
                        UINT8 old_phi1 = m_phi1;
 
629
                        if (BIT(~m_counter_34, PHI_CLOCK_BIT) & m_master_clock)
 
630
                                m_phi1 = 1;
 
631
                        else if (BIT(m_counter_34, PHI_CLOCK_BIT))
 
632
                                m_phi1 = 0;
 
633
 
 
634
                        // derive alternate phi2 clock:
 
635
                        //  set if (m_counter_34.PHI_CLOCK_BIT & clock) == 1
 
636
                        //  reset if (m_counter_34.PHI_CLOCK_BIT == 0)
 
637
                        UINT8 old_phi2_20 = m_phi2_20;
 
638
                        if (BIT(m_counter_34, PHI_CLOCK_BIT + 2) & m_master_clock)
 
639
                                m_phi2_20 = 1;
 
640
                        else if (!BIT(m_counter_34, PHI_CLOCK_BIT + 2))
 
641
                                m_phi2_20 = 0;
 
642
 
 
643
                        // derive alternate phi1 clock:
 
644
                        //  set if (!m_counter_34.PHI_CLOCK_BIT & clock) == 1
 
645
                        //  reset if (m_counter_34.PHI_CLOCK_BIT == 1)
 
646
//          UINT8 old_phi1_20 = m_phi1_20;
 
647
                        if (BIT(~m_counter_34, PHI_CLOCK_BIT + 2) & m_master_clock)
 
648
                                m_phi1_20 = 1;
 
649
                        else if (BIT(m_counter_34, PHI_CLOCK_BIT + 2))
 
650
                                m_phi1_20 = 0;
 
651
 
 
652
                        // determine rising edges of each clock of interest
 
653
//          UINT8 beta1_rising = (old_beta1 ^ m_beta1) & m_beta1;
 
654
                        UINT8 p2_rising = (old_p2 ^ m_p2) & m_p2;
 
655
//          UINT8 p1_rising = (old_p1 ^ m_p1) & m_p1;
 
656
                        UINT8 phi2_rising = (old_phi2 ^ m_phi2) & m_phi2;
 
657
                        UINT8 phi1_rising = (old_phi1 ^ m_phi1) & m_phi1;
 
658
                        UINT8 phi2_20_rising = (old_phi2_20 ^ m_phi2_20) & m_phi2_20;
 
659
//          UINT8 phi1_20_rising = (old_phi1_20 ^ m_phi1_20) & m_phi1_20;
 
660
                        UINT8 a0_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 0);
 
661
                        UINT8 a2_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 2);
 
662
                        UINT8 _125k_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 3);
 
663
 
 
664
                        // track subphoneme counter state
 
665
                        if (!(m_latch_42 | m_phi1))
 
666
                                m_subphoneme_count = 0;
 
667
                        else
 
668
                                m_subphoneme_count++;
 
669
                        if (p2_rising)
 
670
                                m_latch_42 = (m_subphoneme_count < m_subphoneme_period);
 
671
 
 
672
                        // update the state of the subphoneme clock line
 
673
                        UINT8 old_clock_88 = m_clock_88;
 
674
                        m_clock_88 = !m_latch_42;       //!(m_latch_42 | m_phi1); -- figure 7 seems to be wrong here
 
675
                        UINT8 clock_88_rising = (old_clock_88 ^ m_clock_88) & m_clock_88;
 
676
 
 
677
                        // the A/R line holds the counter in reset except during phoneme processing,
 
678
                        // when it is clocked on the rising edge of the subphoneme timer clock
 
679
                        if (m_internal_request != CLEAR_LINE)
 
680
                                m_counter_84 = 0xf;
 
681
                        else if (clock_88_rising)
 
682
                        {
 
683
                                m_counter_84 = (m_counter_84 - 1) & 0x0f;
 
684
mame_printf_debug("counter=%d\n", m_counter_84);
 
685
                        }
 
686
 
 
687
                        // clock the zero count latch
 
688
                        if (p2_rising)
 
689
                                m_latch_92 = ((m_counter_84 == 0) | (m_latch_92 << 1)) & 3;
 
690
 
 
691
                        // once both bits are set, the request line goes high
 
692
                        if (m_latch_92 == 3)
 
693
                        {
 
694
                                // if the request line was previously low, reset the VD/CLD flip-flops
 
695
                                if (m_internal_request == CLEAR_LINE)
 
696
                                        m_srff_112 = m_srff_114 = 0;
 
697
                                m_internal_request = ASSERT_LINE;
 
698
                        }
 
699
 
 
700
                        //==============================================
 
701
                        //
 
702
                        // Low parameter clocking (patent figure 2b)
 
703
                        //
 
704
                        //==============================================
 
705
 
 
706
                        // fetch ROM data; note that the address lines come directly from
 
707
                        // counter_34 and not from the latches, which are 1 cycle delayed
 
708
                        UINT8 romdata = m_rom[(m_phoneme << 3) | ((m_counter_34 >> 4) & 7)];
 
709
 
 
710
                        // update the ROM data; ROM format is (upper nibble/lower nibble)
 
711
                        //  +00 = F1 parameter / 0
 
712
                        //  +01 = F2 parameter / 0
 
713
                        //  +02 = FC parameter / 0
 
714
                        //  +03 = F3 parameter / CL
 
715
                        //  +04 = F2Q Parameter / CLD
 
716
                        //  +05 = VA Parameter / VD
 
717
                        //  +06 = FA Parameter / PAC
 
718
                        //  +07 = Phoneme timing (full 7 bits)
 
719
 
 
720
                        // latch a new value from ROM on phi2
 
721
                        UINT8 a = m_latch_72 & 7;
 
722
                        UINT8 romdata_swapped;
 
723
                        if (phi2_rising)
 
724
                        {
 
725
                                switch (a)
 
726
                                {
 
727
                                        // update CL
 
728
                                        case 3:
 
729
                                                m_srff_132 = m_srff_114 & BIT(~romdata, 3);
 
730
                                                break;
 
731
 
 
732
                                        // update CLD
 
733
                                        case 4:
 
734
                                                romdata_swapped = (BIT(romdata, 0) << 3) | (BIT(romdata, 1) << 2) | (BIT(romdata, 2) << 1) | (BIT(romdata, 3) << 0);
 
735
                                                if (m_counter_84 != 0 && romdata_swapped == (m_counter_84 ^ 0xf))
 
736
                                                        m_srff_114 = 1;
 
737
                                                break;
 
738
 
 
739
                                        // update VD
 
740
                                        case 5:
 
741
                                                romdata_swapped = (BIT(romdata, 0) << 3) | (BIT(romdata, 1) << 2) | (BIT(romdata, 2) << 1) | (BIT(romdata, 3) << 0);
 
742
                                                if (m_counter_84 != 0 && romdata_swapped == (m_counter_84 ^ 0xf))
 
743
                                                        m_srff_112 = 1;
 
744
                                                break;
 
745
 
 
746
                                        // update FF == PAC & (VA | FA)
 
747
                                        case 6:
 
748
                                                m_srff_142 = BIT(romdata, 3);
 
749
                                                break;
 
750
 
 
751
                                        // update PH
 
752
                                        case 7:
 
753
                                                if (m_latch_80 != (romdata & 0x7f))
 
754
                                                {
 
755
                                                        m_latch_80 = romdata & 0x7f;
 
756
mame_printf_debug("[PH=%02X]\n", m_latch_80);
 
757
                                                        UINT32 old_period = m_subphoneme_period;
 
758
                                                        update_subphoneme_clock_period();
 
759
                                                        m_subphoneme_count = (m_subphoneme_count * m_subphoneme_period) / old_period;
 
760
                                                        m_phoneme_timer->adjust(attotime::zero);
 
761
                                                }
 
762
                                                break;
 
763
                                }
 
764
                        }
 
765
 
 
766
                        //==============================================
 
767
                        //
 
768
                        // Glottal circuit (patent figure 6)
 
769
                        //
 
770
                        //==============================================
 
771
 
 
772
                        // determine the TC output from the counters (note that TC requires ET)
 
773
                        UINT8 counter_222_tc = (m_counter_222 == 0xf);
 
774
                        UINT8 counter_220_tc = (m_counter_220 == 0xf && counter_222_tc);
 
775
                        UINT8 counter_224_tc = (m_counter_224 == 0xf && counter_222_tc);
 
776
 
 
777
                        // clock glottal counter 224 on rising edge of a0
 
778
                        if (a0_rising)
 
779
                        {
 
780
                                // counter 224 is only enabled if TC of counter 222 is 1
 
781
                                if (counter_222_tc)
 
782
                                {
 
783
                                        // if counter 220's TC is 1, do a load instead of a count
 
784
                                        if (counter_220_tc)
 
785
                                                m_counter_224 = (m_inflection << 1) | ((~m_f1 & 0x8) >> 3);
 
786
                                        else
 
787
                                                m_counter_224 = (m_counter_224 + 1) & 0xf;
 
788
                                }
 
789
                        }
 
790
 
 
791
                        // clock remaining glottal counters (220, 222, 236) on rising edge of phi2
 
792
                        if (phi2_20_rising)
 
793
                        {
 
794
                                // counter 220 is only enabled if TC of counter 222 is 1
 
795
                                if (counter_222_tc)
 
796
                                {
 
797
                                        // if counter 220's TC is 1, do a load instead of a count
 
798
                                        if (counter_220_tc)
 
799
                                                m_counter_220 = (m_inflection << 1) | ((~m_f1 & 0x8) >> 3);
 
800
                                        else
 
801
                                                m_counter_220 = (m_counter_220 + 1) & 0xf;
 
802
                                }
 
803
 
 
804
                                // counter 222 is always enabled
 
805
                                if (1)
 
806
                                {
 
807
                                        // if counter 220's TC is 1, do a load instead of a count
 
808
                                        if (counter_220_tc)
 
809
                                                m_counter_222 = (~m_f1 & 0x7) << 1;
 
810
                                        else
 
811
                                                m_counter_222 = (m_counter_222 + 1) & 0xf;
 
812
                                }
 
813
 
 
814
                                // counter 236 is always enabled
 
815
                                if (1)
 
816
                                {
 
817
                                        m_counter_236 = (m_counter_236 + 1) & 0xf;
 
818
 
 
819
                                        // rising edge of Q1 from counter 236 clocks counter 234
 
820
                                        if ((m_counter_236 & 0x3) == 0x2)
 
821
                                        {
 
822
                                                // counter 234 is only enabled if it has not reached terminal
 
823
                                                if (m_counter_234 != 0xf)
 
824
                                                        m_counter_234 = (m_counter_234 + 1) & 0xf;
 
825
                                        }
 
826
                                }
 
827
                        }
 
828
 
 
829
                        // update FGATE state
 
830
                        if (counter_220_tc)
 
831
                                m_fgate = 0;
 
832
                        if (counter_224_tc)
 
833
                                m_fgate = 1;
 
834
 
 
835
                        // apply asynchronous clear to counters 234/236
 
836
                        if (counter_220_tc && m_phi1_20)
 
837
                                m_counter_236 = m_counter_234 = 0;
 
838
 
 
839
                        // derive glottal circuit output signals
 
840
#if !TEMP_HACKS
 
841
                        UINT8 old_glottal_sync = m_glottal_sync;
 
842
#endif
 
843
                        m_glottal_sync = (m_counter_234 == 0);
 
844
                        glottal_out = s_glottal_wave[m_counter_234];
 
845
 
 
846
                        //==============================================
 
847
                        //
 
848
                        // Transition circuit (patent figure 3a/3b)
 
849
                        //
 
850
                        //==============================================
 
851
 
 
852
                        // divide 1.25k clock by 2 (lower-left of 46)
 
853
                        UINT8 old_0625_clock = m_0625_clock;
 
854
                        if (_125k_rising)
 
855
                                m_0625_clock = !m_0625_clock;
 
856
                        UINT8 _0625_rising = (old_0625_clock ^ m_0625_clock) & m_0625_clock;
 
857
 
 
858
                        // update counter above
 
859
                        if (_0625_rising)
 
860
                        {
 
861
                                if (m_counter_46 == 0xf)
 
862
                                        m_counter_46 = 0xd;
 
863
                                else
 
864
                                        m_counter_46 = (m_counter_46 + 1) & 0xf;
 
865
                        }
 
866
 
 
867
                        // and then the latch to the right
 
868
                        if (a2_rising)
 
869
                                m_latch_46 = (BIT(m_counter_46, 1) << 0) |
 
870
                                                         (BIT(m_latch_46, 0) << 1) |
 
871
                                                         (m_0625_clock << 2) |
 
872
                                                         (BIT(m_latch_46, 2) << 3);
 
873
 
 
874
#if TEMP_HACKS
 
875
                        m_latch_46 = 0xf;
 
876
#endif
 
877
 
 
878
                        // determine the read/write signal
 
879
                        UINT8 ram_write = 0;
 
880
                        switch (a)
 
881
                        {
 
882
                                // write if not FF and low 2 bits of latch
 
883
                                // FF is the S/R flip-flop at 142 ANDed with !(/FA & /VA)
 
884
                                case 0: case 1: case 2: case 3: case 4:
 
885
                                        if (!(m_srff_142 & !((m_fa == 0) & (m_va == 0))) && (m_latch_46 & 0x3) == 0x3)
 
886
                                                ram_write = 1;
 
887
                                        break;
 
888
 
 
889
                                case 5:
 
890
                                        if ((m_latch_46 & 0xc) == 0xc && m_srff_112)
 
891
                                                ram_write = 1;
 
892
                                        break;
 
893
 
 
894
                                case 6:
 
895
                                        if ((m_latch_46 & 0xc) == 0xc && m_srff_114)
 
896
                                                ram_write = 1;
 
897
                                        break;
 
898
                        }
 
899
 
 
900
                        // gate on the phi2 clock (OR gate @ 172)
 
901
                        ram_write &= m_phi2;
 
902
 
 
903
                        // write the transitioned values to RAM if requested
 
904
                        // (note we consolidate the serial addition and clocking steps here)
 
905
                        if (ram_write)
 
906
                        {
 
907
                                UINT8 old = (m_latch_168 << 4) | m_latch_170;
 
908
                                m_ram[a] = old - (old >> 3) + ((romdata & 0xf0) >> 3);
 
909
                        }
 
910
 
 
911
                        // latch some parameter values on rising edge of phi2
 
912
                        if (phi2_rising)
 
913
                        {
 
914
                                switch (a)
 
915
                                {
 
916
                                        case 2:
 
917
                                                m_fc = m_latch_168;
 
918
                                                break;
 
919
 
 
920
                                        case 5:
 
921
                                                m_va = m_latch_168;
 
922
                                                break;
 
923
 
 
924
                                        case 6:
 
925
                                                m_fa = m_latch_168;
 
926
                                                break;
 
927
                                }
 
928
                        }
 
929
 
 
930
                        // latch remaining parameter values on rising edge of (phi2 & glottal sync)
 
931
#if TEMP_HACKS
 
932
                        if (phi2_rising)
 
933
#else
 
934
                        UINT8 old_phi2_glottal = (old_phi2 & old_glottal_sync);
 
935
                        UINT8 new_phi2_glottal = m_phi2 & m_glottal_sync;
 
936
                        if ((old_phi2_glottal ^ new_phi2_glottal) & new_phi2_glottal)
 
937
#endif
 
938
                                switch (a)
 
939
                                {
 
940
                                        case 0:
 
941
                                                m_f1 = m_latch_168;
 
942
                                                break;
 
943
 
 
944
                                        case 1:
 
945
                                                m_f2 = (m_latch_168 << 1) | (m_latch_170 >> 3);
 
946
                                                break;
 
947
 
 
948
                                        case 3:
 
949
                                                m_f3 = m_latch_168;
 
950
                                                break;
 
951
 
 
952
                                        case 4:
 
953
                                                m_f2q = m_latch_168;
 
954
                                                break;
 
955
                                }
 
956
 
 
957
                        // latch value from RAM on rising edge of phi1
 
958
                        if (phi1_rising)
 
959
                        {
 
960
                                m_latch_168 = m_ram[a] >> 4;
 
961
                                m_latch_170 = m_ram[a] & 0xf;
 
962
                        }
 
963
 
 
964
                        //==============================================
 
965
                        //
 
966
                        // Noise generator circuit (patent figure 8)
 
967
                        //
 
968
                        //==============================================
 
969
 
 
970
                        // nose is clocked by the NOR of /FA and P1
 
971
                        UINT8 old_noise_clock = m_noise_clock;
 
972
                        m_noise_clock = !((m_fa == 0) | m_p1);
 
973
                        UINT8 noise_clock_rising = (old_noise_clock ^ m_noise_clock) & m_noise_clock;
 
974
                        UINT8 noise_clock_falling = (old_noise_clock ^ m_noise_clock) & old_noise_clock;
 
975
 
 
976
                        // falling edge clocks the shift register
 
977
                        if (noise_clock_falling)
 
978
                        {
 
979
                                // shift register 252 is actually 4 shift registers (2 4-bit, 2 5-bit)
 
980
                                // d1 and d3 are the 4-bit registers, d2 and d4 are the 5-bit registers
 
981
                                // XOR'ed input goes into d4, which shifts in to d2, then d3, then d1
 
982
                                // thus the full 18-bit value is effectively
 
983
                                //
 
984
                                //  d4 = (m_shift_252 >> 0) & 0x1f;
 
985
                                //  d2 = (m_shift_252 >> 5) & 0x1f;
 
986
                                //  d3 = (m_shift_252 >> 10) & 0xf;
 
987
                                //  d1 = (m_shift_252 >> 14) & 0xf;
 
988
                                //
 
989
                                // input at the low end is ((d1+4 ^ d2+5) ^ (d4+4 ^ d4+5)) ^ !(counter2 | counter3)
 
990
                                // output is tapped at d3+4
 
991
 
 
992
                                UINT32 old_shift = m_shift_252;
 
993
                                m_shift_252 <<= 1;
 
994
                                m_shift_252 |= ((BIT(old_shift, 17) ^ BIT(old_shift, 9)) ^ (BIT(old_shift, 3) ^ BIT(old_shift, 4))) ^
 
995
                                                                 ((m_counter_250 & 0xc) == 0);
 
996
                        }
 
997
 
 
998
                        // rising edge clocks the counter
 
999
                        if (noise_clock_rising)
 
1000
                        {
 
1001
                                // counter is reset to 1 if terminal, otherwise it increments
 
1002
                                if (m_counter_250 == 0xf)
 
1003
                                        m_counter_250 = 0x1;
 
1004
                                else
 
1005
                                        m_counter_250 = (m_counter_250 + 1) & 0xf;
 
1006
                        }
 
1007
 
 
1008
                        // compute final noise out signal
 
1009
                        noise_out_digital = !(BIT(m_shift_252, 13) & (m_fgate | (m_va == 0)));
 
1010
                }
 
1011
 
 
1012
                // TODO: cache the filters
 
1013
                // filter coefs
 
1014
                double k[3], a[4], b[4];
 
1015
 
 
1016
                // base frequencies
 
1017
                double fc = m_master_clock_freq / 30.0; // Nominal is 20KHz
 
1018
                double fs = stream.sample_rate();
 
1019
 
 
1020
                // useful temporaries
 
1021
                double rcp, rcq, rca;
 
1022
 
 
1023
                // amplification stage
 
1024
                static const double va_caps[4] = { 27, 53, 107, 213 };
 
1025
                double va_out = glottal_out * bits_to_caps(m_va, 4, va_caps) / 400;
 
1026
 
 
1027
                shift_hist(va_out, m_va_hist, 4);
 
1028
 
 
1029
 
 
1030
                // noise shaping
 
1031
                static const double fa_caps[4] = { 27, 53, 107, 213 };
 
1032
                rcp = bits_to_caps(m_fa,  4, fa_caps);
 
1033
 
 
1034
                shift_hist(-noise_out_digital * 400*rcp/(358.0*100000*566*(fc*rcp*1e-12 + 1.0/100000 + 1.0/2000)), m_ni_hist, 4);
 
1035
 
 
1036
                k[0] = 400/(fc*358);
 
1037
                k[1] = 400*400/(fc*358*566);
 
1038
                k[2] = 400*400/(fc*fc*358*358);
 
1039
 
 
1040
                filter_s_to_z(k, fs, a, b);
 
1041
                double no_out = apply_filter(m_ni_hist, m_no_hist, a, b);
 
1042
                shift_hist(no_out, m_no_hist, 4);
 
1043
 
 
1044
 
 
1045
                // stage 1 filter
 
1046
 
 
1047
                static const double s1_p_caps[4] = { 16.4, 33, 66, 130 };
 
1048
                rcp = 24 + bits_to_caps(m_f1, 4, s1_p_caps);
 
1049
                rcq = 20;
 
1050
 
 
1051
                k[0] = 253/(fc*270);
 
1052
                k[1] = 1080*rcq/(fc*270*rcp);
 
1053
                k[2] = 1080*1080/(fc*fc*270*rcp);
 
1054
 
 
1055
                filter_s_to_z(k, fs, a, b);
 
1056
                double s1_out = apply_filter(m_va_hist, m_s1_hist, a, b);
 
1057
                shift_hist(s1_out, m_s1_hist, 4);
 
1058
 
 
1059
 
 
1060
                // stage 2 filter, glottal half
 
1061
 
 
1062
                static const double s2_p_caps[5] = { 14, 28, 56, 113, 226 };
 
1063
                static const double s2_q_caps[4] = { 23, 46, 93, 186 };
 
1064
                rcp = 46 + bits_to_caps(m_f2,  5, s2_p_caps);
 
1065
                rcq = 20 + bits_to_caps(m_f2q, 4, s2_q_caps);;
 
1066
 
 
1067
                k[0] = 400/(fc*470);
 
1068
                k[1] = 620*rcq/(fc*470*rcp);
 
1069
                k[2] = 620*620/(fc*fc*470*rcp);
 
1070
 
 
1071
                filter_s_to_z(k, fs, a, b);
 
1072
                double s2g_out = apply_filter(m_s1_hist, m_s2g_hist, a, b);
 
1073
                shift_hist(s2g_out, m_s2g_hist, 4);
 
1074
 
 
1075
 
 
1076
                // stage 2 filter, noise half (rcp and rcq kept from stage 2 glottal)
 
1077
 
 
1078
                static const double s2_n_caps[5] = { 19, 38, 76, 152 };
 
1079
                rca = bits_to_caps(m_fc, 4, s2_n_caps);
 
1080
 
 
1081
                shift_hist(-no_out*rcq*rca/(470*rcp), m_s2ni_hist, 4);
 
1082
 
 
1083
                k[0] = 400/(fc*470);
 
1084
                k[1] = 620*rcq/(fc*470*rcp);
 
1085
                k[2] = 620*620/(fc*fc*470*rcp);
 
1086
 
 
1087
                filter_s_to_z(k, fs, a, b);
 
1088
                double s2n_out = apply_filter(m_s2ni_hist, m_s2n_hist, a, b);
 
1089
                shift_hist(s2n_out, m_s2n_hist, 4);
 
1090
 
 
1091
                // sum the stage 2 outputs
 
1092
                double s2_out = s2g_out + s2n_out;
 
1093
                shift_hist(s2_out, m_s2_hist, 4);
 
1094
 
 
1095
 
 
1096
                // stage 3 filter
 
1097
 
 
1098
                static const double s3_p_caps[4] = { 21, 42, 84, 168 };
 
1099
                rcp = 76 + bits_to_caps(m_f3, 4, s3_p_caps);
 
1100
                rcq = 20;
 
1101
 
 
1102
                k[0] = 0;
 
1103
                k[1] = 420*rcq/(fc*390*rcp);
 
1104
                k[2] = 420*420/(fc*fc*390*rcp);
 
1105
 
 
1106
                filter_s_to_z(k, fs, a, b);
 
1107
                double s3_out = apply_filter(m_s2_hist, m_s3_hist, a, b);
 
1108
                shift_hist(s3_out, m_s3_hist, 4);
 
1109
 
 
1110
 
 
1111
                // stage 4 filter, noise injection
 
1112
 
 
1113
                // The resulting non-amplifying filter is identical, so we
 
1114
                // inject instead of splitting
 
1115
 
 
1116
                static const double s4_n_caps[4] = { 24, 48, 96, 192 };
 
1117
                rca = 115 + bits_to_caps(~m_fc, 4, s4_n_caps);
 
1118
 
 
1119
                shift_hist(s3_out + no_out*470/rca, m_s4i_hist, 4);
 
1120
 
 
1121
 
 
1122
                // stage 4 filter
 
1123
 
 
1124
                rcp = 30;
 
1125
                rcq = 20;
 
1126
 
 
1127
                k[0] = 0;
 
1128
                k[1] = 338*rcq/(fc*470*rcp);
 
1129
                k[2] = 338*338/(fc*fc*470*rcp);
 
1130
 
 
1131
                filter_s_to_z(k, fs, a, b);
 
1132
                double s4_out = apply_filter(m_s4i_hist, m_s4_hist, a, b);
 
1133
                shift_hist(s4_out, m_s4_hist, 4);
 
1134
 
 
1135
 
 
1136
                // TODO: apply closure circuit (undocumented)
 
1137
 
 
1138
                // output the current result
 
1139
                *dest++ = INT16(s4_out * 4000);
 
1140
        }
 
1141
}
 
1142
 
 
1143
 
 
1144
 
 
1145
//**************************************************************************
 
1146
//  DEVICE INTERFACE
 
1147
//**************************************************************************
 
1148
 
 
1149
//-------------------------------------------------
 
1150
//  rom_region - return a pointer to the device's
 
1151
//  internal ROM region
 
1152
//-------------------------------------------------
 
1153
 
 
1154
const rom_entry *votrax_sc01_device::device_rom_region() const
 
1155
{
 
1156
        return ROM_NAME( votrax_sc01 );
 
1157
}
 
1158
 
 
1159
 
 
1160
//-------------------------------------------------
 
1161
//  device_start - handle device startup
 
1162
//-------------------------------------------------
 
1163
 
 
1164
void votrax_sc01_device::device_start()
 
1165
{
 
1166
        // initialize internal state
 
1167
        m_master_clock_freq = clock();
 
1168
        m_stream = stream_alloc(0, 1, m_master_clock_freq / 16);
 
1169
        m_phoneme_timer = timer_alloc();
 
1170
        m_rom = memregion("phoneme")->base();
 
1171
 
 
1172
        // reset inputs
 
1173
        m_inflection = 0;
 
1174
        m_phoneme = 0x3f;
 
1175
 
 
1176
        // reset outputs
 
1177
        m_request_func.resolve(m_request_cb, *this);
 
1178
        m_request_state = ASSERT_LINE;
 
1179
        m_internal_request = ASSERT_LINE;
 
1180
 
 
1181
        // save inputs
 
1182
        save_item(NAME(m_inflection));
 
1183
        save_item(NAME(m_phoneme));
 
1184
 
 
1185
        // save outputs
 
1186
        save_item(NAME(m_request_state));
 
1187
        save_item(NAME(m_internal_request));
 
1188
 
 
1189
        // save timing circuit
 
1190
        save_item(NAME(m_master_clock_freq));
 
1191
        save_item(NAME(m_master_clock));
 
1192
        save_item(NAME(m_counter_34));
 
1193
        save_item(NAME(m_latch_70));
 
1194
        save_item(NAME(m_latch_72));
 
1195
        save_item(NAME(m_beta1));
 
1196
        save_item(NAME(m_p2));
 
1197
        save_item(NAME(m_p1));
 
1198
        save_item(NAME(m_phi2));
 
1199
        save_item(NAME(m_phi1));
 
1200
        save_item(NAME(m_subphoneme_period));
 
1201
        save_item(NAME(m_subphoneme_count));
 
1202
        save_item(NAME(m_clock_88));
 
1203
        save_item(NAME(m_latch_42));
 
1204
        save_item(NAME(m_counter_84));
 
1205
        save_item(NAME(m_latch_92));
 
1206
 
 
1207
        // save low parameter clocking
 
1208
        save_item(NAME(m_srff_132));
 
1209
        save_item(NAME(m_srff_114));
 
1210
        save_item(NAME(m_srff_112));
 
1211
        save_item(NAME(m_srff_142));
 
1212
        save_item(NAME(m_latch_80));
 
1213
 
 
1214
        // save glottal circuit
 
1215
        save_item(NAME(m_counter_220));
 
1216
        save_item(NAME(m_counter_222));
 
1217
        save_item(NAME(m_counter_224));
 
1218
        save_item(NAME(m_counter_234));
 
1219
        save_item(NAME(m_counter_236));
 
1220
        save_item(NAME(m_fgate));
 
1221
        save_item(NAME(m_glottal_sync));
 
1222
 
 
1223
        // save transition circuit
 
1224
        save_item(NAME(m_0625_clock));
 
1225
        save_item(NAME(m_counter_46));
 
1226
        save_item(NAME(m_latch_46));
 
1227
        save_item(NAME(m_ram));
 
1228
        save_item(NAME(m_latch_168));
 
1229
        save_item(NAME(m_latch_170));
 
1230
        save_item(NAME(m_f1));
 
1231
        save_item(NAME(m_f2));
 
1232
        save_item(NAME(m_fc));
 
1233
        save_item(NAME(m_f3));
 
1234
        save_item(NAME(m_f2q));
 
1235
        save_item(NAME(m_va));
 
1236
        save_item(NAME(m_fa));
 
1237
 
 
1238
        // save noise generator circuit
 
1239
        save_item(NAME(m_noise_clock));
 
1240
        save_item(NAME(m_shift_252));
 
1241
        save_item(NAME(m_counter_250));
 
1242
 
 
1243
        // save filter histories
 
1244
        save_item(NAME(m_ni_hist));
 
1245
        save_item(NAME(m_no_hist));
 
1246
        save_item(NAME(m_va_hist));
 
1247
        save_item(NAME(m_s1_hist));
 
1248
        save_item(NAME(m_s2g_hist));
 
1249
        save_item(NAME(m_s2n_hist));
 
1250
        save_item(NAME(m_s2ni_hist));
 
1251
        save_item(NAME(m_s2_hist));
 
1252
        save_item(NAME(m_s3_hist));
 
1253
        save_item(NAME(m_s4i_hist));
 
1254
        save_item(NAME(m_s4_hist));
 
1255
}
 
1256
 
 
1257
 
 
1258
//-------------------------------------------------
 
1259
//  device_reset - handle device reset
 
1260
//-------------------------------------------------
 
1261
 
 
1262
void votrax_sc01_device::device_reset()
 
1263
{
 
1264
        // set the initial state
 
1265
        m_stream->update();
 
1266
 
 
1267
        // reset inputs
 
1268
        m_phoneme = 0x3f;
 
1269
        m_request_func(m_internal_request = m_request_state = ASSERT_LINE);
 
1270
 
 
1271
        // reset timing circuit
 
1272
        m_master_clock = 0;
 
1273
        m_counter_34 = 0;
 
1274
        m_latch_70 = 0;
 
1275
        m_latch_72 = 0;
 
1276
        m_beta1 = 0;
 
1277
        m_p2 = 0;
 
1278
        m_p1 = 0;
 
1279
        m_phi2 = 0;
 
1280
        m_phi1 = 0;
 
1281
        m_subphoneme_period = 1000;
 
1282
        m_subphoneme_count = 0;
 
1283
        m_clock_88 = 0;
 
1284
        m_latch_42 = 0;
 
1285
        m_counter_84 = 0;
 
1286
        m_latch_92 = 0;
 
1287
 
 
1288
        // reset low parameter clocking
 
1289
        m_srff_132 = 0;
 
1290
        m_srff_114 = 0;
 
1291
        m_srff_112 = 0;
 
1292
        m_srff_142 = 0;
 
1293
        m_latch_80 = 50;
 
1294
        update_subphoneme_clock_period();
 
1295
 
 
1296
        // reset glottal circuit
 
1297
        m_counter_220 = 0;
 
1298
        m_counter_222 = 0;
 
1299
        m_counter_224 = 0;
 
1300
        m_counter_234 = 0;
 
1301
        m_counter_236 = 0;
 
1302
        m_fgate = 0;
 
1303
        m_glottal_sync = 0;
 
1304
 
 
1305
        // reset transition circuit
 
1306
        m_0625_clock = 0;
 
1307
        m_counter_46 = 0;
 
1308
        m_latch_46 = 0;
 
1309
        memset(m_ram, 0, sizeof(m_ram));
 
1310
        m_latch_168 = 0;
 
1311
        m_latch_170 = 0;
 
1312
        m_f1 = 0;
 
1313
        m_f2 = 0;
 
1314
        m_fc = 0;
 
1315
        m_f3 = 0;
 
1316
        m_f2q = 0;
 
1317
        m_va = 0;
 
1318
        m_fa = 0;
 
1319
 
 
1320
        // reset noise circuit
 
1321
        m_noise_clock = 0;
 
1322
        m_shift_252 = 0;
 
1323
        m_counter_250 = 0;
 
1324
 
 
1325
        // reset filter histories
 
1326
        memset(m_ni_hist,   0, sizeof(m_ni_hist));
 
1327
        memset(m_no_hist,   0, sizeof(m_no_hist));
 
1328
        memset(m_va_hist,   0, sizeof(m_va_hist));
 
1329
        memset(m_s1_hist,   0, sizeof(m_s1_hist));
 
1330
        memset(m_s2g_hist,  0, sizeof(m_s2g_hist));
 
1331
        memset(m_s2n_hist,  0, sizeof(m_s2n_hist));
 
1332
        memset(m_s2ni_hist, 0, sizeof(m_s2ni_hist));
 
1333
        memset(m_s2_hist,   0, sizeof(m_s2_hist));
 
1334
        memset(m_s3_hist,   0, sizeof(m_s3_hist));
 
1335
        memset(m_s4i_hist,  0, sizeof(m_s4i_hist));
 
1336
        memset(m_s4_hist,   0, sizeof(m_s4_hist));
 
1337
}
 
1338
 
 
1339
 
 
1340
//-------------------------------------------------
 
1341
//  device_clock_changed - handle dynamic clock
 
1342
//  changes by altering our output frequency
 
1343
//-------------------------------------------------
 
1344
 
 
1345
void votrax_sc01_device::device_clock_changed()
 
1346
{
 
1347
        // compute new frequency of the master clock, and update if changed
 
1348
        UINT32 newfreq = clock();
 
1349
        if (newfreq != m_master_clock_freq)
 
1350
        {
 
1351
                // if we have a stream
 
1352
                if (m_stream != NULL)
 
1353
                {
 
1354
                        m_stream->update();
 
1355
                        m_stream->set_sample_rate(newfreq / 16);
 
1356
                }
 
1357
 
 
1358
                // determine how many clock ticks remained on the phoneme timer
 
1359
                UINT64 remaining = m_phoneme_timer->remaining().as_ticks(m_master_clock_freq);
 
1360
 
 
1361
                // recompute the master clock
 
1362
                m_master_clock_freq = newfreq;
 
1363
 
 
1364
                // adjust the phoneme timer to the same number of ticks based on the new frequency
 
1365
                if (remaining > 0)
 
1366
                        m_phoneme_timer->adjust(attotime::from_ticks(remaining, newfreq));
 
1367
        }
 
1368
}
 
1369
 
 
1370
 
 
1371
//-------------------------------------------------
 
1372
//  device_timer - handle device timer
 
1373
//-------------------------------------------------
 
1374
 
 
1375
void votrax_sc01_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
 
1376
{
 
1377
        // force a stream update
 
1378
        m_stream->update();
 
1379
 
 
1380
        // if we're requesting more data, no need for timing
 
1381
        if (m_request_state == ASSERT_LINE)
 
1382
                return;
 
1383
 
 
1384
        // if we're supposed to have fired, do it now
 
1385
        if (m_internal_request == ASSERT_LINE)
 
1386
        {
 
1387
mame_printf_debug("%s: REQUEST\n", timer.machine().time().as_string(3));
 
1388
                m_request_func(m_request_state = ASSERT_LINE);
 
1389
                return;
 
1390
        }
 
1391
 
 
1392
        // account for the rest of this subphoneme clock
 
1393
        UINT32 clocks_until_request = 0;
 
1394
        if (m_counter_84 != 0)
 
1395
        {
 
1396
                if (m_subphoneme_count < m_subphoneme_period)
 
1397
                        clocks_until_request += m_subphoneme_period - m_subphoneme_count;
 
1398
                clocks_until_request += m_subphoneme_period * (m_counter_84 - 1);
 
1399
        }
 
1400
 
 
1401
        // plus 1/2
 
1402
        clocks_until_request = MAX(clocks_until_request, (1 << P_CLOCK_BIT) / 2);
 
1403
        timer.adjust(attotime::from_ticks(clocks_until_request, m_master_clock_freq));
 
1404
}