mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-14 23:34:08 +00:00
linux-pulseaudio: Surround speaker map
When using more than two channels, the channel map of pulse-audio is incorrect. Add an API for getting a speaker map based on OBS speaker layout. Then use the speaker map when connecting to a pulse-audio device, for both source and monitor output.
This commit is contained in:
parent
9b9d57a7ee
commit
48a8e750bb
|
@ -61,6 +61,61 @@ static enum audio_format pulseaudio_to_obs_audio_format(
|
|||
}
|
||||
}
|
||||
|
||||
static pa_channel_map pulseaudio_channel_map(enum speaker_layout layout)
|
||||
{
|
||||
pa_channel_map ret;
|
||||
|
||||
ret.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
|
||||
ret.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
|
||||
ret.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
|
||||
ret.map[3] = PA_CHANNEL_POSITION_LFE;
|
||||
ret.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
|
||||
ret.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
|
||||
ret.map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
|
||||
ret.map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
|
||||
|
||||
switch (layout) {
|
||||
case SPEAKERS_MONO:
|
||||
ret.channels = 1;
|
||||
ret.map[0] = PA_CHANNEL_POSITION_MONO;
|
||||
break;
|
||||
|
||||
case SPEAKERS_STEREO:
|
||||
ret.channels = 2;
|
||||
break;
|
||||
|
||||
case SPEAKERS_2POINT1:
|
||||
ret.channels = 3;
|
||||
ret.map[2] = PA_CHANNEL_POSITION_LFE;
|
||||
break;
|
||||
|
||||
case SPEAKERS_4POINT0:
|
||||
ret.channels = 4;
|
||||
ret.map[3] = PA_CHANNEL_POSITION_REAR_CENTER;
|
||||
break;
|
||||
|
||||
case SPEAKERS_4POINT1:
|
||||
ret.channels = 5;
|
||||
ret.map[4] = PA_CHANNEL_POSITION_REAR_CENTER;
|
||||
break;
|
||||
|
||||
case SPEAKERS_5POINT1:
|
||||
ret.channels = 6;
|
||||
break;
|
||||
|
||||
case SPEAKERS_7POINT1:
|
||||
ret.channels = 8;
|
||||
break;
|
||||
|
||||
case SPEAKERS_UNKNOWN:
|
||||
default:
|
||||
ret.channels = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void process_byte(void *p, size_t frames, size_t channels, float vol)
|
||||
{
|
||||
register char *cur = (char *) p;
|
||||
|
@ -370,8 +425,10 @@ static bool audio_monitor_init(struct audio_monitor *monitor,
|
|||
monitor->speakers = pulseaudio_channels_to_obs_speakers(spec.channels);
|
||||
monitor->bytes_per_frame = pa_frame_size(&spec);
|
||||
|
||||
pa_channel_map channel_map = pulseaudio_channel_map(monitor->speakers);
|
||||
|
||||
monitor->stream = pulseaudio_stream_new(
|
||||
obs_source_get_name(monitor->source), &spec, NULL);
|
||||
obs_source_get_name(monitor->source), &spec, &channel_map);
|
||||
if (!monitor->stream) {
|
||||
blog(LOG_ERROR, "Unable to create stream");
|
||||
return false;
|
||||
|
|
|
@ -51,15 +51,24 @@ enum audio_format {
|
|||
AUDIO_FORMAT_FLOAT_PLANAR,
|
||||
};
|
||||
|
||||
/**
|
||||
* The speaker layout describes where the speakers are located in the room.
|
||||
* For OBS it dictates:
|
||||
* * how many channels are available and
|
||||
* * which channels are used for which speakers.
|
||||
*
|
||||
* Standard channel layouts where retrieved from ffmpeg documentation at:
|
||||
* https://trac.ffmpeg.org/wiki/AudioChannelManipulation
|
||||
*/
|
||||
enum speaker_layout {
|
||||
SPEAKERS_UNKNOWN,
|
||||
SPEAKERS_MONO,
|
||||
SPEAKERS_STEREO,
|
||||
SPEAKERS_2POINT1,
|
||||
SPEAKERS_4POINT0,
|
||||
SPEAKERS_4POINT1,
|
||||
SPEAKERS_5POINT1,
|
||||
SPEAKERS_7POINT1=8,
|
||||
SPEAKERS_UNKNOWN, /**< Unknown setting, fallback is stereo. */
|
||||
SPEAKERS_MONO, /**< Channels: MONO */
|
||||
SPEAKERS_STEREO, /**< Channels: FL, FR */
|
||||
SPEAKERS_2POINT1, /**< Channels: FL, FR, LFE */
|
||||
SPEAKERS_4POINT0, /**< Channels: FL, FR, FC, RC */
|
||||
SPEAKERS_4POINT1, /**< Channels: FL, FR, FC, LFE, RC */
|
||||
SPEAKERS_5POINT1, /**< Channels: FL, FR, FC, LFE, RL, RR */
|
||||
SPEAKERS_7POINT1=8, /**< Channels: FL, FR, FC, LFE, RL, RR, SL, SR */
|
||||
};
|
||||
|
||||
struct audio_data {
|
||||
|
|
|
@ -93,6 +93,61 @@ static enum speaker_layout pulse_channels_to_obs_speakers(
|
|||
return SPEAKERS_UNKNOWN;
|
||||
}
|
||||
|
||||
static pa_channel_map pulse_channel_map(enum speaker_layout layout)
|
||||
{
|
||||
pa_channel_map ret;
|
||||
|
||||
ret.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
|
||||
ret.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
|
||||
ret.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
|
||||
ret.map[3] = PA_CHANNEL_POSITION_LFE;
|
||||
ret.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
|
||||
ret.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
|
||||
ret.map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
|
||||
ret.map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
|
||||
|
||||
switch (layout) {
|
||||
case SPEAKERS_MONO:
|
||||
ret.channels = 1;
|
||||
ret.map[0] = PA_CHANNEL_POSITION_MONO;
|
||||
break;
|
||||
|
||||
case SPEAKERS_STEREO:
|
||||
ret.channels = 2;
|
||||
break;
|
||||
|
||||
case SPEAKERS_2POINT1:
|
||||
ret.channels = 3;
|
||||
ret.map[2] = PA_CHANNEL_POSITION_LFE;
|
||||
break;
|
||||
|
||||
case SPEAKERS_4POINT0:
|
||||
ret.channels = 4;
|
||||
ret.map[3] = PA_CHANNEL_POSITION_REAR_CENTER;
|
||||
break;
|
||||
|
||||
case SPEAKERS_4POINT1:
|
||||
ret.channels = 5;
|
||||
ret.map[4] = PA_CHANNEL_POSITION_REAR_CENTER;
|
||||
break;
|
||||
|
||||
case SPEAKERS_5POINT1:
|
||||
ret.channels = 6;
|
||||
break;
|
||||
|
||||
case SPEAKERS_7POINT1:
|
||||
ret.channels = 8;
|
||||
break;
|
||||
|
||||
case SPEAKERS_UNKNOWN:
|
||||
default:
|
||||
ret.channels = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint64_t samples_to_ns(size_t frames, uint_fast32_t rate)
|
||||
{
|
||||
return frames * NSEC_PER_SEC / rate;
|
||||
|
@ -286,8 +341,10 @@ static int_fast32_t pulse_start_recording(struct pulse_data *data)
|
|||
data->speakers = pulse_channels_to_obs_speakers(spec.channels);
|
||||
data->bytes_per_frame = pa_frame_size(&spec);
|
||||
|
||||
pa_channel_map channel_map = pulse_channel_map(data->speakers);
|
||||
|
||||
data->stream = pulse_stream_new(obs_source_get_name(data->source),
|
||||
&spec, NULL);
|
||||
&spec, &channel_map);
|
||||
if (!data->stream) {
|
||||
blog(LOG_ERROR, "Unable to create stream");
|
||||
return -1;
|
||||
|
|
Loading…
Reference in a new issue