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;
       }