1 /* Simple example of using SoX libraries
2  *
3  * Copyright (c) 2008 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 #ifdef NDEBUG /* N.B. assert used with active statements so enable always. */
21 #undef NDEBUG /* Must undef above assert.h or other that might include it. */
22 #endif
23 
24 #include "sox.h"
25 #include "util.h"
26 #include <stdio.h>
27 #include <math.h>
28 #include <assert.h>
29 
30 /*
31  * Reads input file and displays a few seconds of wave-form, starting from
32  * a given time through the audio.   E.g. example2 song2.au 30.75 1
33  */
main(int argc,char * argv[])34 int main(int argc, char * argv[])
35 {
36   sox_format_t * in;
37   sox_sample_t * buf;
38   size_t blocks, block_size;
39   /* Period of audio over which we will measure its volume in order to
40    * display the wave-form: */
41   static const double block_period = 0.025; /* seconds */
42   double start_secs = 0, period = 2;
43   char dummy;
44   uint64_t seek;
45 
46   /* All libSoX applications must start by initialising the SoX library */
47   assert(sox_init() == SOX_SUCCESS);
48 
49   assert(argc > 1);
50   ++argv, --argc; /* Move to 1st parameter */
51 
52   /* Open the input file (with default parameters) */
53   assert((in = sox_open_read(*argv, NULL, NULL, NULL)));
54   ++argv, --argc; /* Move past this parameter */
55 
56   if (argc) { /* If given, read the start time: */
57     assert(sscanf(*argv, "%lf%c", &start_secs, &dummy) == 1);
58     ++argv, --argc; /* Move past this parameter */
59   }
60 
61   if (argc) { /* If given, read the period of time to display: */
62     assert(sscanf(*argv, "%lf%c", &period, &dummy) == 1);
63     ++argv, --argc; /* Move past this parameter */
64   }
65 
66   /* Calculate the start position in number of samples: */
67   seek = start_secs * in->signal.rate * in->signal.channels + .5;
68   /* Make sure that this is at a `wide sample' boundary: */
69   seek -= seek % in->signal.channels;
70   /* Move the file pointer to the desired starting position */
71   assert(sox_seek(in, seek, SOX_SEEK_SET) == SOX_SUCCESS);
72 
73   /* Convert block size (in seconds) to a number of samples: */
74   block_size = block_period * in->signal.rate * in->signal.channels + .5;
75   /* Make sure that this is at a `wide sample' boundary: */
76   block_size -= block_size % in->signal.channels;
77   /* Allocate a block of memory to store the block of audio samples: */
78   assert((buf = malloc(sizeof(sox_sample_t) * block_size)));
79 
80   /* This example program requires that the audio has precisely 2 channels: */
81   assert(in->signal.channels == 2);
82 
83   /* Read and process blocks of audio for the selected period or until EOF: */
84   for (blocks = 0; sox_read(in, buf, block_size) == block_size && blocks * block_period < period; ++blocks) {
85     double left = 0, right = 0;
86     size_t i;
87     static const char line[] = "===================================";
88     int l, r;
89 
90     for (i = 0; i < block_size; ++i) {
91       SOX_SAMPLE_LOCALS;
92       /* convert the sample from SoX's internal format to a `double' for
93        * processing in this application: */
94       double sample = SOX_SAMPLE_TO_FLOAT_64BIT(buf[i],);
95 
96       /* The samples for each channel are interleaved; in this example
97        * we allow only stereo audio, so the left channel audio can be found in
98        * even-numbered samples, and the right channel audio in odd-numbered
99        * samples: */
100       if (i & 1)
101         right = max(right, fabs(sample)); /* Find the peak volume in the block */
102       else
103         left = max(left, fabs(sample)); /* Find the peak volume in the block */
104     }
105 
106     /* Build up the wave form by displaying the left & right channel
107      * volume as a line length: */
108     l = (1 - left) * 35 + .5;
109     r = (1 - right) * 35 + .5;
110     printf("%8.3f%36s|%s\n", start_secs + blocks * block_period, line + l, line + r);
111   }
112 
113   /* All done; tidy up: */
114   free(buf);
115   sox_close(in);
116   sox_quit();
117   return 0;
118 }
119