Mercurial > mplayer.hg
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 = { |