1 /* audio.c
2  * stereo->mono downmixing
3  * resampling
4  *
5  * $Id: audio.c,v 1.10 2003/08/01 22:38:04 karl Exp $
6  *
7  * Copyright (c) 2001 Michael Smith <msmith@xiph.org>
8  *
9  * This program is distributed under the terms of the GNU General
10  * Public License, version 2. You may use, modify, and redistribute
11  * it under the terms of this license. A copy should be included
12  * with this source.
13  */
14 
15 #ifdef HAVE_CONFIG_H
16  #include <config.h>
17 #endif
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "cfgparse.h"
24 #include "audio.h"
25 
26 #include "resample.h"
27 
28 #define MODULE "audio/"
29 #include "logging.h"
30 
downmix_initialise(void)31 downmix_state *downmix_initialise(void) {
32     downmix_state *state = calloc(1, sizeof(downmix_state));
33 
34     LOG_INFO0("Enabling stereo->mono downmixing");
35 
36     return state;
37 }
38 
downmix_clear(downmix_state * s)39 void downmix_clear(downmix_state *s) {
40     if(s) {
41         if (s->buffer)
42             free(s->buffer);
43         free(s);
44     }
45 }
46 
downmix_buffer_float(downmix_state * s,float ** buf,int samples)47 void downmix_buffer_float(downmix_state *s, float **buf, int samples)
48 {
49     int i;
50 
51     if(samples > s->buflen) {
52         void *tmp = realloc(s->buffer, samples * sizeof(float));
53         if (tmp==NULL)
54             return;
55         s->buffer = tmp;
56         s->buflen = samples;
57     }
58 
59     for(i=0; i < samples; i++) {
60         s->buffer[i] = (buf[0][i] + buf[1][i])*0.5;
61     }
62 
63 }
64 
65 
downmix_buffer(downmix_state * s,signed char * buf,int len,int be)66 void downmix_buffer(downmix_state *s, signed char *buf, int len, int be)
67 {
68     int samples = len/4;
69     int i;
70 
71     if(samples > s->buflen) {
72         void *tmp = realloc(s->buffer, samples * sizeof(float));
73         if (tmp==NULL)
74             return;
75         s->buffer = tmp;
76         s->buflen = samples;
77     }
78 
79     if(be) {
80         for(i=0; i < samples; i++) {
81             s->buffer[i] = (((buf[4*i]<<8) | (buf[4*i + 1]&0xff)) +
82                            ((buf[4*i + 2]<<8) | (buf[4*i + 3]&0xff)))/65536.f;
83         }
84     }
85     else {
86         for(i=0; i < samples; i++) {
87             s->buffer[i] = (((buf[4*i + 1]<<8) | (buf[4*i]&0xff)) +
88                            ((buf[4*i + 3]<<8) | (buf[4*i + 2]&0xff)))/65536.f;
89         }
90     }
91 }
92 
resample_initialise(int channels,int infreq,int outfreq)93 resample_state *resample_initialise(int channels, int infreq, int outfreq)
94 {
95     resample_state *state = calloc(1, sizeof(resample_state));
96     int failed = 1;
97 
98     do
99     {
100         if (state==NULL)
101             break;
102         if (resampler_init(&state->resampler, channels, outfreq, infreq, RES_END)) {
103             LOG_ERROR0("Couldn't initialise resampler to specified frequency");
104             return NULL;
105         }
106 
107         if ((state->buffers = calloc(channels, sizeof(float *))) == NULL)
108             break;
109         if ((state->convbuf = calloc(channels, sizeof(float *))) == NULL)
110             break;
111         failed = 0;
112     }
113     while (0); /* not a loop */
114 
115     if (failed)
116     {
117         LOG_ERROR0("Couldn't initialise resampler due to memory allocation failure");
118         resample_clear (state);
119         return NULL;
120     }
121     state->channels = channels;
122 
123     LOG_INFO3("Initialised resampler for %d channels, from %d Hz to %d Hz",
124             channels, infreq, outfreq);
125 
126     return state;
127 }
128 
resample_clear(resample_state * s)129 void resample_clear(resample_state *s)
130 {
131     int c;
132 
133     if(s) {
134         if(s->buffers) {
135             for(c=0; c<s->channels; c++)
136                 if (s->buffers[c])
137                     free(s->buffers[c]);
138             free(s->buffers);
139         }
140         if(s->convbuf) {
141             for(c=0; c<s->channels; c++)
142                 if (s->convbuf[c])
143                     free(s->convbuf[c]);
144             free(s->convbuf);
145         }
146         resampler_clear(&s->resampler);
147         free(s);
148     }
149 }
150 
resample_buffer(resample_state * s,signed char * buf,int buflen,int be)151 void resample_buffer(resample_state *s, signed char *buf, int buflen, int be)
152 {
153     int c,i;
154     buflen /= 2*s->channels; /* bytes -> samples conversion */
155 
156     if(s->convbuflen < buflen) {
157         s->convbuflen = buflen;
158         for(c=0; c < s->channels; c++)
159             s->convbuf[c] = realloc(s->convbuf[c], buflen * sizeof(float));
160     }
161 
162     if(be) {
163         for(i=0; i < buflen; i++) {
164             for(c=0; c < s->channels; c++) {
165                 s->convbuf[c][i] = ((buf[2*(i*s->channels + c)]<<8) |
166                                     (0x00ff&(int)buf[2*(i*s->channels + c)+1]))/
167                     32768.f;
168             }
169         }
170     }
171     else {
172         for(i=0; i < buflen; i++) {
173             for(c=0; c < s->channels; c++) {
174                 s->convbuf[c][i] = ((buf[2*(i*s->channels + c) + 1]<<8) |
175                                     (0x00ff&(int)buf[2*(i*s->channels + c)]))/
176                     32768.f;
177             }
178         }
179     }
180 
181     resample_buffer_float(s, s->convbuf, buflen);
182 }
183 
resample_buffer_float(resample_state * s,float ** buf,int buflen)184 void resample_buffer_float(resample_state *s, float **buf, int buflen)
185 {
186     int c;
187     int res;
188 
189     s->buffill = resampler_push_check(&s->resampler, buflen);
190     if(s->buffill <= 0) {
191         LOG_ERROR1("Fatal reencoding error: resampler_push_check returned %d",
192                 s->buffill);
193     }
194 
195     if(s->bufsize < s->buffill) {
196         s->bufsize = s->buffill;
197         for(c=0; c<s->channels; c++)
198             s->buffers[c] = realloc(s->buffers[c], s->bufsize * sizeof(float));
199     }
200 
201     if((res = resampler_push(&s->resampler, s->buffers, (float const **)buf, buflen))
202             != s->buffill) {
203         LOG_ERROR2("Internal error in resampling: returned number of samples %d"
204                    ", expected %d", res, s->buffill);
205         s->buffill = res;
206         return;
207     }
208 
209 }
210 
resample_finish(resample_state * s)211 void resample_finish(resample_state *s)
212 {
213     int ret;
214 
215     if(!s->buffers[0])
216         return;
217 
218     ret = resampler_drain(&s->resampler, s->buffers);
219 
220     if(ret > s->bufsize) {
221         LOG_ERROR0("Fatal error in resampler: buffers too small");
222         return;
223     }
224 
225     s->buffill = ret;
226 }
227