1 /* Simple example of using SoX libraries
2  *
3  * Copyright (c) 2009 robs@users.sourceforge.net
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
13  * Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include "sox.h"
21 #include <stdio.h>
22 
23 /* Concatenate audio files.  Note that the files must have the same number
24  * of channels and the same sample rate.
25  *
26  * Usage: example4 input-1 input-2 [... input-n] output
27  */
28 
29 #define check(x) do if (!(x)) { \
30   fprintf(stderr, "check failed: %s\n", #x); goto error; } while (0)
31 
main(int argc,char * argv[])32 int main(int argc, char * argv[])
33 {
34   sox_format_t * output = NULL;
35   int i;
36 
37   check(argc >= 1 + 2 + 1); /* Need at least 2 input files + 1 output file. */
38   check(sox_init() == SOX_SUCCESS);
39 
40   /* Defer openning the output file as we want to set its characteristics
41    * based on those of the input files. */
42 
43   for (i = 1; i < argc - 1; ++i) { /* For each input file... */
44     sox_format_t * input;
45     static sox_signalinfo_t signal; /* static quashes `uninitialised' warning.*/
46 
47     /* The (maximum) number of samples that we shall read/write at a time;
48      * chosen as a rough match to typical operating system I/O buffer size: */
49     #define MAX_SAMPLES (size_t)2048
50     sox_sample_t samples[MAX_SAMPLES]; /* Temporary store whilst copying. */
51     size_t number_read;
52 
53     /* Open this input file: */
54     check(input = sox_open_read(argv[i], NULL, NULL, NULL));
55 
56     if (i == 1) { /* If this is the first input file... */
57 
58       /* Open the output file using the same signal and encoding character-
59        * istics as the first input file.  Note that here, input->signal.length
60        * will not be equal to the output file length so we are relying on
61        * libSoX to set the output length correctly (i.e. non-seekable output
62        * is not catered for); an alternative would be to first calculate the
63        * output length by summing the lengths of the input files and modifying
64        * the second parameter to sox_open_write accordingly. */
65       check(output = sox_open_write(argv[argc - 1],
66             &input->signal, &input->encoding, NULL, NULL, NULL));
67 
68       /* Also, we'll store the signal characteristics of the first file
69        * so that we can check that these match those of the other inputs: */
70       signal = input->signal;
71     }
72     else { /* Second or subsequent input file... */
73 
74       /* Check that this input file's signal matches that of the first file: */
75       check(input->signal.channels == signal.channels);
76       check(input->signal.rate == signal.rate);
77     }
78 
79     /* Copy all of the audio from this input file to the output file: */
80     while ((number_read = sox_read(input, samples, MAX_SAMPLES)))
81       check(sox_write(output, samples, number_read) == number_read);
82 
83     check(sox_close(input) == SOX_SUCCESS); /* Finished with this input file.*/
84   }
85 
86   check(sox_close(output) == SOX_SUCCESS); /* Finished with the output file. */
87   output = NULL;
88   check(sox_quit() == SOX_SUCCESS);
89   return 0;
90 
91 error: /* Truncate output file on error: */
92   if (output) {
93     FILE * f;
94     sox_close(output);
95     if ((f = fopen(argv[argc - 1], "w"))) fclose(f);
96   }
97   return 1;
98 }
99