~ubuntu-branches/debian/squeeze/stella/squeeze

« back to all changes in this revision

Viewing changes to src/emucore/SpeakJet.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna, Franczen Attila, Luca Falavigna
  • Date: 2008-11-08 12:04:12 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20081108120412-w6xq87vzgokstfey
Tags: 2.6.1-0ubuntu1
[ Franczen Attila ]
* New upstream release (LP: #183571).
* Updated policy to 3.8.0.

[ Luca Falavigna ]
* debian/patches/gcc-4.3: fix FTBFS with gcc-4.3 compiler.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//============================================================================
 
2
//
 
3
//   SSSS    tt          lll  lll       
 
4
//  SS  SS   tt           ll   ll        
 
5
//  SS     tttttt  eeee   ll   ll   aaaa 
 
6
//   SSSS    tt   ee  ee  ll   ll      aa
 
7
//      SS   tt   eeeeee  ll   ll   aaaaa  --  "An Atari 2600 VCS Emulator"
 
8
//  SS  SS   tt   ee      ll   ll  aa  aa
 
9
//   SSSS     ttt  eeeee llll llll  aaaaa
 
10
//
 
11
// Copyright (c) 1995-2008 by Bradford W. Mott and the Stella team
 
12
//
 
13
// See the file "license" for information on usage and redistribution of
 
14
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
 
15
//
 
16
// $Id: SpeakJet.cxx,v 1.9 2008/03/31 00:59:30 stephena Exp $
 
17
//============================================================================
 
18
 
 
19
#ifdef SPEAKJET_EMULATION
 
20
 
 
21
#include "SpeakJet.hxx"
 
22
 
 
23
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
24
SpeakJet::SpeakJet()
 
25
{
 
26
  // Initialize output buffers. Each one points to the next element,
 
27
  // except the last, which points back to the first.
 
28
  SpeechBuffer *first = &outputBuffers[0];
 
29
  SpeechBuffer *last = 0;
 
30
  for(int i=0; i<SPEECH_BUFFERS; i++) {
 
31
    SpeechBuffer *sb = &outputBuffers[i];
 
32
    sb->items = 0;
 
33
    sb->lock = SDL_CreateSemaphore(1);
 
34
    if(last) {
 
35
       last->next = sb;
 
36
    }
 
37
    last = sb;
 
38
  }
 
39
  last->next = first;
 
40
 
 
41
  myCurrentOutputBuffer = ourCurrentWriteBuffer = first;
 
42
  ourCurrentWritePosition = 0;
 
43
 
 
44
  // Init rsynth library
 
45
  darray_init(&rsynthSamples, sizeof(short), 2048);
 
46
 
 
47
/*
 
48
  rsynth = rsynth_init(samp_rate, mSec_per_frame,
 
49
                       rsynth_speaker(F0Hz, gain, Elements),
 
50
                       save_sample, flush_samples, &samples);
 
51
*/
 
52
  rsynth = rsynth_init(31400, 10.0,
 
53
                       rsynth_speaker(133.0, 57, Elements),
 
54
                       save_sample, flush_samples, &rsynthSamples);
 
55
  spawnThread();
 
56
}
 
57
 
 
58
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
59
SpeakJet::~SpeakJet()
 
60
{
 
61
}
 
62
 
 
63
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
64
void SpeakJet::spawnThread()
 
65
{
 
66
  ourInputSemaphore = SDL_CreateSemaphore(1); // 1==unlocked
 
67
  uInt32 sem = SDL_SemValue(ourInputSemaphore);
 
68
  cerr << "before SDL_CreateThread(), sem==" << sem << endl;
 
69
  ourThread = SDL_CreateThread(thread, 0);
 
70
  sem = SDL_SemValue(ourInputSemaphore);
 
71
  cerr << "after SDL_CreateThread(), sem==" << sem << endl;
 
72
}
 
73
 
 
74
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
75
int SpeakJet::thread(void *data) {
 
76
  cerr << "rsynth thread spawned" << endl;
 
77
  while(1) {
 
78
    speak();
 
79
    usleep(10);
 
80
  }
 
81
  return 0;
 
82
}
 
83
 
 
84
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
85
void SpeakJet::write(uInt8 code)
 
86
{
 
87
  cerr << "SpeakJet: output byte " << ((int)(code)) << endl;
 
88
 
 
89
  // TODO: clean up this mess.
 
90
  const char *rsynthPhones = xlatePhoneme(code);
 
91
//  cerr << "rsynth: \"" << rsynthPhones << "\"" << endl;
 
92
  int len = strlen(rsynthPhones);
 
93
 
 
94
  if(ourInputCount + len + 1 >= INPUT_BUFFER_SIZE) {
 
95
    cerr << "phonemeBuffer is full, dropping" << endl;
 
96
    return;
 
97
  }
 
98
 
 
99
  uInt32 sem = SDL_SemValue(ourInputSemaphore);
 
100
//  cerr << "write() waiting on semaphore (value " << sem << ")" << endl;
 
101
  SDL_SemWait(ourInputSemaphore);
 
102
//  cerr << "write() got semaphore" << endl;
 
103
  for(int i=0; i<len; i++)
 
104
    phonemeBuffer[ourInputCount++] = rsynthPhones[i];
 
105
  phonemeBuffer[ourInputCount] = '\0';
 
106
//  cerr << "phonemeBuffer contains \"" << phonemeBuffer << "\"" << endl;
 
107
//  cerr << "write() releasing semaphore" << endl;
 
108
  SDL_SemPost(ourInputSemaphore);
 
109
}
 
110
 
 
111
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
112
void SpeakJet::speak()
 
113
{
 
114
  // TODO: clean up this mess.
 
115
  static char myInput[INPUT_BUFFER_SIZE];
 
116
 
 
117
  if(!ourInputCount)
 
118
    return;
 
119
 
 
120
  uInt32 sem = SDL_SemValue(ourInputSemaphore);
 
121
//  cerr << "speak() waiting on semaphore (value " << sem << ")" << endl;
 
122
  SDL_SemWait(ourInputSemaphore);
 
123
//  cerr << "speak() got semaphore" << endl;
 
124
 
 
125
  // begin locked section
 
126
 
 
127
  bool foundSpace = false;
 
128
  for(int i=0; i<ourInputCount; i++)
 
129
    if( (myInput[i] = phonemeBuffer[i]) == ' ')
 
130
      foundSpace = true;
 
131
 
 
132
  if(ourInputCount >= INPUT_BUFFER_SIZE - 5)
 
133
    foundSpace = true;
 
134
 
 
135
  if(foundSpace)
 
136
    ourInputCount = 0;
 
137
 
 
138
  // end locked section
 
139
//  cerr << "speak() releasing semaphore" << endl;
 
140
  SDL_SemPost(ourInputSemaphore);
 
141
 
 
142
  if(foundSpace)
 
143
  {
 
144
    // Lock current buffer. save_sample will unlock it when it gets full.
 
145
    SDL_SemWait(ourCurrentWriteBuffer->lock);
 
146
    rsynth_phones(rsynth, myInput, strlen(myInput));
 
147
  }
 
148
}
 
149
 
 
150
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
151
const char *SpeakJet::xlatePhoneme(uInt8 code)
 
152
{
 
153
  if(code <= 6)
 
154
    return " ";
 
155
 
 
156
  if(code >= 128 && code <= 199)
 
157
    return ourPhonemeTable[ code - 128 ];
 
158
 
 
159
  return "";
 
160
}
 
161
 
 
162
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
163
uInt8 *SpeakJet::getSamples(int *count) {
 
164
  static uInt8 contents[OUTPUT_BUFFER_SIZE];
 
165
  SDL_sem *lock = myCurrentOutputBuffer->lock;
 
166
  SDL_SemWait(lock);
 
167
  *count = myCurrentOutputBuffer->items;
 
168
  for(int i=0; i<*count; i++)
 
169
    contents[i] = myCurrentOutputBuffer->contents[i];
 
170
  myCurrentOutputBuffer->items = 0;
 
171
  myCurrentOutputBuffer = myCurrentOutputBuffer->next;
 
172
  SDL_SemPost(lock);
 
173
  return contents;
 
174
}
 
175
 
 
176
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
177
bool SpeakJet::chipReady()
 
178
{
 
179
  return true;
 
180
}
 
181
 
 
182
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
183
void *SpeakJet::save_sample(void *user_data,
 
184
                            float sample,
 
185
                            unsigned nsamp,
 
186
                            rsynth_t *rsynth)
 
187
{
 
188
  static long clip_max;
 
189
  static float peak;
 
190
  short shortSamp;
 
191
  uInt8 output;
 
192
 
 
193
  darray_t *buf = (darray_t *) user_data;
 
194
  shortSamp = clip(&clip_max, sample, &peak);
 
195
  darray_short(buf, shortSamp);
 
196
 
 
197
  // Convert to 8-bit
 
198
  // output = (uInt8)( (((float)shortSamp) + 32768.0) / 256.0 );
 
199
  double d = shortSamp + 32768.0;
 
200
  output = (uInt8)(d/256.0);
 
201
//  cerr << "Output sample: " << ((int)(output)) << endl;
 
202
 
 
203
  // Put in buffer
 
204
  ourCurrentWriteBuffer->contents[ourCurrentWritePosition++] = output;
 
205
  ourCurrentWriteBuffer->items = ourCurrentWritePosition;
 
206
 
 
207
  // If buffer is full, unlock it and use the next one.
 
208
  if(ourCurrentWritePosition == OUTPUT_BUFFER_SIZE)
 
209
  {
 
210
    SDL_SemWait(ourCurrentWriteBuffer->next->lock);
 
211
    SDL_SemPost(ourCurrentWriteBuffer->lock);
 
212
    ourCurrentWriteBuffer = ourCurrentWriteBuffer->next;
 
213
    ourCurrentWriteBuffer->items = ourCurrentWritePosition = 0;
 
214
  }
 
215
  return (void *) buf;
 
216
}
 
217
 
 
218
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
219
void *SpeakJet::flush_samples(void *user_data,
 
220
                           unsigned nsamp,
 
221
                           rsynth_t *rsynth)
 
222
{
 
223
  darray_t *buf = (darray_t *) user_data;
 
224
  buf->items = 0;
 
225
  for (;ourCurrentWritePosition < OUTPUT_BUFFER_SIZE; ourCurrentWritePosition++)
 
226
    ourCurrentWriteBuffer->contents[ourCurrentWritePosition] = 0;
 
227
  ourCurrentWritePosition = 0;
 
228
  SDL_SemPost(ourCurrentWriteBuffer->lock);
 
229
  ourCurrentWriteBuffer = ourCurrentWriteBuffer->next; // NOT locked
 
230
  return (void *) buf;
 
231
}
 
232
 
 
233
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
234
short SpeakJet::clip(long *clip_max, float input, float *peak)
 
235
{
 
236
  long temp = (long) input;
 
237
  float isq = input * input;
 
238
#ifdef PEAK
 
239
  if (isq > *peak)
 
240
    *peak = isq;
 
241
#else
 
242
  *peak += isq;
 
243
#endif 
 
244
  if (-temp > *clip_max)
 
245
    *clip_max = -temp;
 
246
  if (temp > *clip_max)
 
247
    *clip_max = temp;
 
248
  if (temp < -32767) {
 
249
    temp = -32767;
 
250
  }
 
251
  else if (temp > 32767) {
 
252
    temp = 32767;
 
253
  }
 
254
  return (temp);
 
255
}
 
256
 
 
257
 
 
258
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
259
 
 
260
/*
 
261
Table of rsynth phonemes, indexed by SpeakJet phoneme code number.
 
262
Table is offset by 128 bytes (ourPhonemeTable[0] is code #128)
 
263
see rsynth/phones.def for definitions of rsynth phonemes.
 
264
We prefix a "'" to the rsynth phoneme for stress or a ","
 
265
for relax.
 
266
FIXME: This will need a lot of tweaking, once I get a real
 
267
SpeakJet to test with.
 
268
*/
 
269
 
 
270
const char *SpeakJet::ourPhonemeTable[] = {
 
271
//"rsynth phoneme(s) (phones.def)",   // SJ phonemes (p. 16 in SJ manual)
 
272
  "i:",   // 128 IY   See, Even, Feed
 
273
  "I",    // 129 IH   Sit, Fix, Pin
 
274
  "eI",   // 130 EY   Hair, Gate, Beige
 
275
  "E",    // 131 EH   Met, Check, Red
 
276
  "{",    // 132 AY   Hat, Fast, Fan
 
277
  "A:",   // 133 AX   Cotten // maybe "@" instead?
 
278
  "V",    // 134 UX   Luck, Up, Uncle
 
279
  "Q",    // 135 OH   Hot, Clock, Fox
 
280
  "A:",   // 136 AW   Father, Fall
 
281
  "oU",   // 137 OW   Comb, Over, Hold
 
282
  "U",    // 138 UH   Book, Could, Should
 
283
  "u:",   // 139 UW   Food, June
 
284
  "m",    // 140 MM   Milk, Famous,
 
285
  "n",    // 141 NE   Nip, Danger, Thin
 
286
  "n",    // 142 NO   No, Snow, On
 
287
  "N",    // 143 NGE  Think, Ping
 
288
  "N",    // 144 NGO  Hung, Song
 
289
  "l",    // 145 LE   Lake, Alarm, Lapel
 
290
  "l",    // 146 LO   Clock, Plus, Hello
 
291
  "w",    // 147 WW   Wool, Sweat
 
292
  "r",    // 148 RR   Ray, Brain, Over
 
293
  "I@",   // 149 IYRR Clear, Hear, Year
 
294
  "e@",   // 150 EYRR Hair, Stair, Repair
 
295
  "3:",   // 151 AXRR Fir, Bird, Burn
 
296
  "A:",   // 152 AWRR Part, Farm, Yarn
 
297
  "Qr",   // 153 OWRR Corn, Four, Your [*]
 
298
  "eI",   // 154 EYIY Gate, Ate, Ray
 
299
  "aI",   // 155 OHIY Mice, Fight, White
 
300
  "OI",   // 156 OWIY Boy, Toy, Voice
 
301
  "aI",   // 157 OHIH Sky, Five, I
 
302
  "j",    // 158 IYEH Yes, Yarn, Million
 
303
  "el",   // 159 EHLL Saddle, Angle, Spell [*]
 
304
  "U@",   // 160 IYUW Cute, Few // maybe u
 
305
  "aU",   // 161 AXUW Brown, Clown, Thousan
 
306
  "U@",   // 162 IHWW Two, New, Zoo
 
307
  "aU",   // 163 AYWW Our, Ouch, Owl
 
308
  "@U",   // 164 OWWW Go, Hello, Snow // maybe "oU"?
 
309
  "dZ",   // 165 JH   Dodge, Jet, Savage
 
310
  "v",    // 166 VV   Vest, Even,
 
311
  "z",    // 167 ZZ   Zoo, Zap
 
312
  "Z",    // 168 ZH   Azure, Treasure
 
313
  "D",    // 169 DH   There, That, This
 
314
  "b",    // 170 BE   Bear, Bird, Beed   ???
 
315
  "b",    // 171 BO   Bone, Book Brown ???
 
316
  "b",    // 172 EB   Cab, Crib, Web   ???
 
317
  "b",    // 173 OB   Bob, Sub, Tub   ???
 
318
  "d",    // 174 DE   Deep, Date, Divide   ???
 
319
  "d",    // 175 DO   Do, Dust, Dog   ???
 
320
  "d",    // 176 ED   Could, Bird   ???
 
321
  "d",    // 177 OD   Bud, Food   ???
 
322
  "g",    // 178 GE   Get, Gate, Guest,   ???
 
323
  "g",    // 179 GO   Got, Glue, Goo   ???
 
324
  "g",    // 180 EG   Peg, Wig   ???
 
325
  "g",    // 181 OG   Dog, Peg   ???
 
326
  "tS",   // 182 CH   Church, Feature, March
 
327
  "h",    // 183 HE   Help, Hand, Hair
 
328
  "h",    // 184 HO   Hoe, Hot, Hug
 
329
  "hw",   // 185 WH   Who, Whale, White [*]
 
330
  "f",    // 186 FF   Food, Effort, Off
 
331
  "s",    // 187 SE   See, Vest, Plus
 
332
  "s",    // 188 SO   So, Sweat      ???
 
333
  "S",    // 189 SH   Ship, Fiction, Leash
 
334
  "T",    // 190 TH   Thin, month
 
335
  "t",    // 191 TT   Part, Little, Sit
 
336
  "t",    // 192 TU   To, Talk, Ten
 
337
  "ts",   // 193 TS   Parts, Costs, Robots
 
338
  "k",    // 194 KE   Can't, Clown, Key
 
339
  "k",    // 195 KO   Comb, Quick, Fox ???
 
340
  "k",    // 196 EK   Speak, Task ???
 
341
  "k",    // 197 OK   Book, Took, October ???
 
342
  "p",    // 198 PE   People, Computer
 
343
  "p"     // 199 PO   Paw, Copy ???
 
344
};
 
345
 
 
346
#endif