1 // ----------------------------------------------------------------------------
2 //
3 // Copyright (C) 2006-2011 Fons Adriaensen <fons@linuxaudio.org>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // ----------------------------------------------------------------------------
19 //
20 // This is a modified version of zresample, with getopt() and command line
21 // parsing removed so it can be called from within rlvm.
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <math.h>
27 #include <zita-resampler/resampler.h>
28 #include "audiofile.h"
29
30
31 enum { HELP, CAF, WAV, AMB, BIT16, BIT24, FLOAT, RATE, REC, TRI, LIPS, PAD };
32 enum { BUFFSIZE = 0x4000, FILTSIZE = 96 };
33
34
35 static unsigned int type = Audiofile::TYPE_WAV;
36 static unsigned int form = Audiofile::FORM_16BIT;
37 static unsigned int dith = Audiofile::DITHER_NONE;
38 static bool zpad = false;
39
zresample_main(const char * infile,const char * outfile,unsigned int rout)40 int zresample_main(const char* infile, const char* outfile, unsigned int rout) {
41 Audiofile Ainp;
42 Audiofile Aout;
43 Resampler R;
44 unsigned int k, chan, rinp, z1, z2;
45 float *inpb, *outb;
46 bool done;
47
48 if (Ainp.open_read(infile))
49 {
50 fprintf (stderr, "Can't open input file '%s'.\n", infile);
51 return 1;
52 }
53
54 chan = Ainp.chan ();
55 rinp = Ainp.rate ();
56
57 if (rout != rinp)
58 {
59 if ((rinp < 8000) || (rinp > 192000))
60 {
61 fprintf (stderr, "Input sample %d rate is out of range.\n", rinp);
62 Ainp.close ();
63 return 1;
64 }
65 if ((rout < 8000) || (rout > 192000))
66 {
67 fprintf (stderr, "Output sample rate %d is out of range.\n", rout);
68 Ainp.close ();
69 return 1;
70 }
71 if (R.setup (rinp, rout, chan, FILTSIZE))
72 {
73 fprintf (stderr, "Sample rate ratio %d/%d is not supported.\n", rout, rinp);
74 Ainp.close ();
75 return 1;
76 }
77 }
78
79 if (Aout.open_write(outfile, type, form, rout, chan))
80 {
81 fprintf (stderr, "Can't open output file '%s'.\n", outfile);
82 Ainp.close ();
83 return 1;
84 }
85 if (dith != Audiofile::DITHER_NONE)
86 {
87 Aout.set_dither (dith);
88 }
89
90 if (zpad)
91 {
92 z1 = R.inpsize () - 1;
93 z2 = R.inpsize () - 1;
94 }
95 else
96 {
97 z1 = R.inpsize () / 2 - 1;
98 z2 = R.inpsize () / 2;
99 }
100
101 inpb = new float [chan * BUFFSIZE];
102 if (rout != rinp)
103 {
104 outb = new float [chan * BUFFSIZE];
105 // Insert zero samples at start.
106 R.inp_count = z1;
107 R.inp_data = 0;
108 R.out_count = BUFFSIZE;
109 R.out_data = outb;
110 done = false;
111 while (true)
112 {
113 R.process ();
114 if (R.inp_count == 0)
115 {
116 // Input buffer empty, read more samples, insert
117 // zeros at the end, or terminate.
118 if (done)
119 {
120 // We already inserted final zero samples.
121 // Write out any remaining output samples and terminate.
122 Aout.write (outb, BUFFSIZE - R.out_count);
123 break;
124 }
125 k = Ainp.read (inpb, BUFFSIZE);
126 if (k)
127 {
128 // Process next 'k' input samples.
129 R.inp_count = k;
130 R.inp_data = inpb;
131 }
132 else
133 {
134 // At end of input, insert zero samples.
135 R.inp_count = z2;
136 R.inp_data = 0;
137 done = true;
138 }
139 }
140 if (R.out_count == 0)
141 {
142 // Output buffer full, write to file.
143 Aout.write (outb, BUFFSIZE);
144 R.out_count = BUFFSIZE;
145 R.out_data = outb;
146 }
147 }
148 delete[] outb;
149 }
150 else
151 {
152 // No resampling, just copy.
153 while (1)
154 {
155 k = Ainp.read (inpb, BUFFSIZE);
156 if (k) Aout.write (inpb, k);
157 else break;
158 }
159 }
160
161 Ainp.close ();
162 Aout.close ();
163 delete[] inpb;
164
165 return 0;
166 }
167