comparison libaf/af_bs2b.c @ 29202:239573db53a1

Support for libbs2b ver. 3.0.0 API. Now filter parameters are highly controllable, virtually all audio formats are supported, and new profiles are available.
author bircoph
date Sun, 03 May 2009 21:51:37 +0000
parents 3afe8b737f43
children 80865c30ee80
comparison
equal deleted inserted replaced
29201:06e7728c5b34 29202:239573db53a1
22 */ 22 */
23 23
24 #include <bs2b.h> 24 #include <bs2b.h>
25 #include <inttypes.h> 25 #include <inttypes.h>
26 #include <stdlib.h> 26 #include <stdlib.h>
27 #include <string.h>
27 28
28 #include "af.h" 29 #include "af.h"
29 #include "subopt-helper.h" 30 #include "subopt-helper.h"
30 31
31 /// Internal specific data of the filter 32 /// Internal specific data of the filter
32 struct af_bs2b { 33 struct af_bs2b {
33 int level; ///< crossfeed level 34 int fcut; ///< cut frequency in Hz
34 int profile; ///< profile (easy or normal) 35 int feed; ///< feed level for low frequencies in 0.1*dB
36 char *profile; ///< profile (available crossfeed presets)
35 t_bs2bdp filter; ///< instance of a library filter 37 t_bs2bdp filter; ///< instance of a library filter
36 }; 38 };
37 39
38 #define PLAY(name,type) \ 40 #define PLAY(name,type) \
39 static af_data_t *play_##name(struct af_instance_s *af, af_data_t *data) \ 41 static af_data_t *play_##name(struct af_instance_s *af, af_data_t *data) \
47 49
48 PLAY(f,float) 50 PLAY(f,float)
49 PLAY(fbe,float) 51 PLAY(fbe,float)
50 PLAY(fle,float) 52 PLAY(fle,float)
51 PLAY(s32be,int32_t) 53 PLAY(s32be,int32_t)
54 PLAY(u32be, uint32_t)
52 PLAY(s32le,int32_t) 55 PLAY(s32le,int32_t)
56 PLAY(u32le, uint32_t)
53 PLAY(s24be,bs2b_int24_t) 57 PLAY(s24be,bs2b_int24_t)
58 PLAY(u24be, bs2b_uint24_t)
54 PLAY(s24le,bs2b_int24_t) 59 PLAY(s24le,bs2b_int24_t)
60 PLAY(u24le, bs2b_uint24_t)
55 PLAY(s16be,int16_t) 61 PLAY(s16be,int16_t)
62 PLAY(u16be, uint16_t)
56 PLAY(s16le,int16_t) 63 PLAY(s16le,int16_t)
64 PLAY(u16le, uint16_t)
57 PLAY(s8,int8_t) 65 PLAY(s8,int8_t)
58 PLAY(u8,uint8_t) 66 PLAY(u8,uint8_t)
59 67
60 /// Sanity check for level value 68 /// Sanity check for fcut value
61 static int test_level(void *par) 69 static int test_fcut(void *par)
62 { 70 {
63 const int val = *(int*)par; 71 const int val = *(int*)par;
64 if (val >= 1 && val <= BS2B_CLEVELS) 72 if (val >= BS2B_MINFCUT && val <= BS2B_MAXFCUT)
65 return 1; 73 return 1;
66 74
67 mp_msg(MSGT_AFILTER,MSGL_ERR, "[bs2b] Level must be in range 1..%i, but " 75 mp_msg(MSGT_AFILTER, MSGL_ERR,
68 "current value is %i.\n", BS2B_CLEVELS, val); 76 "[bs2b] Cut frequency must be in range [%d..%d], but current value is %d.\n",
77 BS2B_MINFCUT, BS2B_MAXFCUT, val);
69 return 0; 78 return 0;
70 } 79 }
71 80
72 /// Sanity check for profile value 81 /// Sanity check for feed value
73 static int test_profile(void *par) 82 static int test_feed(void *par)
74 { 83 {
75 const int val = *(int*)par; 84 const int val = *(int*)par;
76 if (val >= 0 && val <= 1) 85 if (val >= BS2B_MINFEED && val <= BS2B_MAXFEED)
77 return 1; 86 return 1;
78 87
79 mp_msg(MSGT_AFILTER,MSGL_ERR, "[bs2b] Profile must be either 0 or 1, but " 88 mp_msg(MSGT_AFILTER, MSGL_ERR,
80 "current value is %i.\n", val); 89 "[bs2b] Feed level must be in range [%d..%d], but current value is %d.\n",
90 BS2B_MINFEED, BS2B_MAXFEED, val);
81 return 0; 91 return 0;
82 } 92 }
83 93
84 /// Initialization and runtime control 94 /// Initialization and runtime control
85 static int control(struct af_instance_s *af, int cmd, void *arg) 95 static int control(struct af_instance_s *af, int cmd, void *arg)
109 af->play = play_fle; 119 af->play = play_fle;
110 break; 120 break;
111 case AF_FORMAT_S32_BE: 121 case AF_FORMAT_S32_BE:
112 af->play = play_s32be; 122 af->play = play_s32be;
113 break; 123 break;
124 case AF_FORMAT_U32_BE:
125 af->play = play_u32be;
126 break;
114 case AF_FORMAT_S32_LE: 127 case AF_FORMAT_S32_LE:
115 af->play = play_s32le; 128 af->play = play_s32le;
116 break; 129 break;
130 case AF_FORMAT_U32_LE:
131 af->play = play_u32le;
132 break;
117 case AF_FORMAT_S24_BE: 133 case AF_FORMAT_S24_BE:
118 af->play = play_s24be; 134 af->play = play_s24be;
119 break; 135 break;
136 case AF_FORMAT_U24_BE:
137 af->play = play_u24be;
138 break;
120 case AF_FORMAT_S24_LE: 139 case AF_FORMAT_S24_LE:
121 af->play = play_s24le; 140 af->play = play_s24le;
122 break; 141 break;
142 case AF_FORMAT_U24_LE:
143 af->play = play_u24le;
144 break;
123 case AF_FORMAT_S16_BE: 145 case AF_FORMAT_S16_BE:
124 af->play = play_s16be; 146 af->play = play_s16be;
125 break; 147 break;
148 case AF_FORMAT_U16_BE:
149 af->play = play_u16be;
150 break;
126 case AF_FORMAT_S16_LE: 151 case AF_FORMAT_S16_LE:
127 af->play = play_s16le; 152 af->play = play_s16le;
153 break;
154 case AF_FORMAT_U16_LE:
155 af->play = play_u16le;
128 break; 156 break;
129 case AF_FORMAT_S8: 157 case AF_FORMAT_S8:
130 af->play = play_s8; 158 af->play = play_s8;
131 break; 159 break;
132 case AF_FORMAT_U8: 160 case AF_FORMAT_U8:
137 af->data->format = AF_FORMAT_FLOAT_NE; 165 af->data->format = AF_FORMAT_FLOAT_NE;
138 af->data->bps=4; 166 af->data->bps=4;
139 break; 167 break;
140 } 168 }
141 169
170 // bs2b have srate limits, try to resample if needed
171 if (af->data->rate > BS2B_MAXSRATE || af->data->rate < BS2B_MINSRATE) {
172 af->data->rate = BS2B_DEFAULT_SRATE;
173 mp_msg(MSGT_AFILTER, MSGL_WARN,
174 "[bs2b] Requested sample rate %d Hz is out of bounds [%d..%d] Hz.\n"
175 "[bs2b] Trying to resample to %d Hz.\n",
176 af->data->rate, BS2B_MINSRATE, BS2B_MAXSRATE, BS2B_DEFAULT_SRATE);
177 }
142 bs2b_set_srate(s->filter, (long)af->data->rate); 178 bs2b_set_srate(s->filter, (long)af->data->rate);
143 mp_msg(MSGT_AFILTER,MSGL_V, "[bs2b] using format %s\n", 179 mp_msg(MSGT_AFILTER,MSGL_V, "[bs2b] using format %s\n",
144 af_fmt2str(af->data->format,buf,256)); 180 af_fmt2str(af->data->format,buf,256));
145 181
146 return af_test_output(af,(af_data_t*)arg); 182 return af_test_output(af,(af_data_t*)arg);
147 } 183 }
148 case AF_CONTROL_COMMAND_LINE: { 184 case AF_CONTROL_COMMAND_LINE: {
149 const opt_t subopts[] = { 185 const opt_t subopts[] = {
150 {"level", OPT_ARG_INT, &s->level, test_level}, 186 {"fcut", OPT_ARG_INT, &s->fcut, test_fcut},
151 {"profile", OPT_ARG_INT, &s->profile, test_profile}, 187 {"feed", OPT_ARG_INT, &s->feed, test_feed},
188 {"profile", OPT_ARG_MSTRZ, &s->profile, NULL},
152 {NULL} 189 {NULL}
153 }; 190 };
154 if (subopt_parse(arg, subopts) != 0) { 191 if (subopt_parse(arg, subopts) != 0) {
155 mp_msg(MSGT_AFILTER,MSGL_ERR, "[bs2b] Invalid option specified.\n"); 192 mp_msg(MSGT_AFILTER,MSGL_ERR, "[bs2b] Invalid option specified.\n");
193 free(s->profile);
156 return AF_ERROR; 194 return AF_ERROR;
157 } 195 }
158 196 // parse profile if specified
159 bs2b_set_level(s->filter, s->level + s->profile ? BS2B_CLEVELS : 0); 197 if (s->profile) {
160 mp_msg(MSGT_AFILTER,MSGL_V, "[bs2b] using profile %i, level %i\n", 198 if (!strcmp(s->profile, "default"))
161 s->profile, s->level); 199 bs2b_set_level(s->filter, BS2B_DEFAULT_CLEVEL);
200 else if (!strcmp(s->profile, "cmoy"))
201 bs2b_set_level(s->filter, BS2B_CMOY_CLEVEL);
202 else if (!strcmp(s->profile, "jmeier"))
203 bs2b_set_level(s->filter, BS2B_JMEIER_CLEVEL);
204 else {
205 mp_msg(MSGT_AFILTER, MSGL_ERR,
206 "[bs2b] Invalid profile specified: %s.\n"
207 "[bs2b] Available profiles are: default, cmoy, jmeier.\n",
208 s->profile);
209 free(s->profile);
210 return AF_ERROR;
211 }
212 }
213 // set fcut and feed only if specified, otherwise defaults will be used
214 if (s->fcut)
215 bs2b_set_level_fcut(s->filter, s->fcut);
216 if (s->feed)
217 bs2b_set_level_feed(s->filter, s->feed);
218
219 mp_msg(MSGT_AFILTER, MSGL_V,
220 "[bs2b] using cut frequency %d, LF feed level %d\n",
221 bs2b_get_level_fcut(s->filter), bs2b_get_level_feed(s->filter));
222 free(s->profile);
162 return AF_OK; 223 return AF_OK;
163 } 224 }
164 } 225 }
165 return AF_UNKNOWN; 226 return AF_UNKNOWN;
166 } 227 }
193 if (!(s->filter = bs2b_open())) { 254 if (!(s->filter = bs2b_open())) {
194 free(af->data); 255 free(af->data);
195 free(af->setup); 256 free(af->setup);
196 return AF_ERROR; 257 return AF_ERROR;
197 } 258 }
198 // Set defaults the same as in the library: 259 // Set zero defaults indicating no option was specified.
199 s->level = 3; 260 s->profile = NULL;
200 s->profile = 1; 261 s->fcut = 0;
262 s->feed = 0;
201 return AF_OK; 263 return AF_OK;
202 } 264 }
203 265
204 /// Description of this filter 266 /// Description of this filter
205 af_info_t af_info_bs2b = { 267 af_info_t af_info_bs2b = {