const char * UsageLines [] = {
	"Usage: swmix ((input file) (input weight) )+",
	"Mixes specified sound files, writes result sound file to",
	"standard output.",
	"All sound files are headerless signed word (.sw): two bytes",
	"per sample, least significant byte first.",
	"(input weight) must be an integer > 0",
	"May 16, 2011.  Newest is at gopher -p users/julianbr sdf.org",
	};
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );

#include <stdlib.h>
#include <stdio.h>


void Mix (FILE * * InputHdls, int * Weights, int NumInputs)
	{
	unsigned long int UnsignedValue;
	int TotalWeight;
	long int WeightedValue;
	int InputNum, EndOfAllInputs, ms, ls;

	TotalWeight = 0;
	for (InputNum = 0; InputNum < NumInputs; InputNum++)
		TotalWeight += Weights [InputNum];
	EndOfAllInputs = 0;
	while (!EndOfAllInputs) {
		EndOfAllInputs = 1;
		WeightedValue = 0;
		for (InputNum = 0; InputNum < NumInputs; InputNum++) {
			if (Weights [InputNum] > 0) {
				ls = fgetc (InputHdls [InputNum] );
				if (ls == EOF)
					Weights [InputNum] = 0;
				else {
					ms = fgetc (InputHdls [InputNum] );
					if (ms == EOF)
						Weights [InputNum] = 0;
					}
				}
			if (Weights [InputNum] > 0) {
				UnsignedValue = 256*(ms ^ 128) + ls;
				WeightedValue += Weights [InputNum]
					*(UnsignedValue - 32768);
				EndOfAllInputs = 0;
				}
			}
		if (!EndOfAllInputs) {
			UnsignedValue = 32768 + (WeightedValue/TotalWeight);
			putchar (UnsignedValue%256);
			putchar ((UnsignedValue/256) ^ 128);
			}
		}
	}


int main (int argc, char * argv [] )
	{
	FILE * * InputHdls;
	int i, ok, NumInputs, InputNum, * Weights;
	char c;

	if (argc < 2) {
		for (i = 0; i < NumUsageLines; i++)
			printf ("%s\n", UsageLines [i] );
		}
	else {
		ok = 1;
		NumInputs = (argc - 1)/2;
		if (NumInputs > 0) {
			InputHdls = malloc (
				NumInputs*sizeof (InputHdls [0] ) );
			if (InputHdls == NULL) {
				fprintf (stderr, "***swmix: Not enough");
				fprintf (stderr, " memory.\n");
				ok = 0;
				}
			Weights = malloc (
				NumInputs*sizeof (Weights [0] ) );
			if (Weights == NULL) {
				fprintf (stderr, "***swmix: Not enough");
				fprintf (stderr, " memory.\n");
				ok = 0;
				}
			}
		for (InputNum = 0; InputNum < NumInputs; InputNum++) {
			InputHdls [InputNum] = fopen (argv [2*InputNum + 1],
							"rb");
			if (InputHdls [InputNum] == NULL) {
				fprintf (stderr, "***swmix: \"");
				fprintf (stderr, "%s", argv [2*InputNum + 1] );
				fprintf (stderr, "\" not found.\n");
				ok = 0;
				}
			if (sscanf (argv [2*InputNum + 2],
				"%d%c", Weights + InputNum, & c) != 1
					|| Weights [InputNum] < 1) {
				fprintf (stderr, "***swmix:");
				fprintf (stderr, " Expecting number > 0");
				fprintf (stderr, " for weight, found \"");
				fprintf (stderr, "%s", argv [2*InputNum + 2] );
				fprintf (stderr, "\".\n");
				ok = 0;
				}
			}
		if (argc > 2*NumInputs + 1) {
			fprintf (stderr, "***swmix: Improper");
			fprintf (stderr, " \"%s\"", argv [2*NumInputs + 1] );
			fprintf (stderr, ".\n");
			ok = 0;
			}
		if (ok)
			Mix (InputHdls, Weights, NumInputs);
		for (InputNum = 0; InputNum < NumInputs; InputNum++) {
			if (InputHdls [InputNum] != NULL)
				fclose (InputHdls [InputNum] );
			}
		if (NumInputs > 0) {
			if (InputHdls != NULL)
				free (InputHdls);
			if (Weights != NULL)
				free (Weights);
			}
		}
	return 0;
	}