~ubuntu-branches/ubuntu/lucid/squeak-vm/lucid

« back to all changes in this revision

Viewing changes to platforms/unix/src/vm/intplugins/SoundGenerationPlugin/SoundGenerationPlugin.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2005-07-15 11:44:08 UTC
  • Revision ID: james.westby@ubuntu.com-20050715114408-lgcvpntigab09l00
Tags: upstream-3.7.7
ImportĀ upstreamĀ versionĀ 3.7.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Automatically generated from Squeak on #(19 March 2005 10:09:04 am) */
 
2
 
 
3
#include <math.h>
 
4
#include <stdio.h>
 
5
#include <stdlib.h>
 
6
#include <string.h>
 
7
#include <time.h>
 
8
 
 
9
/* Default EXPORT macro that does nothing (see comment in sq.h): */
 
10
#define EXPORT(returnType) returnType
 
11
 
 
12
/* Do not include the entire sq.h file but just those parts needed. */
 
13
/*  The virtual machine proxy definition */
 
14
#include "sqVirtualMachine.h"
 
15
/* Configuration options */
 
16
#include "sqConfig.h"
 
17
/* Platform specific definitions */
 
18
#include "sqPlatformSpecific.h"
 
19
 
 
20
#define true 1
 
21
#define false 0
 
22
#define null 0  /* using 'null' because nil is predefined in Think C */
 
23
#ifdef SQUEAK_BUILTIN_PLUGIN
 
24
#undef EXPORT
 
25
// was #undef EXPORT(returnType) but screws NorCroft cc
 
26
#define EXPORT(returnType) static returnType
 
27
#endif
 
28
 
 
29
/* memory access macros */
 
30
#define byteAt(i) (*((unsigned char *) (i)))
 
31
#define byteAtput(i, val) (*((unsigned char *) (i)) = val)
 
32
#define longAt(i) (*((int *) (i)))
 
33
#define longAtput(i, val) (*((int *) (i)) = val)
 
34
 
 
35
 
 
36
 
 
37
/*** Proxy Functions ***/
 
38
#define stackValue(i) (interpreterProxy->stackValue(i))
 
39
#define stackIntegerValue(i) (interpreterProxy->stackIntegerValue(i))
 
40
#define successFlag (!interpreterProxy->failed())
 
41
#define success(bool) (interpreterProxy->success(bool))
 
42
#define arrayValueOf(oop) (interpreterProxy->arrayValueOf(oop))
 
43
#define checkedIntegerValueOf(oop) (interpreterProxy->checkedIntegerValueOf(oop))
 
44
#define fetchArrayofObject(idx,oop) (interpreterProxy->fetchArrayofObject(idx,oop))
 
45
#define fetchFloatofObject(idx,oop) (interpreterProxy->fetchFloatofObject(idx,oop))
 
46
#define fetchIntegerofObject(idx,oop) (interpreterProxy->fetchIntegerofObject(idx,oop))
 
47
#define floatValueOf(oop) (interpreterProxy->floatValueOf(oop))
 
48
#define pop(n) (interpreterProxy->pop(n))
 
49
#define pushInteger(n) (interpreterProxy->pushInteger(n))
 
50
#define sizeOfSTArrayFromCPrimitive(cPtr) (interpreterProxy->sizeOfSTArrayFromCPrimitive(cPtr))
 
51
#define storeIntegerofObjectwithValue(idx,oop,value) (interpreterProxy->storeIntegerofObjectwithValue(idx,oop,value))
 
52
#define primitiveFail() interpreterProxy->primitiveFail()
 
53
/* allows accessing Strings in both C and Smalltalk */
 
54
#define asciiValue(c) c
 
55
 
 
56
 
 
57
/*** Constants ***/
 
58
#define IncrementFractionBits 16
 
59
#define LoopIndexFractionMask 511
 
60
#define LoopIndexScaleFactor 512
 
61
#define ScaleFactor 32768
 
62
#define ScaledIndexOverflow 536870912
 
63
 
 
64
/*** Variables ***/
 
65
 
 
66
#ifdef SQUEAK_BUILTIN_PLUGIN
 
67
extern
 
68
#endif
 
69
struct VirtualMachine* interpreterProxy;
 
70
static const char *moduleName =
 
71
#ifdef SQUEAK_BUILTIN_PLUGIN
 
72
        "SoundGenerationPlugin 19 March 2005 (i)"
 
73
#else
 
74
        "SoundGenerationPlugin 19 March 2005 (e)"
 
75
#endif
 
76
;
 
77
 
 
78
/*** Function Prototypes ***/
 
79
#pragma export on
 
80
EXPORT(const char*) getModuleName(void);
 
81
#pragma export off
 
82
static int halt(void);
 
83
static int msg(char *s);
 
84
#pragma export on
 
85
EXPORT(int) primitiveApplyReverb(void);
 
86
EXPORT(int) primitiveMixFMSound(void);
 
87
EXPORT(int) primitiveMixLoopedSampledSound(void);
 
88
EXPORT(int) primitiveMixPluckedSound(void);
 
89
EXPORT(int) primitiveMixSampledSound(void);
 
90
EXPORT(int) setInterpreter(struct VirtualMachine* anInterpreter);
 
91
#pragma export off
 
92
 
 
93
 
 
94
/*      Note: This is hardcoded so it can be run from Squeak.
 
95
        The module name is used for validating a module *after*
 
96
        it is loaded to check if it does really contain the module
 
97
        we're thinking it contains. This is important! */
 
98
 
 
99
EXPORT(const char*) getModuleName(void) {
 
100
        return moduleName;
 
101
}
 
102
 
 
103
static int halt(void) {
 
104
        ;
 
105
}
 
106
 
 
107
static int msg(char *s) {
 
108
        fprintf(stderr, "\n%s: %s", moduleName, s);
 
109
}
 
110
 
 
111
EXPORT(int) primitiveApplyReverb(void) {
 
112
    int rcvr;
 
113
    short int *aSoundBuffer;
 
114
    int startIndex;
 
115
    int n;
 
116
    int tapGain;
 
117
    int sliceIndex;
 
118
    int i;
 
119
    int tapIndex;
 
120
    int j;
 
121
    int delayedLeft;
 
122
    int out;
 
123
    int delayedRight;
 
124
    int *tapDelays;
 
125
    int *tapGains;
 
126
    int tapCount;
 
127
    int bufferSize;
 
128
    int bufferIndex;
 
129
    short int *leftBuffer;
 
130
    short int *rightBuffer;
 
131
 
 
132
        rcvr = stackValue(3);
 
133
        aSoundBuffer = arrayValueOf(stackValue(2));
 
134
        aSoundBuffer -= 1;
 
135
        startIndex = stackIntegerValue(1);
 
136
        n = stackIntegerValue(0);
 
137
        tapDelays = fetchArrayofObject(7, rcvr);
 
138
        tapDelays -= 1;
 
139
        tapGains = fetchArrayofObject(8, rcvr);
 
140
        tapGains -= 1;
 
141
        tapCount = fetchIntegerofObject(9, rcvr);
 
142
        bufferSize = fetchIntegerofObject(10, rcvr);
 
143
        bufferIndex = fetchIntegerofObject(11, rcvr);
 
144
        leftBuffer = fetchArrayofObject(12, rcvr);
 
145
        leftBuffer -= 1;
 
146
        rightBuffer = fetchArrayofObject(13, rcvr);
 
147
        rightBuffer -= 1;
 
148
        if (!(successFlag)) {
 
149
                return null;
 
150
        }
 
151
        for (sliceIndex = startIndex; sliceIndex <= ((startIndex + n) - 1); sliceIndex += 1) {
 
152
                delayedLeft = delayedRight = 0;
 
153
                for (tapIndex = 1; tapIndex <= tapCount; tapIndex += 1) {
 
154
                        i = bufferIndex - (tapDelays[tapIndex]);
 
155
                        if (i < 1) {
 
156
                                i += bufferSize;
 
157
                        }
 
158
                        tapGain = tapGains[tapIndex];
 
159
                        delayedLeft += tapGain * (leftBuffer[i]);
 
160
                        delayedRight += tapGain * (rightBuffer[i]);
 
161
                }
 
162
                j = (2 * sliceIndex) - 1;
 
163
                out = (aSoundBuffer[j]) + (((int) delayedLeft >> 15));
 
164
                if (out > 32767) {
 
165
                        out = 32767;
 
166
                }
 
167
                if (out < -32767) {
 
168
                        out = -32767;
 
169
                }
 
170
                aSoundBuffer[j] = out;
 
171
                leftBuffer[bufferIndex] = out;
 
172
                j += 1;
 
173
                out = (aSoundBuffer[j]) + (((int) delayedRight >> 15));
 
174
                if (out > 32767) {
 
175
                        out = 32767;
 
176
                }
 
177
                if (out < -32767) {
 
178
                        out = -32767;
 
179
                }
 
180
                aSoundBuffer[j] = out;
 
181
                rightBuffer[bufferIndex] = out;
 
182
                bufferIndex = (bufferIndex % bufferSize) + 1;
 
183
        }
 
184
        if (!(successFlag)) {
 
185
                return null;
 
186
        }
 
187
        storeIntegerofObjectwithValue(11, rcvr, bufferIndex);
 
188
        pop(3);
 
189
}
 
190
 
 
191
 
 
192
/*      Play samples from a wave table by stepping a fixed amount through the table on every sample. The table index and increment are scaled to allow fractional increments for greater pitch accuracy. */
 
193
/*      (FMSound pitch: 440.0 dur: 1.0 loudness: 0.5) play */
 
194
 
 
195
EXPORT(int) primitiveMixFMSound(void) {
 
196
    int rcvr;
 
197
    int n;
 
198
    short int *aSoundBuffer;
 
199
    int startIndex;
 
200
    int leftVol;
 
201
    int rightVol;
 
202
    int sliceIndex;
 
203
    int i;
 
204
    int s;
 
205
    int lastIndex;
 
206
    int offset;
 
207
    int sample;
 
208
    int doingFM;
 
209
    int scaledVol;
 
210
    int scaledVolIncr;
 
211
    int scaledVolLimit;
 
212
    int count;
 
213
    short int *waveTable;
 
214
    int scaledWaveTableSize;
 
215
    int scaledIndex;
 
216
    int scaledIndexIncr;
 
217
    int normalizedModulation;
 
218
    int scaledOffsetIndex;
 
219
    int scaledOffsetIndexIncr;
 
220
 
 
221
        rcvr = stackValue(5);
 
222
        n = stackIntegerValue(4);
 
223
        aSoundBuffer = arrayValueOf(stackValue(3));
 
224
        aSoundBuffer -= 1;
 
225
        startIndex = stackIntegerValue(2);
 
226
        leftVol = stackIntegerValue(1);
 
227
        rightVol = stackIntegerValue(0);
 
228
        scaledVol = fetchIntegerofObject(3, rcvr);
 
229
        scaledVolIncr = fetchIntegerofObject(4, rcvr);
 
230
        scaledVolLimit = fetchIntegerofObject(5, rcvr);
 
231
        count = fetchIntegerofObject(7, rcvr);
 
232
        waveTable = fetchArrayofObject(8, rcvr);
 
233
        waveTable -= 1;
 
234
        scaledWaveTableSize = fetchIntegerofObject(9, rcvr);
 
235
        scaledIndex = fetchIntegerofObject(10, rcvr);
 
236
        scaledIndexIncr = fetchIntegerofObject(11, rcvr);
 
237
        normalizedModulation = fetchIntegerofObject(14, rcvr);
 
238
        scaledOffsetIndex = fetchIntegerofObject(15, rcvr);
 
239
        scaledOffsetIndexIncr = fetchIntegerofObject(16, rcvr);
 
240
        if (!(successFlag)) {
 
241
                return null;
 
242
        }
 
243
        doingFM = (normalizedModulation != 0) && (scaledOffsetIndexIncr != 0);
 
244
        lastIndex = (startIndex + n) - 1;
 
245
        for (sliceIndex = startIndex; sliceIndex <= lastIndex; sliceIndex += 1) {
 
246
                sample = ((int) (scaledVol * (waveTable[(((int) scaledIndex >> 15)) + 1])) >> 15);
 
247
                if (doingFM) {
 
248
                        offset = normalizedModulation * (waveTable[(((int) scaledOffsetIndex >> 15)) + 1]);
 
249
                        scaledOffsetIndex = (scaledOffsetIndex + scaledOffsetIndexIncr) % scaledWaveTableSize;
 
250
                        if (scaledOffsetIndex < 0) {
 
251
                                scaledOffsetIndex += scaledWaveTableSize;
 
252
                        }
 
253
                        scaledIndex = ((scaledIndex + scaledIndexIncr) + offset) % scaledWaveTableSize;
 
254
                        if (scaledIndex < 0) {
 
255
                                scaledIndex += scaledWaveTableSize;
 
256
                        }
 
257
                } else {
 
258
                        scaledIndex = (scaledIndex + scaledIndexIncr) % scaledWaveTableSize;
 
259
                }
 
260
                if (leftVol > 0) {
 
261
                        i = (2 * sliceIndex) - 1;
 
262
                        s = (aSoundBuffer[i]) + (((int) (sample * leftVol) >> 15));
 
263
                        if (s > 32767) {
 
264
                                s = 32767;
 
265
                        }
 
266
                        if (s < -32767) {
 
267
                                s = -32767;
 
268
                        }
 
269
                        aSoundBuffer[i] = s;
 
270
                }
 
271
                if (rightVol > 0) {
 
272
                        i = 2 * sliceIndex;
 
273
                        s = (aSoundBuffer[i]) + (((int) (sample * rightVol) >> 15));
 
274
                        if (s > 32767) {
 
275
                                s = 32767;
 
276
                        }
 
277
                        if (s < -32767) {
 
278
                                s = -32767;
 
279
                        }
 
280
                        aSoundBuffer[i] = s;
 
281
                }
 
282
                if (scaledVolIncr != 0) {
 
283
                        scaledVol += scaledVolIncr;
 
284
                        if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) {
 
285
                                scaledVol = scaledVolLimit;
 
286
                                scaledVolIncr = 0;
 
287
                        }
 
288
                }
 
289
        }
 
290
        count -= n;
 
291
        if (!(successFlag)) {
 
292
                return null;
 
293
        }
 
294
        storeIntegerofObjectwithValue(3, rcvr, scaledVol);
 
295
        storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr);
 
296
        storeIntegerofObjectwithValue(7, rcvr, count);
 
297
        storeIntegerofObjectwithValue(10, rcvr, scaledIndex);
 
298
        storeIntegerofObjectwithValue(15, rcvr, scaledOffsetIndex);
 
299
        pop(5);
 
300
}
 
301
 
 
302
 
 
303
/*      Play samples from a wave table by stepping a fixed amount through the table on every sample. The table index and increment are scaled to allow fractional increments for greater pitch accuracy.  If a loop length is specified, then the index is looped back when the loopEnd index is reached until count drops below releaseCount. This allows a short sampled sound to be sustained indefinitely. */
 
304
/*      (LoopedSampledSound pitch: 440.0 dur: 5.0 loudness: 0.5) play */
 
305
 
 
306
EXPORT(int) primitiveMixLoopedSampledSound(void) {
 
307
    int rcvr;
 
308
    int n;
 
309
    short int *aSoundBuffer;
 
310
    int startIndex;
 
311
    int leftVol;
 
312
    int rightVol;
 
313
    int nextSampleIndex;
 
314
    int i;
 
315
    int s;
 
316
    int sliceIndex;
 
317
    int lastIndex;
 
318
    int leftVal;
 
319
    int sampleIndex;
 
320
    int compositeLeftVol;
 
321
    int compositeRightVol;
 
322
    int rightVal;
 
323
    int isInStereo;
 
324
    int m;
 
325
    int scaledVol;
 
326
    int scaledVolIncr;
 
327
    int scaledVolLimit;
 
328
    int count;
 
329
    int releaseCount;
 
330
    short int *leftSamples;
 
331
    short int *rightSamples;
 
332
    int lastSample;
 
333
    int loopEnd;
 
334
    int scaledLoopLength;
 
335
    int scaledIndex;
 
336
    int scaledIndexIncr;
 
337
 
 
338
        rcvr = stackValue(5);
 
339
        n = stackIntegerValue(4);
 
340
        aSoundBuffer = arrayValueOf(stackValue(3));
 
341
        aSoundBuffer -= 1;
 
342
        startIndex = stackIntegerValue(2);
 
343
        leftVol = stackIntegerValue(1);
 
344
        rightVol = stackIntegerValue(0);
 
345
        scaledVol = fetchIntegerofObject(3, rcvr);
 
346
        scaledVolIncr = fetchIntegerofObject(4, rcvr);
 
347
        scaledVolLimit = fetchIntegerofObject(5, rcvr);
 
348
        count = fetchIntegerofObject(7, rcvr);
 
349
        releaseCount = fetchIntegerofObject(8, rcvr);
 
350
        leftSamples = fetchArrayofObject(10, rcvr);
 
351
        leftSamples -= 1;
 
352
        rightSamples = fetchArrayofObject(11, rcvr);
 
353
        rightSamples -= 1;
 
354
        lastSample = fetchIntegerofObject(16, rcvr);
 
355
        loopEnd = fetchIntegerofObject(17, rcvr);
 
356
        scaledLoopLength = fetchIntegerofObject(18, rcvr);
 
357
        scaledIndex = fetchIntegerofObject(19, rcvr);
 
358
        scaledIndexIncr = fetchIntegerofObject(20, rcvr);
 
359
        if (!(successFlag)) {
 
360
                return null;
 
361
        }
 
362
        isInStereo = leftSamples != rightSamples;
 
363
        compositeLeftVol = ((int) (leftVol * scaledVol) >> 15);
 
364
        compositeRightVol = ((int) (rightVol * scaledVol) >> 15);
 
365
        i = (2 * startIndex) - 1;
 
366
        lastIndex = (startIndex + n) - 1;
 
367
        for (sliceIndex = startIndex; sliceIndex <= lastIndex; sliceIndex += 1) {
 
368
                sampleIndex = ((int) (scaledIndex += scaledIndexIncr) >> 9);
 
369
                if ((sampleIndex > loopEnd) && (count > releaseCount)) {
 
370
                        sampleIndex = ((int) (scaledIndex -= scaledLoopLength) >> 9);
 
371
                }
 
372
                if ((nextSampleIndex = sampleIndex + 1) > lastSample) {
 
373
                        if (sampleIndex > lastSample) {
 
374
                                count = 0;
 
375
                                if (!(successFlag)) {
 
376
                                        return null;
 
377
                                }
 
378
                                storeIntegerofObjectwithValue(3, rcvr, scaledVol);
 
379
                                storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr);
 
380
                                storeIntegerofObjectwithValue(7, rcvr, count);
 
381
                                storeIntegerofObjectwithValue(19, rcvr, scaledIndex);
 
382
                                pop(6);
 
383
                                pushInteger(null);
 
384
                                return null;
 
385
                        }
 
386
                        if (scaledLoopLength == 0) {
 
387
                                nextSampleIndex = sampleIndex;
 
388
                        } else {
 
389
                                nextSampleIndex = (((int) (scaledIndex - scaledLoopLength) >> 9)) + 1;
 
390
                        }
 
391
                }
 
392
                m = scaledIndex & LoopIndexFractionMask;
 
393
                rightVal = leftVal = ((int) (((leftSamples[sampleIndex]) * (LoopIndexScaleFactor - m)) + ((leftSamples[nextSampleIndex]) * m)) >> 9);
 
394
                if (isInStereo) {
 
395
                        rightVal = ((int) (((rightSamples[sampleIndex]) * (LoopIndexScaleFactor - m)) + ((rightSamples[nextSampleIndex]) * m)) >> 9);
 
396
                }
 
397
                if (leftVol > 0) {
 
398
                        s = (aSoundBuffer[i]) + (((int) (compositeLeftVol * leftVal) >> 15));
 
399
                        if (s > 32767) {
 
400
                                s = 32767;
 
401
                        }
 
402
                        if (s < -32767) {
 
403
                                s = -32767;
 
404
                        }
 
405
                        aSoundBuffer[i] = s;
 
406
                }
 
407
                i += 1;
 
408
                if (rightVol > 0) {
 
409
                        s = (aSoundBuffer[i]) + (((int) (compositeRightVol * rightVal) >> 15));
 
410
                        if (s > 32767) {
 
411
                                s = 32767;
 
412
                        }
 
413
                        if (s < -32767) {
 
414
                                s = -32767;
 
415
                        }
 
416
                        aSoundBuffer[i] = s;
 
417
                }
 
418
                i += 1;
 
419
                if (scaledVolIncr != 0) {
 
420
                        scaledVol += scaledVolIncr;
 
421
                        if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) {
 
422
                                scaledVol = scaledVolLimit;
 
423
                                scaledVolIncr = 0;
 
424
                        }
 
425
                        compositeLeftVol = ((int) (leftVol * scaledVol) >> 15);
 
426
                        compositeRightVol = ((int) (rightVol * scaledVol) >> 15);
 
427
                }
 
428
        }
 
429
        count -= n;
 
430
        if (!(successFlag)) {
 
431
                return null;
 
432
        }
 
433
        storeIntegerofObjectwithValue(3, rcvr, scaledVol);
 
434
        storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr);
 
435
        storeIntegerofObjectwithValue(7, rcvr, count);
 
436
        storeIntegerofObjectwithValue(19, rcvr, scaledIndex);
 
437
        pop(5);
 
438
}
 
439
 
 
440
 
 
441
/*      The Karplus-Strong plucked string algorithm: start with a buffer full of random noise and repeatedly play the contents of that buffer while averaging adjacent samples. High harmonics damp out more quickly, transfering their energy to lower ones. The length of the buffer corresponds to the length of the string. */
 
442
/*      (PluckedSound pitch: 220.0 dur: 6.0 loudness: 0.8) play */
 
443
 
 
444
EXPORT(int) primitiveMixPluckedSound(void) {
 
445
    int rcvr;
 
446
    int n;
 
447
    short int *aSoundBuffer;
 
448
    int startIndex;
 
449
    int leftVol;
 
450
    int rightVol;
 
451
    int sliceIndex;
 
452
    int i;
 
453
    int s;
 
454
    int lastIndex;
 
455
    int average;
 
456
    int scaledThisIndex;
 
457
    int scaledNextIndex;
 
458
    int sample;
 
459
    int scaledVol;
 
460
    int scaledVolIncr;
 
461
    int scaledVolLimit;
 
462
    int count;
 
463
    short int *ring;
 
464
    int scaledIndex;
 
465
    int scaledIndexIncr;
 
466
    int scaledIndexLimit;
 
467
 
 
468
        rcvr = stackValue(5);
 
469
        n = stackIntegerValue(4);
 
470
        aSoundBuffer = arrayValueOf(stackValue(3));
 
471
        aSoundBuffer -= 1;
 
472
        startIndex = stackIntegerValue(2);
 
473
        leftVol = stackIntegerValue(1);
 
474
        rightVol = stackIntegerValue(0);
 
475
        scaledVol = fetchIntegerofObject(3, rcvr);
 
476
        scaledVolIncr = fetchIntegerofObject(4, rcvr);
 
477
        scaledVolLimit = fetchIntegerofObject(5, rcvr);
 
478
        count = fetchIntegerofObject(7, rcvr);
 
479
        ring = fetchArrayofObject(8, rcvr);
 
480
        ring -= 1;
 
481
        scaledIndex = fetchIntegerofObject(9, rcvr);
 
482
        scaledIndexIncr = fetchIntegerofObject(10, rcvr);
 
483
        scaledIndexLimit = fetchIntegerofObject(11, rcvr);
 
484
        if (!(successFlag)) {
 
485
                return null;
 
486
        }
 
487
        lastIndex = (startIndex + n) - 1;
 
488
        scaledThisIndex = scaledNextIndex = scaledIndex;
 
489
        for (sliceIndex = startIndex; sliceIndex <= lastIndex; sliceIndex += 1) {
 
490
                scaledNextIndex = scaledThisIndex + scaledIndexIncr;
 
491
                if (scaledNextIndex >= scaledIndexLimit) {
 
492
                        scaledNextIndex = ScaleFactor + (scaledNextIndex - scaledIndexLimit);
 
493
                }
 
494
                average = ((int) ((ring[((int) scaledThisIndex >> 15)]) + (ring[((int) scaledNextIndex >> 15)])) >> 1);
 
495
                ring[((int) scaledThisIndex >> 15)] = average;
 
496
 
 
497
                /* scale by volume */
 
498
 
 
499
                sample = ((int) (average * scaledVol) >> 15);
 
500
                scaledThisIndex = scaledNextIndex;
 
501
                if (leftVol > 0) {
 
502
                        i = (2 * sliceIndex) - 1;
 
503
                        s = (aSoundBuffer[i]) + (((int) (sample * leftVol) >> 15));
 
504
                        if (s > 32767) {
 
505
                                s = 32767;
 
506
                        }
 
507
                        if (s < -32767) {
 
508
                                s = -32767;
 
509
                        }
 
510
                        aSoundBuffer[i] = s;
 
511
                }
 
512
                if (rightVol > 0) {
 
513
                        i = 2 * sliceIndex;
 
514
                        s = (aSoundBuffer[i]) + (((int) (sample * rightVol) >> 15));
 
515
                        if (s > 32767) {
 
516
                                s = 32767;
 
517
                        }
 
518
                        if (s < -32767) {
 
519
                                s = -32767;
 
520
                        }
 
521
                        aSoundBuffer[i] = s;
 
522
                }
 
523
                if (scaledVolIncr != 0) {
 
524
                        scaledVol += scaledVolIncr;
 
525
                        if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) {
 
526
                                scaledVol = scaledVolLimit;
 
527
                                scaledVolIncr = 0;
 
528
                        }
 
529
                }
 
530
        }
 
531
        scaledIndex = scaledNextIndex;
 
532
        count -= n;
 
533
        if (!(successFlag)) {
 
534
                return null;
 
535
        }
 
536
        storeIntegerofObjectwithValue(3, rcvr, scaledVol);
 
537
        storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr);
 
538
        storeIntegerofObjectwithValue(7, rcvr, count);
 
539
        storeIntegerofObjectwithValue(9, rcvr, scaledIndex);
 
540
        pop(5);
 
541
}
 
542
 
 
543
 
 
544
/*      Mix the given number of samples with the samples already in the given buffer starting at the given index. Assume that the buffer size is at least (index + count) - 1. */
 
545
 
 
546
EXPORT(int) primitiveMixSampledSound(void) {
 
547
    int rcvr;
 
548
    int n;
 
549
    short int *aSoundBuffer;
 
550
    int startIndex;
 
551
    int leftVol;
 
552
    int rightVol;
 
553
    int outIndex;
 
554
    int i;
 
555
    int s;
 
556
    int lastIndex;
 
557
    int sampleIndex;
 
558
    int sample;
 
559
    int overflow;
 
560
    int scaledVol;
 
561
    int scaledVolIncr;
 
562
    int scaledVolLimit;
 
563
    int count;
 
564
    short int *samples;
 
565
    int samplesSize;
 
566
    int scaledIndex;
 
567
    int indexHighBits;
 
568
    int scaledIncrement;
 
569
 
 
570
        rcvr = stackValue(5);
 
571
        n = stackIntegerValue(4);
 
572
        aSoundBuffer = arrayValueOf(stackValue(3));
 
573
        aSoundBuffer -= 1;
 
574
        startIndex = stackIntegerValue(2);
 
575
        leftVol = stackIntegerValue(1);
 
576
        rightVol = stackIntegerValue(0);
 
577
        scaledVol = fetchIntegerofObject(3, rcvr);
 
578
        scaledVolIncr = fetchIntegerofObject(4, rcvr);
 
579
        scaledVolLimit = fetchIntegerofObject(5, rcvr);
 
580
        count = fetchIntegerofObject(7, rcvr);
 
581
        samples = fetchArrayofObject(8, rcvr);
 
582
        samples -= 1;
 
583
        samplesSize = fetchIntegerofObject(10, rcvr);
 
584
        scaledIndex = fetchIntegerofObject(11, rcvr);
 
585
        indexHighBits = fetchIntegerofObject(12, rcvr);
 
586
        scaledIncrement = fetchIntegerofObject(13, rcvr);
 
587
        if (!(successFlag)) {
 
588
                return null;
 
589
        }
 
590
        lastIndex = (startIndex + n) - 1;
 
591
 
 
592
        /* index of next stereo output sample pair */
 
593
 
 
594
        outIndex = startIndex;
 
595
        sampleIndex = indexHighBits + (((unsigned) scaledIndex) >> IncrementFractionBits);
 
596
        while ((sampleIndex <= samplesSize) && (outIndex <= lastIndex)) {
 
597
                sample = ((int) ((samples[sampleIndex]) * scaledVol) >> 15);
 
598
                if (leftVol > 0) {
 
599
                        i = (2 * outIndex) - 1;
 
600
                        s = (aSoundBuffer[i]) + (((int) (sample * leftVol) >> 15));
 
601
                        if (s > 32767) {
 
602
                                s = 32767;
 
603
                        }
 
604
                        if (s < -32767) {
 
605
                                s = -32767;
 
606
                        }
 
607
                        aSoundBuffer[i] = s;
 
608
                }
 
609
                if (rightVol > 0) {
 
610
                        i = 2 * outIndex;
 
611
                        s = (aSoundBuffer[i]) + (((int) (sample * rightVol) >> 15));
 
612
                        if (s > 32767) {
 
613
                                s = 32767;
 
614
                        }
 
615
                        if (s < -32767) {
 
616
                                s = -32767;
 
617
                        }
 
618
                        aSoundBuffer[i] = s;
 
619
                }
 
620
                if (scaledVolIncr != 0) {
 
621
                        scaledVol += scaledVolIncr;
 
622
                        if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) {
 
623
                                scaledVol = scaledVolLimit;
 
624
                                scaledVolIncr = 0;
 
625
                        }
 
626
                }
 
627
                scaledIndex += scaledIncrement;
 
628
                if (scaledIndex >= ScaledIndexOverflow) {
 
629
                        overflow = ((unsigned) scaledIndex) >> IncrementFractionBits;
 
630
                        indexHighBits += overflow;
 
631
                        scaledIndex -= overflow << IncrementFractionBits;
 
632
                }
 
633
                sampleIndex = indexHighBits + (((unsigned) scaledIndex) >> IncrementFractionBits);
 
634
                outIndex += 1;
 
635
        }
 
636
        count -= n;
 
637
        if (!(successFlag)) {
 
638
                return null;
 
639
        }
 
640
        storeIntegerofObjectwithValue(3, rcvr, scaledVol);
 
641
        storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr);
 
642
        storeIntegerofObjectwithValue(7, rcvr, count);
 
643
        storeIntegerofObjectwithValue(11, rcvr, scaledIndex);
 
644
        storeIntegerofObjectwithValue(12, rcvr, indexHighBits);
 
645
        pop(5);
 
646
}
 
647
 
 
648
 
 
649
/*      Note: This is coded so that is can be run from Squeak. */
 
650
 
 
651
EXPORT(int) setInterpreter(struct VirtualMachine* anInterpreter) {
 
652
    int ok;
 
653
 
 
654
        interpreterProxy = anInterpreter;
 
655
        ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
 
656
        if (ok == 0) {
 
657
                return 0;
 
658
        }
 
659
        ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
 
660
        return ok;
 
661
}
 
662
 
 
663
 
 
664
#ifdef SQUEAK_BUILTIN_PLUGIN
 
665
 
 
666
 
 
667
void* SoundGenerationPlugin_exports[][3] = {
 
668
        {"SoundGenerationPlugin", "primitiveMixFMSound", (void*)primitiveMixFMSound},
 
669
        {"SoundGenerationPlugin", "primitiveMixLoopedSampledSound", (void*)primitiveMixLoopedSampledSound},
 
670
        {"SoundGenerationPlugin", "primitiveMixPluckedSound", (void*)primitiveMixPluckedSound},
 
671
        {"SoundGenerationPlugin", "primitiveMixSampledSound", (void*)primitiveMixSampledSound},
 
672
        {"SoundGenerationPlugin", "getModuleName", (void*)getModuleName},
 
673
        {"SoundGenerationPlugin", "primitiveApplyReverb", (void*)primitiveApplyReverb},
 
674
        {"SoundGenerationPlugin", "setInterpreter", (void*)setInterpreter},
 
675
        {NULL, NULL, NULL}
 
676
};
 
677
 
 
678
 
 
679
#endif /* ifdef SQ_BUILTIN_PLUGIN */
 
680