aurateconv.c:

- Simplify the source
  - Accept any convresions such that sample_rate < hw_sample_rate

uaudio.c:
  - Request the above conversion.  This is needed for 4ch-only devices to
    play monaural/stereo data.
This commit is contained in:
kent 2002-03-17 16:14:21 +00:00
parent e6ff25795b
commit fe274639f9
2 changed files with 126 additions and 401 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: aurateconv.c,v 1.2 2002/03/17 11:36:37 kent Exp $ */
/* $NetBSD: aurateconv.c,v 1.3 2002/03/17 16:14:21 kent Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: aurateconv.c,v 1.2 2002/03/17 11:36:37 kent Exp $");
__KERNEL_RCSID(0, "$NetBSD: aurateconv.c,v 1.3 2002/03/17 16:14:21 kent Exp $");
#include <sys/systm.h>
#include <sys/types.h>
@ -54,21 +54,13 @@ __KERNEL_RCSID(0, "$NetBSD: aurateconv.c,v 1.2 2002/03/17 11:36:37 kent Exp $");
static int auconv_play_slinear16_le(struct auconv_context *,
const struct audio_params *, uint8_t *, const uint8_t *, int);
static int auconv_play_slinear16_channels_le(struct auconv_context *,
const struct audio_params *, uint8_t *, const uint8_t *, int);
static int auconv_play_slinear24_le(struct auconv_context *,
const struct audio_params *, uint8_t *, const uint8_t *, int);
static int auconv_play_slinear24_channels_le(struct auconv_context *,
const struct audio_params *, uint8_t *, const uint8_t *, int);
static int auconv_record_slinear16_le(struct auconv_context *,
const struct audio_params *, uint8_t *, const uint8_t *, int);
static int auconv_record_slinear16_channels_le(struct auconv_context *,
const struct audio_params *, uint8_t *, const uint8_t *, int);
static int auconv_record_slinear24_le(struct auconv_context *,
const struct audio_params *, uint8_t *, const uint8_t *, int);
static int auconv_record_slinear24_channels_le(struct auconv_context *,
const struct audio_params *, uint8_t *, const uint8_t *, int);
int
auconv_check_params(const struct audio_params *params)
@ -85,11 +77,19 @@ auconv_check_params(const struct audio_params *params)
|| (params->hw_precision != 16 && params->hw_precision != 24))
return (EINVAL);
/* Only 1:2 or 2:1 */
if (params->hw_channels != params->channels)
if (!((params->hw_channels == 1 && params->channels == 2)
|| (params->hw_channels == 2 && params->channels == 1)))
if (params->hw_channels != params->channels) {
if (params->hw_channels == 1 && params->channels == 2) {
/* Ok */
} else if (params->hw_channels == 2 && params->channels == 1) {
/* Ok */
} else if (params->hw_channels > params->channels) {
/* Ok */
} else
return (EINVAL);
}
if (params->hw_channels > AUDIO_MAX_CHANNELS
|| params->channels > AUDIO_MAX_CHANNELS)
return (EINVAL);
if (params->hw_sample_rate != params->sample_rate)
if (params->hw_sample_rate <= 0 || params->sample_rate <= 0)
@ -144,19 +144,11 @@ auconv_record(struct auconv_context *context,
}
switch (params->hw_precision) {
case 16:
if (params->hw_channels != params->channels)
return auconv_record_slinear16_channels_le(context,
params, dest, src, srcsize);
else
return auconv_record_slinear16_le(context,
params, dest, src, srcsize);
return auconv_record_slinear16_le(context, params,
dest, src, srcsize);
case 24:
if (params->hw_channels != params->channels)
return auconv_record_slinear24_channels_le(context,
params, dest, src, srcsize);
else
return auconv_record_slinear24_le(context,
params, dest, src, srcsize);
return auconv_record_slinear24_le(context, params,
dest, src, srcsize);
}
printf("auconv_record: unimplemented precision: %d\n",
params->hw_precision);
@ -192,19 +184,11 @@ auconv_play(struct auconv_context *context, const struct audio_params *params,
}
switch (params->hw_precision) {
case 16:
if (params->hw_channels != params->channels)
return auconv_play_slinear16_channels_le(context,
params, dest, src, srcsize);
else
return auconv_play_slinear16_le(context,
params, dest, src, srcsize);
return auconv_play_slinear16_le(context, params,
dest, src, srcsize);
case 24:
if (params->hw_channels != params->channels)
return auconv_play_slinear24_channels_le(context,
params, dest, src, srcsize);
else
return auconv_play_slinear24_le(context,
params, dest, src, srcsize);
return auconv_play_slinear24_le(context, params,
dest, src, srcsize);
}
printf("auconv_play: unimplemented precision: %d\n",
params->hw_precision);
@ -239,193 +223,74 @@ auconv_play(struct auconv_context *context, const struct audio_params *params,
(P)[2] = vvv >> 16; \
} while (0)
#define P_READ_LR_S16LE(LV, RV, RP, PAR) \
#define P_READ_SnLE(BITS, V, RP, PAR) \
do { \
LV = READ_S16LE(RP); \
RP += sizeof(int16_t); \
if ((PAR)->channels == 1) \
RV = LV; \
else { \
RV = READ_S16LE(RP); \
RP += sizeof(int16_t); \
int j; \
for (j = 0; j < (PAR)->channels; j++) { \
(V)[j] = READ_S##BITS##LE(RP); \
RP += (BITS) / NBBY; \
} \
} while (0)
#define P_WRITE_LR_S16LE(LV, RV, WP, PAR, CON, WC) \
#define P_WRITE_SnLE(BITS, V, WP, PAR, CON, WC) \
do { \
if ((PAR)->hw_channels == 1) { \
WRITE_S16LE(WP, (LV + RV) / 2); \
WP += sizeof(int16_t); \
WC += sizeof(int16_t); \
} else { \
WRITE_S16LE(WP, LV); \
WP += sizeof(int16_t); \
if ((PAR)->channels == 2 && (PAR)->hw_channels == 1) { \
WRITE_S##BITS##LE(WP, ((V)[0] + (V)[1]) / 2); \
WP += (BITS) / NBBY; \
RING_CHECK(CON, WP); \
WRITE_S16LE(WP, RV); \
WP += sizeof(int16_t); \
WC += sizeof(int16_t) * 2; \
WC += (BITS) / NBBY; \
} else { /* channels <= hw_channels */ \
int j; \
for (j = 0; j < (PAR)->channels; j++) { \
WRITE_S##BITS##LE(WP, (V)[j]); \
WP += (BITS) / NBBY; \
RING_CHECK(CON, WP); \
} \
if (j == 1 && 1 < (PAR)->hw_channels) { \
WRITE_S##BITS##LE(WP, (V)[0]); \
WP += (BITS) / NBBY; \
RING_CHECK(CON, WP); \
j++; \
} \
for (; j < (PAR)->hw_channels; j++) { \
WRITE_S##BITS##LE(WP, 0); \
WP += (BITS) / NBBY; \
RING_CHECK(CON, WP); \
} \
WC += (BITS) / NBBY * j; \
} \
RING_CHECK(CON, WP); \
} while (0)
#define P_READ_N_S16LE(V, RP, PAR) \
do { \
int i; \
for (i = 0; i < (PAR)->channels; i++) { \
(V)[i] = READ_S16LE(RP); \
RP += sizeof(int16_t); \
} \
} while (0)
#define P_WRITE_N_S16LE(V, WP, PAR, CON, WC) \
do { \
int i; \
for (i = 0; i < (PAR)->channels; i++) { \
WRITE_S16LE(WP, (V)[i]); \
WP += sizeof(int16_t); \
RING_CHECK(CON, WP); \
} \
WC += sizeof(int16_t) * i; \
} while (0)
#define P_READ_LR_S24LE(LV, RV, RP, PAR) \
do { \
LV = READ_S24LE(RP); \
RP += 3; \
if ((PAR)->channels == 1) \
RV = LV; \
else { \
RV = READ_S24LE(RP); \
RP += 3; \
} \
} while (0)
#define P_WRITE_LR_S24LE(LV, RV, WP, PAR, CON, WC) \
do { \
if ((PAR)->hw_channels == 1) { \
WRITE_S24LE(WP, (LV + RV) / 2); \
WP += 3; \
WC += 3; \
} else { \
WRITE_S24LE(WP, LV); \
WP += 3; \
RING_CHECK(CON, WP); \
WRITE_S24LE(WP, RV); \
WP += 3; \
WC += 3 * 2; \
} \
RING_CHECK(CON, WP); \
} while (0)
#define P_READ_N_S24LE(V, RP, PAR) \
do { \
int i; \
for (i = 0; i < (PAR)->channels; i++) { \
(V)[i] = READ_S24LE(RP); \
RP += 3; \
} \
} while (0)
#define P_WRITE_N_S24LE(V, WP, PAR, CON, WC) \
do { \
int i; \
for (i = 0; i < (PAR)->channels; i++) { \
WRITE_S24LE(WP, (V)[i]); \
WP += 3; \
RING_CHECK(CON, WP); \
} \
WC += 3 * i; \
} while (0)
#define R_READ_LR_S16LE(LV, RV, RP, PAR, CON, RC) \
#define R_READ_SnLE(BITS, V, RP, PAR, CON, RC) \
do { \
LV = READ_S16LE(RP); \
RP += sizeof(int16_t); \
RING_CHECK(CON, RP); \
RC += sizeof(int16_t); \
if ((PAR)->hw_channels == 1) \
RV = LV; \
else { \
RV = READ_S16LE(RP); \
RP += sizeof(int16_t); \
int j; \
for (j = 0; j < (PAR)->hw_channels; j++) { \
(V)[j] = READ_S##BITS##LE(RP); \
RP += (BITS) / NBBY; \
RING_CHECK(CON, RP); \
RC += sizeof(int16_t); \
RC += (BITS) / NBBY; \
} \
} while (0)
#define R_WRITE_LR_S16LE(LV, RV, WP, PAR, WC) \
#define R_WRITE_SnLE(BITS, V, WP, PAR, WC) \
do { \
if ((PAR)->channels == 1) { \
WRITE_S16LE(WP, (LV + RV) / 2); \
WP += sizeof(int16_t); \
WC += sizeof(int16_t); \
} else { \
WRITE_S16LE(WP, LV); \
WP += sizeof(int16_t); \
WRITE_S16LE(WP, RV); \
WP += sizeof(int16_t); \
WC += sizeof(int16_t) * 2; \
if ((PAR)->channels == 2 && (PAR)->hw_channels == 1) { \
WRITE_S##BITS##LE(WP, (V)[0]); \
WP += (BITS) / NBBY; \
WRITE_S##BITS##LE(WP, (V)[0]); \
WP += (BITS) / NBBY; \
WC += (BITS) / NBBY * 2; \
} else if ((PAR)->channels == 1 && (PAR)->hw_channels >= 2) { \
WRITE_S##BITS##LE(WP, ((V)[0] + (V)[1]) / 2); \
WP += (BITS) / NBBY; \
WC += (BITS) / NBBY; \
} else { /* channels <= hw_channels */ \
int j; \
for (j = 0; j < (PAR)->channels; j++) { \
WRITE_S##BITS##LE(WP, (V)[j]); \
WP += (BITS) / NBBY; \
} \
WC += (BITS) / NBBY * j; \
} \
} while (0)
#define R_READ_N_S16LE(V, RP, PAR, CON, RC) \
do { \
int i; \
for (i = 0; i < (PAR)->channels; i++) { \
(V)[i] = READ_S16LE(RP); \
RP += sizeof(int16_t); \
RING_CHECK(CON, RP); \
RC += sizeof(int16_t); \
} \
} while (0)
#define R_WRITE_N_S16LE(V, WP, PAR, WC) \
do { \
int i; \
for (i = 0; i < (PAR)->channels; i++) { \
WRITE_S16LE(WP, (V)[i]); \
WP += sizeof(int16_t); \
} \
WC += sizeof(int16_t) * i; \
} while (0)
#define R_READ_LR_S24LE(LV, RV, RP, PAR, CON, RC) \
do { \
LV = READ_S24LE(RP); \
RP += 3; \
RING_CHECK(CON, RP); \
RC += 3; \
if ((PAR)->hw_channels == 1) \
RV = LV; \
else { \
RV = READ_S24LE(RP); \
RP += 3; \
RING_CHECK(CON, RP); \
RC += 3; \
} \
} while (0)
#define R_WRITE_LR_S24LE(LV, RV, WP, PAR, WC) \
do { \
if ((PAR)->channels == 1) { \
WRITE_S24LE(WP, (LV + RV) / 2); \
WP += 3; \
WC += 3; \
} else { \
WRITE_S24LE(WP, LV); \
WP += 3; \
WRITE_S24LE(WP, RV); \
WP += 3; \
WC += 3 * 2; \
} \
} while (0)
#define R_READ_N_S24LE(V, RP, PAR, CON, RC) \
do { \
int i; \
for (i = 0; i < (PAR)->channels; i++) { \
(V)[i] = READ_S24LE(RP); \
RP += 3; \
RING_CHECK(CON, RP); \
RC += 3; \
} \
} while (0)
#define R_WRITE_N_S24LE(V, WP, PAR, WC) \
do { \
int i; \
for (i = 0; i < (PAR)->channels; i++) { \
WRITE_S24LE(WP, (V)[i]); \
WP += 3; \
} \
WC += 3 * i; \
} while (0)
/*
* Function templates
@ -435,66 +300,6 @@ auconv_play(struct auconv_context *context, const struct audio_params *params,
* Don't use them for 32bit data because this linear interpolation overflows
* for 32bit data.
*/
#define AUCONV_PLAY_SLINEAR_CHANNELS_LE(BITS) \
static int \
auconv_play_slinear##BITS##_channels_le(struct auconv_context *context, \
const struct audio_params *params, \
uint8_t *dest, const uint8_t *src, \
int srcsize) \
{ \
int wrote; \
uint8_t *w; \
const uint8_t *r; \
const uint8_t *src_end; \
register int32_t lv, rv; \
int32_t prev_l, prev_r, next_l, next_r, c256; \
\
wrote = 0; \
w = dest; \
r = src; \
src_end = src + srcsize; \
if (params->sample_rate == params->hw_sample_rate) { \
while (r < src_end) { \
P_READ_LR_S##BITS##LE(lv, rv, r, params); \
P_WRITE_LR_S##BITS##LE(lv, rv, w, params, context, wrote); \
} \
} else if (params->hw_sample_rate < params->sample_rate) { \
for (;;) { \
do { \
if (r >= src_end) \
return wrote; \
P_READ_LR_S##BITS##LE(lv, rv, r, params); \
context->count += params->hw_sample_rate; \
} while (context->count < params->sample_rate); \
context->count -= params->sample_rate; \
P_WRITE_LR_S##BITS##LE(lv, rv, w, params, context, wrote); \
} \
} else { \
/* Initial value of context->count is params->sample_rate */ \
prev_l = context->prev[0]; \
prev_r = context->prev[1]; \
P_READ_LR_S##BITS##LE(next_l, next_r, r, params); \
for (;;) { \
c256 = context->count * 256 / params->hw_sample_rate; \
lv = (c256 * next_l + (256 - c256) * prev_l) >> 8; \
rv = (c256 * next_r + (256 - c256) * prev_r) >> 8; \
P_WRITE_LR_S##BITS##LE(lv, rv, w, params, context, wrote); \
context->count += params->sample_rate; \
if (context->count >= params->hw_sample_rate) { \
context->count -= params->hw_sample_rate; \
prev_l = next_l; \
prev_r = next_r; \
if (r >= src_end) \
break; \
P_READ_LR_S##BITS##LE(next_l, next_r, r, params); \
} \
} \
context->prev[0] = next_l; \
context->prev[1] = next_r; \
} \
return wrote; \
}
#define AUCONV_PLAY_SLINEAR_LE(BITS) \
static int \
auconv_play_slinear##BITS##_le(struct auconv_context *context, \
@ -516,37 +321,37 @@ auconv_play_slinear##BITS##_le(struct auconv_context *context, \
src_end = src + srcsize; \
if (params->sample_rate == params->hw_sample_rate) { \
while (r < src_end) { \
P_READ_N_S##BITS##LE(v, r, params); \
P_WRITE_N_S##BITS##LE(v, w, params, context, wrote); \
P_READ_SnLE(BITS, v, r, params); \
P_WRITE_SnLE(BITS, v, w, params, context, wrote); \
} \
} else if (params->hw_sample_rate < params->sample_rate) { \
for (;;) { \
do { \
if (r >= src_end) \
return wrote; \
P_READ_N_S##BITS##LE(v, r, params); \
P_READ_SnLE(BITS, v, r, params); \
context->count += params->hw_sample_rate; \
} while (context->count < params->sample_rate); \
context->count -= params->sample_rate; \
P_WRITE_N_S##BITS##LE(v, w, params, context, wrote); \
P_WRITE_SnLE(BITS, v, w, params, context, wrote); \
} \
} else { \
/* Initial value of context->count is params->sample_rate */ \
values_size = sizeof(int32_t) * params->channels; \
memcpy(prev, context->prev, values_size); \
P_READ_N_S##BITS##LE(next, r, params); \
P_READ_SnLE(BITS, next, r, params); \
for (;;) { \
c256 = context->count * 256 / params->hw_sample_rate; \
for (i = 0; i < params->channels; i++) \
v[i] = (c256 * next[i] + (256 - c256) * prev[i]) >> 8; \
P_WRITE_N_S##BITS##LE(v, w, params, context, wrote); \
P_WRITE_SnLE(BITS, v, w, params, context, wrote); \
context->count += params->sample_rate; \
if (context->count >= params->hw_sample_rate) { \
context->count -= params->hw_sample_rate; \
memcpy(prev, next, values_size); \
if (r >= src_end) \
break; \
P_READ_N_S##BITS##LE(next, r, params); \
P_READ_SnLE(BITS, next, r, params); \
} \
} \
memcpy(context->prev, next, values_size); \
@ -554,67 +359,6 @@ auconv_play_slinear##BITS##_le(struct auconv_context *context, \
return wrote; \
}
#define AUCONV_RECORD_SLINEAR_CHANNELS_LE(BITS) \
static int \
auconv_record_slinear##BITS##_channels_le(struct auconv_context *context, \
const struct audio_params *params, \
uint8_t *dest, const uint8_t *src, \
int srcsize) \
{ \
int wrote, rsize; \
uint8_t *w; \
const uint8_t *r; \
register int32_t lv, rv; \
int32_t prev_l, prev_r, next_l, next_r, c256; \
\
wrote = 0; \
rsize = 0; \
w = dest; \
r = src; \
if (params->sample_rate == params->hw_sample_rate) { \
while (rsize < srcsize) { \
R_READ_LR_S##BITS##LE(lv, rv, r, params, context, rsize); \
R_WRITE_LR_S##BITS##LE(lv, rv, w, params, wrote); \
} \
} else if (params->sample_rate < params->hw_sample_rate) { \
for (;;) { \
do { \
if (rsize >= srcsize) \
return wrote; \
R_READ_LR_S##BITS##LE(lv, rv, r, params, \
context, rsize); \
context->count += params->sample_rate; \
} while (context->count < params->hw_sample_rate); \
context->count -= params->hw_sample_rate; \
R_WRITE_LR_S##BITS##LE(lv, rv, w, params, wrote); \
} \
} else { \
/* Initial value of context->count is params->hw_sample_rate */ \
prev_l = context->prev[0]; \
prev_r = context->prev[1]; \
R_READ_LR_S##BITS##LE(next_l, next_r, r, params, context, rsize); \
for (;;) { \
c256 = context->count * 256 / params->sample_rate; \
lv = (c256 * next_l + (256 - c256) * prev_l) >> 8; \
rv = (c256 * next_r + (256 - c256) * prev_r) >> 8; \
R_WRITE_LR_S##BITS##LE(lv, rv, w, params, wrote); \
context->count += params->hw_sample_rate; \
if (context->count >= params->sample_rate) { \
context->count -= params->sample_rate; \
prev_l = next_l; \
prev_r = next_r; \
if (rsize >= srcsize) \
break; \
R_READ_LR_S##BITS##LE(next_l, next_r, r, \
params, context, rsize); \
} \
} \
context->prev[0] = next_l; \
context->prev[1] = next_r; \
} \
return wrote; \
}
#define AUCONV_RECORD_SLINEAR_LE(BITS) \
static int \
auconv_record_slinear##BITS##_le(struct auconv_context *context, \
@ -635,37 +379,37 @@ auconv_record_slinear##BITS##_le(struct auconv_context *context, \
r = src; \
if (params->sample_rate == params->hw_sample_rate) { \
while (rsize < srcsize) { \
R_READ_N_S##BITS##LE(v, r, params, context, rsize); \
R_WRITE_N_S##BITS##LE(v, w, params, wrote); \
R_READ_SnLE(BITS, v, r, params, context, rsize); \
R_WRITE_SnLE(BITS, v, w, params, wrote); \
} \
} else if (params->sample_rate < params->hw_sample_rate) { \
for (;;) { \
do { \
if (rsize >= srcsize) \
return wrote; \
R_READ_N_S##BITS##LE(v, r, params, context, rsize); \
R_READ_SnLE(BITS, v, r, params, context, rsize); \
context->count += params->sample_rate; \
} while (context->count < params->hw_sample_rate); \
context->count -= params->hw_sample_rate; \
R_WRITE_N_S##BITS##LE(v, w, params, wrote); \
R_WRITE_SnLE(BITS, v, w, params, wrote); \
} \
} else { \
/* Initial value of context->count is params->hw_sample_rate */ \
values_size = sizeof(int32_t) * params->channels; \
values_size = sizeof(int32_t) * params->hw_channels; \
memcpy(prev, context->prev, values_size); \
R_READ_N_S##BITS##LE(next, r, params, context, rsize); \
R_READ_SnLE(BITS, next, r, params, context, rsize); \
for (;;) { \
c256 = context->count * 256 / params->sample_rate; \
for (i = 0; i < params->channels; i++) \
for (i = 0; i < params->hw_channels; i++) \
v[i] = (c256 * next[i] + (256 - c256) * prev[i]) >> 8; \
R_WRITE_N_S##BITS##LE(v, w, params, wrote); \
R_WRITE_SnLE(BITS, v, w, params, wrote); \
context->count += params->hw_sample_rate; \
if (context->count >= params->sample_rate) { \
context->count -= params->sample_rate; \
memcpy(prev, next, values_size); \
if (rsize >= srcsize) \
break; \
R_READ_N_S##BITS##LE(next, r, params, context, rsize); \
R_READ_SnLE(BITS, next, r, params, context, rsize); \
} \
} \
memcpy(context->prev, next, values_size); \
@ -675,9 +419,5 @@ auconv_record_slinear##BITS##_le(struct auconv_context *context, \
AUCONV_PLAY_SLINEAR_LE(16)
AUCONV_PLAY_SLINEAR_LE(24)
AUCONV_PLAY_SLINEAR_CHANNELS_LE(16)
AUCONV_PLAY_SLINEAR_CHANNELS_LE(24)
AUCONV_RECORD_SLINEAR_LE(16)
AUCONV_RECORD_SLINEAR_LE(24)
AUCONV_RECORD_SLINEAR_CHANNELS_LE(16)
AUCONV_RECORD_SLINEAR_CHANNELS_LE(24)

View File

@ -1,4 +1,4 @@
/* $NetBSD: uaudio.c,v 1.52 2002/03/15 17:20:14 kent Exp $ */
/* $NetBSD: uaudio.c,v 1.53 2002/03/17 16:14:22 kent Exp $ */
/*
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -44,7 +44,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.52 2002/03/15 17:20:14 kent Exp $");
__KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.53 2002/03/17 16:14:22 kent Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -272,6 +272,8 @@ Static void uaudio_get_minmax_rates(int, const struct as_info *,
Static int uaudio_match_alt_sub(int, const struct as_info *,
const struct audio_params *,
int, u_long);
Static int uaudio_match_alt_chan(int, const struct as_info *,
struct audio_params *, int);
Static int uaudio_match_alt(int, const struct as_info *,
struct audio_params *, int);
Static int uaudio_set_params(void *, int, int,
@ -2223,7 +2225,7 @@ uaudio_match_alt_sub(int nalts, const struct as_info *alts,
int i, j;
struct usb_audio_streaming_type1_descriptor *a1d;
DPRINTF(("uaudio_match_alt_sub: Check for %luHz %dCh\n",
DPRINTF(("uaudio_match_alt_sub: search for %luHz %dch\n",
rate, p->hw_channels));
for (i = 0; i < nalts; i++) {
a1d = alts[i].asf1desc;
@ -2256,63 +2258,23 @@ uaudio_match_alt_sub(int nalts, const struct as_info *alts,
}
int
uaudio_match_alt(int nalts, const struct as_info *alts,
struct audio_params *p, int mode)
uaudio_match_alt_chan(int nalts, const struct as_info *alts,
struct audio_params *p, int mode)
{
int i, n;
u_long min, max;
u_long rate;
mode = mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN;
/* Exact match */
DPRINTF(("uaudio_match_alt: search for %ldHz.\n", p->sample_rate));
DPRINTF(("uaudio_match_alt_chan: examine %ldHz %dch %dbit.\n",
p->sample_rate, p->hw_channels, p->hw_precision));
i = uaudio_match_alt_sub(nalts, alts, p, mode, p->sample_rate);
if (i >= 0)
return i;
DPRINTF(("uaudio_match_alt: gets min-max rates.\n"));
DPRINTF(("uaudio_match_alt_chan: get min-max rates.\n"));
uaudio_get_minmax_rates(nalts, alts, p, mode, &min, &max);
DPRINTF(("uaudio_match_alt: min=%lu max=%lu\n", min, max));
if (max > 0) {
/* Search for biggers */
n = 2;
while ((rate = p->sample_rate * n++) <= max) {
i = uaudio_match_alt_sub(nalts, alts, p, mode, rate);
if (i >= 0) {
p->hw_sample_rate = rate;
return i;
}
}
if (p->sample_rate >= min) {
i = uaudio_match_alt_sub(nalts, alts, p, mode, max);
if (i >= 0) {
p->hw_sample_rate = max;
return i;
}
} else {
i = uaudio_match_alt_sub(nalts, alts, p, mode, min);
if (i >= 0) {
p->hw_sample_rate = min;
return i;
}
}
}
if (p->channels > 2)
return -1;
if (p->channels == 2)
p->hw_channels = 1; /* stereo -> mono */
else
p->hw_channels = 2; /* mono -> stereo */
/* Exact match */
DPRINTF(("uaudio_match_alt: search for %ldHz.\n", p->sample_rate));
i = uaudio_match_alt_sub(nalts, alts, p, mode, p->sample_rate);
if (i >= 0)
return i;
DPRINTF(("uaudio_match_alt: gets min-max rates.\n"));
uaudio_get_minmax_rates(nalts, alts, p, mode, &min, &max);
DPRINTF(("uaudio_match_alt: min=%lu max=%lu\n", min, max));
DPRINTF(("uaudio_match_alt_chan: min=%lu max=%lu\n", min, max));
if (max <= 0)
return -1;
/* Search for biggers */
@ -2337,10 +2299,33 @@ uaudio_match_alt(int nalts, const struct as_info *alts,
return i;
}
}
return -1;
}
int
uaudio_match_alt(int nalts, const struct as_info *alts,
struct audio_params *p, int mode)
{
int i, n;
mode = mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN;
i = uaudio_match_alt_chan(nalts, alts, p, mode);
if (i >= 0)
return i;
for (n = p->channels + 1; n <= AUDIO_MAX_CHANNELS; n++) {
p->hw_channels = n;
i = uaudio_match_alt_chan(nalts, alts, p, mode);
if (i >= 0)
return i;
}
if (p->channels != 2)
return -1;
p->hw_channels = 1;
return uaudio_match_alt_chan(nalts, alts, p, mode);
}
int
uaudio_set_params(void *addr, int setmode, int usemode,
struct audio_params *play, struct audio_params *rec)