/*
 * Sound.c
 *		User Primitive Code for MODE on Objectworks\Smalltalk R4
 *			Vector Arithmetic and sample crunching in C
 *
 * Copyright (C) 1991, Stephen Travis Pope, Nomad Computer Music Research.
 *		All rights reserved.
 *
 *			V4.0: File created: 8/24/91--stp
 */
#include "userprim.h"					/* Basic ST80 UP header */
#include "MODE_Primitives.h"		/* Declarations of MODE UP fcns */


int ModeIntSampleAt(/* upHandle uiBytes; int i */);
void ModeIntSampleAtPut(/* upHandle uiBytes; int i, sample */);


/*****************************************************/
/*		----SampledSound>>interpolating	*/
/*		maxFrom: aStart to: aStop	*/
/*			"Answer the max (or min) abs sample in the last argument."	*/
ModeMaxSampleInt(receiverSound, startSamp, stopSamp)
upHandle receiverSound, startSamp, stopSamp; {
	short sample, max;
	upHandle uiBytes;
	int start, stop, i;
	float tempF;

	ModeCheckSound(receiverSound, uiBytes)
	ModeCheckInt(startSamp, start);
	ModeCheckInt(stopSamp, stop);
	max = 0;
	for (i=start; i<=stop; i++) {
		sample = ModeIntSampleAt(uiBytes, i);
		if (abs(sample) > max) 
			max = abs(sample);
	}
	UPreturnHandle(UPCtoSTint(max));
}

/*		sampledFrom: aStart to: aStop into: aSound					*/
/*			"Place a down-sampled version of the receiver in the argument sound."		*/
ModeDownSampleInt(receiverSound, startSamp, stopSamp, resultSound)
upHandle receiverSound, startSamp, stopSamp, resultSound; {

}

/*		rmsFrom: aStart to: aStop into: anArray						*/
/*			"Place a version of the root-mean-square energy of the receiver in the array."	*/
ModeRMSSampleInt(receiverSound, startSamp, stopSamp, resultArray)
upHandle receiverSound, startSamp, stopSamp, resultArray; {

}

/*		----SampledSound>>merging								*/
/*		extractChannel: cNumber into: aSound		*/
/*			"Extract the given channel from the receiver into the argument sound."	*/
ModeExtractChannelInt(receiverSound, channelNum, resultSound)
upHandle receiverSound, channelNum, resultSound; {

}

/*		mergeChannel: cNumber from: aSound		*/
/*			"Merge the argument sound into the given channel of the receiver."		*/
ModeMergeChannelInt(receiverSound, channelNum, argumentSound)
upHandle receiverSound, channelNum, argumentSound; {

}

/*		----SampledSound>>envelopes			*/
/*		scaledFrom: aStart to: aStop by: aScaleFactor into: aSound		*/
/*			"Answer a copy of the receiver scaled by the given factor in the argument sound."	*/
ModeScaleSampleInt(receiverSound, startSamp, stopSamp, factorFloat, resultSound)
upHandle receiverSound, startSamp, stopSamp, factorFloat, resultSound; {
	short sample, max;
	upHandle uiBytes, resultBytes;
	int start, stop, iFactor, i;
	float fFactor;

	ModeCheckSound(receiverSound, uiBytes)
	ModeCheckInt(startSamp, start);
	ModeCheckInt(stopSamp, stop);
	ModeCheckFloat(factorFloat, fFactor);
	ModeCheckSound(resultSound, resultBytes)
	iFactor = (int) (fFactor * 32768);
	for (i=start; i<=stop; i++) {
		sample = ModeIntSampleAt(uiBytes, i);
		ModeIntSampleAtPut(resultBytes, i, (sample * iFactor));
	}
	UPreturnHandle(resultSound);
}

/*		scaledFrom: aStart to: aStop byBPEnvelope: anArrayOfPoints into: aSound		*/
/*			"Answer a copy of the receiver scaled by the given breakpoint	*/
/*			 envelope expressed as points in the argument sound."			*/
ModeEnvelopeSampleInt(receiverSound, startSamp, stopSamp, envelopePoints, resultSound)
upHandle receiverSound, startSamp, stopSamp, envelopePoints, resultSound; {

}

/*		scaledFrom: aStart to: aStop byEnvelopeArray: anArray into: aSound		*/
/*			"Answer a copy of the receiver scaled by the envelope array in the argument sound."*/
ModeMultiEnvelopeSampleInt(receiverSound, startSamp, stopSamp, envelopePoints, resultSound)
upHandle receiverSound, startSamp, stopSamp, envelopePoints, resultSound; {

}


/************************************
 *	Utility Routines
 ************************************/

/*
 *	ModeIntSampleAt/AtPut -- Sample accessing within uiBytes objects
 */
int ModeIntSampleAt(uiBytes, i) upHandle uiBytes; int i; {
	unsigned char b1, b2;
	upByte b1a, b2a;

	b1a = UPbyteAt(uiBytes, ((i*2)-1));
	b2a = UPbyteAt(uiBytes, (i*2));
	b1 = UPSTtoCbyte(b1a);
	b2 = UPSTtoCbyte(b2a);
	return((b1 << 8) || b2);
}

void ModeIntSampleAtPut(uiBytes, i, sample) upHandle uiBytes; int i, sample; {
	unsigned char b1, b2;
	upByte b1a, b2a;

	b1 = (sample >> 8) & 0x00ff;
	b2 = sample & 0x00ff;
	b1a = UPCtoSTbyte(b1);
	b2a = UPCtoSTbyte(b2);
	UPbyteAtPut(uiBytes, ((i*2)-1), b1a);
	UPbyteAtPut(uiBytes, (i*2), b2a);
}
