root/rat/trunk/convert.c @ 1747

Revision 1747, 25.5 KB (checked in by ucaccsp, 16 years ago)

Couple of fixes to make it compile! :-)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * FILE:    convert.c
3 * PROGRAM: RAT
4 * AUTHOR:  O.Hodson <O.Hodson@cs.ucl.ac.uk>
5 *
6 * $Revision$
7 * $Date$
8 *
9 * Copyright (c) 1995,1996 University College London
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, is permitted, for non-commercial use only, provided
14 * that the following conditions are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 *    must display the following acknowledgement:
22 *      This product includes software developed by the Computer Science
23 *      Department at University College London
24 * 4. Neither the name of the University nor of the Department may be used
25 *    to endorse or promote products derived from this software without
26 *    specific prior written permission.
27 * Use of this software for commercial purposes is explicitly forbidden
28 * unless prior written permission is obtained from the authors.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 */
42
43#include <math.h>
44#include <stdio.h>
45
46#include "assert.h"
47#include "rat_types.h"
48#include "convert.h"
49#include "util.h"
50
51#ifdef WIN32
52#include <mmreg.h>
53#include <msacm.h>
54#endif
55
56typedef struct s_converter_fmt{
57        u_int16 from_channels;
58        u_int16 from_freq;
59        u_int16 to_channels;
60        u_int16 to_freq;
61} converter_fmt_t;
62
63/* Mono-Stereo Conversion ****************************************************/ 
64/* Note src_len is length block in number of samples i.e
65 *                                              nChannels * nSamplingIntervals
66 */
67
68static void
69converter_change_channels (sample *src,
70                           int src_len,
71                           int src_channels,
72                           sample *dst,
73                           int dst_len,
74                           int dst_channels)
75{
76        int i;
77        sample *s, *d;
78        int t;
79        assert(src_channels == 1 || src_channels == 2);
80        assert(dst_channels == 1 || dst_channels == 2);
81        assert(dst_channels != src_channels);
82        assert(src_len/src_channels == dst_len/dst_channels);
83       
84        /* nb we run backwards through bufs so inplace conversion
85         * works if necessary.
86         */
87
88        switch(src_channels) {
89        case 1:
90                s = src + src_len - 1;
91                d = dst + dst_len - 1;
92                for(i = 0; i < src_len; i++) {
93                        *d-- = *s;
94                        *d-- = *s--;
95                }
96                break;
97        case 2:
98                s = src + src_len - 1;
99                d = dst + dst_len - 1;
100                for(i = 0; i < src_len; i++) {
101                        t    = *s--;
102                        t   += *s--;
103                        t   /= 2;
104                        *d-- = t;
105                }
106                break;
107        }
108}
109
110static int
111gcd (int a, int b)
112{
113        if (b) return gcd(b, a%b);
114        return 0;
115}
116
117#ifdef WIN32
118
119/* WINDOWS ACM CONVERSION CODE **********************************************/
120
121static HACMDRIVER hDrv;
122
123static BOOL CALLBACK
124getPCMConverter (HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport)
125{
126        if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CONVERTER) {
127                ACMDRIVERDETAILS add;
128                add.cbStruct = sizeof(ACMDRIVERDETAILS);
129                if (acmDriverDetails(hadid, &add, 0)
130                    || strcmp(add.szShortName,"MS-PCM")
131                    || acmDriverOpen(&hDrv, hadid, 0)) return TRUE;
132                return FALSE;
133        }
134        return TRUE;
135}
136
137static int 
138acm_conv_load (void)
139{
140     acmDriverEnum(getPCMConverter, 0L, 0L);
141     if (hDrv) return TRUE;
142     return FALSE;                /* Failed initialization, entry disabled in table */
143}
144
145static void 
146acm_conv_unload (void)
147{
148        if (hDrv) acmDriverClose(hDrv, 0);
149        hDrv = 0;
150}
151
152void
153acm_conv_init_fmt (WAVEFORMATEX *pwfx, u_int16 nChannels, u_int16 nSamplesPerSec)
154{
155       pwfx->wFormatTag      = WAVE_FORMAT_PCM;
156       pwfx->nChannels       = nChannels;
157       pwfx->nSamplesPerSec  = nSamplesPerSec;
158       pwfx->nAvgBytesPerSec = nSamplesPerSec * nChannels * sizeof(sample);
159       pwfx->nBlockAlign     = nChannels * sizeof(sample);
160       pwfx->wBitsPerSample  = 8 * sizeof(sample);
161}
162
163static int
164acm_conv_init (converter_t *c)
165{
166        LPHACMSTREAM lpa;
167        WAVEFORMATEX wfxSrc, wfxDst;
168
169        lpa = (LPHACMSTREAM)c->data;
170
171        acm_conv_init_fmt(&wfxSrc, c->conv_fmt->from_channels, c->conv_fmt->from_freq);
172        acm_conv_init_fmt(&wfxDst, c->conv_fmt->to_channels,   c->conv_fmt->to_freq);
173
174        if (acmStreamOpen(lpa, hDrv, &wfxSrc, &wfxDst, NULL, 0L, 0L, 0L)) return FALSE;
175 
176        return TRUE;
177}
178
179static void
180acm_convert (converter_t *c, sample *src_buf, int src_len, sample *dst_buf, int dst_len)
181{
182        ACMSTREAMHEADER ash;
183        LPHACMSTREAM    lphs;
184
185        memset(&ash, 0, sizeof(ash));
186        ash.cbStruct        = sizeof(ash);
187        ash.pbSrc           = (LPBYTE)src_buf;
188        ash.cbSrcLength     = src_len * sizeof(sample);
189        ash.pbDst           = (LPBYTE)dst_buf;
190        ash.cbDstLength     = dst_len * sizeof(sample);
191
192        lphs = (LPHACMSTREAM)c->data;
193
194        if (acmStreamPrepareHeader(*lphs, &ash, 0) ||
195            acmStreamConvert(*lphs, &ash, ACM_STREAMCONVERTF_BLOCKALIGN)) {
196                memset(dst_buf, 0, dst_len * sizeof(sample));
197        }
198        return;
199}
200
201static void
202acm_conv_free(converter_t *c)
203{
204        if (c->data) {
205                xfree(c->data);
206                c->data     = NULL;
207                c->data_len = 0;
208        }
209}
210
211#endif /* WIN32 */
212
213/* FILTERED SAMPLE RATE CONVERSION CODE *************************************/
214
215#define SRF_FILTW_SCALE  6
216#define SRF_NTABLES      5
217#define SRF_SCALE        256
218
219/* Tables are for M = 2, 3, 4, 5(not used), 6 */
220int **srf_tbl_up;
221int **srf_tbl_dn;
222
223/* If you want better quality make tbl sizes bigger (costs more),
224 * stick to multiples of these sizes otherwise converter becomes
225 * a noise generator.
226 */
227
228int tbl_sz_up[] = {8, 12, 16, 20, 24};
229int tbl_sz_dn[] = {8, 12, 16, 20, 24};
230
231#define SF2IDX(x) ((x)-2)
232#define IDX2SF(x) ((x)+2)
233
234struct s_srf_filter_state;
235
236typedef void (*srf_cf)(int offset, int channels, sample* src_buf, int src_len, sample* dst_buf, struct s_srf_filter_state *sf);
237
238typedef struct s_srf_filter_state {
239        short   scale;
240        short   tbl_idx;
241        int*    tbl;
242        srf_cf  convert_f;
243        sample *last;
244        short   last_sz;
245        short   phase;
246        short   dst_freq;
247} srf_filter_state_t;
248
249typedef struct s_srf_state {
250        srf_filter_state_t *fs;
251        int                 steps;      /* number of steps conversion takes */
252        sample             *tmp_buf;
253        int                 tmp_sz;
254} srf_state_t;
255
256static int 
257srf_tbl_init(void)
258{
259        int i,j;
260        double f;
261        srf_tbl_up = (int**)xmalloc(sizeof(int*)*SRF_NTABLES);
262        srf_tbl_dn = (int**)xmalloc(sizeof(int*)*SRF_NTABLES);
263
264        for(i = 0; i < SRF_NTABLES; i++) {
265                srf_tbl_up[i] = (int*)xmalloc(sizeof(int)*tbl_sz_up[i]);
266                srf_tbl_dn[i] = (int*)xmalloc(sizeof(int)*tbl_sz_dn[i]);
267                srf_tbl_up[i][0] = SRF_SCALE;
268                for(j = 1; j < tbl_sz_up[i]; j++) {
269                        f = M_PI * (double)j / (double)IDX2SF(i);
270                        srf_tbl_up[i][j] = (int)((double)SRF_SCALE * sin(f)/ f);
271                }
272                srf_tbl_dn[i][0] = (int)((double)SRF_SCALE * (1.0 / (double)(i+2)));
273                for(j = 1; j < tbl_sz_dn[i]; j++) {
274                        f = M_PI * (double)j / (double)IDX2SF(i);
275                        srf_tbl_up[i][j] = (int)((double)SRF_SCALE * sin(f)/ f);
276                        srf_tbl_dn[i][j] = IDX2SF(i) * ((int)((double)SRF_SCALE * sin(f)/ f));
277                }
278        }
279
280        return TRUE;
281}
282
283static void
284srf_tbl_free (void)
285{
286        int i;
287        for(i = 0; i < SRF_NTABLES; i++) {
288                xfree(srf_tbl_up[i]);
289                xfree(srf_tbl_dn[i]);
290        }
291        xfree(srf_tbl_up);
292        xfree(srf_tbl_dn);
293}
294
295static void
296srf_downsample(int offset, int channels, sample *src, int src_len, sample *dst, srf_filter_state_t *sf)
297{
298        sample *src_c, *src_l, *src_r, *src_e;
299        int *h_c, *h, *h_e;
300        int win_sz, result, i;
301        int src_step;
302
303        /* added these two to make it compile :-) [csp] */
304        UNUSED(src);
305        UNUSED(src_len);
306
307        win_sz = 2 * tbl_sz_dn[sf->tbl_idx] - 1;
308        h_c = srf_tbl_dn[sf->tbl_idx];
309        h_e = srf_tbl_dn[sf->tbl_idx] + tbl_sz_dn[sf->tbl_idx];
310       
311        src_c    = sf->last + offset + (tbl_sz_dn[sf->tbl_idx] * channels)/2;
312        src_e    = sf->last + win_sz * channels;     
313        src_step = channels * IDX2SF(sf->tbl_idx);
314
315        assert(win_sz * channels == sf->last_sz);
316        dst   += offset;
317
318        /* Stage 1: RHS of filter overlaps with last and current block */
319
320        /* Stage 2: LHS of filter overlaps last and current */
321
322        /* Stage 3: Filter completely within last block */
323        UNUSED(result);
324        UNUSED(src_l);
325        UNUSED(h);
326        UNUSED(src_r);
327        UNUSED(i);
328}
329
330static void
331srf_upsample(int offset, int channels, sample *src, int src_len, sample *dst, srf_filter_state_t *sf)
332{
333        sample *src_c, *src_l = NULL, *src_r = NULL, *src_e = NULL;
334        int win_sz, result, i;
335        int *h_c, *h_l, *h_r, *h_e;
336       
337        win_sz = 2 * tbl_sz_up[sf->tbl_idx] - 1;
338        h_c = srf_tbl_up[sf->tbl_idx];
339        h_e = srf_tbl_up[sf->tbl_idx] + tbl_sz_up[sf->tbl_idx];
340
341        src_c  = sf->last + offset + (tbl_sz_up[sf->tbl_idx] * channels)/2;
342        src_e  = sf->last + win_sz * channels;
343        assert(win_sz * channels == sf->last_sz);
344
345        dst   += offset;
346
347        /* Stage One: Right hand side of window overlaps with last buffer and current,
348         *            left hand side of window completely within last.
349         */
350        assert(sf->phase == 0);
351       
352        while(src_c < src_e) {
353                if (sf->phase == 0) {
354                        *dst      = *src_c;
355                        dst      += channels;
356                        sf->phase = 1;
357                }
358                h_l = h_c + sf->phase;
359                h_r = h_c + sf->scale - sf->phase;
360                src_l = src_c;
361                result = 0;
362               
363                while(h_l < h_e) {
364                        result += (*h_l) * (*src_l);
365                        src_l  -= channels;
366                        h_l++;
367                }
368                src_r = src_c + channels;
369                assert(src_r < src_e);
370                i = (src_e - src_c)/channels;
371               
372                while(i) {
373                        assert(src_r < src_e);
374                        result += (*src_r) * (*h_r);
375                        src_r++;
376                        h_r++;
377                        i--;
378                }
379               
380                src_r = src + offset;
381                while(h_r < h_e) {
382                        result += (*src_r) * (*h_r);
383                        src_r++;
384                        h_r++;
385                }
386
387                *dst = (short)(result/SRF_SCALE);
388                dst += channels;
389                sf->phase++;
390                if (sf->phase == sf->scale) {
391                        sf->phase =0;
392                        src_c+= channels;
393                }
394        }
395
396        /* Stage Two: Left hand side of window overlaps with last buffer and current,
397         *            right hand side of window completely within current.
398         */
399        assert(sf->phase == 0);
400
401        src_c = src   + offset;
402        src_e = src_c + win_sz * channels;
403
404        while(src_c < src_e) {
405                if (sf->phase == 0) {
406                        *dst      = *src_c;
407                        dst      += channels;
408                        sf->phase = 1;
409                }
410                h_l = h_c + sf->phase;
411                h_r = h_c + sf->scale - sf->phase;
412                src_r = src_c + channels;
413               
414                result = 0;
415                while(h_r < h_e) {
416                        result += (*src_r) * (*h_r);
417                        src_r  += channels;
418                        h_r    ++;
419                }
420
421                src_l = src_c;
422                while(src_l >= src) {
423                        result += (*src_l) * (*h_l);
424                        src_l  -= channels;
425                        h_l    ++;
426                }
427
428                src_l = sf->last + sf->last_sz - channels + offset;
429                while(h_l < h_e) {
430                        result += (*src_l) * (*h_l);
431                        src_l  -= channels;
432                        h_l    ++;
433                }
434               
435                *dst = (short)(result/SRF_SCALE);
436                dst += channels;
437                sf->phase++;
438                if (sf->phase == sf->scale) {
439                        sf->phase = 0;
440                        src_c += channels;
441                }
442        }
443
444        /* Stage Three: All of window within current buffer. */
445        assert(sf->phase == 0);
446        src_e = src + src_len - tbl_sz_up[sf->tbl_idx] * channels;
447
448        while(src_c < src_e) {
449                if (sf->phase == 0) {
450                        *dst = *src_c;
451                        dst += channels;
452                }
453                src_l = src_c;
454                src_r = src_c + channels;
455                h_l   = h_c   + sf->phase;
456                h_r   = h_c   + sf->scale - sf->phase;
457                result = 0;
458                while (h_r != h_e) {
459                        result += (*src_l)*(*h_l) + (*src_r)*(*h_r);
460                        src_l  -= channels;
461                        src_r  += channels;
462                        h_l++;
463                        h_r++;
464                }
465                *dst = (short)(result / SRF_SCALE);
466                dst += channels;
467                sf->phase++;
468                if (sf->phase == sf->scale) {
469                        sf->phase = 1;
470                        src_c += channels;
471                }
472        }
473
474        src_c = src + src_len - win_sz;
475        if (offset == 0) {
476                memcpy(sf->last,src_c,win_sz);
477        } else {
478                src_c++;
479                dst = sf->last++;
480                while(src_c < src + src_len) {
481                        *dst = *src_c;
482                        src_c += channels;
483                        dst   += channels;
484                }
485        }
486        xmemchk();
487}
488
489static 
490void srf_init_filter(srf_filter_state_t *sf, int src_freq, int dst_freq, int channels)
491{
492        if (src_freq > dst_freq) {
493                sf->scale     = src_freq / dst_freq;
494                sf->tbl_idx   = (SF2IDX(src_freq/dst_freq));
495                sf->tbl       = srf_tbl_dn[sf->tbl_idx];
496                sf->convert_f = srf_downsample;
497                sf->last_sz   = (2 * tbl_sz_dn[sf->tbl_idx] - 1) * channels;
498                sf->last      = (sample *) xmalloc (sf->last_sz * sizeof(sample));
499                sf->phase     = 0;
500                sf->dst_freq  = dst_freq;
501        } else {
502                sf->scale     = dst_freq / src_freq;
503                sf->tbl_idx   = (SF2IDX(dst_freq/src_freq));
504                sf->tbl       = srf_tbl_up[sf->tbl_idx];
505                sf->convert_f = srf_upsample;
506                sf->last_sz   = (2 * tbl_sz_up[sf->tbl_idx] - 1) * channels;
507                sf->last      = (sample *) xmalloc (sf->last_sz * sizeof(sample));
508                sf->phase     = 0;
509                sf->dst_freq  = dst_freq;
510        }
511        memset(sf->last, 0, sizeof(sample) * sf->last_sz);
512}
513
514/* This code is written so that if we do non-integer rate conversion
515 * we downsample to lowest common divisor, and then upsample again.
516 *
517 * This is really the wrong thing to do, we should upsample to a
518 * common multiple, then downsample, but this requires much more
519 * work and memory.  The reality for RAT is that we only ever convert
520 * between multiples of 8K, so the only problem is with conversion
521 * between 32K and 48K.  For sake of argument, most computer audio
522 * hardware isn't good enough too tell either way, so we'll take the
523 * cheap ticket.
524 */
525
526static int 
527srf_init (converter_t *c)
528{
529        srf_state_t *s;
530        int denom, src_freq, dst_freq, src_channels, dst_channels;
531
532        assert(c->conv_fmt->from_freq % 8000 == 0);
533        assert(c->conv_fmt->to_freq   % 8000 == 0);
534       
535        if (c->conv_fmt->to_freq == c->conv_fmt->from_freq) {
536                c->data     = NULL;
537                c->data_len = 0;
538                return TRUE;
539        }
540
541        s = (srf_state_t*) xmalloc(sizeof(srf_state_t));
542        memset(s, 0, sizeof(srf_state_t));
543       
544        c->data     = (char*)s;
545        c->data_len = sizeof(srf_state_t);
546       
547        src_freq     = c->conv_fmt->from_freq;
548        src_channels = c->conv_fmt->from_channels;
549        dst_freq     = c->conv_fmt->to_freq;
550        dst_channels = c->conv_fmt->to_channels;
551
552        denom = gcd(src_freq, dst_freq);
553        if (denom == 8000) {
554                s->fs    = (srf_filter_state_t*)xmalloc(sizeof(srf_filter_state_t));
555                s->steps = 1;
556                srf_init_filter(s->fs,    src_freq, dst_freq, src_channels);
557        } else {
558                s->fs    = (srf_filter_state_t*)xmalloc(sizeof(srf_filter_state_t) * 2);
559                s->steps = 2;
560                srf_init_filter(s->fs,    src_freq, denom,    src_channels);
561                srf_init_filter(s->fs+ 1, denom,    dst_freq, dst_channels);
562        }
563
564        return TRUE;
565}
566
567static void
568srf_convert (converter_t  *c, sample* src_buf, int src_len, sample *dst_buf, int dst_len)
569{
570        int channels = c->conv_fmt->from_channels;
571       
572        if (c->conv_fmt->from_channels == 2 && c->conv_fmt->to_channels == 1) {
573                /* stereo->mono then sample rate change */
574                converter_change_channels(src_buf, src_len, 2, src_buf, src_len / 2, 1);
575                src_len /= 2;
576                channels = 1;
577        }
578
579        if (c->data) {
580                srf_state_t *s = (srf_state_t*)c->data;
581                int i;
582                if (s->steps == 1) {
583                        for (i = 0; i < channels; i++)  {
584                                s->fs[0].convert_f(i, channels, src_buf, src_len, dst_buf, s->fs);
585                        }
586                } else {
587                        assert(s->steps == 2);
588                        if (s->tmp_buf == NULL) {
589                                s->tmp_sz  = src_len * c->conv_fmt->from_freq / s->fs->dst_freq;
590                                s->tmp_buf = (sample*)xmalloc(sizeof(sample) * s->tmp_sz);
591                        }
592                        for(i = 0; i < channels; i++) {
593                                s->fs[0].convert_f(i, channels, src_buf, src_len, s->tmp_buf, s->fs);
594                        }
595                        for(i = 0; i < channels; i++) {
596                                s->fs[1].convert_f(i, channels, s->tmp_buf, s->tmp_sz, dst_buf, s->fs);
597                        }
598                }
599        }
600
601        if (c->conv_fmt->from_channels == 2 && c->conv_fmt->to_channels == 1) {
602                /* sample rate change before mono-> stereo */
603                converter_change_channels(dst_buf, dst_len, 1, dst_buf, dst_len * 2, 2);
604        }
605}
606
607static void 
608srf_free (converter_t *c)
609{
610        int i;
611        srf_state_t *s = (srf_state_t*)c->data;
612        assert(c->data_len == sizeof(srf_state_t));
613        for(i = 0; i < s->steps; i++)  {
614                if (s->fs[i].last) xfree(s->fs[i].last);
615        }
616        xfree(s->fs);
617        if (s->tmp_buf) xfree(s->tmp_buf);
618        xfree(s);
619        c->data     = NULL;
620        c->data_len = 0;
621}
622
623static int 
624linear_init (converter_t *c)
625{
626        UNUSED(c);
627        return TRUE;
628}
629
630static void
631linear_convert (converter_t  *c, sample* src_buf, int src_len, sample *dst_buf, int dst_len)
632{
633        UNUSED(c);
634        UNUSED(src_buf);
635        UNUSED(src_len);
636        UNUSED(dst_buf);
637        UNUSED(dst_len);
638}
639
640static void 
641linear_free (converter_t *c)
642{
643        UNUSED(c);
644}
645
646
647typedef int  (*pcm_startup)     (void);  /* converter specific one time initialization */
648typedef void (*pcm_cleanup)     (void);  /* converter specific one time cleanup */
649typedef int  (*pcm_conv_init_f) (converter_t *c);
650typedef void (*pcm_conv_do_f)   (converter_t *c, sample* src_buf, int src_len, sample *dst_buf, int dst_len);
651typedef void (*pcm_conv_free_f) (converter_t *c);
652
653typedef struct s_pcm_converter{
654        u_char  id;
655        char    *name;
656        u_char  enabled;
657        pcm_startup     cf_start;
658        pcm_cleanup     cf_clean;
659        pcm_conv_init_f cf_init;
660        pcm_conv_do_f   cf_convert;
661        pcm_conv_free_f cf_free;
662        int      data_len;
663} pcm_converter_t;
664
665#define CONVERT_NONE     255
666#define CONVERT_PLATFORM 1
667#define CONVERT_SRF      2
668#define CONVERT_LINEAR   3
669#define CONVERT_CUBIC    4
670
671/* In this table of converters the platform specific converters should go at the
672 * beginning, before the default (and worst) linear interpolation conversion.  The
673 * intension is to have a mechanism which enables/disables more complex default schemes
674 * such as interpolation with filtering, cubic interpolation, etc...
675 */
676
677pcm_converter_t converter_tbl[] = {
678#ifdef WIN32
679        {CONVERT_PLATFORM, "MS Converter", FALSE, acm_conv_load, acm_conv_unload, acm_conv_init, acm_convert,  acm_conv_free, sizeof(HACMSTREAM)},
680#endif
681        {CONVERT_SRF     , "Filtered",     TRUE,  srf_tbl_init,  srf_tbl_free,    srf_init,    srf_convert,       srf_free,      0},
682        {CONVERT_LINEAR  , "Linear",       TRUE , NULL,          NULL,            linear_init, linear_convert, linear_free,   0},
683        {CONVERT_NONE    , "None",         FALSE, NULL,          NULL,            NULL,        NULL,           NULL,          0}
684};
685
686converter_t *
687converter_create(int from_channels, int from_freq, int to_channels, int to_freq)
688{
689        converter_t     *c  = NULL;
690        converter_fmt_t *cf = NULL;
691        pcm_converter_t *pc = converter_tbl;
692
693        while(pc->id != CONVERT_NONE) {
694                if (pc->enabled) break;
695                pc++;
696        }
697       
698        if (pc->id == CONVERT_NONE) return NULL;
699       
700        c  = (converter_t*)xmalloc(sizeof(converter_t));
701
702        if (c == NULL) {
703                return NULL;
704        }
705        memset(c, 0, sizeof(converter_t));
706
707        cf = (converter_fmt_t*)xmalloc(sizeof(converter_fmt_t));
708        if (cf == NULL) {
709                converter_destroy(&c);
710                return NULL;
711        }
712
713        cf->from_channels = from_channels;
714        cf->from_freq     = from_freq;
715        cf->to_channels   = to_channels;
716        cf->to_freq       = to_freq;
717
718        c->pcm_conv = pc;
719        c->conv_fmt = cf;
720
721        if (pc->data_len) {
722                c->data     = (char*)xmalloc(pc->data_len);
723                c->data_len = pc->data_len;
724                if (c->data == NULL) {
725                        converter_destroy(&c);
726                        return NULL;
727                }
728        }
729
730        if ((pc->cf_init) && (pc->cf_init(c) == FALSE)) {
731                converter_destroy(&c);
732                return NULL;
733        }
734        return c;
735}
736
737void 
738converter_destroy(converter_t **c)
739{
740        if (*c == NULL) return;
741        if ((*c)->pcm_conv->cf_free) (*c)->pcm_conv->cf_free(*c);
742        if ((*c)->conv_fmt)          xfree((*c)->conv_fmt);
743        if ((*c)->data != NULL)      xfree((*c)->data);
744        xfree(*c); (*c) = NULL;
745}
746
747int
748converter_format (converter_t *c, rx_queue_element_struct *ip)
749{
750        converter_fmt_t *cf;
751        assert(c);
752        assert(c->pcm_conv);
753        assert(c->pcm_conv->cf_convert);
754        assert(ip->native_data);
755        assert(ip->native_count);
756       
757        cf = c->conv_fmt;
758        ip->native_size[ip->native_count] = ip->native_size[ip->native_count - 1] * cf->to_channels * cf->to_freq / (cf->from_channels * cf->from_freq);
759        ip->native_data[ip->native_count] = (sample*)block_alloc(ip->native_size[ip->native_count]);
760        c->pcm_conv->cf_convert(c,
761                                ip->native_data[ip->native_count - 1],
762                                ip->native_size[ip->native_count - 1] / sizeof(sample),
763                                ip->native_data[ip->native_count],
764                                ip->native_size[ip->native_count] / sizeof(sample));
765        ip->native_count++;
766
767        return TRUE;
768}
769
770void         
771converters_init()
772{
773        pcm_converter_t *pc = converter_tbl;
774        while(pc->id != CONVERT_NONE) {
775                if (pc->cf_start) pc->enabled = pc->cf_start();
776                pc++;
777        }
778}
779
780void
781converters_free()
782{
783        pcm_converter_t *pc = converter_tbl;
784        while(pc->id != CONVERT_NONE) {
785                if (pc->cf_clean) pc->cf_clean();
786                pc++;
787        }
788}
Note: See TracBrowser for help on using the browser.