diff --git a/cfg-mplayer.h b/cfg-mplayer.h index 43aeb80e1f..ed76bdeb69 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -83,6 +83,7 @@ struct config ao_plugin_conf[]={ {"list", &ao_plugin_cfg.plugin_list, CONF_TYPE_STRING, 0, 0, 0}, {"delay", &ao_plugin_cfg.pl_delay_len, CONF_TYPE_INT, CONF_MIN, 0, 0}, {"format", &ao_plugin_cfg.pl_format_type, CONF_TYPE_INT, CONF_MIN, 0, 0}, + {"fout", &ao_plugin_cfg.pl_resample_fout, CONF_TYPE_INT, CONF_MIN, 0, 0}, {NULL, NULL, 0, 0, 0, 0} }; diff --git a/libao2/Makefile b/libao2/Makefile index 1ae0862619..fe4a787fbc 100644 --- a/libao2/Makefile +++ b/libao2/Makefile @@ -4,7 +4,8 @@ include config.mak LIBNAME = libao2.a # TODO: moveout ao_sdl.c so it's only used when SDL is detected -SRCS=afmt.c audio_out.c ao_mpegpes.c ao_null.c ao_pcm.c ao_plugin.c pl_delay.c pl_format.c pl_surround.c remez.c $(OPTIONAL_SRCS) +SRCS=afmt.c audio_out.c ao_mpegpes.c ao_null.c ao_pcm.c ao_plugin.c pl_delay.c pl_format.c pl_surround.c remez.c pl_resample.c $(OPTIONAL_SRCS) + OBJS=$(SRCS:.c=.o) CFLAGS = $(OPTFLAGS) -I. -I.. $(SDL_INC) $(X11_INC) $(EXTRA_INC) diff --git a/libao2/audio_plugin.h b/libao2/audio_plugin.h index 59f20d7c05..cfe71792ce 100644 --- a/libao2/audio_plugin.h +++ b/libao2/audio_plugin.h @@ -34,6 +34,7 @@ typedef struct ao_plugin_cfg_s char* plugin_list; // List of used plugins read from cfg int pl_format_type; // Output format int pl_delay_len; // Number of samples to delay sound output + int pl_resample_fout; // Output frequency from resampling } ao_plugin_cfg_t; extern volatile ao_plugin_cfg_t ao_plugin_cfg; @@ -42,23 +43,26 @@ extern volatile ao_plugin_cfg_t ao_plugin_cfg; #define CFG_DEFAULTS { \ NULL, \ AFMT_S16_LE, \ - 0 \ + 0, \ + 48000 \ }; // This block should not be available in the pl_xxxx files // due to compilation issues #ifndef PLUGIN -#define NPL 3+1 // Number of PLugins ( +1 list ends with NULL ) +#define NPL 4+1 // Number of PLugins ( +1 list ends with NULL ) // List of plugins extern ao_plugin_functions_t audio_plugin_delay; extern ao_plugin_functions_t audio_plugin_format; extern ao_plugin_functions_t audio_plugin_surround; +extern ao_plugin_functions_t audio_plugin_resample; #define AO_PLUGINS { \ &audio_plugin_delay, \ &audio_plugin_format, \ &audio_plugin_surround, \ + &audio_plugin_resample, \ NULL \ } #endif /* PLUGIN */ diff --git a/libao2/filter.h b/libao2/filter.h new file mode 100644 index 0000000000..964e335672 --- /dev/null +++ b/libao2/filter.h @@ -0,0 +1,223 @@ +/*============================================================================= +// +// This file is part of mplayer. +// +// mplayer is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// mplayer is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with mplayer; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Copyright 2001 Anders Johansson ajh@atri.curtin.edu.au +// +//============================================================================= +*/ + +/* Polyphase filters. Designed using window method and kaiser window + with beta=10. */ + +#define W4 { \ +0, 36, 32767, -35, 0, 113, 32756, -103, \ +0, 193, 32733, -167, 0, 278, 32699, -227, \ +0, 367, 32654, -282, -1, 461, 32597, -335, \ +-1, 560, 32530, -383, -1, 664, 32451, -429, \ +-1, 772, 32361, -470, -2, 886, 32260, -509, \ +-2, 1004, 32148, -544, -2, 1128, 32026, -577, \ +-3, 1257, 31892, -606, -4, 1392, 31749, -633, \ +-4, 1532, 31594, -657, -5, 1677, 31430, -678, \ +-6, 1828, 31255, -697, -7, 1985, 31070, -713, \ +-8, 2147, 30876, -727, -9, 2315, 30671, -739, \ +-10, 2489, 30457, -749, -11, 2668, 30234, -756, \ +-13, 2854, 30002, -762, -14, 3045, 29761, -766, \ +-16, 3243, 29511, -769, -18, 3446, 29252, -769, \ +-20, 3656, 28985, -769, -22, 3871, 28710, -766, \ +-25, 4093, 28427, -763, -27, 4320, 28137, -758, \ +-30, 4553, 27839, -752, -33, 4793, 27534, -745, \ +-36, 5038, 27222, -737, -39, 5290, 26904, -727, \ +-43, 5547, 26579, -717, -47, 5811, 26248, -707, \ +-51, 6080, 25911, -695, -55, 6355, 25569, -683, \ +-60, 6636, 25221, -670, -65, 6922, 24868, -657, \ +-70, 7214, 24511, -643, -76, 7512, 24149, -628, \ +-81, 7815, 23782, -614, -87, 8124, 23412, -599, \ +-94, 8437, 23038, -583, -101, 8757, 22661, -568, \ +-108, 9081, 22281, -552, -115, 9410, 21898, -537, \ +-123, 9744, 21513, -521, -131, 10082, 21125, -505, \ +-139, 10425, 20735, -489, -148, 10773, 20344, -473, \ +-157, 11125, 19951, -457, -166, 11481, 19557, -441, \ +-176, 11841, 19162, -426, -186, 12205, 18767, -410, \ +-197, 12572, 18372, -395, -208, 12942, 17976, -380, \ +-219, 13316, 17581, -365, -231, 13693, 17186, -350, \ +-243, 14073, 16791, -336, -255, 14455, 16398, -321, \ +-268, 14840, 16006, -307, -281, 15227, 15616, -294, \ +-294, 15616, 15227, -281, -307, 16006, 14840, -268, \ +-321, 16398, 14455, -255, -336, 16791, 14073, -243, \ +-350, 17186, 13693, -231, -365, 17581, 13316, -219, \ +-380, 17976, 12942, -208, -395, 18372, 12572, -197, \ +-410, 18767, 12205, -186, -426, 19162, 11841, -176, \ +-441, 19557, 11481, -166, -457, 19951, 11125, -157, \ +-473, 20344, 10773, -148, -489, 20735, 10425, -139, \ +-505, 21125, 10082, -131, -521, 21513, 9744, -123, \ +-537, 21898, 9410, -115, -552, 22281, 9081, -108, \ +-568, 22661, 8757, -101, -583, 23038, 8437, -94, \ +-599, 23412, 8124, -87, -614, 23782, 7815, -81, \ +-628, 24149, 7512, -76, -643, 24511, 7214, -70, \ +-657, 24868, 6922, -65, -670, 25221, 6636, -60, \ +-683, 25569, 6355, -55, -695, 25911, 6080, -51, \ +-707, 26248, 5811, -47, -717, 26579, 5547, -43, \ +-727, 26904, 5290, -39, -737, 27222, 5038, -36, \ +-745, 27534, 4793, -33, -752, 27839, 4553, -30, \ +-758, 28137, 4320, -27, -763, 28427, 4093, -25, \ +-766, 28710, 3871, -22, -769, 28985, 3656, -20, \ +-769, 29252, 3446, -18, -769, 29511, 3243, -16, \ +-766, 29761, 3045, -14, -762, 30002, 2854, -13, \ +-756, 30234, 2668, -11, -749, 30457, 2489, -10, \ +-739, 30671, 2315, -9, -727, 30876, 2147, -8, \ +-713, 31070, 1985, -7, -697, 31255, 1828, -6, \ +-678, 31430, 1677, -5, -657, 31594, 1532, -4, \ +-633, 31749, 1392, -4, -606, 31892, 1257, -3, \ +-577, 32026, 1128, -2, -544, 32148, 1004, -2, \ +-509, 32260, 886, -2, -470, 32361, 772, -1, \ +-429, 32451, 664, -1, -383, 32530, 560, -1, \ +-335, 32597, 461, -1, -282, 32654, 367, 0, \ +-227, 32699, 278, 0, -167, 32733, 193, 0, \ +-103, 32756, 113, 0, -35, 32767, 36, 0, \ +} + +#define W8 { \ +0, 2, -18, 95, 32767, -94, 18, -2, \ +0, 6, -55, 289, 32759, -279, 53, -5, \ +0, 9, -93, 488, 32744, -458, 87, -8, \ +0, 13, -132, 692, 32720, -633, 120, -11, \ +0, 18, -173, 900, 32689, -804, 151, -14, \ +0, 22, -214, 1113, 32651, -969, 182, -17, \ +0, 27, -256, 1331, 32604, -1130, 212, -20, \ +0, 31, -299, 1553, 32550, -1286, 241, -22, \ +0, 36, -343, 1780, 32488, -1437, 268, -25, \ +0, 41, -389, 2011, 32419, -1583, 295, -27, \ +-1, 47, -435, 2247, 32342, -1724, 320, -29, \ +-1, 52, -482, 2488, 32257, -1861, 345, -31, \ +-1, 58, -530, 2733, 32165, -1993, 368, -32, \ +-1, 64, -579, 2982, 32066, -2121, 391, -34, \ +-1, 70, -629, 3236, 31959, -2243, 412, -36, \ +-1, 76, -679, 3494, 31844, -2361, 433, -37, \ +-1, 82, -731, 3756, 31723, -2475, 452, -38, \ +-1, 89, -783, 4022, 31594, -2583, 471, -40, \ +-2, 96, -837, 4293, 31458, -2688, 488, -41, \ +-2, 102, -891, 4567, 31315, -2787, 505, -42, \ +-2, 110, -946, 4846, 31164, -2883, 521, -42, \ +-2, 117, -1001, 5128, 31007, -2973, 535, -43, \ +-2, 124, -1057, 5414, 30843, -3060, 549, -44, \ +-3, 132, -1114, 5704, 30672, -3142, 562, -44, \ +-3, 140, -1172, 5998, 30495, -3219, 574, -45, \ +-3, 148, -1230, 6295, 30311, -3292, 585, -45, \ +-3, 156, -1289, 6596, 30120, -3362, 596, -46, \ +-4, 164, -1349, 6900, 29923, -3426, 605, -46, \ +-4, 173, -1408, 7208, 29719, -3487, 614, -46, \ +-4, 181, -1469, 7519, 29509, -3544, 621, -46, \ +-4, 190, -1530, 7832, 29294, -3597, 628, -46, \ +-5, 199, -1591, 8149, 29072, -3645, 635, -46, \ +-5, 208, -1652, 8469, 28844, -3690, 640, -46, \ +-6, 217, -1714, 8792, 28610, -3731, 645, -46, \ +-6, 227, -1777, 9118, 28371, -3768, 649, -45, \ +-6, 236, -1839, 9446, 28126, -3801, 652, -45, \ +-7, 246, -1902, 9776, 27875, -3831, 655, -45, \ +-7, 255, -1964, 10109, 27620, -3857, 657, -44, \ +-8, 265, -2027, 10445, 27359, -3880, 658, -44, \ +-8, 275, -2090, 10782, 27092, -3899, 659, -43, \ +-9, 285, -2153, 11121, 26821, -3915, 659, -43, \ +-9, 295, -2216, 11463, 26546, -3927, 658, -42, \ +-10, 306, -2278, 11806, 26265, -3936, 657, -42, \ +-10, 316, -2341, 12151, 25980, -3942, 655, -41, \ +-11, 326, -2403, 12497, 25690, -3945, 653, -40, \ +-11, 337, -2465, 12845, 25396, -3945, 650, -40, \ +-12, 347, -2526, 13194, 25098, -3941, 647, -39, \ +-12, 358, -2588, 13544, 24796, -3935, 643, -38, \ +-13, 368, -2648, 13896, 24490, -3926, 639, -38, \ +-14, 379, -2708, 14248, 24181, -3914, 634, -37, \ +-14, 389, -2768, 14601, 23867, -3900, 629, -36, \ +-15, 400, -2827, 14954, 23551, -3883, 623, -35, \ +-16, 410, -2885, 15308, 23231, -3863, 617, -34, \ +-16, 421, -2943, 15662, 22908, -3841, 611, -34, \ +-17, 431, -2999, 16016, 22581, -3817, 604, -33, \ +-18, 442, -3055, 16371, 22252, -3790, 597, -32, \ +-19, 452, -3109, 16725, 21921, -3761, 590, -31, \ +-19, 462, -3163, 17079, 21587, -3730, 582, -30, \ +-20, 472, -3215, 17432, 21250, -3697, 574, -29, \ +-21, 483, -3266, 17785, 20911, -3662, 566, -28, \ +-22, 492, -3316, 18138, 20570, -3624, 558, -28, \ +-23, 502, -3365, 18489, 20227, -3585, 549, -27, \ +-23, 512, -3412, 18839, 19883, -3545, 540, -26, \ +-24, 522, -3458, 19188, 19536, -3502, 531, -25, \ +-25, 531, -3502, 19536, 19188, -3458, 522, -24, \ +-26, 540, -3545, 19883, 18839, -3412, 512, -23, \ +-27, 549, -3585, 20227, 18489, -3365, 502, -23, \ +-28, 558, -3624, 20570, 18138, -3316, 492, -22, \ +-28, 566, -3662, 20911, 17785, -3266, 483, -21, \ +-29, 574, -3697, 21250, 17432, -3215, 472, -20, \ +-30, 582, -3730, 21587, 17079, -3163, 462, -19, \ +-31, 590, -3761, 21921, 16725, -3109, 452, -19, \ +-32, 597, -3790, 22252, 16371, -3055, 442, -18, \ +-33, 604, -3817, 22581, 16016, -2999, 431, -17, \ +-34, 611, -3841, 22908, 15662, -2943, 421, -16, \ +-34, 617, -3863, 23231, 15308, -2885, 410, -16, \ +-35, 623, -3883, 23551, 14954, -2827, 400, -15, \ +-36, 629, -3900, 23867, 14601, -2768, 389, -14, \ +-37, 634, -3914, 24181, 14248, -2708, 379, -14, \ +-38, 639, -3926, 24490, 13896, -2648, 368, -13, \ +-38, 643, -3935, 24796, 13544, -2588, 358, -12, \ +-39, 647, -3941, 25098, 13194, -2526, 347, -12, \ +-40, 650, -3945, 25396, 12845, -2465, 337, -11, \ +-40, 653, -3945, 25690, 12497, -2403, 326, -11, \ +-41, 655, -3942, 25980, 12151, -2341, 316, -10, \ +-42, 657, -3936, 26265, 11806, -2278, 306, -10, \ +-42, 658, -3927, 26546, 11463, -2216, 295, -9, \ +-43, 659, -3915, 26821, 11121, -2153, 285, -9, \ +-43, 659, -3899, 27092, 10782, -2090, 275, -8, \ +-44, 658, -3880, 27359, 10445, -2027, 265, -8, \ +-44, 657, -3857, 27620, 10109, -1964, 255, -7, \ +-45, 655, -3831, 27875, 9776, -1902, 246, -7, \ +-45, 652, -3801, 28126, 9446, -1839, 236, -6, \ +-45, 649, -3768, 28371, 9118, -1777, 227, -6, \ +-46, 645, -3731, 28610, 8792, -1714, 217, -6, \ +-46, 640, -3690, 28844, 8469, -1652, 208, -5, \ +-46, 635, -3645, 29072, 8149, -1591, 199, -5, \ +-46, 628, -3597, 29294, 7832, -1530, 190, -4, \ +-46, 621, -3544, 29509, 7519, -1469, 181, -4, \ +-46, 614, -3487, 29719, 7208, -1408, 173, -4, \ +-46, 605, -3426, 29923, 6900, -1349, 164, -4, \ +-46, 596, -3362, 30120, 6596, -1289, 156, -3, \ +-45, 585, -3292, 30311, 6295, -1230, 148, -3, \ +-45, 574, -3219, 30495, 5998, -1172, 140, -3, \ +-44, 562, -3142, 30672, 5704, -1114, 132, -3, \ +-44, 549, -3060, 30843, 5414, -1057, 124, -2, \ +-43, 535, -2973, 31007, 5128, -1001, 117, -2, \ +-42, 521, -2883, 31164, 4846, -946, 110, -2, \ +-42, 505, -2787, 31315, 4567, -891, 102, -2, \ +-41, 488, -2688, 31458, 4293, -837, 96, -2, \ +-40, 471, -2583, 31594, 4022, -783, 89, -1, \ +-38, 452, -2475, 31723, 3756, -731, 82, -1, \ +-37, 433, -2361, 31844, 3494, -679, 76, -1, \ +-36, 412, -2243, 31959, 3236, -629, 70, -1, \ +-34, 391, -2121, 32066, 2982, -579, 64, -1, \ +-32, 368, -1993, 32165, 2733, -530, 58, -1, \ +-31, 345, -1861, 32257, 2488, -482, 52, -1, \ +-29, 320, -1724, 32342, 2247, -435, 47, -1, \ +-27, 295, -1583, 32419, 2011, -389, 41, 0, \ +-25, 268, -1437, 32488, 1780, -343, 36, 0, \ +-22, 241, -1286, 32550, 1553, -299, 31, 0, \ +-20, 212, -1130, 32604, 1331, -256, 27, 0, \ +-17, 182, -969, 32651, 1113, -214, 22, 0, \ +-14, 151, -804, 32689, 900, -173, 18, 0, \ +-11, 120, -633, 32720, 692, -132, 13, 0, \ +-8, 87, -458, 32744, 488, -93, 9, 0, \ +-5, 53, -279, 32759, 289, -55, 6, 0, \ +-2, 18, -94, 32767, 95, -18, 2, 0, \ +} diff --git a/libao2/fir.h b/libao2/fir.h new file mode 100644 index 0000000000..0124d03d9e --- /dev/null +++ b/libao2/fir.h @@ -0,0 +1,144 @@ +/*============================================================================= +// +// This file is part of mplayer. +// +// mplayer is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// mplayer is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with mplayer; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Copyright 2001 Anders Johansson ajh@atri.curtin.edu.au +// +//============================================================================= +*/ + +#ifndef __FIR_H__ +#define __FIR_H__ + +/* 4, 8 and 16 tap FIR filters implemented using SSE instructions + int16_t* x Input data + int16_t* y Output value + int16_t* w Filter weights + + C function + for(int i = 0 ; i < L ; i++) + *y += w[i]*x[i]; +*/ + +#ifdef HAVE_SSE + +// This block should be MMX only compatible, but it isn't... +#ifdef L4 +#define LOAD_QUE(x) \ + __asm __volatile("movq %0, %%mm2\n\t" \ + : \ + :"m"((x)[0]) \ + :"memory"); +#define SAVE_QUE(x) \ + __asm __volatile("movq %%mm2, %0\n\t" \ + :"=m"(x[0]) \ + : \ + :"memory"); +#define UPDATE_QUE(in) \ + __asm __volatile("psllq $16, %%mm2\n\t" \ + "pinsrw $0, %0,%%mm2\n\t" \ + : \ + :"m" ((in)[0]) \ + :"memory"); +#define FIR(x,w,y) \ + __asm __volatile("movq %%mm2, %%mm0\n\t" \ + "pmaddwd %1, %%mm0\n\t" \ + "movq %%mm0, %%mm1\n\t" \ + "psrlq $32, %%mm1\n\t" \ + "paddd %%mm0, %%mm1\n\t" \ + "movd %%mm1, %%esi\n\t" \ + "shrl $16, %%esi\n\t" \ + "movw %%si, %0\n\t" \ + : "=m" ((y)[0]) \ + : "m" ((w)[0]) \ + : "memory", "%esi"); +#endif /* L4 */ + +// It is possible to make the 8 bit filter a lot faster by using the +// 128 bit registers, feel free to optimize. +#ifdef L8 +#define LOAD_QUE(x) \ + __asm __volatile("movq %0, %%mm5\n\t" \ + "movq %1, %%mm4\n\t" \ + : \ + :"m"((x)[0]), \ + "m"((x)[4]) \ + :"memory"); +#define SAVE_QUE(x) \ + __asm __volatile("movq %%mm5, %0\n\t" \ + "movq %%mm4, %1\n\t" \ + :"=m"((x)[0]), \ + "=m"((x)[4]) \ + : \ + :"memory"); + +// Below operation could replace line 2 to 5 in macro below but can +// not cause of compiler bug ??? +// "pextrw $3, %%mm5,%%eax\n\t" +#define UPDATE_QUE(in) \ + __asm __volatile("psllq $16, %%mm4\n\t" \ + "movq %%mm5, %%mm0\n\t" \ + "psrlq $48, %%mm0\n\t" \ + "movd %%mm0, %%eax\n\t" \ + "pinsrw $0, %%eax,%%mm4\n\t" \ + "psllq $16, %%mm5\n\t" \ + "pinsrw $0, %0,%%mm5\n\t" \ + : \ + :"m" ((in)[0]) \ + :"memory", "%eax"); +#define FIR(x,w,y) \ + __asm __volatile("movq %%mm5, %%mm0\n\t" \ + "pmaddwd %1, %%mm0\n\t" \ + "movq %%mm4, %%mm1\n\t" \ + "pmaddwd %2, %%mm1\n\t" \ + "paddd %%mm1, %%mm0\n\t" \ + "movq %%mm0, %%mm1\n\t" \ + "psrlq $32, %%mm1\n\t" \ + "paddd %%mm0, %%mm1\n\t" \ + "movd %%mm1, %%esi\n\t" \ + "shrl $16, %%esi\n\t" \ + "movw %%si, %0\n\t" \ + : "=m" ((y)[0]) \ + : "m" ((w)[0]), \ + "m" ((w)[4]) \ + : "memory", "%esi"); +#endif /* L8 */ + +#else /* HAVE_SSE */ + +#define LOAD_QUE(x) +#define SAVE_QUE(x) +#define UPDATE_QUE(inm) \ + xi=(--xi)&(L-1); \ + x[xi]=x[xi+L]=*inm; + +#ifdef L4 +#define FIR(x,w,y) \ + y[0]=(w[0]*x[0]+w[1]*x[1]+w[2]*x[2]+w[3]*x[3]) >> 16; +#else +#define FIR(x,w,y){ \ + int16_t a = (w[0]*x[0]+w[1]*x[1]+w[2]*x[2]+w[3]*x[3]) >> 16; \ + int16_t b = (w[4]*x[4]+w[5]*x[5]+w[6]*x[6]+w[7]*x[7]) >> 16; \ + y[0] = a+b; \ +} +#endif /* L4 */ + +#endif /* HAVE_SSE */ + +#endif /* __FIR_H__ */ + + diff --git a/libao2/pl_resample.c b/libao2/pl_resample.c new file mode 100644 index 0000000000..3ab049ca08 --- /dev/null +++ b/libao2/pl_resample.c @@ -0,0 +1,239 @@ +/*============================================================================= +// +// This file is part of mplayer. +// +// mplayer is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// mplayer is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with mplayer; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Copyright 2001 Anders Johansson ajh@atri.curtin.edu.au +// +//============================================================================= +*/ + +/* This audio output plugin changes the sample rate. The output + samplerate from this plugin is specified by using the switch + `fout=F' where F is the desired output sample frequency +*/ + +#define PLUGIN + +#include +#include +#include +#include + +#include "audio_out.h" +#include "audio_plugin.h" +#include "audio_plugin_internal.h" +#include "afmt.h" +//#include "../config.h" + +static ao_info_t info = +{ + "Sample frequency conversion audio plugin", + "resample", + "Anders", + "" +}; + +LIBAO_PLUGIN_EXTERN(resample) + +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) + +/* Below definition selects the length of each poly phase component. + Valid definitions are L4 and L8, where the number denotes the + length of the filter. This definition affects the computational + complexity (see play()), the performance (see filter.h) and the + memory usage. For now the filterlenght is choosen to 4 and without + assembly optimization if no SSE is present. +*/ +#ifdef HAVE_SSE +#define L8 1 // Filter bank type +#define W W8 // Filter bank parameters +#define L 8 // Filter length +#else +#define L4 1 +#define W W4 +#define L 4 +#endif + +#define CH 6 // Max number of channels +#define UP 128 /* Up sampling factor. Increasing this value will + improve frequency accuracy. Think about the L1 + cashing of filter parameters - how big can it be? */ + +#include "fir.h" +#include "filter.h" + +// local data +typedef struct pl_resample_s +{ + int16_t* data; // Data buffer + int16_t* w; // Current filter weights + uint16_t dn; // Down sampling factor + uint16_t up; // Up sampling factor + int channels; // Number of channels + int len; // Lenght of buffer + int bypass; // Bypass this plugin + int16_t ws[UP*L]; // List of all available filters + int16_t xs[CH][L*2]; // Circular buffers +} pl_resample_t; + +static pl_resample_t pl_resample = {NULL,NULL,1,1,1,0,0,W}; + +// to set/get/query special features/parameters +static int control(int cmd,int arg){ + switch(cmd){ + case AOCONTROL_PLUGIN_SET_LEN: + if(pl_resample.data) + free(pl_resample.data); + pl_resample.len = ao_plugin_data.len; + pl_resample.data=(int16_t*)malloc(pl_resample.len); + if(!pl_resample.data) + return CONTROL_ERROR; + ao_plugin_data.len = (int)((double)ao_plugin_data.len * + ((double)pl_resample.up)/ + ((double)pl_resample.dn)); + return CONTROL_OK; + } + return -1; +} + +// open & setup audio device +// return: 1=success 0=fail +static int init(){ + int fin=ao_plugin_data.rate; + int fout=ao_plugin_cfg.pl_resample_fout; + pl_resample.w=pl_resample.ws; + pl_resample.up=UP; + + // Sheck input format + if(ao_plugin_data.format != AFMT_S16_LE){ + fprintf(stderr,"[pl_resample] Input audio format not yet suported. \n"); + return 0; + } + // Sanity check and calculate down sampling factor + if((float)max(fin,fout)/(float)min(fin,fout) > 10){ + fprintf(stderr,"[pl_resample] The difference between fin and fout is too large.\n"); + return 0; + } + pl_resample.dn=(int)(0.5+((float)(fin*pl_resample.up))/((float)fout)); + if(pl_resample.dn == pl_resample.up){ + fprintf(stderr,"[pl_resample] Fin is too close to fout no conversion is needed.\n"); + pl_resample.bypass=1; + return 1; + } + pl_resample.channels=ao_plugin_data.channels; + if(ao_plugin_data.channels>CH){ + fprintf(stderr,"[pl_resample] Too many channels, max is 6.\n"); + return 0; + } + + // Tell the world what we are up to + printf("[pl_resample] Up=%i, Down=%i, True fout=%f\n", + pl_resample.up,pl_resample.dn, + ((float)fin*pl_resample.up)/((float)pl_resample.dn)); + + // This plugin changes buffersize and adds some delay + ao_plugin_data.sz_mult/=((float)pl_resample.up)/((float)pl_resample.dn); + ao_plugin_data.delay_fix-= ((float)L/2) * (1/fout); + ao_plugin_data.rate=fout; + return 1; +} + +// close plugin +static void uninit(){ + if(pl_resample.data) + free(pl_resample.data); + pl_resample.data=NULL; +} + +// empty buffers +static void reset(){ +} + +// processes 'ao_plugin_data.len' bytes of 'data' +// called for every block of data +// FIXME: this routine needs to be optimized (it is probably possible to do a lot here) +static int play(){ + static uint16_t pwi = 0; // Index for w + static uint16_t pxi = 0; // Index for circular queue + static uint16_t pi = 1; // Number of new samples to put in x queue + + uint16_t ci = pl_resample.channels; // Index for channels + uint16_t len = 0; // Number of output samples + uint16_t nch = pl_resample.channels; // Number of channels + uint16_t inc = pl_resample.dn/pl_resample.up; + uint16_t level = pl_resample.dn%pl_resample.up; + uint16_t up = pl_resample.up; + uint16_t dn = pl_resample.dn; + + register uint16_t i,wi,xi; // Temporary indexes + + if(pl_resample.bypass) + return 1; + + // Index current channel + while(ci--){ + // Temporary pointers + register int16_t* x = pl_resample.xs[ci]; + register int16_t* in = ((int16_t*)ao_plugin_data.data)+ci; + register int16_t* out = pl_resample.data+ci; + // Block loop end + register int16_t* end = in+ao_plugin_data.len/2; + i = pi; wi = pwi; xi = pxi; + + LOAD_QUE(x); + if(0!=i) goto L1; + while(in < end){ + // Update wi to point at the correct polyphase component + wi=(wi+dn)%up; + + /* Update circular buffer x. This loop will be updated 0 or 1 time + for upsamling and inc or inc + 1 times for downsampling */ + if(wi= end) goto L2; + if(i) goto L1; + L2: if(i) goto L5; + i=inc; + + /* Get the correct polyphase component and the correct startpoint + in the circular bufer and run the FIR filter */ + FIR((&x[xi]),(&pl_resample.w[wi*L]),out); + len++; + out+=nch; + } +L5: + SAVE_QUE(x); + } + + // Save values that needs to be kept for next time + pwi = wi; + pxi = xi; + pi = i; + // Set new data + ao_plugin_data.len=len*2; + ao_plugin_data.data=pl_resample.data; + return 1; +} + + + + +