瀏覽代碼

Merge pull request #1139 from takev/pulseaudio-surround-selection

linux-pulseaudio: Surround speaker map
Jim 7 年之前
父節點
當前提交
77643cce1e
共有 3 個文件被更改,包括 133 次插入10 次删除
  1. 58 1
      libobs/audio-monitoring/pulse/pulseaudio-output.c
  2. 17 8
      libobs/media-io/audio-io.h
  3. 58 1
      plugins/linux-pulseaudio/pulse-input.c

+ 58 - 1
libobs/audio-monitoring/pulse/pulseaudio-output.c

@@ -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;

+ 17 - 8
libobs/media-io/audio-io.h

@@ -55,15 +55,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 {

+ 58 - 1
plugins/linux-pulseaudio/pulse-input.c

@@ -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;