fix silly bad pointer bug
[xiph/unicode.git] / ices / src / audio.c
blobe4d9450b545b29774f6e46f89ae38723ff77d848
1 /* audio.c
2 * stereo->mono downmixing
3 * resampling
5 * $Id: audio.c,v 1.10 2003/08/01 22:38:04 karl Exp $
7 * Copyright (c) 2001 Michael Smith <msmith@labyrinth.net.au>
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.
15 #ifdef HAVE_CONFIG_H
16 #include <config.h>
17 #endif
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
23 #include "cfgparse.h"
24 #include "audio.h"
26 #include "resample.h"
28 #define MODULE "audio/"
29 #include "logging.h"
31 downmix_state *downmix_initialise(void) {
32 downmix_state *state = calloc(1, sizeof(downmix_state));
34 LOG_INFO0("Enabling stereo->mono downmixing");
36 return state;
39 void downmix_clear(downmix_state *s) {
40 if(s) {
41 if (s->buffer)
42 free(s->buffer);
43 free(s);
47 void downmix_buffer_float(downmix_state *s, float **buf, int samples)
49 int i;
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;
59 for(i=0; i < samples; i++) {
60 s->buffer[i] = (buf[0][i] + buf[1][i])*0.5;
66 void downmix_buffer(downmix_state *s, signed char *buf, int len, int be)
68 int samples = len/4;
69 int i;
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;
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;
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;
93 resample_state *resample_initialise(int channels, int infreq, int outfreq)
95 resample_state *state = calloc(1, sizeof(resample_state));
96 int failed = 1;
98 do
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;
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;
113 while (0); /* not a loop */
115 if (failed)
117 LOG_ERROR0("Couldn't initialise resampler due to memory allocation failure");
118 resample_clear (state);
119 return NULL;
121 state->channels = channels;
123 LOG_INFO3("Initialised resampler for %d channels, from %d Hz to %d Hz",
124 channels, infreq, outfreq);
126 return state;
129 void resample_clear(resample_state *s)
131 int c;
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);
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);
146 resampler_clear(&s->resampler);
147 free(s);
151 void resample_buffer(resample_state *s, signed char *buf, int buflen, int be)
153 int c,i;
154 buflen /= 2*s->channels; /* bytes -> samples conversion */
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));
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;
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;
181 resample_buffer_float(s, s->convbuf, buflen);
184 void resample_buffer_float(resample_state *s, float **buf, int buflen)
186 int c;
187 int res;
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);
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));
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;
211 void resample_finish(resample_state *s)
213 int ret;
215 if(!s->buffers[0])
216 return;
218 ret = resampler_drain(&s->resampler, s->buffers);
220 if(ret > s->bufsize) {
221 LOG_ERROR0("Fatal error in resampler: buffers too small");
222 return;
225 s->buffill = ret;