1 /* $NetBSD: auconv.c,v 1.21 2008/03/04 18:23:44 cube Exp $ */
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the Computer Systems
18 * Engineering Group at Lawrence Berkeley Laboratory.
19 * 4. Neither the name of the University nor of the Laboratory may be used
20 * to endorse or promote products derived from this software without
21 * specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: auconv.c,v 1.21 2008/03/04 18:23:44 cube Exp $");
40 #include <sys/types.h>
41 #include <sys/audioio.h>
42 #include <sys/device.h>
43 #include <sys/errno.h>
44 #include <sys/malloc.h>
46 #include <sys/systm.h>
47 #include <dev/audio_if.h>
48 #include <dev/auconv.h>
49 #include <dev/mulaw.h>
50 #include <machine/limits.h>
59 #include <aurateconv.h> /* generated by config(8) */
60 #include <mulaw.h> /* generated by config(8) */
62 /* #define AUCONV_DEBUG */
64 # define DPRINTF(x) printf x
70 static int auconv_rateconv_supportable(u_int
, u_int
, u_int
);
71 static int auconv_rateconv_check_channels(const struct audio_format
*, int,
72 int, const audio_params_t
*,
73 stream_filter_list_t
*);
74 static int auconv_rateconv_check_rates(const struct audio_format
*, int,
75 int, const audio_params_t
*,
77 stream_filter_list_t
*);
80 static void auconv_dump_formats(const struct audio_format
*, int);
82 static void auconv_dump_params(const audio_params_t
*);
83 static int auconv_exact_match(const struct audio_format
*, int, int,
84 const struct audio_params
*);
85 static u_int
auconv_normalize_encoding(u_int
, u_int
);
86 static int auconv_is_supported_rate(const struct audio_format
*, u_int
);
87 static int auconv_add_encoding(int, int, int, struct audio_encoding_set
**,
91 #define AUCONV_MALLOC(size) malloc(size, M_DEVBUF, M_NOWAIT)
92 #define AUCONV_REALLOC(p, size) realloc(p, size, M_DEVBUF, M_NOWAIT)
93 #define AUCONV_FREE(p) free(p, M_DEVBUF)
95 #define AUCONV_MALLOC(size) malloc(size)
96 #define AUCONV_REALLOC(p, size) realloc(p, size)
97 #define AUCONV_FREE(p) free(p)
100 struct audio_encoding_set
{
102 audio_encoding_t items
[1];
104 #define ENCODING_SET_SIZE(n) (offsetof(struct audio_encoding_set, items) \
105 + sizeof(audio_encoding_t) * (n))
111 stream_filter_factory_t
*play_conv
;
112 stream_filter_factory_t
*rec_conv
;
115 * SLINEAR-16 or SLINEAR-24 should precede in a table because
116 * aurateconv supports only SLINEAR.
118 static const struct conv_table s8_table
[] = {
119 {AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
120 linear8_to_linear16
, linear16_to_linear8
},
121 {AUDIO_ENCODING_SLINEAR_BE
, 16, 16,
122 linear8_to_linear16
, linear16_to_linear8
},
123 {AUDIO_ENCODING_ULINEAR_LE
, 8, 8,
124 change_sign8
, change_sign8
},
125 {0, 0, 0, NULL
, NULL
}};
126 static const struct conv_table u8_table
[] = {
127 {AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
128 linear8_to_linear16
, linear16_to_linear8
},
129 {AUDIO_ENCODING_SLINEAR_BE
, 16, 16,
130 linear8_to_linear16
, linear16_to_linear8
},
131 {AUDIO_ENCODING_SLINEAR_LE
, 8, 8,
132 change_sign8
, change_sign8
},
133 {AUDIO_ENCODING_ULINEAR_LE
, 16, 16,
134 linear8_to_linear16
, linear16_to_linear8
},
135 {AUDIO_ENCODING_ULINEAR_BE
, 16, 16,
136 linear8_to_linear16
, linear16_to_linear8
},
137 {0, 0, 0, NULL
, NULL
}};
138 static const struct conv_table s16le_table
[] = {
139 {AUDIO_ENCODING_SLINEAR_BE
, 16, 16,
140 swap_bytes
, swap_bytes
},
141 {AUDIO_ENCODING_ULINEAR_LE
, 16, 16,
142 change_sign16
, change_sign16
},
143 {AUDIO_ENCODING_ULINEAR_BE
, 16, 16,
144 swap_bytes_change_sign16
, swap_bytes_change_sign16
},
145 {0, 0, 0, NULL
, NULL
}};
146 static const struct conv_table s16be_table
[] = {
147 {AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
148 swap_bytes
, swap_bytes
},
149 {AUDIO_ENCODING_ULINEAR_BE
, 16, 16,
150 change_sign16
, change_sign16
},
151 {AUDIO_ENCODING_ULINEAR_LE
, 16, 16,
152 swap_bytes_change_sign16
, swap_bytes_change_sign16
},
153 {0, 0, 0, NULL
, NULL
}};
154 static const struct conv_table u16le_table
[] = {
155 {AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
156 change_sign16
, change_sign16
},
157 {AUDIO_ENCODING_ULINEAR_BE
, 16, 16,
158 swap_bytes
, swap_bytes
},
159 {AUDIO_ENCODING_SLINEAR_BE
, 16, 16,
160 swap_bytes_change_sign16
, swap_bytes_change_sign16
},
161 {0, 0, 0, NULL
, NULL
}};
162 static const struct conv_table u16be_table
[] = {
163 {AUDIO_ENCODING_SLINEAR_BE
, 16, 16,
164 change_sign16
, change_sign16
},
165 {AUDIO_ENCODING_ULINEAR_LE
, 16, 16,
166 swap_bytes
, swap_bytes
},
167 {AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
168 swap_bytes_change_sign16
, swap_bytes_change_sign16
},
169 {0, 0, 0, NULL
, NULL
}};
171 static const struct conv_table mulaw_table
[] = {
172 {AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
173 mulaw_to_linear16
, linear16_to_mulaw
},
174 {AUDIO_ENCODING_SLINEAR_BE
, 16, 16,
175 mulaw_to_linear16
, linear16_to_mulaw
},
176 {AUDIO_ENCODING_ULINEAR_LE
, 16, 16,
177 mulaw_to_linear16
, linear16_to_mulaw
},
178 {AUDIO_ENCODING_ULINEAR_BE
, 16, 16,
179 mulaw_to_linear16
, linear16_to_mulaw
},
180 {AUDIO_ENCODING_SLINEAR_LE
, 8, 8,
181 mulaw_to_linear8
, linear8_to_mulaw
},
182 {AUDIO_ENCODING_ULINEAR_LE
, 8, 8,
183 mulaw_to_linear8
, linear8_to_mulaw
},
184 {0, 0, 0, NULL
, NULL
}};
185 static const struct conv_table alaw_table
[] = {
186 {AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
187 alaw_to_linear16
, linear16_to_alaw
},
188 {AUDIO_ENCODING_SLINEAR_BE
, 16, 16,
189 alaw_to_linear16
, linear16_to_alaw
},
190 {AUDIO_ENCODING_ULINEAR_LE
, 16, 16,
191 alaw_to_linear16
, linear16_to_alaw
},
192 {AUDIO_ENCODING_ULINEAR_BE
, 16, 16,
193 alaw_to_linear16
, linear16_to_alaw
},
194 {AUDIO_ENCODING_SLINEAR_LE
, 8, 8,
195 alaw_to_linear8
, linear8_to_alaw
},
196 {AUDIO_ENCODING_ULINEAR_LE
, 8, 8,
197 alaw_to_linear8
, linear8_to_alaw
},
198 {0, 0, 0, NULL
, NULL
}};
201 static const char *encoding_dbg_names
[] = {
202 "none", AudioEmulaw
, AudioEalaw
, "pcm16",
203 "pcm8", AudioEadpcm
, AudioEslinear_le
, AudioEslinear_be
,
204 AudioEulinear_le
, AudioEulinear_be
,
205 AudioEslinear
, AudioEulinear
,
206 AudioEmpeg_l1_stream
, AudioEmpeg_l1_packets
,
207 AudioEmpeg_l1_system
, AudioEmpeg_l2_stream
,
208 AudioEmpeg_l2_packets
, AudioEmpeg_l2_system
213 stream_filter_set_fetcher(stream_filter_t
*this, stream_fetcher_t
*p
)
219 stream_filter_set_inputbuffer(stream_filter_t
*this, audio_stream_t
*stream
)
225 auconv_nocontext_filter_factory(
226 int (*fetch_to
)(stream_fetcher_t
*, audio_stream_t
*, int))
228 stream_filter_t
*this;
230 this = AUCONV_MALLOC(sizeof(stream_filter_t
));
233 this->base
.fetch_to
= fetch_to
;
234 this->dtor
= auconv_nocontext_filter_dtor
;
235 this->set_fetcher
= stream_filter_set_fetcher
;
236 this->set_inputbuffer
= stream_filter_set_inputbuffer
;
243 auconv_nocontext_filter_dtor(struct stream_filter
*this)
249 #define DEFINE_FILTER(name) \
251 name##_fetch_to(stream_fetcher_t *, audio_stream_t *, int); \
253 name(struct audio_softc *sc, const audio_params_t *from, \
254 const audio_params_t *to) \
256 return auconv_nocontext_filter_factory(name##_fetch_to); \
259 name##_fetch_to(stream_fetcher_t *self, audio_stream_t *dst, int max_used)
261 DEFINE_FILTER(change_sign8
)
263 stream_filter_t
*this;
266 this = (stream_filter_t
*)self
;
267 if ((err
= this->prev
->fetch_to(this->prev
, this->src
, max_used
)))
269 m
= dst
->end
- dst
->start
;
270 m
= min(m
, max_used
);
271 FILTER_LOOP_PROLOGUE(this->src
, 1, dst
, 1, m
) {
273 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
277 DEFINE_FILTER(change_sign16
)
279 stream_filter_t
*this;
282 this = (stream_filter_t
*)self
;
283 max_used
= (max_used
+ 1) & ~1; /* round up to even */
284 if ((err
= this->prev
->fetch_to(this->prev
, this->src
, max_used
)))
286 m
= (dst
->end
- dst
->start
) & ~1;
287 m
= min(m
, max_used
);
288 enc
= dst
->param
.encoding
;
289 if (enc
== AUDIO_ENCODING_SLINEAR_LE
290 || enc
== AUDIO_ENCODING_ULINEAR_LE
) {
291 FILTER_LOOP_PROLOGUE(this->src
, 2, dst
, 2, m
) {
294 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
296 FILTER_LOOP_PROLOGUE(this->src
, 2, dst
, 2, m
) {
299 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
304 DEFINE_FILTER(swap_bytes
)
306 stream_filter_t
*this;
309 this = (stream_filter_t
*)self
;
310 max_used
= (max_used
+ 1) & ~1; /* round up to even */
311 if ((err
= this->prev
->fetch_to(this->prev
, this->src
, max_used
)))
313 m
= (dst
->end
- dst
->start
) & ~1;
314 m
= min(m
, max_used
);
315 FILTER_LOOP_PROLOGUE(this->src
, 2, dst
, 2, m
) {
318 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
322 DEFINE_FILTER(swap_bytes_change_sign16
)
324 stream_filter_t
*this;
327 this = (stream_filter_t
*)self
;
328 max_used
= (max_used
+ 1) & ~1; /* round up to even */
329 if ((err
= this->prev
->fetch_to(this->prev
, this->src
, max_used
)))
331 m
= (dst
->end
- dst
->start
) & ~1;
332 m
= min(m
, max_used
);
333 enc
= dst
->param
.encoding
;
334 if (enc
== AUDIO_ENCODING_SLINEAR_LE
335 || enc
== AUDIO_ENCODING_ULINEAR_LE
) {
336 FILTER_LOOP_PROLOGUE(this->src
, 2, dst
, 2, m
) {
339 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
341 FILTER_LOOP_PROLOGUE(this->src
, 2, dst
, 2, m
) {
344 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
349 DEFINE_FILTER(linear8_to_linear16
)
351 stream_filter_t
*this;
352 int m
, err
, enc_dst
, enc_src
;
354 this = (stream_filter_t
*)self
;
355 max_used
= (max_used
+ 1) & ~1; /* round up to even */
356 if ((err
= this->prev
->fetch_to(this->prev
, this->src
, max_used
/ 2)))
358 m
= (dst
->end
- dst
->start
) & ~1;
359 m
= min(m
, max_used
);
360 enc_dst
= dst
->param
.encoding
;
361 enc_src
= this->src
->param
.encoding
;
362 if ((enc_src
== AUDIO_ENCODING_SLINEAR_LE
363 && enc_dst
== AUDIO_ENCODING_SLINEAR_LE
)
364 || (enc_src
== AUDIO_ENCODING_ULINEAR_LE
365 && enc_dst
== AUDIO_ENCODING_ULINEAR_LE
)) {
367 * slinear8 -> slinear16_le
368 * ulinear8 -> ulinear16_le
370 FILTER_LOOP_PROLOGUE(this->src
, 1, dst
, 2, m
) {
373 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
374 } else if ((enc_src
== AUDIO_ENCODING_SLINEAR_LE
375 && enc_dst
== AUDIO_ENCODING_SLINEAR_BE
)
376 || (enc_src
== AUDIO_ENCODING_ULINEAR_LE
377 && enc_dst
== AUDIO_ENCODING_ULINEAR_BE
)) {
379 * slinear8 -> slinear16_be
380 * ulinear8 -> ulinear16_be
382 FILTER_LOOP_PROLOGUE(this->src
, 1, dst
, 2, m
) {
385 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
386 } else if ((enc_src
== AUDIO_ENCODING_SLINEAR_LE
387 && enc_dst
== AUDIO_ENCODING_ULINEAR_LE
)
388 || (enc_src
== AUDIO_ENCODING_ULINEAR_LE
389 && enc_dst
== AUDIO_ENCODING_SLINEAR_LE
)) {
391 * slinear8 -> ulinear16_le
392 * ulinear8 -> slinear16_le
394 FILTER_LOOP_PROLOGUE(this->src
, 1, dst
, 2, m
) {
397 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
400 * slinear8 -> ulinear16_be
401 * ulinear8 -> slinear16_be
403 FILTER_LOOP_PROLOGUE(this->src
, 1, dst
, 2, m
) {
406 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
411 DEFINE_FILTER(linear16_to_linear8
)
413 stream_filter_t
*this;
414 int m
, err
, enc_src
, enc_dst
;
416 this = (stream_filter_t
*)self
;
417 if ((err
= this->prev
->fetch_to(this->prev
, this->src
, max_used
* 2)))
419 m
= dst
->end
- dst
->start
;
420 m
= min(m
, max_used
);
421 enc_dst
= dst
->param
.encoding
;
422 enc_src
= this->src
->param
.encoding
;
423 if ((enc_src
== AUDIO_ENCODING_SLINEAR_LE
424 && enc_dst
== AUDIO_ENCODING_SLINEAR_LE
)
425 || (enc_src
== AUDIO_ENCODING_ULINEAR_LE
426 && enc_dst
== AUDIO_ENCODING_ULINEAR_LE
)) {
428 * slinear16_le -> slinear8
429 * ulinear16_le -> ulinear8
431 FILTER_LOOP_PROLOGUE(this->src
, 2, dst
, 1, m
) {
433 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
434 } else if ((enc_src
== AUDIO_ENCODING_SLINEAR_LE
435 && enc_dst
== AUDIO_ENCODING_ULINEAR_LE
)
436 || (enc_src
== AUDIO_ENCODING_ULINEAR_LE
437 && enc_dst
== AUDIO_ENCODING_SLINEAR_LE
)) {
439 * slinear16_le -> ulinear8
440 * ulinear16_le -> slinear8
442 FILTER_LOOP_PROLOGUE(this->src
, 2, dst
, 1, m
) {
444 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
445 } else if ((enc_src
== AUDIO_ENCODING_SLINEAR_BE
446 && enc_dst
== AUDIO_ENCODING_SLINEAR_LE
)
447 || (enc_src
== AUDIO_ENCODING_ULINEAR_BE
448 && enc_dst
== AUDIO_ENCODING_ULINEAR_LE
)) {
450 * slinear16_be -> slinear8
451 * ulinear16_be -> ulinear8
453 FILTER_LOOP_PROLOGUE(this->src
, 2, dst
, 1, m
) {
455 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
458 * slinear16_be -> ulinear8
459 * ulinear16_be -> slinear8
461 FILTER_LOOP_PROLOGUE(this->src
, 2, dst
, 1, m
) {
463 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
469 * Set appropriate parameters in `param,' and return the index in
470 * the hardware capability array `formats.'
472 * @param formats [IN] An array of formats which a hardware can support.
473 * @param nformats [IN] The number of elements of the array.
474 * @param mode [IN] Either AUMODE_PLAY or AUMODE_RECORD.
475 * @param param [IN] Requested format. param->sw_code may be set.
476 * @param rateconv [IN] true if aurateconv may be used.
477 * @param list [OUT] stream_filters required for param.
478 * @return The index of selected audio_format entry. -1 if the device
479 * can not support the specified param.
482 auconv_set_converter(const struct audio_format
*formats
, int nformats
,
483 int mode
, const audio_params_t
*param
, int rateconv
,
484 stream_filter_list_t
*list
)
487 const struct conv_table
*table
;
488 stream_filter_factory_t
*conv
;
493 DPRINTF(("%s: ENTER rateconv=%d\n", __func__
, rateconv
));
494 auconv_dump_formats(formats
, nformats
);
496 enc
= auconv_normalize_encoding(param
->encoding
, param
->precision
);
498 /* check support by native format */
499 i
= auconv_exact_match(formats
, nformats
, mode
, param
);
501 DPRINTF(("%s: LEAVE with %d (exact)\n", __func__
, i
));
506 /* native format with aurateconv */
507 DPRINTF(("%s: native with aurateconv\n", __func__
));
509 && auconv_rateconv_supportable(enc
, param
->precision
,
511 i
= auconv_rateconv_check_channels(formats
, nformats
,
514 DPRINTF(("%s: LEAVE with %d (aurateconv1)\n", __func__
, i
));
520 /* check for emulation */
521 DPRINTF(("%s: encoding emulation\n", __func__
));
524 case AUDIO_ENCODING_SLINEAR_LE
:
525 if (param
->precision
== 8)
527 else if (param
->precision
== 16)
530 case AUDIO_ENCODING_SLINEAR_BE
:
531 if (param
->precision
== 8)
533 else if (param
->precision
== 16)
536 case AUDIO_ENCODING_ULINEAR_LE
:
537 if (param
->precision
== 8)
539 else if (param
->precision
== 16)
542 case AUDIO_ENCODING_ULINEAR_BE
:
543 if (param
->precision
== 8)
545 else if (param
->precision
== 16)
549 case AUDIO_ENCODING_ULAW
:
552 case AUDIO_ENCODING_ALAW
:
558 DPRINTF(("%s: LEAVE with -1 (no-emultable)\n", __func__
));
562 for (j
= 0; table
[j
].precision
!= 0; j
++) {
563 work
.encoding
= table
[j
].encoding
;
564 work
.precision
= table
[j
].precision
;
565 work
.validbits
= table
[j
].validbits
;
566 i
= auconv_exact_match(formats
, nformats
, mode
, &work
);
568 conv
= mode
== AUMODE_PLAY
569 ? table
[j
].play_conv
: table
[j
].rec_conv
;
570 list
->append(list
, conv
, &work
);
571 DPRINTF(("%s: LEAVE with %d (emultable)\n", __func__
, i
));
578 /* emulation with aurateconv */
579 DPRINTF(("%s: encoding emulation with aurateconv\n", __func__
));
581 DPRINTF(("%s: LEAVE with -1 (no-rateconv)\n", __func__
));
585 for (j
= 0; table
[j
].precision
!= 0; j
++) {
586 if (!auconv_rateconv_supportable(table
[j
].encoding
,
590 work
.encoding
= table
[j
].encoding
;
591 work
.precision
= table
[j
].precision
;
592 work
.validbits
= table
[j
].validbits
;
593 i
= auconv_rateconv_check_channels(formats
, nformats
,
596 /* work<=>hw conversion is already registered */
597 conv
= mode
== AUMODE_PLAY
598 ? table
[j
].play_conv
: table
[j
].rec_conv
;
599 /* register userland<=>work conversion */
600 list
->append(list
, conv
, &work
);
601 DPRINTF(("%s: LEAVE with %d (rateconv2)\n", __func__
, i
));
607 DPRINTF(("%s: LEAVE with -1 (bottom)\n", __func__
));
613 auconv_rateconv_supportable(u_int encoding
, u_int precision
, u_int validbits
)
615 if (encoding
!= AUDIO_ENCODING_SLINEAR_LE
616 && encoding
!= AUDIO_ENCODING_SLINEAR_BE
)
618 if (precision
!= 16 && precision
!= 24 && precision
!= 32)
620 if (precision
< validbits
)
626 auconv_rateconv_check_channels(const struct audio_format
*formats
, int nformats
,
627 int mode
, const audio_params_t
*param
,
628 stream_filter_list_t
*list
)
630 audio_params_t hw_param
;
634 /* check for the specified number of channels */
635 ind
= auconv_rateconv_check_rates(formats
, nformats
, mode
, param
,
640 /* check for larger numbers */
641 for (n
= param
->channels
+ 1; n
<= AUDIO_MAX_CHANNELS
; n
++) {
642 hw_param
.channels
= n
;
643 ind
= auconv_rateconv_check_rates(formats
, nformats
, mode
,
644 param
, &hw_param
, list
);
649 /* check for stereo:monaural conversion */
650 if (param
->channels
== 2) {
651 hw_param
.channels
= 1;
652 ind
= auconv_rateconv_check_rates(formats
, nformats
, mode
,
653 param
, &hw_param
, list
);
661 auconv_rateconv_check_rates(const struct audio_format
*formats
, int nformats
,
662 int mode
, const audio_params_t
*param
,
663 audio_params_t
*hw_param
, stream_filter_list_t
*list
)
665 int ind
, i
, j
, enc
, f_enc
;
666 u_int rate
, minrate
, maxrate
, orig_rate
;
669 ind
= auconv_exact_match(formats
, nformats
, mode
, hw_param
);
673 /* determine min/max of specified encoding/precision/channels */
676 enc
= auconv_normalize_encoding(param
->encoding
,
678 for (i
= 0; i
< nformats
; i
++) {
679 if (!AUFMT_IS_VALID(&formats
[i
]))
681 if ((formats
[i
].mode
& mode
) == 0)
683 f_enc
= auconv_normalize_encoding(formats
[i
].encoding
,
684 formats
[i
].precision
);
687 if (formats
[i
].validbits
!= hw_param
->validbits
)
689 if (formats
[i
].precision
!= hw_param
->precision
)
691 if (formats
[i
].channels
!= hw_param
->channels
)
693 if (formats
[i
].frequency_type
== 0) {
694 if (formats
[i
].frequency
[0] < minrate
)
695 minrate
= formats
[i
].frequency
[0];
696 if (formats
[i
].frequency
[1] > maxrate
)
697 maxrate
= formats
[i
].frequency
[1];
699 for (j
= 0; j
< formats
[i
].frequency_type
; j
++) {
700 if (formats
[i
].frequency
[j
] < minrate
)
701 minrate
= formats
[i
].frequency
[j
];
702 if (formats
[i
].frequency
[j
] > maxrate
)
703 maxrate
= formats
[i
].frequency
[j
];
710 /* try multiples of sample_rate */
711 orig_rate
= hw_param
->sample_rate
;
712 for (i
= 2; (rate
= param
->sample_rate
* i
) <= maxrate
; i
++) {
713 hw_param
->sample_rate
= rate
;
714 ind
= auconv_exact_match(formats
, nformats
, mode
, hw_param
);
719 hw_param
->sample_rate
= param
->sample_rate
>= minrate
721 ind
= auconv_exact_match(formats
, nformats
, mode
, hw_param
);
724 hw_param
->sample_rate
= orig_rate
;
728 list
->append(list
, aurateconv
, hw_param
);
731 #endif /* NAURATECONV */
735 auconv_dump_formats(const struct audio_format
*formats
, int nformats
)
737 const struct audio_format
*f
;
740 for (i
= 0; i
< nformats
; i
++) {
742 printf("[%2d]: mode=", i
);
743 if (!AUFMT_IS_VALID(f
)) {
745 } else if (f
->mode
== AUMODE_PLAY
) {
747 } else if (f
->mode
== AUMODE_RECORD
) {
749 } else if (f
->mode
== (AUMODE_PLAY
| AUMODE_RECORD
)) {
750 printf("PLAY|RECORD");
752 printf("0x%x", f
->mode
);
754 printf(" enc=%s", encoding_dbg_names
[f
->encoding
]);
755 printf(" %u/%ubit", f
->validbits
, f
->precision
);
756 printf(" %uch", f
->channels
);
758 printf(" channel_mask=");
759 if (f
->channel_mask
== AUFMT_MONAURAL
) {
761 } else if (f
->channel_mask
== AUFMT_STEREO
) {
763 } else if (f
->channel_mask
== AUFMT_SURROUND4
) {
765 } else if (f
->channel_mask
== AUFMT_DOLBY_5_1
) {
768 printf("0x%x", f
->channel_mask
);
771 if (f
->frequency_type
== 0) {
772 printf(" %uHz-%uHz", f
->frequency
[0],
775 printf(" %uHz", f
->frequency
[0]);
776 for (j
= 1; j
< f
->frequency_type
; j
++)
777 printf(",%uHz", f
->frequency
[j
]);
784 auconv_dump_params(const audio_params_t
*p
)
786 printf("enc=%s", encoding_dbg_names
[p
->encoding
]);
787 printf(" %u/%ubit", p
->validbits
, p
->precision
);
788 printf(" %uch", p
->channels
);
789 printf(" %uHz", p
->sample_rate
);
794 auconv_dump_params(const audio_params_t
*p
)
797 #endif /* AUCONV_DEBUG */
800 * a sub-routine for auconv_set_converter()
803 auconv_exact_match(const struct audio_format
*formats
, int nformats
,
804 int mode
, const audio_params_t
*param
)
808 DPRINTF(("%s: ENTER: mode=0x%x target:", __func__
, mode
));
809 auconv_dump_params(param
);
810 enc
= auconv_normalize_encoding(param
->encoding
,
812 DPRINTF(("%s: target normalized: %s\n", __func__
,
813 encoding_dbg_names
[enc
]));
814 for (i
= 0; i
< nformats
; i
++) {
815 if (!AUFMT_IS_VALID(&formats
[i
]))
817 if ((formats
[i
].mode
& mode
) == 0)
819 f_enc
= auconv_normalize_encoding(formats
[i
].encoding
,
820 formats
[i
].precision
);
821 DPRINTF(("%s: format[%d] normalized: %s\n",
822 __func__
, i
, encoding_dbg_names
[f_enc
]));
826 * XXX we need encoding-dependent check.
827 * XXX Is to check precision/channels meaningful for
830 if (formats
[i
].validbits
!= param
->validbits
)
832 if (formats
[i
].precision
!= param
->precision
)
834 if (formats
[i
].channels
!= param
->channels
)
836 if (!auconv_is_supported_rate(&formats
[i
],
845 * a sub-routine for auconv_set_converter()
846 * SLINEAR ==> SLINEAR_<host-endian>
847 * ULINEAR ==> ULINEAR_<host-endian>
848 * SLINEAR_BE 8bit ==> SLINEAR_LE 8bit
849 * ULINEAR_BE 8bit ==> ULINEAR_LE 8bit
850 * This should be the same rule as audio_check_params()
853 auconv_normalize_encoding(u_int encoding
, u_int precision
)
858 if (enc
== AUDIO_ENCODING_SLINEAR_LE
)
860 if (enc
== AUDIO_ENCODING_ULINEAR_LE
)
862 #if BYTE_ORDER == LITTLE_ENDIAN
863 if (enc
== AUDIO_ENCODING_SLINEAR
)
864 return AUDIO_ENCODING_SLINEAR_LE
;
865 else if (enc
== AUDIO_ENCODING_ULINEAR
)
866 return AUDIO_ENCODING_ULINEAR_LE
;
868 if (enc
== AUDIO_ENCODING_SLINEAR
)
869 enc
= AUDIO_ENCODING_SLINEAR_BE
;
870 else if (enc
== AUDIO_ENCODING_ULINEAR
)
871 enc
= AUDIO_ENCODING_ULINEAR_BE
;
873 if (precision
== 8 && enc
== AUDIO_ENCODING_SLINEAR_BE
)
874 return AUDIO_ENCODING_SLINEAR_LE
;
875 if (precision
== 8 && enc
== AUDIO_ENCODING_ULINEAR_BE
)
876 return AUDIO_ENCODING_ULINEAR_LE
;
881 * a sub-routine for auconv_set_converter()
884 auconv_is_supported_rate(const struct audio_format
*format
, u_int rate
)
888 if (format
->frequency_type
== 0) {
889 return format
->frequency
[0] <= rate
890 && rate
<= format
->frequency
[1];
892 for (i
= 0; i
< format
->frequency_type
; i
++) {
893 if (format
->frequency
[i
] == rate
)
900 * Create an audio_encoding_set besed on hardware capability represented
906 * if (auconv_create_encodings(formats, nformats,
907 * &sc->sc_encodings) != 0) {
911 * @param formats [IN] An array of formats which a hardware can support.
912 * @param nformats [IN] The number of elements of the array.
913 * @param encodings [OUT] receives an address of an audio_encoding_set.
914 * @return errno; 0 for success.
917 auconv_create_encodings(const struct audio_format
*formats
, int nformats
,
918 struct audio_encoding_set
**encodings
)
920 struct audio_encoding_set
*buf
;
925 #define ADD_ENCODING(enc, prec, flags) do { \
926 err = auconv_add_encoding(enc, prec, flags, &buf, &capacity); \
927 if (err != 0) goto err_exit; \
928 } while (/*CONSTCOND*/0)
931 buf
= AUCONV_MALLOC(ENCODING_SET_SIZE(capacity
));
937 for (i
= 0; i
< nformats
; i
++) {
938 if (!AUFMT_IS_VALID(&formats
[i
]))
940 switch (formats
[i
].encoding
) {
941 case AUDIO_ENCODING_SLINEAR_LE
:
942 ADD_ENCODING(formats
[i
].encoding
,
943 formats
[i
].precision
, 0);
944 ADD_ENCODING(AUDIO_ENCODING_SLINEAR_BE
,
945 formats
[i
].precision
,
946 AUDIO_ENCODINGFLAG_EMULATED
);
947 ADD_ENCODING(AUDIO_ENCODING_ULINEAR_LE
,
948 formats
[i
].precision
,
949 AUDIO_ENCODINGFLAG_EMULATED
);
950 ADD_ENCODING(AUDIO_ENCODING_ULINEAR_BE
,
951 formats
[i
].precision
,
952 AUDIO_ENCODINGFLAG_EMULATED
);
954 if (formats
[i
].precision
== 8
955 || formats
[i
].precision
== 16) {
956 ADD_ENCODING(AUDIO_ENCODING_ULAW
, 8,
957 AUDIO_ENCODINGFLAG_EMULATED
);
958 ADD_ENCODING(AUDIO_ENCODING_ALAW
, 8,
959 AUDIO_ENCODINGFLAG_EMULATED
);
963 case AUDIO_ENCODING_SLINEAR_BE
:
964 ADD_ENCODING(formats
[i
].encoding
,
965 formats
[i
].precision
, 0);
966 ADD_ENCODING(AUDIO_ENCODING_SLINEAR_LE
,
967 formats
[i
].precision
,
968 AUDIO_ENCODINGFLAG_EMULATED
);
969 ADD_ENCODING(AUDIO_ENCODING_ULINEAR_LE
,
970 formats
[i
].precision
,
971 AUDIO_ENCODINGFLAG_EMULATED
);
972 ADD_ENCODING(AUDIO_ENCODING_ULINEAR_BE
,
973 formats
[i
].precision
,
974 AUDIO_ENCODINGFLAG_EMULATED
);
976 if (formats
[i
].precision
== 8
977 || formats
[i
].precision
== 16) {
978 ADD_ENCODING(AUDIO_ENCODING_ULAW
, 8,
979 AUDIO_ENCODINGFLAG_EMULATED
);
980 ADD_ENCODING(AUDIO_ENCODING_ALAW
, 8,
981 AUDIO_ENCODINGFLAG_EMULATED
);
985 case AUDIO_ENCODING_ULINEAR_LE
:
986 ADD_ENCODING(formats
[i
].encoding
,
987 formats
[i
].precision
, 0);
988 ADD_ENCODING(AUDIO_ENCODING_SLINEAR_BE
,
989 formats
[i
].precision
,
990 AUDIO_ENCODINGFLAG_EMULATED
);
991 ADD_ENCODING(AUDIO_ENCODING_SLINEAR_LE
,
992 formats
[i
].precision
,
993 AUDIO_ENCODINGFLAG_EMULATED
);
994 ADD_ENCODING(AUDIO_ENCODING_ULINEAR_BE
,
995 formats
[i
].precision
,
996 AUDIO_ENCODINGFLAG_EMULATED
);
998 if (formats
[i
].precision
== 8
999 || formats
[i
].precision
== 16) {
1000 ADD_ENCODING(AUDIO_ENCODING_ULAW
, 8,
1001 AUDIO_ENCODINGFLAG_EMULATED
);
1002 ADD_ENCODING(AUDIO_ENCODING_ALAW
, 8,
1003 AUDIO_ENCODINGFLAG_EMULATED
);
1007 case AUDIO_ENCODING_ULINEAR_BE
:
1008 ADD_ENCODING(formats
[i
].encoding
,
1009 formats
[i
].precision
, 0);
1010 ADD_ENCODING(AUDIO_ENCODING_SLINEAR_BE
,
1011 formats
[i
].precision
,
1012 AUDIO_ENCODINGFLAG_EMULATED
);
1013 ADD_ENCODING(AUDIO_ENCODING_ULINEAR_LE
,
1014 formats
[i
].precision
,
1015 AUDIO_ENCODINGFLAG_EMULATED
);
1016 ADD_ENCODING(AUDIO_ENCODING_SLINEAR_LE
,
1017 formats
[i
].precision
,
1018 AUDIO_ENCODINGFLAG_EMULATED
);
1020 if (formats
[i
].precision
== 8
1021 || formats
[i
].precision
== 16) {
1022 ADD_ENCODING(AUDIO_ENCODING_ULAW
, 8,
1023 AUDIO_ENCODINGFLAG_EMULATED
);
1024 ADD_ENCODING(AUDIO_ENCODING_ALAW
, 8,
1025 AUDIO_ENCODINGFLAG_EMULATED
);
1030 case AUDIO_ENCODING_ULAW
:
1031 case AUDIO_ENCODING_ALAW
:
1032 case AUDIO_ENCODING_ADPCM
:
1033 case AUDIO_ENCODING_MPEG_L1_STREAM
:
1034 case AUDIO_ENCODING_MPEG_L1_PACKETS
:
1035 case AUDIO_ENCODING_MPEG_L1_SYSTEM
:
1036 case AUDIO_ENCODING_MPEG_L2_STREAM
:
1037 case AUDIO_ENCODING_MPEG_L2_PACKETS
:
1038 case AUDIO_ENCODING_MPEG_L2_SYSTEM
:
1039 ADD_ENCODING(formats
[i
].encoding
,
1040 formats
[i
].precision
, 0);
1043 case AUDIO_ENCODING_SLINEAR
:
1044 case AUDIO_ENCODING_ULINEAR
:
1045 case AUDIO_ENCODING_LINEAR
:
1046 case AUDIO_ENCODING_LINEAR8
:
1048 printf("%s: invalid encoding value "
1049 "for audio_format: %d\n",
1050 __func__
, formats
[i
].encoding
);
1065 * a sub-routine for auconv_create_encodings()
1068 auconv_add_encoding(int enc
, int prec
, int flags
,
1069 struct audio_encoding_set
**buf
, int *capacity
)
1071 static const char *encoding_names
[] = {
1072 NULL
, AudioEmulaw
, AudioEalaw
, NULL
,
1073 NULL
, AudioEadpcm
, AudioEslinear_le
, AudioEslinear_be
,
1074 AudioEulinear_le
, AudioEulinear_be
,
1075 AudioEslinear
, AudioEulinear
,
1076 AudioEmpeg_l1_stream
, AudioEmpeg_l1_packets
,
1077 AudioEmpeg_l1_system
, AudioEmpeg_l2_stream
,
1078 AudioEmpeg_l2_packets
, AudioEmpeg_l2_system
1080 struct audio_encoding_set
*set
;
1081 struct audio_encoding_set
*new_buf
;
1082 audio_encoding_t
*e
;
1086 /* already has the same encoding? */
1088 for (i
= 0; i
< set
->size
; i
++, e
++) {
1089 if (e
->encoding
== enc
&& e
->precision
== prec
) {
1090 /* overwrite EMULATED flag */
1091 if ((e
->flags
& AUDIO_ENCODINGFLAG_EMULATED
)
1092 && (flags
& AUDIO_ENCODINGFLAG_EMULATED
) == 0) {
1093 e
->flags
&= ~AUDIO_ENCODINGFLAG_EMULATED
;
1098 /* We don't have the specified one. */
1100 if (set
->size
>= *capacity
) {
1101 new_buf
= AUCONV_REALLOC(set
,
1102 ENCODING_SET_SIZE(*capacity
+ 10));
1103 if (new_buf
== NULL
)
1110 e
= &set
->items
[set
->size
];
1112 strlcpy(e
->name
, encoding_names
[enc
], MAX_AUDIO_DEV_LEN
);
1114 e
->precision
= prec
;
1121 * Delete an audio_encoding_set created by auconv_create_encodings().
1126 * auconv_delete_encodings(sc->sc_encodings);
1130 * @param encodings [IN] An audio_encoding_set which was created by
1131 * auconv_create_encodings().
1132 * @return errno; 0 for success.
1134 int auconv_delete_encodings(struct audio_encoding_set
*encodings
)
1136 if (encodings
!= NULL
)
1137 AUCONV_FREE(encodings
);
1142 * Copy the element specified by aep->index.
1145 * int foo_query_encoding(void *v, audio_encoding_t *aep) {
1146 * struct foo_softc *sc = (struct foo_softc *)v;
1147 * return auconv_query_encoding(sc->sc_encodings, aep);
1150 * @param encodings [IN] An audio_encoding_set created by
1151 * auconv_create_encodings().
1152 * @param aep [IN/OUT] resultant audio_encoding_t.
1155 auconv_query_encoding(const struct audio_encoding_set
*encodings
,
1156 audio_encoding_t
*aep
)
1158 if (aep
->index
>= encodings
->size
)
1160 strlcpy(aep
->name
, encodings
->items
[aep
->index
].name
,
1162 aep
->encoding
= encodings
->items
[aep
->index
].encoding
;
1163 aep
->precision
= encodings
->items
[aep
->index
].precision
;
1164 aep
->flags
= encodings
->items
[aep
->index
].flags
;