Add stereoize (bug #3142), faster than soxmix
[asterisk/asterisk.git] / utils / stereorize.c
1 /****************************************************************************
2  *
3  * Programs for processing sound files in raw- or WAV-format.
4  * -- Merge two mono WAV-files to one stereo WAV-file.
5  *
6  * Name:    stereorize.c
7  * Version: 1.1
8  * Author:  Mark Roberts <mark@manumark.de>
9  *          Michael Labuschke <michael@labuschke.de>
10  *
11  ****************************************************************************/
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <time.h>
18 #include <assert.h>
19 #include "frame.h"
20
21 static char *Version = "stereorize 1.1, November 5th 2000";
22 static char *Usage =
23 "Usage: stereorize [options] infile-left infile-right outfile\n\n"
24
25 "Example:\n"
26 " stereorize left.wav right.wav stereo.wav -h\n\n"
27
28 "Creates stereo.wav (with WAV-header, option -h) from data in mono files\n"
29 "left.wav and right.wav.\n"
30 ;
31
32 int main( int argcount, char *args[])
33 {
34    int i, k[2], maxk, stdin_in_use=FALSE;
35    short *leftsample, *rightsample, *stereosample;
36    FILE *channel[2];
37    char *filename[2], *tempname;
38
39    version = Version;
40    usage = Usage;
41
42    channel[0] = NULL;
43    channel[1] = NULL;
44
45    parseargs( argcount, args, NOFILES | NOCOMPLAIN);
46
47    for (i = 0; i < 2; i++)
48      {
49        filename[i] = parsefilearg( argcount, args);
50        if (filename[i] == NULL)
51          argerrornum( NULL, ME_NOTENOUGHFILES);
52        if (strcmp (filename[i], "-") == 0)
53          {
54            if (stdin_in_use)
55              argerrortxt( filename[i] + 1,
56                           "Cannot use <stdin> for both input files");
57            filename[i] = "<stdin>";
58            channel[i] = stdin;
59            stdin_in_use = TRUE;
60          }
61        else
62          {
63            channel[i] = fopen(filename[i], "rb");
64          }
65        if (channel[i] == NULL)
66            fatalerror( "Error opening input file '%s': %s\n", filename[i],strerror(errno));
67        else
68          inform("Using file '%s' as input\n", filename[i]);
69      }
70    for (i = 0; i < 2; i++)
71      {
72        assert ( channel[i] != NULL);
73        readwavheader( channel[i]);
74        if (iswav && channels != 1)
75          inform("Warning: '%s' is no mono file\n", filename[i]);
76      }
77
78    outfilename = parsefilearg( argcount, args);
79    if (outfilename == NULL) argerrornum( NULL, ME_NOOUTFILE);
80    if (strcmp (outfilename, "-") == 0)
81      {
82        outfilename = "<stdout>";
83        out = stdout;
84      }
85    else
86      {
87        out = fopen(outfilename, "wb");
88      }
89    if (out == NULL)
90      fatalerror( "Error opening output file '%s': %s\n", outfilename,strerror(errno));
91    else
92      inform("Using file '%s' as output\n", outfilename);
93
94    if ((tempname = parsefilearg( argcount, args)) != NULL)
95      argerrornum( tempname, ME_TOOMANYFILES);
96
97    checknoargs(argcount, args);      /* Check that no arguments are left */
98
99    leftsample = malloc( sizeof(*leftsample) * BUFFSIZE);
100    rightsample = malloc( sizeof(*leftsample) * BUFFSIZE);
101    stereosample = malloc( sizeof(*leftsample) * 2 * BUFFSIZE);
102    if (leftsample == NULL || rightsample == NULL || stereosample == NULL)
103      fatalperror ("");
104
105    channels = 2;   /* Output files are stereo */
106    if (wavout)
107      {
108        if ((strcmp(outfilename,"<stdout>")!=0) && (fseek( out, 0, SEEK_SET) != 0)) 
109          fatalerror("Couldn't navigate output file '%s': %s\n",outfilename, strerror(errno));
110        makewavheader();
111      }
112
113    startstopwatch();
114    while (TRUE)
115    {
116       maxk = 0;
117       for (i = 0; i < 2; i++)
118         {
119           k[i] = fread(i==0? leftsample : rightsample,
120                        sizeof(*leftsample),
121                        BUFFSIZE,
122                        channel[i]);
123           if (k[i] == -1)
124             fatalerror("Error reading file '%s': %s\n", filename[i],strerror(errno));
125           if (k[i] > maxk)
126             maxk = k[i];
127         }
128       if (maxk == 0)
129         myexit (0);
130
131       /*-------------------------------------------------*
132        * First the left channel as far as it goes ...    *
133        *-------------------------------------------------*/
134       for (i = 0; i < k[0]; i++)
135         stereosample[2 * i] = leftsample[i];
136       /*-------------------------------------------------*
137        * ... and fill up till the end of this buffer.    *
138        *-------------------------------------------------*/
139       for (; i < maxk; i++)
140         stereosample[2 * i] = 0;
141
142       /*-------------------------------------------------*
143        * Next the right channel as far as it goes ...    *
144        *-------------------------------------------------*/
145       for (i = 0; i < k[1]; i++)
146         stereosample[2 * i + 1] = rightsample[i];
147       /*-------------------------------------------------*
148        * ... and fill up till the end of this buffer.    *
149        *-------------------------------------------------*/
150       for (; i < maxk; i++)
151         stereosample[2 * i + 1] = 0;
152
153       fwrite(stereosample, sizeof(*leftsample), 2 * maxk, out);
154       if (ferror( out) != 0)
155         fatalerror("Error writing to file '%s': %s\n",
156                    outfilename, strerror(errno));
157    }
158    /* That was an endless loop. This point is never reached. */
159 }