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