audio/pw: improve channel position code

Follow PulseAudio backend comment and code, and only implement the
channels QEMU actually supports at this point, and add the same comment
about limits and future mappings. Simplify a bit the code.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Volker Rümelin <vr_qemu@t-online.de>
Message-Id: <20230506163735.3481387-13-marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2023-05-06 20:37:35 +04:00
parent 8297b3d3d0
commit 92f69a2c9b

View file

@ -417,7 +417,7 @@ pw_to_audfmt(enum spa_audio_format fmt, int *endianness,
} }
static int static int
create_stream(pwaudio *c, PWVoice *v, const char *stream_name, qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name,
const char *name, enum spa_direction dir) const char *name, enum spa_direction dir)
{ {
int res; int res;
@ -482,62 +482,37 @@ create_stream(pwaudio *c, PWVoice *v, const char *stream_name,
return 0; return 0;
} }
static int static void
qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name, qpw_set_position(uint32_t channels, uint32_t position[SPA_AUDIO_MAX_CHANNELS])
const char *name, enum spa_direction dir)
{ {
switch (v->info.channels) { memcpy(position, (uint32_t[SPA_AUDIO_MAX_CHANNELS]) { SPA_AUDIO_CHANNEL_UNKNOWN, },
sizeof(uint32_t) * SPA_AUDIO_MAX_CHANNELS);
/*
* TODO: This currently expects the only frontend supporting more than 2
* channels is the usb-audio. We will need some means to set channel
* order when a new frontend gains multi-channel support.
*/
switch (channels) {
case 8: case 8:
v->info.position[0] = SPA_AUDIO_CHANNEL_FL; position[6] = SPA_AUDIO_CHANNEL_SL;
v->info.position[1] = SPA_AUDIO_CHANNEL_FR; position[7] = SPA_AUDIO_CHANNEL_SR;
v->info.position[2] = SPA_AUDIO_CHANNEL_FC; /* fallthrough */
v->info.position[3] = SPA_AUDIO_CHANNEL_LFE;
v->info.position[4] = SPA_AUDIO_CHANNEL_RL;
v->info.position[5] = SPA_AUDIO_CHANNEL_RR;
v->info.position[6] = SPA_AUDIO_CHANNEL_SL;
v->info.position[7] = SPA_AUDIO_CHANNEL_SR;
break;
case 6: case 6:
v->info.position[0] = SPA_AUDIO_CHANNEL_FL; position[2] = SPA_AUDIO_CHANNEL_FC;
v->info.position[1] = SPA_AUDIO_CHANNEL_FR; position[3] = SPA_AUDIO_CHANNEL_LFE;
v->info.position[2] = SPA_AUDIO_CHANNEL_FC; position[4] = SPA_AUDIO_CHANNEL_RL;
v->info.position[3] = SPA_AUDIO_CHANNEL_LFE; position[5] = SPA_AUDIO_CHANNEL_RR;
v->info.position[4] = SPA_AUDIO_CHANNEL_RL; /* fallthrough */
v->info.position[5] = SPA_AUDIO_CHANNEL_RR;
break;
case 5:
v->info.position[0] = SPA_AUDIO_CHANNEL_FL;
v->info.position[1] = SPA_AUDIO_CHANNEL_FR;
v->info.position[2] = SPA_AUDIO_CHANNEL_FC;
v->info.position[3] = SPA_AUDIO_CHANNEL_LFE;
v->info.position[4] = SPA_AUDIO_CHANNEL_RC;
break;
case 4:
v->info.position[0] = SPA_AUDIO_CHANNEL_FL;
v->info.position[1] = SPA_AUDIO_CHANNEL_FR;
v->info.position[2] = SPA_AUDIO_CHANNEL_FC;
v->info.position[3] = SPA_AUDIO_CHANNEL_RC;
break;
case 3:
v->info.position[0] = SPA_AUDIO_CHANNEL_FL;
v->info.position[1] = SPA_AUDIO_CHANNEL_FR;
v->info.position[2] = SPA_AUDIO_CHANNEL_LFE;
break;
case 2: case 2:
v->info.position[0] = SPA_AUDIO_CHANNEL_FL; position[0] = SPA_AUDIO_CHANNEL_FL;
v->info.position[1] = SPA_AUDIO_CHANNEL_FR; position[1] = SPA_AUDIO_CHANNEL_FR;
break; break;
case 1: case 1:
v->info.position[0] = SPA_AUDIO_CHANNEL_MONO; position[0] = SPA_AUDIO_CHANNEL_MONO;
break; break;
default: default:
for (size_t i = 0; i < v->info.channels; i++) { dolog("Internal error: unsupported channel count %d\n", channels);
v->info.position[i] = SPA_AUDIO_CHANNEL_UNKNOWN;
} }
break;
}
return create_stream(c, v, stream_name, name, dir);
} }
static int static int
@ -555,6 +530,7 @@ qpw_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
v->info.format = audfmt_to_pw(as->fmt, as->endianness); v->info.format = audfmt_to_pw(as->fmt, as->endianness);
v->info.channels = as->nchannels; v->info.channels = as->nchannels;
qpw_set_position(as->nchannels, v->info.position);
v->info.rate = as->freq; v->info.rate = as->freq;
obt_as.fmt = obt_as.fmt =
@ -601,6 +577,7 @@ qpw_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
v->info.format = audfmt_to_pw(as->fmt, as->endianness); v->info.format = audfmt_to_pw(as->fmt, as->endianness);
v->info.channels = as->nchannels; v->info.channels = as->nchannels;
qpw_set_position(as->nchannels, v->info.position);
v->info.rate = as->freq; v->info.rate = as->freq;
obt_as.fmt = obt_as.fmt =