root/rat/trunk/convert.c @ 1746

Revision 1746, 25.4 KB (checked in by ucacoxh, 16 years ago)

- Start of downsampling re-implementation.

  • 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
234typedef void (*srf_cf)(int offset, int channels, sample* src_buf, int src_len, sample* dst_buf, struct s_srf_filter_state *sf);
235
236typedef struct s_srf_filter_state {
237        short   scale;
238        short   tbl_idx;
239        int*    tbl;
240        srf_cf  convert_f;
241        sample *last;
242        short   last_sz;
243        short   phase;
244        short   dst_freq;
245} srf_filter_state_t;
246
247typedef struct s_srf_state {
248        srf_filter_state_t *fs;
249        int                 steps;      /* number of steps conversion takes */
250        sample             *tmp_buf;
251        int                 tmp_sz;
252} srf_state_t;
253
254static int 
255srf_tbl_init(void)
256{
257        int i,j;
258        double f;
259        srf_tbl_up = (int**)xmalloc(sizeof(int*)*SRF_NTABLES);
260        srf_tbl_dn = (int**)xmalloc(sizeof(int*)*SRF_NTABLES);
261
262        for(i = 0; i < SRF_NTABLES; i++) {
263                srf_tbl_up[i] = (int*)xmalloc(sizeof(int)*tbl_sz_up[i]);
264                srf_tbl_dn[i] = (int*)xmalloc(sizeof(int)*tbl_sz_dn[i]);
265                srf_tbl_up[i][0] = SRF_SCALE;
266                for(j = 1; j < tbl_sz_up[i]; j++) {
267                        f = M_PI * (double)j / (double)IDX2SF(i);
268                        srf_tbl_up[i][j] = (int)((double)SRF_SCALE * sin(f)/ f);
269                }
270                srf_tbl_dn[i][0] = (int)((double)SRF_SCALE * (1.0 / (double)(i+2)));
271                for(j = 1; j < tbl_sz_dn[i]; j++) {
272                        f = M_PI * (double)j / (double)IDX2SF(i);
273                        srf_tbl_up[i][j] = (int)((double)SRF_SCALE * sin(f)/ f);
274                        srf_tbl_dn[i][j] = IDX2SF(i) * ((int)((double)SRF_SCALE * sin(f)/ f));
275                }
276        }
277
278        return TRUE;
279}
280
281static void
282srf_tbl_free (void)
283{
284        int i;
285        for(i = 0; i < SRF_NTABLES; i++) {
286                xfree(srf_tbl_up[i]);
287                xfree(srf_tbl_dn[i]);
288        }
289        xfree(srf_tbl_up);
290        xfree(srf_tbl_dn);
291}
292
293static void
294srf_downsample(int offset, int channels, sample *src, int src_len, sample *dst, srf_filter_state_t *sf)
295{
296        sample *src_c, *src_l, *src_r, *src_e;
297        int *h_c, *h, *h_e;
298        int win_sz, result, i;
299        int src_step;
300
301        win_sz = 2 * tbl_sz_dn[sf->tbl_idx] - 1;
302        h_c = srf_tbl_dn[sf->tbl_idx];
303        h_e = srf_tbl_dn[sf->tbl_idx] + tbl_sz_dn[sf->tbl_idx];
304       
305        src_c    = sf->last + offset + (tbl_sz_dn[sf->tbl_idx] * channels)/2;
306        src_e    = sf->last + win_sz * channels;     
307        src_step = channels * IDX2SF(sf->tbl_idx);
308
309        assert(win_sz * channels == sf->last_sz);
310        dst   += offset;
311
312        /* Stage 1: RHS of filter overlaps with last and current block */
313
314        /* Stage 2: LHS of filter overlaps last and current */
315
316        /* Stage 3: Filter completely within last block */
317        UNUSED(result);
318        UNUSED(src_l);
319        UNUSED(h);
320        UNUSED(src_r);
321        UNUSED(i);
322}
323
324static void
325srf_upsample(int offset, int channels, sample *src, int src_len, sample *dst, srf_filter_state_t *sf)
326{
327        sample *src_c, *src_l = NULL, *src_r = NULL, *src_e = NULL;
328        int win_sz, result, i;
329        int *h_c, *h_l, *h_r, *h_e;
330       
331        win_sz = 2 * tbl_sz_up[sf->tbl_idx] - 1;
332        h_c = srf_tbl_up[sf->tbl_idx];
333        h_e = srf_tbl_up[sf->tbl_idx] + tbl_sz_up[sf->tbl_idx];
334
335        src_c  = sf->last + offset + (tbl_sz_up[sf->tbl_idx] * channels)/2;
336        src_e  = sf->last + win_sz * channels;
337        assert(win_sz * channels == sf->last_sz);
338
339        dst   += offset;
340
341        /* Stage One: Right hand side of window overlaps with last buffer and current,
342         *            left hand side of window completely within last.
343         */
344        assert(sf->phase == 0);
345       
346        while(src_c < src_e) {
347                if (sf->phase == 0) {
348                        *dst      = *src_c;
349                        dst      += channels;
350                        sf->phase = 1;
351                }
352                h_l = h_c + sf->phase;
353                h_r = h_c + sf->scale - sf->phase;
354                src_l = src_c;
355                result = 0;
356               
357                while(h_l < h_e) {
358                        result += (*h_l) * (*src_l);
359                        src_l  -= channels;
360                        h_l++;
361                }
362                src_r = src_c + channels;
363                assert(src_r < src_e);
364                i = (src_e - src_c)/channels;
365               
366                while(i) {
367                        assert(src_r < src_e);
368                        result += (*src_r) * (*h_r);
369                        src_r++;
370                        h_r++;
371                        i--;
372                }
373               
374                src_r = src + offset;
375                while(h_r < h_e) {
376                        result += (*src_r) * (*h_r);
377                        src_r++;
378                        h_r++;
379                }
380
381                *dst = (short)(result/SRF_SCALE);
382                dst += channels;
383                sf->phase++;
384                if (sf->phase == sf->scale) {
385                        sf->phase =0;
386                        src_c+= channels;
387                }
388        }
389
390        /* Stage Two: Left hand side of window overlaps with last buffer and current,
391         *            right hand side of window completely within current.
392         */
393        assert(sf->phase == 0);
394
395        src_c = src   + offset;
396        src_e = src_c + win_sz * channels;
397
398        while(src_c < src_e) {
399                if (sf->phase == 0) {
400                        *dst      = *src_c;
401                        dst      += channels;
402                        sf->phase = 1;
403                }
404                h_l = h_c + sf->phase;
405                h_r = h_c + sf->scale - sf->phase;
406                src_r = src_c + channels;
407               
408                result = 0;
409                while(h_r < h_e) {
410                        result += (*src_r) * (*h_r);
411                        src_r  += channels;
412                        h_r    ++;
413                }
414
415                src_l = src_c;
416                while(src_l >= src) {
417                        result += (*src_l) * (*h_l);
418                        src_l  -= channels;
419                        h_l    ++;
420                }
421
422                src_l = sf->last + sf->last_sz - channels + offset;
423                while(h_l < h_e) {
424                        result += (*src_l) * (*h_l);
425                        src_l  -= channels;
426                        h_l    ++;
427                }
428               
429                *dst = (short)(result/SRF_SCALE);
430                dst += channels;
431                sf->phase++;
432                if (sf->phase == sf->scale) {
433                        sf->phase = 0;
434                        src_c += channels;
435                }
436        }
437
438        /* Stage Three: All of window within current buffer. */
439        assert(sf->phase == 0);
440        src_e = src + src_len - tbl_sz_up[sf->tbl_idx] * channels;
441
442        while(src_c < src_e) {
443                if (sf->phase == 0) {
444                        *dst = *src_c;
445                        dst += channels;
446                }
447                src_l = src_c;
448                src_r = src_c + channels;
449                h_l   = h_c   + sf->phase;
450                h_r   = h_c   + sf->scale - sf->phase;
451                result = 0;
452                while (h_r != h_e) {
453                        result += (*src_l)*(*h_l) + (*src_r)*(*h_r);
454                        src_l  -= channels;
455                        src_r  += channels;
456                        h_l++;
457                        h_r++;
458                }
459                *dst = (short)(result / SRF_SCALE);
460                dst += channels;
461                sf->phase++;
462                if (sf->phase == sf->scale) {
463                        sf->phase = 1;
464                        src_c += channels;
465                }
466        }
467
468        src_c = src + src_len - win_sz;
469        if (offset == 0) {
470                memcpy(sf->last,src_c,win_sz);
471        } else {
472                src_c++;
473                dst = sf->last++;
474                while(src_c < src + src_len) {
475                        *dst = *src_c;
476                        src_c += channels;
477                        dst   += channels;
478                }
479        }
480        xmemchk();
481}
482
483static 
484void srf_init_filter(srf_filter_state_t *sf, int src_freq, int dst_freq, int channels)
485{
486        if (src_freq > dst_freq) {
487                sf->scale     = src_freq / dst_freq;
488                sf->tbl_idx   = (SF2IDX(src_freq/dst_freq));
489                sf->tbl       = srf_tbl_dn[sf->tbl_idx];
490                sf->convert_f = srf_downsample;
491                sf->last_sz   = (2 * tbl_sz_dn[sf->tbl_idx] - 1) * channels;
492                sf->last      = (sample *) xmalloc (sf->last_sz * sizeof(sample));
493                sf->phase     = 0;
494                sf->dst_freq  = dst_freq;
495        } else {
496                sf->scale     = dst_freq / src_freq;
497                sf->tbl_idx   = (SF2IDX(dst_freq/src_freq));
498                sf->tbl       = srf_tbl_up[sf->tbl_idx];
499                sf->convert_f = srf_upsample;
500                sf->last_sz   = (2 * tbl_sz_up[sf->tbl_idx] - 1) * channels;
501                sf->last      = (sample *) xmalloc (sf->last_sz * sizeof(sample));
502                sf->phase     = 0;
503                sf->dst_freq  = dst_freq;
504        }
505        memset(sf->last, 0, sizeof(sample) * sf->last_sz);
506}
507
508/* This code is written so that if we do non-integer rate conversion
509 * we downsample to lowest common divisor, and then upsample again.
510 *
511 * This is really the wrong thing to do, we should upsample to a
512 * common multiple, then downsample, but this requires much more
513 * work and memory.  The reality for RAT is that we only ever convert
514 * between multiples of 8K, so the only problem is with conversion
515 * between 32K and 48K.  For sake of argument, most computer audio
516 * hardware isn't good enough too tell either way, so we'll take the
517 * cheap ticket.
518 */
519
520static int 
521srf_init (converter_t *c)
522{
523        srf_state_t *s;
524        int denom, src_freq, dst_freq, src_channels, dst_channels;
525
526        assert(c->conv_fmt->from_freq % 8000 == 0);
527        assert(c->conv_fmt->to_freq   % 8000 == 0);
528       
529        if (c->conv_fmt->to_freq == c->conv_fmt->from_freq) {
530                c->data     = NULL;
531                c->data_len = 0;
532                return TRUE;
533        }
534
535        s = (srf_state_t*) xmalloc(sizeof(srf_state_t));
536        memset(s, 0, sizeof(srf_state_t));
537       
538        c->data     = (char*)s;
539        c->data_len = sizeof(srf_state_t);
540       
541        src_freq     = c->conv_fmt->from_freq;
542        src_channels = c->conv_fmt->from_channels;
543        dst_freq     = c->conv_fmt->to_freq;
544        dst_channels = c->conv_fmt->to_channels;
545
546        denom = gcd(src_freq, dst_freq);
547        if (denom == 8000) {
548                s->fs    = (srf_filter_state_t*)xmalloc(sizeof(srf_filter_state_t));
549                s->steps = 1;
550                srf_init_filter(s->fs,    src_freq, dst_freq, src_channels);
551        } else {
552                s->fs    = (srf_filter_state_t*)xmalloc(sizeof(srf_filter_state_t) * 2);
553                s->steps = 2;
554                srf_init_filter(s->fs,    src_freq, denom,    src_channels);
555                srf_init_filter(s->fs+ 1, denom,    dst_freq, dst_channels);
556        }
557
558        return TRUE;
559}
560
561static void
562srf_convert (converter_t  *c, sample* src_buf, int src_len, sample *dst_buf, int dst_len)
563{
564        int channels = c->conv_fmt->from_channels;
565       
566        if (c->conv_fmt->from_channels == 2 && c->conv_fmt->to_channels == 1) {
567                /* stereo->mono then sample rate change */
568                converter_change_channels(src_buf, src_len, 2, src_buf, src_len / 2, 1);
569                src_len /= 2;
570                channels = 1;
571        }
572
573        if (c->data) {
574                srf_state_t *s = (srf_state_t*)c->data;
575                int i;
576                if (s->steps == 1) {
577                        for (i = 0; i < channels; i++)  {
578                                s->fs[0].convert_f(i, channels, src_buf, src_len, dst_buf, s->fs);
579                        }
580                } else {
581                        assert(s->steps == 2);
582                        if (s->tmp_buf == NULL) {
583                                s->tmp_sz  = src_len * c->conv_fmt->from_freq / s->fs->dst_freq;
584                                s->tmp_buf = (sample*)xmalloc(sizeof(sample) * s->tmp_sz);
585                        }
586                        for(i = 0; i < channels; i++) {
587                                s->fs[0].convert_f(i, channels, src_buf, src_len, s->tmp_buf, s->fs);
588                        }
589                        for(i = 0; i < channels; i++) {
590                                s->fs[1].convert_f(i, channels, s->tmp_buf, s->tmp_sz, dst_buf, s->fs);
591                        }
592                }
593        }
594
595        if (c->conv_fmt->from_channels == 2 && c->conv_fmt->to_channels == 1) {
596                /* sample rate change before mono-> stereo */
597                converter_change_channels(dst_buf, dst_len, 1, dst_buf, dst_len * 2, 2);
598        }
599}
600
601static void 
602srf_free (converter_t *c)
603{
604        int i;
605        srf_state_t *s = (srf_state_t*)c->data;
606        assert(c->data_len == sizeof(srf_state_t));
607        for(i = 0; i < s->steps; i++)  {
608                if (s->fs[i].last) xfree(s->fs[i].last);
609        }
610        xfree(s->fs);
611        if (s->tmp_buf) xfree(s->tmp_buf);
612        xfree(s);
613        c->data     = NULL;
614        c->data_len = 0;
615}
616
617static int 
618linear_init (converter_t *c)
619{
620        UNUSED(c);
621        return TRUE;
622}
623
624static void
625linear_convert (converter_t  *c, sample* src_buf, int src_len, sample *dst_buf, int dst_len)
626{
627        UNUSED(c);
628        UNUSED(src_buf);
629        UNUSED(src_len);
630        UNUSED(dst_buf);
631        UNUSED(dst_len);
632}
633
634static void 
635linear_free (converter_t *c)
636{
637        UNUSED(c);
638}
639
640
641typedef int  (*pcm_startup)     (void);  /* converter specific one time initialization */
642typedef void (*pcm_cleanup)     (void);  /* converter specific one time cleanup */
643typedef int  (*pcm_conv_init_f) (converter_t *c);
644typedef void (*pcm_conv_do_f)   (converter_t *c, sample* src_buf, int src_len, sample *dst_buf, int dst_len);
645typedef void (*pcm_conv_free_f) (converter_t *c);
646
647typedef struct s_pcm_converter{
648        u_char  id;
649        char    *name;
650        u_char  enabled;
651        pcm_startup     cf_start;
652        pcm_cleanup     cf_clean;
653        pcm_conv_init_f cf_init;
654        pcm_conv_do_f   cf_convert;
655        pcm_conv_free_f cf_free;
656        int      data_len;
657} pcm_converter_t;
658
659#define CONVERT_NONE     255
660#define CONVERT_PLATFORM 1
661#define CONVERT_SRF      2
662#define CONVERT_LINEAR   3
663#define CONVERT_CUBIC    4
664
665/* In this table of converters the platform specific converters should go at the
666 * beginning, before the default (and worst) linear interpolation conversion.  The
667 * intension is to have a mechanism which enables/disables more complex default schemes
668 * such as interpolation with filtering, cubic interpolation, etc...
669 */
670
671pcm_converter_t converter_tbl[] = {
672#ifdef WIN32
673        {CONVERT_PLATFORM, "MS Converter", FALSE, acm_conv_load, acm_conv_unload, acm_conv_init, acm_convert,  acm_conv_free, sizeof(HACMSTREAM)},
674#endif
675        {CONVERT_SRF     , "Filtered",     TRUE,  srf_tbl_init,  srf_tbl_free,    srf_init,    srf_convert,       srf_free,      0},
676        {CONVERT_LINEAR  , "Linear",       TRUE , NULL,          NULL,            linear_init, linear_convert, linear_free,   0},
677        {CONVERT_NONE    , "None",         FALSE, NULL,          NULL,            NULL,        NULL,           NULL,          0}
678};
679
680converter_t *
681converter_create(int from_channels, int from_freq, int to_channels, int to_freq)
682{
683        converter_t     *c  = NULL;
684        converter_fmt_t *cf = NULL;
685        pcm_converter_t *pc = converter_tbl;
686
687        while(pc->id != CONVERT_NONE) {
688                if (pc->enabled) break;
689                pc++;
690        }
691       
692        if (pc->id == CONVERT_NONE) return NULL;
693       
694        c  = (converter_t*)xmalloc(sizeof(converter_t));
695
696        if (c == NULL) {
697                return NULL;
698        }
699        memset(c, 0, sizeof(converter_t));
700
701        cf = (converter_fmt_t*)xmalloc(sizeof(converter_fmt_t));
702        if (cf == NULL) {
703                converter_destroy(&c);
704                return NULL;
705        }
706
707        cf->from_channels = from_channels;
708        cf->from_freq     = from_freq;
709        cf->to_channels   = to_channels;
710        cf->to_freq       = to_freq;
711
712        c->pcm_conv = pc;
713        c->conv_fmt = cf;
714
715        if (pc->data_len) {
716                c->data     = (char*)xmalloc(pc->data_len);
717                c->data_len = pc->data_len;
718                if (c->data == NULL) {
719                        converter_destroy(&c);
720                        return NULL;
721                }
722        }
723
724        if ((pc->cf_init) && (pc->cf_init(c) == FALSE)) {
725                converter_destroy(&c);
726                return NULL;
727        }
728        return c;
729}
730
731void 
732converter_destroy(converter_t **c)
733{
734        if (*c == NULL) return;
735        if ((*c)->pcm_conv->cf_free) (*c)->pcm_conv->cf_free(*c);
736        if ((*c)->conv_fmt)          xfree((*c)->conv_fmt);
737        if ((*c)->data != NULL)      xfree((*c)->data);
738        xfree(*c); (*c) = NULL;
739}
740
741int
742converter_format (converter_t *c, rx_queue_element_struct *ip)
743{
744        converter_fmt_t *cf;
745        assert(c);
746        assert(c->pcm_conv);
747        assert(c->pcm_conv->cf_convert);
748        assert(ip->native_data);
749        assert(ip->native_count);
750       
751        cf = c->conv_fmt;
752        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);
753        ip->native_data[ip->native_count] = (sample*)block_alloc(ip->native_size[ip->native_count]);
754        c->pcm_conv->cf_convert(c,
755                                ip->native_data[ip->native_count - 1],
756                                ip->native_size[ip->native_count - 1] / sizeof(sample),
757                                ip->native_data[ip->native_count],
758                                ip->native_size[ip->native_count] / sizeof(sample));
759        ip->native_count++;
760
761        return TRUE;
762}
763
764void         
765converters_init()
766{
767        pcm_converter_t *pc = converter_tbl;
768        while(pc->id != CONVERT_NONE) {
769                if (pc->cf_start) pc->enabled = pc->cf_start();
770                pc++;
771        }
772}
773
774void
775converters_free()
776{
777        pcm_converter_t *pc = converter_tbl;
778        while(pc->id != CONVERT_NONE) {
779                if (pc->cf_clean) pc->cf_clean();
780                pc++;
781        }
782}
Note: See TracBrowser for help on using the browser.