/* Automatically generated from Squeak on #(21 October 2001 9:18:25 pm) */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* Default EXPORT macro that does nothing (see comment in sq.h): */
#define EXPORT(returnType) returnType

/* Do not include the entire sq.h file but just those parts needed. */
/*  The virtual machine proxy definition */
#include "sqVirtualMachine.h"
/* Configuration options */
#include "sqConfig.h"
/* Platform specific definitions */
#include "sqPlatformSpecific.h"

#define true 1
#define false 0
#define null 0  /* using 'null' because nil is predefined in Think C */


#include "SoundGenerationPlugin.h"

/* Memory Access Macros */
#define byteAt(i) (*((unsigned char *) (i)))
#define byteAtput(i, val) (*((unsigned char *) (i)) = val)
#define longAt(i) (*((int *) (i)))
#define longAtput(i, val) (*((int *) (i)) = val)

/*** Proxy Functions ***/
#define stackValue(i) (interpreterProxy->stackValue(i))
#define stackIntegerValue(i) (interpreterProxy->stackIntegerValue(i))
#define successFlag (!interpreterProxy->failed())
#define success(bool) (interpreterProxy->success(bool))
#define arrayValueOf(oop) (interpreterProxy->arrayValueOf(oop))
#define checkedIntegerValueOf(oop) (interpreterProxy->checkedIntegerValueOf(oop))
#define fetchArrayofObject(idx,oop) (interpreterProxy->fetchArrayofObject(idx,oop))
#define fetchFloatofObject(idx,oop) (interpreterProxy->fetchFloatofObject(idx,oop))
#define fetchIntegerofObject(idx,oop) (interpreterProxy->fetchIntegerofObject(idx,oop))
#define floatValueOf(oop) (interpreterProxy->floatValueOf(oop))
#define pop(n) (interpreterProxy->pop(n))
#define pushInteger(n) (interpreterProxy->pushInteger(n))
#define sizeOfSTArrayFromCPrimitive(cPtr) (interpreterProxy->sizeOfSTArrayFromCPrimitive(cPtr))
#define storeIntegerofObjectwithValue(idx,oop,value) (interpreterProxy->storeIntegerofObjectwithValue(idx,oop,value))
#define primitiveFail() interpreterProxy->primitiveFail()
/* allows accessing Strings in both C and Smalltalk */
#define asciiValue(c) c


/*** Variables ***/
static struct VirtualMachine* interpreterProxy;
static const char *moduleName = "SoundGenerationPlugin 21 October 2001 (i)";

/*** Function Prototypes ***/
#pragma export on
EXPORT(const char*) SoundGenerationPlugin_getModuleName(void);
EXPORT(int) SoundGenerationPlugin_primitiveApplyReverb(void);
EXPORT(int) SoundGenerationPlugin_primitiveFMSoundMix(void);
EXPORT(int) SoundGenerationPlugin_primitiveMixFMSound(void);
EXPORT(int) SoundGenerationPlugin_primitiveMixLoopedSampledSound(void);
EXPORT(int) SoundGenerationPlugin_primitiveMixPluckedSound(void);
EXPORT(int) SoundGenerationPlugin_primitiveMixSampledSound(void);
EXPORT(int) SoundGenerationPlugin_primitiveOldSampledSoundMix(void);
EXPORT(int) SoundGenerationPlugin_primitivePluckedSoundMix(void);
EXPORT(int) SoundGenerationPlugin_primitiveSampledSoundMix(void);
EXPORT(int) SoundGenerationPlugin_primitiveWaveTableSoundMix(void);
EXPORT(int) SoundGenerationPlugin_setInterpreter(struct VirtualMachine* anInterpreter);
#pragma export off


/*	Note: This is hardcoded so it can be run from Squeak.
	The module name is used for validating a module *after*
	it is loaded to check if it does really contain the module
	we're thinking it contains. This is important! */

EXPORT(const char*) SoundGenerationPlugin_getModuleName(void) {
	return moduleName;
}

EXPORT(int) SoundGenerationPlugin_primitiveApplyReverb(void) {
    int rcvr;
    short int *aSoundBuffer;
    int startIndex;
    int n;
    int sliceIndex;
    int delayedLeft;
    int out;
    int tapGain;
    int i;
    int delayedRight;
    int j;
    int tapIndex;
    int *tapDelays;
    int *tapGains;
    int tapCount;
    int bufferSize;
    int bufferIndex;
    short int *leftBuffer;
    short int *rightBuffer;

	rcvr = stackValue(3);
	aSoundBuffer = arrayValueOf(stackValue(2));
	aSoundBuffer -= 1;
	startIndex = stackIntegerValue(1);
	n = stackIntegerValue(0);
	tapDelays = fetchArrayofObject(7, rcvr);
	tapDelays -= 1;
	tapGains = fetchArrayofObject(8, rcvr);
	tapGains -= 1;
	tapCount = fetchIntegerofObject(9, rcvr);
	bufferSize = fetchIntegerofObject(10, rcvr);
	bufferIndex = fetchIntegerofObject(11, rcvr);
	leftBuffer = fetchArrayofObject(12, rcvr);
	leftBuffer -= 1;
	rightBuffer = fetchArrayofObject(13, rcvr);
	rightBuffer -= 1;
	if (!(successFlag)) {
		return null;
	}
	for (sliceIndex = startIndex; sliceIndex <= ((startIndex + n) - 1); sliceIndex += 1) {
		delayedLeft = delayedRight = 0;
		for (tapIndex = 1; tapIndex <= tapCount; tapIndex += 1) {
			i = bufferIndex - (tapDelays[tapIndex]);
			if (i < 1) {
				i += bufferSize;
			}
			tapGain = tapGains[tapIndex];
			delayedLeft += tapGain * (leftBuffer[i]);
			delayedRight += tapGain * (rightBuffer[i]);
		}
		j = (2 * sliceIndex) - 1;
		out = (aSoundBuffer[j]) + (((int) delayedLeft >> 15));
		if (out > 32767) {
			out = 32767;
		}
		if (out < -32767) {
			out = -32767;
		}
		aSoundBuffer[j] = out;
		leftBuffer[bufferIndex] = out;
		j += 1;
		out = (aSoundBuffer[j]) + (((int) delayedRight >> 15));
		if (out > 32767) {
			out = 32767;
		}
		if (out < -32767) {
			out = -32767;
		}
		aSoundBuffer[j] = out;
		rightBuffer[bufferIndex] = out;
		bufferIndex = (bufferIndex % bufferSize) + 1;
	}
	if (!(successFlag)) {
		return null;
	}
	storeIntegerofObjectwithValue(11, rcvr, bufferIndex);
	pop(3);
}

EXPORT(int) SoundGenerationPlugin_primitiveFMSoundMix(void) {
	return primFMSoundmixSampleCountintostartingAtpan();
}


/*	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. */
/*	(FMSound pitch: 440.0 dur: 1.0 loudness: 0.5) play */

EXPORT(int) SoundGenerationPlugin_primitiveMixFMSound(void) {
    int rcvr;
    int n;
    short int *aSoundBuffer;
    int startIndex;
    int leftVol;
    int rightVol;
    int lastIndex;
    int sliceIndex;
    int doingFM;
    int i;
    int offset;
    int s;
    int sample;
    int scaledVol;
    int scaledVolIncr;
    int scaledVolLimit;
    int count;
    short int *waveTable;
    int scaledWaveTableSize;
    int scaledIndex;
    int scaledIndexIncr;
    int normalizedModulation;
    int scaledOffsetIndex;
    int scaledOffsetIndexIncr;

	rcvr = stackValue(5);
	n = stackIntegerValue(4);
	aSoundBuffer = arrayValueOf(stackValue(3));
	aSoundBuffer -= 1;
	startIndex = stackIntegerValue(2);
	leftVol = stackIntegerValue(1);
	rightVol = stackIntegerValue(0);
	scaledVol = fetchIntegerofObject(3, rcvr);
	scaledVolIncr = fetchIntegerofObject(4, rcvr);
	scaledVolLimit = fetchIntegerofObject(5, rcvr);
	count = fetchIntegerofObject(7, rcvr);
	waveTable = fetchArrayofObject(8, rcvr);
	waveTable -= 1;
	scaledWaveTableSize = fetchIntegerofObject(9, rcvr);
	scaledIndex = fetchIntegerofObject(10, rcvr);
	scaledIndexIncr = fetchIntegerofObject(11, rcvr);
	normalizedModulation = fetchIntegerofObject(14, rcvr);
	scaledOffsetIndex = fetchIntegerofObject(15, rcvr);
	scaledOffsetIndexIncr = fetchIntegerofObject(16, rcvr);
	if (!(successFlag)) {
		return null;
	}
	doingFM = (normalizedModulation != 0) && (scaledOffsetIndexIncr != 0);
	lastIndex = (startIndex + n) - 1;
	for (sliceIndex = startIndex; sliceIndex <= lastIndex; sliceIndex += 1) {
		sample = ((int) (scaledVol * (waveTable[(((int) scaledIndex >> 15)) + 1])) >> 15);
		if (doingFM) {
			offset = normalizedModulation * (waveTable[(((int) scaledOffsetIndex >> 15)) + 1]);
			scaledOffsetIndex = (scaledOffsetIndex + scaledOffsetIndexIncr) % scaledWaveTableSize;
			if (scaledOffsetIndex < 0) {
				scaledOffsetIndex += scaledWaveTableSize;
			}
			scaledIndex = ((scaledIndex + scaledIndexIncr) + offset) % scaledWaveTableSize;
			if (scaledIndex < 0) {
				scaledIndex += scaledWaveTableSize;
			}
		} else {
			scaledIndex = (scaledIndex + scaledIndexIncr) % scaledWaveTableSize;
		}
		if (leftVol > 0) {
			i = (2 * sliceIndex) - 1;
			s = (aSoundBuffer[i]) + (((int) (sample * leftVol) >> 15));
			if (s > 32767) {
				s = 32767;
			}
			if (s < -32767) {
				s = -32767;
			}
			aSoundBuffer[i] = s;
		}
		if (rightVol > 0) {
			i = 2 * sliceIndex;
			s = (aSoundBuffer[i]) + (((int) (sample * rightVol) >> 15));
			if (s > 32767) {
				s = 32767;
			}
			if (s < -32767) {
				s = -32767;
			}
			aSoundBuffer[i] = s;
		}
		if (scaledVolIncr != 0) {
			scaledVol += scaledVolIncr;
			if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) {
				scaledVol = scaledVolLimit;
				scaledVolIncr = 0;
			}
		}
	}
	count -= n;
	if (!(successFlag)) {
		return null;
	}
	storeIntegerofObjectwithValue(3, rcvr, scaledVol);
	storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr);
	storeIntegerofObjectwithValue(7, rcvr, count);
	storeIntegerofObjectwithValue(10, rcvr, scaledIndex);
	storeIntegerofObjectwithValue(15, rcvr, scaledOffsetIndex);
	pop(5);
}


/*	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. */
/*	(LoopedSampledSound pitch: 440.0 dur: 5.0 loudness: 0.5) play */

EXPORT(int) SoundGenerationPlugin_primitiveMixLoopedSampledSound(void) {
    int rcvr;
    int n;
    short int *aSoundBuffer;
    int startIndex;
    int leftVol;
    int rightVol;
    int compositeLeftVol;
    int lastIndex;
    int sampleIndex;
    int sliceIndex;
    int i;
    int isInStereo;
    int m;
    int leftVal;
    int nextSampleIndex;
    int compositeRightVol;
    int s;
    int rightVal;
    int scaledVol;
    int scaledVolIncr;
    int scaledVolLimit;
    int count;
    int releaseCount;
    short int *leftSamples;
    short int *rightSamples;
    int lastSample;
    int loopEnd;
    int scaledLoopLength;
    int scaledIndex;
    int scaledIndexIncr;

	rcvr = stackValue(5);
	n = stackIntegerValue(4);
	aSoundBuffer = arrayValueOf(stackValue(3));
	aSoundBuffer -= 1;
	startIndex = stackIntegerValue(2);
	leftVol = stackIntegerValue(1);
	rightVol = stackIntegerValue(0);
	scaledVol = fetchIntegerofObject(3, rcvr);
	scaledVolIncr = fetchIntegerofObject(4, rcvr);
	scaledVolLimit = fetchIntegerofObject(5, rcvr);
	count = fetchIntegerofObject(7, rcvr);
	releaseCount = fetchIntegerofObject(8, rcvr);
	leftSamples = fetchArrayofObject(10, rcvr);
	leftSamples -= 1;
	rightSamples = fetchArrayofObject(11, rcvr);
	rightSamples -= 1;
	lastSample = fetchIntegerofObject(16, rcvr);
	loopEnd = fetchIntegerofObject(17, rcvr);
	scaledLoopLength = fetchIntegerofObject(18, rcvr);
	scaledIndex = fetchIntegerofObject(19, rcvr);
	scaledIndexIncr = fetchIntegerofObject(20, rcvr);
	if (!(successFlag)) {
		return null;
	}
	isInStereo = leftSamples != rightSamples;
	compositeLeftVol = ((int) (leftVol * scaledVol) >> 15);
	compositeRightVol = ((int) (rightVol * scaledVol) >> 15);
	i = (2 * startIndex) - 1;
	lastIndex = (startIndex + n) - 1;
	for (sliceIndex = startIndex; sliceIndex <= lastIndex; sliceIndex += 1) {
		sampleIndex = ((int) (scaledIndex += scaledIndexIncr) >> 9);
		if ((sampleIndex > loopEnd) && (count > releaseCount)) {
			sampleIndex = ((int) (scaledIndex -= scaledLoopLength) >> 9);
		}
		if ((nextSampleIndex = sampleIndex + 1) > lastSample) {
			if (sampleIndex > lastSample) {
				count = 0;
				if (!(successFlag)) {
					return null;
				}
				storeIntegerofObjectwithValue(3, rcvr, scaledVol);
				storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr);
				storeIntegerofObjectwithValue(7, rcvr, count);
				storeIntegerofObjectwithValue(19, rcvr, scaledIndex);
				pop(6);
				pushInteger(null);
				return null;
			}
			if (scaledLoopLength == 0) {
				nextSampleIndex = sampleIndex;
			} else {
				nextSampleIndex = (((int) (scaledIndex - scaledLoopLength) >> 9)) + 1;
			}
		}
		m = scaledIndex & 511;
		rightVal = leftVal = ((int) (((leftSamples[sampleIndex]) * (512 - m)) + ((leftSamples[nextSampleIndex]) * m)) >> 9);
		if (isInStereo) {
			rightVal = ((int) (((rightSamples[sampleIndex]) * (512 - m)) + ((rightSamples[nextSampleIndex]) * m)) >> 9);
		}
		if (leftVol > 0) {
			s = (aSoundBuffer[i]) + (((int) (compositeLeftVol * leftVal) >> 15));
			if (s > 32767) {
				s = 32767;
			}
			if (s < -32767) {
				s = -32767;
			}
			aSoundBuffer[i] = s;
		}
		i += 1;
		if (rightVol > 0) {
			s = (aSoundBuffer[i]) + (((int) (compositeRightVol * rightVal) >> 15));
			if (s > 32767) {
				s = 32767;
			}
			if (s < -32767) {
				s = -32767;
			}
			aSoundBuffer[i] = s;
		}
		i += 1;
		if (scaledVolIncr != 0) {
			scaledVol += scaledVolIncr;
			if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) {
				scaledVol = scaledVolLimit;
				scaledVolIncr = 0;
			}
			compositeLeftVol = ((int) (leftVol * scaledVol) >> 15);
			compositeRightVol = ((int) (rightVol * scaledVol) >> 15);
		}
	}
	count -= n;
	if (!(successFlag)) {
		return null;
	}
	storeIntegerofObjectwithValue(3, rcvr, scaledVol);
	storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr);
	storeIntegerofObjectwithValue(7, rcvr, count);
	storeIntegerofObjectwithValue(19, rcvr, scaledIndex);
	pop(5);
}


/*	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. */
/*	(PluckedSound pitch: 220.0 dur: 6.0 loudness: 0.8) play */

EXPORT(int) SoundGenerationPlugin_primitiveMixPluckedSound(void) {
    int rcvr;
    int n;
    short int *aSoundBuffer;
    int startIndex;
    int leftVol;
    int rightVol;
    int lastIndex;
    int sliceIndex;
    int scaledNextIndex;
    int i;
    int average;
    int s;
    int scaledThisIndex;
    int sample;
    int scaledVol;
    int scaledVolIncr;
    int scaledVolLimit;
    int count;
    short int *ring;
    int scaledIndex;
    int scaledIndexIncr;
    int scaledIndexLimit;

	rcvr = stackValue(5);
	n = stackIntegerValue(4);
	aSoundBuffer = arrayValueOf(stackValue(3));
	aSoundBuffer -= 1;
	startIndex = stackIntegerValue(2);
	leftVol = stackIntegerValue(1);
	rightVol = stackIntegerValue(0);
	scaledVol = fetchIntegerofObject(3, rcvr);
	scaledVolIncr = fetchIntegerofObject(4, rcvr);
	scaledVolLimit = fetchIntegerofObject(5, rcvr);
	count = fetchIntegerofObject(7, rcvr);
	ring = fetchArrayofObject(8, rcvr);
	ring -= 1;
	scaledIndex = fetchIntegerofObject(9, rcvr);
	scaledIndexIncr = fetchIntegerofObject(10, rcvr);
	scaledIndexLimit = fetchIntegerofObject(11, rcvr);
	if (!(successFlag)) {
		return null;
	}
	lastIndex = (startIndex + n) - 1;
	scaledThisIndex = scaledNextIndex = scaledIndex;
	for (sliceIndex = startIndex; sliceIndex <= lastIndex; sliceIndex += 1) {
		scaledNextIndex = scaledThisIndex + scaledIndexIncr;
		if (scaledNextIndex >= scaledIndexLimit) {
			scaledNextIndex = 32768 + (scaledNextIndex - scaledIndexLimit);
		}
		average = ((int) ((ring[((int) scaledThisIndex >> 15)]) + (ring[((int) scaledNextIndex >> 15)])) >> 1);
		ring[((int) scaledThisIndex >> 15)] = average;

		/* scale by volume */

		sample = ((int) (average * scaledVol) >> 15);
		scaledThisIndex = scaledNextIndex;
		if (leftVol > 0) {
			i = (2 * sliceIndex) - 1;
			s = (aSoundBuffer[i]) + (((int) (sample * leftVol) >> 15));
			if (s > 32767) {
				s = 32767;
			}
			if (s < -32767) {
				s = -32767;
			}
			aSoundBuffer[i] = s;
		}
		if (rightVol > 0) {
			i = 2 * sliceIndex;
			s = (aSoundBuffer[i]) + (((int) (sample * rightVol) >> 15));
			if (s > 32767) {
				s = 32767;
			}
			if (s < -32767) {
				s = -32767;
			}
			aSoundBuffer[i] = s;
		}
		if (scaledVolIncr != 0) {
			scaledVol += scaledVolIncr;
			if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) {
				scaledVol = scaledVolLimit;
				scaledVolIncr = 0;
			}
		}
	}
	scaledIndex = scaledNextIndex;
	count -= n;
	if (!(successFlag)) {
		return null;
	}
	storeIntegerofObjectwithValue(3, rcvr, scaledVol);
	storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr);
	storeIntegerofObjectwithValue(7, rcvr, count);
	storeIntegerofObjectwithValue(9, rcvr, scaledIndex);
	pop(5);
}


/*	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. */

EXPORT(int) SoundGenerationPlugin_primitiveMixSampledSound(void) {
    int rcvr;
    int n;
    short int *aSoundBuffer;
    int startIndex;
    int leftVol;
    int rightVol;
    int lastIndex;
    int sampleIndex;
    int overflow;
    int outIndex;
    int i;
    int s;
    int sample;
    int scaledVol;
    int scaledVolIncr;
    int scaledVolLimit;
    int count;
    short int *samples;
    int samplesSize;
    int scaledIndex;
    int indexHighBits;
    int scaledIncrement;

	rcvr = stackValue(5);
	n = stackIntegerValue(4);
	aSoundBuffer = arrayValueOf(stackValue(3));
	aSoundBuffer -= 1;
	startIndex = stackIntegerValue(2);
	leftVol = stackIntegerValue(1);
	rightVol = stackIntegerValue(0);
	scaledVol = fetchIntegerofObject(3, rcvr);
	scaledVolIncr = fetchIntegerofObject(4, rcvr);
	scaledVolLimit = fetchIntegerofObject(5, rcvr);
	count = fetchIntegerofObject(7, rcvr);
	samples = fetchArrayofObject(8, rcvr);
	samples -= 1;
	samplesSize = fetchIntegerofObject(10, rcvr);
	scaledIndex = fetchIntegerofObject(11, rcvr);
	indexHighBits = fetchIntegerofObject(12, rcvr);
	scaledIncrement = fetchIntegerofObject(13, rcvr);
	if (!(successFlag)) {
		return null;
	}
	lastIndex = (startIndex + n) - 1;

	/* index of next stereo output sample pair */

	outIndex = startIndex;
	sampleIndex = indexHighBits + (((unsigned) scaledIndex) >> 16);
	while ((sampleIndex <= samplesSize) && (outIndex <= lastIndex)) {
		sample = ((int) ((samples[sampleIndex]) * scaledVol) >> 15);
		if (leftVol > 0) {
			i = (2 * outIndex) - 1;
			s = (aSoundBuffer[i]) + (((int) (sample * leftVol) >> 15));
			if (s > 32767) {
				s = 32767;
			}
			if (s < -32767) {
				s = -32767;
			}
			aSoundBuffer[i] = s;
		}
		if (rightVol > 0) {
			i = 2 * outIndex;
			s = (aSoundBuffer[i]) + (((int) (sample * rightVol) >> 15));
			if (s > 32767) {
				s = 32767;
			}
			if (s < -32767) {
				s = -32767;
			}
			aSoundBuffer[i] = s;
		}
		if (scaledVolIncr != 0) {
			scaledVol += scaledVolIncr;
			if (((scaledVolIncr > 0) && (scaledVol >= scaledVolLimit)) || ((scaledVolIncr < 0) && (scaledVol <= scaledVolLimit))) {
				scaledVol = scaledVolLimit;
				scaledVolIncr = 0;
			}
		}
		scaledIndex += scaledIncrement;
		if (scaledIndex >= 536870912) {
			overflow = ((unsigned) scaledIndex) >> 16;
			indexHighBits += overflow;
			scaledIndex -= overflow << 16;
		}
		sampleIndex = indexHighBits + (((unsigned) scaledIndex) >> 16);
		outIndex += 1;
	}
	count -= n;
	if (!(successFlag)) {
		return null;
	}
	storeIntegerofObjectwithValue(3, rcvr, scaledVol);
	storeIntegerofObjectwithValue(4, rcvr, scaledVolIncr);
	storeIntegerofObjectwithValue(7, rcvr, count);
	storeIntegerofObjectwithValue(11, rcvr, scaledIndex);
	storeIntegerofObjectwithValue(12, rcvr, indexHighBits);
	pop(5);
}

EXPORT(int) SoundGenerationPlugin_primitiveOldSampledSoundMix(void) {
	return oldprimSampledSoundmixSampleCountintostartingAtleftVolrightVol();
}

EXPORT(int) SoundGenerationPlugin_primitivePluckedSoundMix(void) {
	return primPluckedSoundmixSampleCountintostartingAtpan();
}

EXPORT(int) SoundGenerationPlugin_primitiveSampledSoundMix(void) {
	return primSampledSoundmixSampleCountintostartingAtpan();
}

EXPORT(int) SoundGenerationPlugin_primitiveWaveTableSoundMix(void) {
	return primWaveTableSoundmixSampleCountintostartingAtpan();
}


/*	Note: This is coded so that is can be run from Squeak. */

EXPORT(int) SoundGenerationPlugin_setInterpreter(struct VirtualMachine* anInterpreter) {
    int ok;

	interpreterProxy = anInterpreter;
	ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
	if (ok == 0) {
		return 0;
	}
	ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
	return ok;
}
