[Scummvm-git-logs] scummvm master -> 749fd8b490b6ea5b685ce7438e4ead3a69f38f30

sev- noreply at scummvm.org
Fri Nov 18 16:17:04 UTC 2022


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
9f4f22b3bf AUDIO: Support mono audio output in the mixer
749fd8b490 SDL: Allow selecting the audio channel count from the command line


Commit: 9f4f22b3bf2a42db172b05c7e15b776e22d23e3d
    https://github.com/scummvm/scummvm/commit/9f4f22b3bf2a42db172b05c7e15b776e22d23e3d
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2022-11-18T17:17:00+01:00

Commit Message:
AUDIO: Support mono audio output in the mixer

Changed paths:
    audio/mixer.cpp
    audio/mixer.h
    audio/mixer_intern.h
    audio/rate.cpp
    audio/rate.h
    backends/mixer/null/null-mixer.cpp
    backends/mixer/sdl/sdl-mixer.cpp
    backends/platform/android/android.cpp
    backends/platform/ios7/ios7_osys_sound.cpp
    backends/platform/iphone/osys_sound.cpp
    engines/sci/sound/audio32.cpp
    engines/sword1/music.cpp


diff --git a/audio/mixer.cpp b/audio/mixer.cpp
index c118b18c40c..3e348402827 100644
--- a/audio/mixer.cpp
+++ b/audio/mixer.cpp
@@ -176,8 +176,8 @@ private:
 #pragma mark --- Mixer ---
 #pragma mark -
 
-MixerImpl::MixerImpl(uint sampleRate, uint outBufSize)
-	: _mutex(), _sampleRate(sampleRate), _outBufSize(outBufSize), _mixerReady(false), _handleSeed(0), _soundTypeSettings() {
+MixerImpl::MixerImpl(uint sampleRate, bool stereo, uint outBufSize)
+	: _mutex(), _sampleRate(sampleRate), _stereo(stereo), _outBufSize(outBufSize), _mixerReady(false), _handleSeed(0), _soundTypeSettings() {
 
 	assert(sampleRate > 0);
 
@@ -200,6 +200,10 @@ uint MixerImpl::getOutputRate() const {
 	return _sampleRate;
 }
 
+bool MixerImpl::getOutputStereo() const {
+	return _stereo;
+}
+
 uint MixerImpl::getOutputBufSize() const {
 	return _outBufSize;
 }
@@ -280,15 +284,21 @@ int MixerImpl::mixCallback(byte *samples, uint len) {
 	Common::StackLock lock(_mutex);
 
 	int16 *buf = (int16 *)samples;
-	// we store stereo, 16-bit samples
-	assert(len % 4 == 0);
-	len >>= 2;
 
 	// Since the mixer callback has been called, the mixer must be ready...
 	_mixerReady = true;
 
 	//  zero the buf
-	memset(buf, 0, 2 * len * sizeof(int16));
+	memset(buf, 0, len);
+
+	// we store 16-bit samples
+	if (_stereo) {
+		assert(len % 4 == 0);
+		len >>= 2;
+	} else {
+		assert(len % 2 == 0);
+		len >>= 1;
+	}
 
 	// mix all channels
 	int res = 0, tmp;
@@ -524,7 +534,7 @@ Channel::Channel(Mixer *mixer, Mixer::SoundType type, AudioStream *stream,
 	assert(stream);
 
 	// Get a rate converter instance
-	_converter = makeRateConverter(_stream->getRate(), mixer->getOutputRate(), _stream->isStereo(), reverseStereo);
+	_converter = makeRateConverter(_stream->getRate(), mixer->getOutputRate(), _stream->isStereo(), mixer->getOutputStereo(), reverseStereo);
 }
 
 Channel::~Channel() {
diff --git a/audio/mixer.h b/audio/mixer.h
index 804022ecf00..ff521799617 100644
--- a/audio/mixer.h
+++ b/audio/mixer.h
@@ -305,6 +305,13 @@ public:
 	 */
 	virtual uint getOutputRate() const = 0;
 
+	/**
+	 * Check whether the output is stereo.
+	 *
+	 * @return true if output is stereo, false if not.
+	 */
+	virtual bool getOutputStereo() const = 0;
+
 	/**
 	 * Return the output sample buffer size of the system.
 	 *
diff --git a/audio/mixer_intern.h b/audio/mixer_intern.h
index 424a0d4853f..c7d67771cbd 100644
--- a/audio/mixer_intern.h
+++ b/audio/mixer_intern.h
@@ -64,6 +64,7 @@ private:
 	Common::Mutex _mutex;
 
 	const uint _sampleRate;
+	const bool _stereo;
 	const uint _outBufSize;
 	bool _mixerReady;
 	uint32 _handleSeed;
@@ -81,7 +82,7 @@ private:
 
 public:
 
-	MixerImpl(uint sampleRate, uint outBufSize = 0);
+	MixerImpl(uint sampleRate, bool stereo = true, uint outBufSize = 0);
 	~MixerImpl();
 
 	virtual bool isReady() const { Common::StackLock lock(_mutex); return _mixerReady; }
@@ -129,6 +130,7 @@ public:
 	virtual int getVolumeForSoundType(SoundType type) const;
 
 	virtual uint getOutputRate() const;
+	virtual bool getOutputStereo() const;
 	virtual uint getOutputBufSize() const;
 
 protected:
diff --git a/audio/rate.cpp b/audio/rate.cpp
index 1bd67c6d181..d85c278d796 100644
--- a/audio/rate.cpp
+++ b/audio/rate.cpp
@@ -62,7 +62,7 @@ enum {
  *
  * Limited to sampling frequency <= 65535 Hz.
  */
-template<bool stereo, bool reverseStereo>
+template<bool inStereo, bool outStereo, bool reverseStereo>
 class SimpleRateConverter : public RateConverter {
 protected:
 	st_sample_t inBuf[INTERMEDIATE_BUFFER_SIZE];
@@ -88,8 +88,8 @@ public:
 /*
  * Prepare processing.
  */
-template<bool stereo, bool reverseStereo>
-SimpleRateConverter<stereo, reverseStereo>::SimpleRateConverter(st_rate_t inrate, st_rate_t outrate) {
+template<bool inStereo, bool outStereo, bool reverseStereo>
+SimpleRateConverter<inStereo, outStereo, reverseStereo>::SimpleRateConverter(st_rate_t inrate, st_rate_t outrate) {
 	if ((inrate % outrate) != 0) {
 		error("Input rate must be a multiple of output rate to use rate effect");
 	}
@@ -110,12 +110,12 @@ SimpleRateConverter<stereo, reverseStereo>::SimpleRateConverter(st_rate_t inrate
  * Processed signed long samples from ibuf to obuf.
  * Return number of sample pairs processed.
  */
-template<bool stereo, bool reverseStereo>
-int SimpleRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
+template<bool inStereo, bool outStereo, bool reverseStereo>
+int SimpleRateConverter<inStereo, outStereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
 	st_sample_t *ostart, *oend;
 
 	ostart = obuf;
-	oend = obuf + osamp * 2;
+	oend = obuf + osamp * (outStereo ? 2 : 1);
 
 	while (obuf < oend) {
 
@@ -126,31 +126,42 @@ int SimpleRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
 				inPtr = inBuf;
 				inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
 				if (inLen <= 0)
-					return (obuf - ostart) / 2;
+					return (obuf - ostart) / (outStereo ? 2 : 1);
 			}
-			inLen -= (stereo ? 2 : 1);
+			inLen -= (inStereo ? 2 : 1);
 			opos--;
 			if (opos >= 0) {
-				inPtr += (stereo ? 2 : 1);
+				inPtr += (inStereo ? 2 : 1);
 			}
 		} while (opos >= 0);
 
-		st_sample_t out0, out1;
-		out0 = *inPtr++;
-		out1 = (stereo ? *inPtr++ : out0);
+		st_sample_t in0, in1;
+		in0 = *inPtr++;
+		in1 = (inStereo ? *inPtr++ : in0);
 
 		// Increment output position
 		opos += opos_inc;
 
-		// output left channel
-		clampedAdd(obuf[reverseStereo    ], (out0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
+		st_sample_t out0, out1;
+		out0 = (in0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume;
+		out1 = (in1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume;
 
-		// output right channel
-		clampedAdd(obuf[reverseStereo ^ 1], (out1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
+		if (outStereo) {
+			// output left channel
+			clampedAdd(obuf[reverseStereo    ], out0);
 
-		obuf += 2;
+			// output right channel
+			clampedAdd(obuf[reverseStereo ^ 1], out1);
+
+			obuf += 2;
+		} else {
+			// output mono channel
+			clampedAdd(obuf[0], (out0 + out1) / 2);
+
+			obuf += 1;
+		}
 	}
-	return (obuf - ostart) / 2;
+	return (obuf - ostart) / (outStereo ? 2 : 1);
 }
 
 /**
@@ -164,7 +175,7 @@ int SimpleRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
  * Limited to sampling frequency <= 65535 Hz.
  */
 
-template<bool stereo, bool reverseStereo>
+template<bool inStereo, bool outStereo, bool reverseStereo>
 class LinearRateConverter : public RateConverter {
 protected:
 	st_sample_t inBuf[INTERMEDIATE_BUFFER_SIZE];
@@ -194,8 +205,8 @@ public:
 /*
  * Prepare processing.
  */
-template<bool stereo, bool reverseStereo>
-LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate, st_rate_t outrate) {
+template<bool inStereo, bool outStereo, bool reverseStereo>
+LinearRateConverter<inStereo, outStereo, reverseStereo>::LinearRateConverter(st_rate_t inrate, st_rate_t outrate) {
 	if (inrate >= 131072 || outrate >= 131072) {
 		error("rate effect can only handle rates < 131072");
 	}
@@ -219,12 +230,12 @@ LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate
  * Processed signed long samples from ibuf to obuf.
  * Return number of sample pairs processed.
  */
-template<bool stereo, bool reverseStereo>
-int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
+template<bool inStereo, bool outStereo, bool reverseStereo>
+int LinearRateConverter<inStereo, outStereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
 	st_sample_t *ostart, *oend;
 
 	ostart = obuf;
-	oend = obuf + osamp * 2;
+	oend = obuf + osamp * (outStereo ? 2 : 1);
 
 	while (obuf < oend) {
 
@@ -235,12 +246,12 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
 				inPtr = inBuf;
 				inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
 				if (inLen <= 0)
-					return (obuf - ostart) / 2;
+					return (obuf - ostart) / (outStereo ? 2 : 1);
 			}
-			inLen -= (stereo ? 2 : 1);
+			inLen -= (inStereo ? 2 : 1);
 			ilast0 = icur0;
 			icur0 = *inPtr++;
-			if (stereo) {
+			if (inStereo) {
 				ilast1 = icur1;
 				icur1 = *inPtr++;
 			}
@@ -251,25 +262,36 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
 		// still space in the output buffer.
 		while (opos < (frac_t)FRAC_ONE_LOW && obuf < oend) {
 			// interpolate
-			st_sample_t out0, out1;
-			out0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * opos + FRAC_HALF_LOW) >> FRAC_BITS_LOW));
-			out1 = (stereo ?
+			st_sample_t in0, in1;
+			in0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * opos + FRAC_HALF_LOW) >> FRAC_BITS_LOW));
+			in1 = (inStereo ?
 						  (st_sample_t)(ilast1 + (((icur1 - ilast1) * opos + FRAC_HALF_LOW) >> FRAC_BITS_LOW)) :
-						  out0);
+						  in0);
 
-			// output left channel
-			clampedAdd(obuf[reverseStereo    ], (out0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
+			st_sample_t out0, out1;
+			out0 = (in0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume;
+			out1 = (in1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume;
 
-			// output right channel
-			clampedAdd(obuf[reverseStereo ^ 1], (out1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
+			if (outStereo) {
+				// output left channel
+				clampedAdd(obuf[reverseStereo    ], out0);
 
-			obuf += 2;
+				// output right channel
+				clampedAdd(obuf[reverseStereo ^ 1], out1);
+
+				obuf += 2;
+			} else {
+				// output mono channel
+				clampedAdd(obuf[0], (out0 + out1) / 2);
+
+				obuf += 1;
+			}
 
 			// Increment output position
 			opos += opos_inc;
 		}
 	}
-	return (obuf - ostart) / 2;
+	return (obuf - ostart) / (outStereo ? 2 : 1);
 }
 
 
@@ -279,7 +301,7 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
 /**
  * Simple audio rate converter for the case that the inrate equals the outrate.
  */
-template<bool stereo, bool reverseStereo>
+template<bool inStereo, bool outStereo, bool reverseStereo>
 class CopyRateConverter : public RateConverter {
 	st_sample_t *_buffer;
 	st_size_t _bufferSize;
@@ -290,20 +312,20 @@ public:
 	}
 
 	int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) override {
-		assert(input.isStereo() == stereo);
+		assert(input.isStereo() == inStereo);
 
 		st_sample_t *ptr;
 		st_size_t len;
 
 		st_sample_t *ostart = obuf;
 
-		if (stereo)
+		if (inStereo)
 			osamp *= 2;
 
 		// Reallocate temp buffer, if necessary
 		if (osamp > _bufferSize) {
 			free(_buffer);
-			_buffer = (st_sample_t *)malloc(osamp * 2);
+			_buffer = (st_sample_t *)malloc(osamp * sizeof(st_sample_t));
 			_bufferSize = osamp;
 		}
 
@@ -315,20 +337,31 @@ public:
 
 		// Mix the data into the output buffer
 		ptr = _buffer;
-		for (; len > 0; len -= (stereo ? 2 : 1)) {
+		for (; len > 0; len -= (inStereo ? 2 : 1)) {
+			st_sample_t in0, in1;
+			in0 = *ptr++;
+			in1 = (inStereo ? *ptr++ : in0);
+
 			st_sample_t out0, out1;
-			out0 = *ptr++;
-			out1 = (stereo ? *ptr++ : out0);
+			out0 = (in0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume;
+			out1 = (in1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume;
 
-			// output left channel
-			clampedAdd(obuf[reverseStereo    ], (out0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
+			if (outStereo) {
+				// output left channel
+				clampedAdd(obuf[reverseStereo    ], out0);
 
-			// output right channel
-			clampedAdd(obuf[reverseStereo ^ 1], (out1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
+				// output right channel
+				clampedAdd(obuf[reverseStereo ^ 1], out1);
 
-			obuf += 2;
+				obuf += 2;
+			} else {
+				// output mono channel
+				clampedAdd(obuf[0], (out0 + out1) / 2);
+
+				obuf += 1;
+			}
 		}
-		return (obuf - ostart) / 2;
+		return (obuf - ostart) / (outStereo ? 2 : 1);
 	}
 
 	int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) override {
@@ -339,30 +372,37 @@ public:
 
 #pragma mark -
 
-template<bool stereo, bool reverseStereo>
+template<bool inStereo, bool outStereo, bool reverseStereo>
 RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate) {
 	if (inrate != outrate) {
 		if ((inrate % outrate) == 0 && (inrate < 65536)) {
-			return new SimpleRateConverter<stereo, reverseStereo>(inrate, outrate);
+			return new SimpleRateConverter<inStereo, outStereo, reverseStereo>(inrate, outrate);
 		} else {
-			return new LinearRateConverter<stereo, reverseStereo>(inrate, outrate);
+			return new LinearRateConverter<inStereo, outStereo, reverseStereo>(inrate, outrate);
 		}
 	} else {
-		return new CopyRateConverter<stereo, reverseStereo>();
+		return new CopyRateConverter<inStereo, outStereo, reverseStereo>();
 	}
 }
 
 /**
  * Create and return a RateConverter object for the specified input and output rates.
  */
-RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) {
-	if (stereo) {
-		if (reverseStereo)
-			return makeRateConverter<true, true>(inrate, outrate);
-		else
-			return makeRateConverter<true, false>(inrate, outrate);
-	} else
-		return makeRateConverter<false, false>(inrate, outrate);
+RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool instereo, bool outstereo, bool reverseStereo) {
+	if (instereo) {
+		if (outstereo) {
+			if (reverseStereo)
+				return makeRateConverter<true, true, true>(inrate, outrate);
+			else
+				return makeRateConverter<true, true, false>(inrate, outrate);
+		} else
+			return makeRateConverter<true, false, false>(inrate, outrate);
+	} else {
+		if (outstereo) {
+			return makeRateConverter<false, true, false>(inrate, outrate);
+		} else
+			return makeRateConverter<false, false, false>(inrate, outrate);
+	}
 }
 
 } // End of namespace Audio
diff --git a/audio/rate.h b/audio/rate.h
index 93d9041ab06..67e34b8de1c 100644
--- a/audio/rate.h
+++ b/audio/rate.h
@@ -84,7 +84,7 @@ public:
 	virtual int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) = 0;
 };
 
-RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo = false);
+RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool instereo, bool outstereo, bool reverseStereo);
 /** @} */
 } // End of namespace Audio
 
diff --git a/backends/mixer/null/null-mixer.cpp b/backends/mixer/null/null-mixer.cpp
index 45f41223424..e7f3f79455a 100644
--- a/backends/mixer/null/null-mixer.cpp
+++ b/backends/mixer/null/null-mixer.cpp
@@ -36,7 +36,7 @@ NullMixerManager::~NullMixerManager() {
 }
 
 void NullMixerManager::init() {
-	_mixer = new Audio::MixerImpl(_outputRate, _samples);
+	_mixer = new Audio::MixerImpl(_outputRate, true, _samples);
 	assert(_mixer);
 	_mixer->setReady(true);
 }
diff --git a/backends/mixer/sdl/sdl-mixer.cpp b/backends/mixer/sdl/sdl-mixer.cpp
index fc9c095970e..f3b9d93e3df 100644
--- a/backends/mixer/sdl/sdl-mixer.cpp
+++ b/backends/mixer/sdl/sdl-mixer.cpp
@@ -73,7 +73,7 @@ void SdlMixerManager::init() {
 		warning("Could not open audio device: %s", SDL_GetError());
 
 		// The mixer is not marked as ready
-		_mixer = new Audio::MixerImpl(desired.freq, desired.samples);
+		_mixer = new Audio::MixerImpl(desired.freq, true, desired.samples);
 		return;
 	}
 
@@ -88,7 +88,7 @@ void SdlMixerManager::init() {
 			warning("Could not open audio device: %s", SDL_GetError());
 
 			// The mixer is not marked as ready
-			_mixer = new Audio::MixerImpl(desired.freq, desired.samples);
+			_mixer = new Audio::MixerImpl(desired.freq, true, desired.samples);
 			return;
 		}
 
@@ -106,7 +106,7 @@ void SdlMixerManager::init() {
 	if (_obtained.channels != 2)
 		error("SDL mixer output requires stereo output device");
 
-	_mixer = new Audio::MixerImpl(_obtained.freq, desired.samples);
+	_mixer = new Audio::MixerImpl(_obtained.freq, true, desired.samples);
 	assert(_mixer);
 	_mixer->setReady(true);
 
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index e947441ebd7..e014520f824 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -470,7 +470,7 @@ void OSystem_Android::initBackend() {
 	// The division by four happens because the Mixer stores the size in frame units
 	// instead of bytes; this means that, since we have audio in stereo (2 channels)
 	// with a word size of 16 bit (2 bytes), we have to divide the effective size by 4.
-	_mixer = new Audio::MixerImpl(_audio_sample_rate, _audio_buffer_size / 4);
+	_mixer = new Audio::MixerImpl(_audio_sample_rate, true, _audio_buffer_size / 4);
 	_mixer->setReady(true);
 
 	_timer_thread_exit = false;
diff --git a/backends/platform/ios7/ios7_osys_sound.cpp b/backends/platform/ios7/ios7_osys_sound.cpp
index 648bceac4b4..65008b26f30 100644
--- a/backends/platform/ios7/ios7_osys_sound.cpp
+++ b/backends/platform/ios7/ios7_osys_sound.cpp
@@ -45,7 +45,7 @@ void OSystem_iOS7::mixCallback(void *sys, byte *samples, int len) {
 }
 
 void OSystem_iOS7::setupMixer() {
-	_mixer = new Audio::MixerImpl(AUDIO_SAMPLE_RATE, WAVE_BUFFER_SIZE);
+	_mixer = new Audio::MixerImpl(AUDIO_SAMPLE_RATE, true, WAVE_BUFFER_SIZE);
 
 	s_soundCallback = mixCallback;
 	s_soundParam = this;
diff --git a/backends/platform/iphone/osys_sound.cpp b/backends/platform/iphone/osys_sound.cpp
index ae6117b9a9f..bc71f3b760d 100644
--- a/backends/platform/iphone/osys_sound.cpp
+++ b/backends/platform/iphone/osys_sound.cpp
@@ -45,7 +45,7 @@ void OSystem_IPHONE::mixCallback(void *sys, byte *samples, int len) {
 }
 
 void OSystem_IPHONE::setupMixer() {
-	_mixer = new Audio::MixerImpl(AUDIO_SAMPLE_RATE, WAVE_BUFFER_SIZE);
+	_mixer = new Audio::MixerImpl(AUDIO_SAMPLE_RATE, true, WAVE_BUFFER_SIZE);
 
 	s_soundCallback = mixCallback;
 	s_soundParam = this;
diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index fd855331dab..69ffb9cfaae 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -694,7 +694,8 @@ bool Audio32::playRobotAudio(const RobotAudioStream::RobotAudioPacket &packet) {
 		channel.soundNode = NULL_REG;
 		channel.volume = kMaxVolume;
 		channel.pan = -1;
-		channel.converter.reset(Audio::makeRateConverter(RobotAudioStream::kRobotSampleRate, getRate(), false));
+		// TODO: Avoid unnecessary channel conversion
+		channel.converter.reset(Audio::makeRateConverter(RobotAudioStream::kRobotSampleRate, getRate(), false, true, false));
 		// The RobotAudioStream buffer size is
 		// ((bytesPerSample * channels * sampleRate * 2000ms) / 1000ms) & ~3
 		// where bytesPerSample = 2, channels = 1, and sampleRate = 22050
@@ -860,7 +861,8 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
 	}
 
 	channel.stream.reset(new MutableLoopAudioStream(audioStream, loop));
-	channel.converter.reset(Audio::makeRateConverter(channel.stream->getRate(), getRate(), channel.stream->isStereo(), false));
+	// TODO: Avoid unnecessary channel conversion
+	channel.converter.reset(Audio::makeRateConverter(channel.stream->getRate(), getRate(), channel.stream->isStereo(), true, false));
 
 	// SSCI sets up a decompression buffer here for the audio stream, plus
 	// writes information about the sample to the channel to convert to the
diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp
index 33a70991268..f8e56256fc8 100644
--- a/engines/sword1/music.cpp
+++ b/engines/sword1/music.cpp
@@ -303,12 +303,14 @@ void Music::startMusic(int32 tuneId, int32 loopFlag) {
 		if (SwordEngine::isPsx()) {
 			if (_handles[newStream].playPSX(tuneId, loopFlag != 0)) {
 				_mutex.lock();
-				_converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false);
+				// TODO: Avoid unnecessary channel conversion
+				_converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), true, false);
 				_mutex.unlock();
 			}
 		} else if (_handles[newStream].play(_tuneList[tuneId], loopFlag != 0)) {
 			_mutex.lock();
-			_converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false);
+			// TODO: Avoid unnecessary channel conversion
+			_converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), true, false);
 			_mutex.unlock();
 		} else {
 			if (tuneId != 81) // file 81 was apparently removed from BS.


Commit: 749fd8b490b6ea5b685ce7438e4ead3a69f38f30
    https://github.com/scummvm/scummvm/commit/749fd8b490b6ea5b685ce7438e4ead3a69f38f30
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2022-11-18T17:17:00+01:00

Commit Message:
SDL: Allow selecting the audio channel count from the command line

Changed paths:
    backends/mixer/sdl/sdl-mixer.cpp
    base/commandLine.cpp
    dists/scummvm.6
    doc/docportal/advanced_topics/command_line.rst
    doc/docportal/advanced_topics/configuration_file.rst


diff --git a/backends/mixer/sdl/sdl-mixer.cpp b/backends/mixer/sdl/sdl-mixer.cpp
index f3b9d93e3df..ae3ff5dfeac 100644
--- a/backends/mixer/sdl/sdl-mixer.cpp
+++ b/backends/mixer/sdl/sdl-mixer.cpp
@@ -73,7 +73,7 @@ void SdlMixerManager::init() {
 		warning("Could not open audio device: %s", SDL_GetError());
 
 		// The mixer is not marked as ready
-		_mixer = new Audio::MixerImpl(desired.freq, true, desired.samples);
+		_mixer = new Audio::MixerImpl(desired.freq, desired.channels >= 2, desired.samples);
 		return;
 	}
 
@@ -88,7 +88,7 @@ void SdlMixerManager::init() {
 			warning("Could not open audio device: %s", SDL_GetError());
 
 			// The mixer is not marked as ready
-			_mixer = new Audio::MixerImpl(desired.freq, true, desired.samples);
+			_mixer = new Audio::MixerImpl(desired.freq, desired.channels >= 2, desired.samples);
 			return;
 		}
 
@@ -103,10 +103,11 @@ void SdlMixerManager::init() {
 	if (_obtained.samples != desired.samples)
 		warning("SDL mixer output buffer size: %d differs from desired: %d", _obtained.samples, desired.samples);
 
-	if (_obtained.channels != 2)
-		error("SDL mixer output requires stereo output device");
+	debug(1, "Output channels: %d", _obtained.channels);
+	if (_obtained.channels != 1 && _obtained.channels != 2)
+		error("SDL mixer output requires mono or stereo output device");
 
-	_mixer = new Audio::MixerImpl(_obtained.freq, true, desired.samples);
+	_mixer = new Audio::MixerImpl(_obtained.freq, _obtained.channels >= 2, desired.samples);
 	assert(_mixer);
 	_mixer->setReady(true);
 
@@ -143,6 +144,12 @@ SDL_AudioSpec SdlMixerManager::getAudioSpec(uint32 outputRate) {
 	if (freq <= 0)
 		freq = outputRate;
 
+	uint32 channels = 2;
+	if (ConfMan.hasKey("output_channels"))
+		channels = ConfMan.getInt("output_channels");
+	if (channels > 2 || channels <= 0)
+		channels = 2;
+
 	// One SDL "sample" is a complete audio frame (i.e. all channels = 1 sample)
 	uint32 samples = 0;
 
@@ -166,7 +173,7 @@ SDL_AudioSpec SdlMixerManager::getAudioSpec(uint32 outputRate) {
 	memset(&desired, 0, sizeof(desired));
 	desired.freq = freq;
 	desired.format = AUDIO_S16SYS;
-	desired.channels = 2;
+	desired.channels = channels;
 	desired.samples = roundDownPowerOfTwo(samples);
 	desired.callback = sdlCallback;
 	desired.userdata = this;
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 831eb10d5fd..099c01c41e9 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -160,6 +160,7 @@ static const char HELP_STRING4[] =
 	"  --dump-midi              Dumps MIDI events to 'dump.mid', until quitting from game\n"
 	"                           (if file already exists, it will be overwritten)\n"
 	"  --enable-gs              Enable Roland GS mode for MIDI playback\n"
+	"  --output-channels=CHANNELS Select output channel count (e.g. 2 for stereo)\n"
 	"  --output-rate=RATE       Select output sample rate in Hz (e.g. 22050)\n"
 	"  --opl-driver=DRIVER      Select AdLib (OPL) emulator (db, mame"
 #ifndef DISABLE_NUKED_OPL
@@ -663,6 +664,9 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
 			DO_LONG_COMMAND("list-audio-devices")
 			END_COMMAND
 
+			DO_LONG_OPTION_INT("output-channels")
+			END_OPTION
+
 			DO_LONG_OPTION_INT("output-rate")
 			END_OPTION
 
diff --git a/dists/scummvm.6 b/dists/scummvm.6
index ec6b83cb2bf..164ab1a0899 100644
--- a/dists/scummvm.6
+++ b/dists/scummvm.6
@@ -326,6 +326,8 @@ Select AdLib (OPL) emulator
 .Ar nuked ,
 .Ar opl2lpt
 .Pc .
+.It Fl -output-channels= Ns Ar RATE
+Set output channel count (e.g. 2 for stereo).
 .It Fl -output-rate= Ns Ar RATE
 Set output sample rate in Hz (e.g. 22050).
 .It Fl -platform= Ns Ar PLATFORM
diff --git a/doc/docportal/advanced_topics/command_line.rst b/doc/docportal/advanced_topics/command_line.rst
index 4d65a075648..bb89472655a 100755
--- a/doc/docportal/advanced_topics/command_line.rst
+++ b/doc/docportal/advanced_topics/command_line.rst
@@ -200,6 +200,7 @@ Short options are listed where they are available.
         ``--no-filtering``,,"Forces unfiltered graphics mode"
         ``--no-fullscreen``,``-F``,"Forces windowed mode"
         ``--opl-driver=DRIVER``,,":ref:`Selects AdLib (OPL) emulator <opl>`"
+        ``--output-channels=CHANNELS``,,"Select output channel count"
         ``--output-rate=RATE``,,"Selects output sample rate in Hz"
         ``--path=PATH``,``-p``,"Sets path to where the game is installed"
         ``--platform=STRING``,,":ref:`Specifes platform of game <platform>`. Allowed values: 2gs, 3do, acorn, amiga, atari, c64, fmtowns, nes, mac, pc pc98, pce, segacd, wii, windows."
diff --git a/doc/docportal/advanced_topics/configuration_file.rst b/doc/docportal/advanced_topics/configuration_file.rst
index d6ae94569b3..55875e97b1d 100755
--- a/doc/docportal/advanced_topics/configuration_file.rst
+++ b/doc/docportal/advanced_topics/configuration_file.rst
@@ -339,6 +339,11 @@ There are many recognized configuration keys. In the table below, each key is ei
 	- op3lpt
 	- rwopl3 "
 		":ref:`originalsaveload <osl>`",boolean,false,
+		":ref:`output_channels <outputchannels>`",integer,,"
+	Supported values are:
+
+	- 1
+	- 2"
 		":ref:`output_rate <outputrate>`",integer,,"
 	Sensible values are:
 




More information about the Scummvm-git-logs mailing list