[Scummvm-git-logs] scummvm master -> 4958fa03eaf5a1c6f5dfe7c4a92cb38a4a7c2564

athrxx noreply at scummvm.org
Sun Feb 4 02:18:33 UTC 2024


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:
a680509332 SCUMM: (INDY3/MAC) - add internal 16 bit handling to sound player
4958fa03ea SCUMM: (INDY3/MAC) - disable sample interpolation for music


Commit: a6805093329cbe0fdb88909878479c88aa48ba8e
    https://github.com/scummvm/scummvm/commit/a6805093329cbe0fdb88909878479c88aa48ba8e
Author: athrxx (athrxx at scummvm.org)
Date: 2024-02-04T03:18:05+01:00

Commit Message:
SCUMM: (INDY3/MAC) - add internal 16 bit handling to sound player

(could improve the music slightly, but probably more in
theory than in practice)

Changed paths:
    engines/scumm/players/player_mac_indy3.cpp


diff --git a/engines/scumm/players/player_mac_indy3.cpp b/engines/scumm/players/player_mac_indy3.cpp
index 4d53143fef8..b753bb1701b 100644
--- a/engines/scumm/players/player_mac_indy3.cpp
+++ b/engines/scumm/players/player_mac_indy3.cpp
@@ -42,7 +42,7 @@ extern const uint32 g_pv2ModTblSize;
 class I3MPlayer;
 class AudioStream_I3M : public Audio::AudioStream {
 public:
-	AudioStream_I3M(I3MPlayer *drv, uint32 scummVMOutputrate, bool stereo, bool interpolate);
+	AudioStream_I3M(I3MPlayer *drv, uint32 scummVMOutputrate, bool stereo, bool interpolate, bool internal16Bit);
 	~AudioStream_I3M() override;
 
 	void initBuffers(uint32 feedBufferSize);
@@ -60,7 +60,7 @@ public:
 	bool endOfData() const override { return false; }
 
 private:
-	void generateData(int8 *dst, uint32 len, Audio::Mixer::SoundType, bool expectStereo) const;
+	void generateData(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType, bool expectStereo) const;
 	void runVblTask();
 
 	I3MPlayer *_drv;
@@ -87,23 +87,29 @@ private:
 
 	const uint32 _outputRate;
 	const uint8 _frameSize;
-	bool _interp;
+	const bool _interp;
+	const int _smpInternalSize;
+	const int _volDown;
 
 	const bool _isStereo;
 };
 
 class I3MSoundDriver {
 public:
-	I3MSoundDriver(Common::Mutex &mutex, uint32 deviceRate, bool isStereo) : _mutex(mutex), _sig(false), _deviceRate(deviceRate), _stereo(isStereo) {}
+	I3MSoundDriver(Common::Mutex &mutex, uint32 deviceRate, bool isStereo, bool internal16Bit) : _mutex(mutex), _sig(false), _deviceRate(deviceRate), _stereo(isStereo),
+		_smpSize(internal16Bit ? 2 : 1), _smpMin(internal16Bit ? -32768 : -128), _smpMax(internal16Bit ? 32767 : 127) {}
 	virtual ~I3MSoundDriver() {}
-	virtual void feed(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) = 0;
+	virtual void feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) = 0;
 	uint32 getDeviceRate() const { return _deviceRate; }
 	bool checkSignal() const { return _sig; }
 	void resetSignal(bool state) { _sig = state; }
 protected:
 	Common::Mutex &_mutex;
 	const bool _stereo;
+	const int _smpSize;
 	const uint32 _deviceRate;
+	const int16 _smpMin;
+	const int16 _smpMax;
 	bool _sig;
 };
 
@@ -119,8 +125,8 @@ public:
 		byte baseFreq;
 	};
 public:
-	I3MLowLevelPCMDriver(Common::Mutex &mutex, uint32 deviceRate, bool enableInterpolation, bool isStereo);
-	void feed(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) override;
+	I3MLowLevelPCMDriver(Common::Mutex &mutex, uint32 deviceRate, bool enableInterpolation, bool isStereo, bool internal16Bit);
+	void feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) override;
 	void play(PCMSound *snd);
 	void stop();
 private:
@@ -150,7 +156,7 @@ public:
 		kSwTriplet = 3
 	};
 
-	I3MMusicDriver(uint16 numChannels, Common::Mutex &mutex, bool isStereo) : I3MSoundDriver(mutex, ASC_DEVICE_RATE, isStereo), _numChan(numChannels) {}
+	I3MMusicDriver(uint16 numChannels, Common::Mutex &mutex, bool isStereo, bool internal16Bit) : I3MSoundDriver(mutex, ASC_DEVICE_RATE, isStereo, internal16Bit), _numChan(numChannels) {}
 	virtual void start() = 0;
 	virtual void stop() = 0;
 	virtual void setParameter(ParaType type, ...) = 0;
@@ -161,16 +167,10 @@ protected:
 
 class I3MFourToneSynthDriver final : public I3MMusicDriver {
 public:
-	struct Data {
-		Data(uint16 dur) : duration(dur) { memset(rate, 0, sizeof(rate)); }
-		uint16 duration;
-		uint16 rate[4];
-	};
-public:
-	I3MFourToneSynthDriver(Common::Mutex &mutex, bool isStereo);
+	I3MFourToneSynthDriver(Common::Mutex &mutex, bool isStereo, bool internal16bit);
 	~I3MFourToneSynthDriver() override;
 
-	void feed(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) override;
+	void feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) override;
 	void start() override;
 	void stop() override;
 	void setParameter(ParaType type, ...) override;
@@ -195,22 +195,22 @@ private:
 
 class I3MSquareWaveSynthDriver final : public I3MMusicDriver {
 public:
-	struct Data {
-		Data() : count(0), ampltd(0), duration(0) {}
-		uint16 count;
-		uint16 ampltd;
-		uint16 duration;
-	};
-public:
-	I3MSquareWaveSynthDriver(Common::Mutex &mutex, bool isStereo) : I3MMusicDriver(1, mutex, isStereo) {}
+	I3MSquareWaveSynthDriver(Common::Mutex &mutex, bool isStereo, bool internal16Bit) : I3MMusicDriver(1, mutex, isStereo, internal16Bit) {}
 	~I3MSquareWaveSynthDriver() override {}
 
-	void feed(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) override;
+	void feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) override;
 	void start() override;
 	void stop() override;
 	void setParameter(ParaType argType, ...) override;
 private:
 	void pushTriplet(uint16 count, uint16 amplitude, uint16 duration);
+
+	struct Triplet {
+		Triplet(uint16 cnt, uint16 ampl, uint16 dur) : count(cnt), amplitude(ampl), duration(dur) {}
+		uint16 count;
+		uint16 amplitude;
+		uint16 duration;
+	};
 };
 
 class I3MPlayer {
@@ -219,7 +219,7 @@ private:
 public:
 	~I3MPlayer();
 	static Common::SharedPtr<I3MPlayer> open(ScummEngine *scumm, Audio::Mixer *mixer);
-	bool startDevices(uint32 outputRate, uint32 pcmDeviceRate, uint32 feedBufferSize, bool enableInterpolation);
+	bool startDevices(uint32 outputRate, uint32 pcmDeviceRate, uint32 feedBufferSize, bool enableInterpolation, bool stereo, bool internal16Bit);
 
 	void setMusicVolume(int vol);
 	void setSfxVolume(int vol);
@@ -232,7 +232,7 @@ public:
 	void saveLoadWithSerializer(Common::Serializer &ser);
 	void restoreAfterLoad();
 
-	void generateData(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) const;
+	void generateData(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) const;
 	uint32 getDriverDeviceRate(uint8 drvID) const;
 	void nextTick();
 
@@ -263,6 +263,8 @@ private:
 	bool _songPlaying;
 	bool _soundEffectPlaying;
 	int _qmode;
+	bool _16bit;
+	bool _stereo;
 	bool _qualHi;
 	bool _mixerThread;
 
@@ -363,8 +365,9 @@ public:
 	MusicChannel *getMusicChannel(uint8 id) const;
 };
 
-AudioStream_I3M::AudioStream_I3M(I3MPlayer *drv, uint32 scummVMOutputrate, bool stereo, bool interpolate) : Audio::AudioStream(), _drv(drv), _vblSmpQty(0), _vblSmpQtyRem(0), _frameSize(stereo ? 2 : 1),
-	_vblCountDown(0), _vblCountDownRem(0), _outputRate(scummVMOutputrate), _vblCbProc(nullptr), _isStereo(stereo), _interp(interpolate) {
+AudioStream_I3M::AudioStream_I3M(I3MPlayer *drv, uint32 scummVMOutputrate, bool stereo, bool interpolate, bool internal16Bit) : Audio::AudioStream(), _drv(drv),
+	_vblSmpQty(0), _vblSmpQtyRem(0), _frameSize((stereo ? 2 : 1) * (internal16Bit ? 2 : 1)), _vblCountDown(0), _vblCountDownRem(0), _outputRate(scummVMOutputrate),
+		_vblCbProc(nullptr), _isStereo(stereo), _interp(interpolate), _smpInternalSize(internal16Bit ? 2 : 1), _volDown(internal16Bit ? 2 : 0) {
 	assert(_drv);
 	_vblSmpQty = (_outputRate << 16) / VBL_UPDATE_RATE;
 	_vblSmpQtyRem = (_outputRate << 16) % VBL_UPDATE_RATE;
@@ -382,9 +385,9 @@ void AudioStream_I3M::initBuffers(uint32 feedBufferSize) {
 		delete[] _buffers[i].start;
 
 	for (int i = 0; i < 2; ++i) {
-		_buffers[i].size = feedBufferSize;
+		_buffers[i].size = feedBufferSize / _frameSize;
 		_buffers[i].start = new int8[_buffers[i].size + PCM_BUFFER_RESERVE];
-		_buffers[i].end = _buffers[i].start + _buffers[i].size;
+		_buffers[i].end = &_buffers[i].start[_buffers[i].size];
 	}
 	clearBuffer();
 }
@@ -444,17 +447,19 @@ int AudioStream_I3M::readBuffer(int16 *buffer, const int numSamples) {
 		int32 smpL = 0;
 		int32 smpR = 0;
 		for (int ii = 0; ii < 2; ++ii) {
-			int diff = _buffers[ii].pos[0] - _buffers[ii].lastL;
+			int smpN = _smpInternalSize == 2 ? *reinterpret_cast<int16*>(_buffers[ii].pos) : _buffers[ii].pos[0];
+			int diff = smpN - _buffers[ii].lastL;
 			if (diff && _buffers[ii].rateConvAcc && _interp)
 				diff = (diff * _buffers[ii].rateConvAcc) >> RATECNV_BIT_PRECSN;
-			smpL += (int32)((_buffers[ii].lastL + diff) * _buffers[ii].volume);
+			smpL += (int32)((_buffers[ii].lastL + diff) * (_buffers[ii].volume >> _volDown));
 		}
 		if (_isStereo) {
 			for (int ii = 0; ii < 2; ++ii) {
-				int diff = _buffers[ii].pos[1] - _buffers[ii].lastR;
+				int smpN = _smpInternalSize == 2 ? *reinterpret_cast<int16*>(&_buffers[ii].pos[2]) : _buffers[ii].pos[1];
+				int diff = smpN - _buffers[ii].lastR;
 				if (diff && _buffers[ii].rateConvAcc && _interp)
 					diff = (diff * _buffers[ii].rateConvAcc) >> RATECNV_BIT_PRECSN;
-				smpR += (int32)((_buffers[ii].lastR + diff) * _buffers[ii].volume);
+				smpR += (int32)((_buffers[ii].lastR + diff) * (_buffers[ii].volume >> _volDown));
 			}
 		}
 
@@ -471,9 +476,16 @@ int AudioStream_I3M::readBuffer(int16 *buffer, const int numSamples) {
 				const int8 *lpos = _buffers[ii].pos;
 				if (lpos >= _buffers[ii].start + _frameSize)
 					lpos -= _frameSize;
-				_buffers[ii].lastL = lpos[0];
-				if (_isStereo)
-					_buffers[ii].lastR = lpos[1];
+
+				if (_smpInternalSize == 2) {
+					_buffers[ii].lastL = *reinterpret_cast<const int16*>(lpos);
+					if (_isStereo)
+						_buffers[ii].lastR = *reinterpret_cast<const int16*>(&lpos[2]);
+				} else {
+					_buffers[ii].lastL = lpos[0];
+					if (_isStereo)
+						_buffers[ii].lastR = lpos[1];
+				}
 
 				if (_buffers[ii].pos >= _buffers[ii].end) {
 					int refreshSize = MIN<int>(_vblCountDown * _frameSize, _buffers[ii].size);
@@ -491,9 +503,9 @@ int AudioStream_I3M::readBuffer(int16 *buffer, const int numSamples) {
 	return numSamples;
 }
 
-void AudioStream_I3M::generateData(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) const {
+void AudioStream_I3M::generateData(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) const {
 	if (_drv)
-		_drv->generateData(dst, len, type, expectStereo);
+		_drv->generateData(dst, byteSize, type, expectStereo);
 }
 
 void AudioStream_I3M::runVblTask() {
@@ -501,16 +513,17 @@ void AudioStream_I3M::runVblTask() {
 		(*_vblCbProc)();
 }
 
-I3MLowLevelPCMDriver::I3MLowLevelPCMDriver(Common::Mutex &mutex, uint32 deviceRate, bool enableInterpolation, bool isStereo) :
-	I3MSoundDriver(mutex, deviceRate, isStereo), _interp(enableInterpolation), _frameSize(isStereo ? 2 : 1), _len(0), _rmH(0), _rmL(0), _smpWtAcc(0), _loopSt(0), _loopEnd(0), _baseFreq(0), _rcPos(0), _data(nullptr) {
-		_lastSmp[0] = _lastSmp[1] = 0;
+I3MLowLevelPCMDriver::I3MLowLevelPCMDriver(Common::Mutex &mutex, uint32 deviceRate, bool enableInterpolation, bool isStereo, bool internal16Bit) :
+	I3MSoundDriver(mutex, deviceRate, isStereo, internal16Bit), _interp(enableInterpolation), _frameSize(isStereo ? 2 : 1), _len(0), _rmH(0), _rmL(0), _smpWtAcc(0), _loopSt(0),
+		_loopEnd(0), _baseFreq(0), _rcPos(0), _data(nullptr) {
+			_lastSmp[0] = _lastSmp[1] = 0;
 }
 
-void I3MLowLevelPCMDriver::feed(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) {
+void I3MLowLevelPCMDriver::feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) {
 	if (dst == nullptr || type != Audio::Mixer::kSFXSoundType)
 		return;
 
-	memset(dst, 0, len);
+	memset(dst, 0, byteSize);
 
 	if (_data == nullptr)
 		return;
@@ -521,7 +534,7 @@ void I3MLowLevelPCMDriver::feed(int8 *dst, uint32 len, Audio::Mixer::SoundType t
 	int32 diff = 0;
 	bool interp = (_interp && _rmL);
 
-	for (const int8 *end = dst + len; dst < end; ) {
+	for (const int8 *end = &dst[byteSize]; dst < end; dst += _smpSize) {
 		if (interp) {
 			for (int i = 0; i < _frameSize; ++ i) {
 				int8 in = _data[_rcPos + i];
@@ -530,10 +543,16 @@ void I3MLowLevelPCMDriver::feed(int8 *dst, uint32 len, Audio::Mixer::SoundType t
 					diff = (diff * (_smpWtAcc >> 1)) >> 15;
 					in = (_lastSmp[i] + diff) & 0xff;
 				}
-				*dst++ = in;
+				if (_smpSize == 2)
+					*reinterpret_cast<int16*>(dst) = in << 2;
+				else
+					*dst = in;
 			}
 		} else {
-			*dst++ = _data[_rcPos];
+			if (_smpSize == 2)
+				*reinterpret_cast<int16*>(dst) = _data[_rcPos] << 2;
+			else
+				*dst = _data[_rcPos];
 		}
 
 		uint32 lpos = _rcPos;
@@ -768,8 +787,8 @@ uint32 I3MLowLevelPCMDriver::calcRate(uint32 outRate, uint32 factor, uint32 data
 	return result;
 }
 
-I3MFourToneSynthDriver::I3MFourToneSynthDriver(Common::Mutex &mutex, bool isStereo) :
-	I3MMusicDriver(4, mutex, isStereo), _duration(0), _pos(0), _chan(nullptr) {
+I3MFourToneSynthDriver::I3MFourToneSynthDriver(Common::Mutex &mutex, bool isStereo, bool internal16Bit) :
+	I3MMusicDriver(4, mutex, isStereo, internal16Bit), _duration(0), _pos(0), _chan(nullptr) {
 	_chan = new Channel[_numChan];
 }
 
@@ -780,14 +799,14 @@ I3MFourToneSynthDriver::~I3MFourToneSynthDriver() {
 	delete[] _chan;
 }
 
-void I3MFourToneSynthDriver::feed(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) {
+void I3MFourToneSynthDriver::feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) {
 	if (dst == nullptr || type != Audio::Mixer::kMusicSoundType)
 		return;
 
 	if (expectStereo != _stereo)
 		error("I3MFourToneSynthDriver::feed(): stereo/mono mismatch between sound data and mixer stream");
 
-	const int8 *end = dst + len;
+	const int8 *end = &dst[byteSize];
 
 	while (_duration && dst < end) {
 		if (_pos == 0)
@@ -800,10 +819,20 @@ void I3MFourToneSynthDriver::feed(int8 *dst, uint32 len, Audio::Mixer::SoundType
 				smp += _chan[i].waveform[(_chan[i].phase >> 16) & 0xff];
 		}
 
-		smp = CLIP<int8>(smp >> 2, -128, 127);
-		*dst++ = smp;
-		if (_stereo)
+		if (_smpSize == 2) {
+			smp = CLIP<int16>(smp, _smpMin, _smpMax);
+			*reinterpret_cast<int16*>(dst) = smp;
+			dst += _smpSize;
+			if (_stereo) {
+				*reinterpret_cast<int16*>(dst) = smp;
+				dst += _smpSize;
+			}
+		} else {
+			smp = CLIP<int16>(smp >> 2, _smpMin, _smpMax);
 			*dst++ = smp;
+			if (_stereo)
+				*dst++ = smp;
+		}
 
 		if (++_pos == 370) {
 			_pos = 0;
@@ -920,7 +949,7 @@ Common::WeakPtr<I3MPlayer> *I3MPlayer::_inst = nullptr;
 
 I3MPlayer::I3MPlayer(ScummEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer), _musicChannels(nullptr), _lastSound(0), _lastSong(-1), _lastSoundEffectPrio(0), _soundEffectNumLoops(-1),
 	_musicIDTable(nullptr), _macstr(nullptr), _musicIDTableLen(0), _soundUsage(0), _idRangeMax(86), _mdrv(nullptr), _sdrv(nullptr), _nextTickProc(this, &I3MPlayer::nextTick),
-	_songPlaying(false), _soundEffectPlaying(false), _songTimer(0), _songTimerInternal(0), _qmode(0), _qualHi(false), _mixerThread(false), _activeChanCount(0), _numMusicChannels(4) {
+	_songPlaying(false), _soundEffectPlaying(false), _songTimer(0), _songTimerInternal(0), _qmode(0), _stereo(false), _16bit(false), _qualHi(false), _mixerThread(false), _activeChanCount(0), _numMusicChannels(4) {
 	assert(_vm);
 	assert(_mixer);
 
@@ -965,26 +994,28 @@ Common::SharedPtr<I3MPlayer> I3MPlayer::open(ScummEngine *vm, Audio::Mixer *mixe
 		_inst = new Common::WeakPtr<I3MPlayer>(scp);
 		// We can start this with the ScummVM mixer output rate instead of the ASC rate. The Mac sample rate converter can handle it (at
 		// least for up to 48 KHz, I haven't tried higher settings) and we don't have to do another rate conversion in the ScummVM mixer.
-		if ((_inst == nullptr) || (mixer == nullptr) || !(scp->startDevices(mixer->getOutputRate(), mixer->getOutputRate() << 16/*ASC_DEVICE_RATE*/, PCM_BUFFER_SIZE, true)))
+		if ((_inst == nullptr) || (mixer == nullptr) || !(scp->startDevices(mixer->getOutputRate(), mixer->getOutputRate() << 16/*ASC_DEVICE_RATE*/, PCM_BUFFER_SIZE, true, false, true)))
 			error("I3MPlayer::open(): Failed to start player");
 	}
 
 	return _inst->lock();
 }
 
-bool I3MPlayer::startDevices(uint32 outputRate, uint32 pcmDeviceRate, uint32 feedBufferSize, bool enableInterpolation) {
-	_macstr = new AudioStream_I3M(this, outputRate, false, enableInterpolation);
+bool I3MPlayer::startDevices(uint32 outputRate, uint32 pcmDeviceRate, uint32 feedBufferSize, bool enableInterpolation, bool stereo, bool internal16Bit) {
+	_macstr = new AudioStream_I3M(this, outputRate, stereo, enableInterpolation, internal16Bit);
 	if (!_macstr || !_mixer)
 		return false;
 
-	_sdrv = new I3MLowLevelPCMDriver(_mixer->mutex(), pcmDeviceRate, enableInterpolation, false);
-	I3MFourToneSynthDriver *mdrv = new I3MFourToneSynthDriver(_mixer->mutex(), false);
+	_sdrv = new I3MLowLevelPCMDriver(_mixer->mutex(), pcmDeviceRate, enableInterpolation, stereo, internal16Bit);
+	I3MFourToneSynthDriver *mdrv = new I3MFourToneSynthDriver(_mixer->mutex(), stereo, internal16Bit);
 	if (!mdrv || !_sdrv)
 		return false;
 
 	for (int i = 0; i < mdrv->numChannels(); ++i)
 		mdrv->setParameter(I3MMusicDriver::kChanWaveform, i, _fourToneSynthWaveForm, sizeof(_fourToneSynthWaveForm));
 	_qualHi = true;
+	_16bit = internal16Bit;
+	_stereo = stereo;
 	_mdrv = mdrv;
 
 	_drivers.push_back(_mdrv);
@@ -1068,14 +1099,14 @@ void I3MPlayer::setQuality(int qual) {
 	_qmode = qual;
 
 	if (isHiQuality()) {
-		I3MFourToneSynthDriver *mdrv = new I3MFourToneSynthDriver(_mixer->mutex(), false);
+		I3MFourToneSynthDriver *mdrv = new I3MFourToneSynthDriver(_mixer->mutex(), _stereo, _16bit);
 		assert(mdrv);
 		for (int i = 0; i < mdrv->numChannels(); ++i)
 			mdrv->setParameter(I3MMusicDriver::kChanWaveform, i, _fourToneSynthWaveForm, sizeof(_fourToneSynthWaveForm));
 		_mdrv = mdrv;
 		_qualHi = true;
 	} else {
-		_mdrv = new I3MSquareWaveSynthDriver(_mixer->mutex(), false);
+		_mdrv = new I3MSquareWaveSynthDriver(_mixer->mutex(), _stereo, _16bit);
 		_qualHi = false;
 		assert(_mdrv);
 	}


Commit: 4958fa03eaf5a1c6f5dfe7c4a92cb38a4a7c2564
    https://github.com/scummvm/scummvm/commit/4958fa03eaf5a1c6f5dfe7c4a92cb38a4a7c2564
Author: athrxx (athrxx at scummvm.org)
Date: 2024-02-04T03:18:15+01:00

Commit Message:
SCUMM: (INDY3/MAC) - disable sample interpolation for music

It was meant as a feature, but seems not to be suitable for high notes.
Disabling it improves the playback quality.

Changed paths:
    engines/scumm/players/player_mac_indy3.cpp


diff --git a/engines/scumm/players/player_mac_indy3.cpp b/engines/scumm/players/player_mac_indy3.cpp
index b753bb1701b..de808bcd7ff 100644
--- a/engines/scumm/players/player_mac_indy3.cpp
+++ b/engines/scumm/players/player_mac_indy3.cpp
@@ -72,7 +72,7 @@ private:
 	const CallbackProc *_vblCbProc;
 
 	struct SmpBuffer {
-		SmpBuffer() : start(0), pos(0), end(0), volume(0x10000), lastL(0), lastR(0), size(0), rateConvInt(0), rateConvFrac(0), rateConvAcc(-1) {}
+		SmpBuffer() : start(0), pos(0), end(0), volume(0x10000), lastL(0), lastR(0), size(0), rateConvInt(0), rateConvFrac(0), rateConvAcc(-1), interpolate(false) {}
 		int8 *start;
 		int8 *pos;
 		const int8 *end;
@@ -83,6 +83,7 @@ private:
 		uint32 rateConvInt;
 		uint32 rateConvFrac;
 		int32 rateConvAcc;
+		bool interpolate;
 	} _buffers[2];
 
 	const uint32 _outputRate;
@@ -96,20 +97,27 @@ private:
 
 class I3MSoundDriver {
 public:
-	I3MSoundDriver(Common::Mutex &mutex, uint32 deviceRate, bool isStereo, bool internal16Bit) : _mutex(mutex), _sig(false), _deviceRate(deviceRate), _stereo(isStereo),
+	I3MSoundDriver(Common::Mutex &mutex, uint32 deviceRate, bool isStereo, bool canInterpolate, bool internal16Bit) : _mutex(mutex), _sig(false), _caps(deviceRate, isStereo, canInterpolate),
 		_smpSize(internal16Bit ? 2 : 1), _smpMin(internal16Bit ? -32768 : -128), _smpMax(internal16Bit ? 32767 : 127) {}
 	virtual ~I3MSoundDriver() {}
 	virtual void feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) = 0;
-	uint32 getDeviceRate() const { return _deviceRate; }
+
 	bool checkSignal() const { return _sig; }
 	void resetSignal(bool state) { _sig = state; }
+
+	struct Caps {
+		Caps(uint32 rate, bool stereo, bool interp) :deviceRate(rate), isStereo(stereo), allowInterPolation(interp) {}
+		const uint32 deviceRate;
+		const bool isStereo;
+		const bool allowInterPolation;
+	};
+	const Caps &getCaps() const { return _caps; }
 protected:
 	Common::Mutex &_mutex;
-	const bool _stereo;
 	const int _smpSize;
-	const uint32 _deviceRate;
 	const int16 _smpMin;
 	const int16 _smpMax;
+	const Caps _caps;
 	bool _sig;
 };
 
@@ -156,7 +164,7 @@ public:
 		kSwTriplet = 3
 	};
 
-	I3MMusicDriver(uint16 numChannels, Common::Mutex &mutex, bool isStereo, bool internal16Bit) : I3MSoundDriver(mutex, ASC_DEVICE_RATE, isStereo, internal16Bit), _numChan(numChannels) {}
+	I3MMusicDriver(uint16 numChannels, Common::Mutex &mutex, bool isStereo, bool internal16Bit) : I3MSoundDriver(mutex, ASC_DEVICE_RATE, isStereo, false, internal16Bit), _numChan(numChannels) {}
 	virtual void start() = 0;
 	virtual void stop() = 0;
 	virtual void setParameter(ParaType type, ...) = 0;
@@ -233,9 +241,10 @@ public:
 	void restoreAfterLoad();
 
 	void generateData(int8 *dst, uint32 byteSize, Audio::Mixer::SoundType type, bool expectStereo) const;
-	uint32 getDriverDeviceRate(uint8 drvID) const;
 	void nextTick();
 
+	const I3MSoundDriver::Caps &getDriverCaps(uint8 drvID) const;
+
 private:
 	void startSong(int id);
 	void startSoundEffect(int id);
@@ -394,13 +403,13 @@ void AudioStream_I3M::initBuffers(uint32 feedBufferSize) {
 
 void AudioStream_I3M::initDrivers() {
 	for (int i = 0; i < 2; ++i) {
-		uint32 dr = _drv ? _drv->getDriverDeviceRate(i) : 0;
-		if (!dr)
+		if (!_drv)
 			error("AudioStream_I3M::initDrivers(): Failed to query device rate for device %d", i);
-		uint64 irt = (uint64)dr * (1 << RATECNV_BIT_PRECSN) / _outputRate;
+		uint64 irt = (uint64)_drv->getDriverCaps(i).deviceRate * (1 << RATECNV_BIT_PRECSN) / _outputRate;
 		_buffers[i].rateConvInt = irt >> (RATECNV_BIT_PRECSN + 16);
 		_buffers[i].rateConvFrac = (irt >> 16) & ((1 << RATECNV_BIT_PRECSN) - 1);
 		_buffers[i].rateConvAcc = 0;
+		_buffers[i].interpolate = _interp && _drv->getDriverCaps(i).allowInterPolation;
 	}
 }
 
@@ -449,7 +458,7 @@ int AudioStream_I3M::readBuffer(int16 *buffer, const int numSamples) {
 		for (int ii = 0; ii < 2; ++ii) {
 			int smpN = _smpInternalSize == 2 ? *reinterpret_cast<int16*>(_buffers[ii].pos) : _buffers[ii].pos[0];
 			int diff = smpN - _buffers[ii].lastL;
-			if (diff && _buffers[ii].rateConvAcc && _interp)
+			if (diff && _buffers[ii].rateConvAcc && _buffers[ii].interpolate)
 				diff = (diff * _buffers[ii].rateConvAcc) >> RATECNV_BIT_PRECSN;
 			smpL += (int32)((_buffers[ii].lastL + diff) * (_buffers[ii].volume >> _volDown));
 		}
@@ -457,7 +466,7 @@ int AudioStream_I3M::readBuffer(int16 *buffer, const int numSamples) {
 			for (int ii = 0; ii < 2; ++ii) {
 				int smpN = _smpInternalSize == 2 ? *reinterpret_cast<int16*>(&_buffers[ii].pos[2]) : _buffers[ii].pos[1];
 				int diff = smpN - _buffers[ii].lastR;
-				if (diff && _buffers[ii].rateConvAcc && _interp)
+				if (diff && _buffers[ii].rateConvAcc && _buffers[ii].interpolate)
 					diff = (diff * _buffers[ii].rateConvAcc) >> RATECNV_BIT_PRECSN;
 				smpR += (int32)((_buffers[ii].lastR + diff) * (_buffers[ii].volume >> _volDown));
 			}
@@ -514,7 +523,7 @@ void AudioStream_I3M::runVblTask() {
 }
 
 I3MLowLevelPCMDriver::I3MLowLevelPCMDriver(Common::Mutex &mutex, uint32 deviceRate, bool enableInterpolation, bool isStereo, bool internal16Bit) :
-	I3MSoundDriver(mutex, deviceRate, isStereo, internal16Bit), _interp(enableInterpolation), _frameSize(isStereo ? 2 : 1), _len(0), _rmH(0), _rmL(0), _smpWtAcc(0), _loopSt(0),
+	I3MSoundDriver(mutex, deviceRate, isStereo, true, internal16Bit), _interp(enableInterpolation), _frameSize(isStereo ? 2 : 1), _len(0), _rmH(0), _rmL(0), _smpWtAcc(0), _loopSt(0),
 		_loopEnd(0), _baseFreq(0), _rcPos(0), _data(nullptr) {
 			_lastSmp[0] = _lastSmp[1] = 0;
 }
@@ -528,7 +537,7 @@ void I3MLowLevelPCMDriver::feed(int8 *dst, uint32 byteSize, Audio::Mixer::SoundT
 	if (_data == nullptr)
 		return;
 
-	if (expectStereo != _stereo)
+	if (expectStereo != _caps.isStereo)
 		error("I3MLowLevelPCMDriver::feed(): stereo/mono mismatch between sound data and mixer stream");
 
 	int32 diff = 0;
@@ -595,7 +604,7 @@ void I3MLowLevelPCMDriver::play(PCMSound *snd) {
 	_res = snd->data.reinterpretCast<const int8>();
 	_data = _res.get();
 	_len = snd->len;
-	uint32 rmul = calcRate(_deviceRate, 0x10000, snd->rate);
+	uint32 rmul = calcRate(_caps.deviceRate, 0x10000, snd->rate);
 
 	if (rmul >= 0x7FFD && rmul <= 0x8003)
 		rmul = 0x8000;
@@ -803,7 +812,7 @@ void I3MFourToneSynthDriver::feed(int8 *dst, uint32 byteSize, Audio::Mixer::Soun
 	if (dst == nullptr || type != Audio::Mixer::kMusicSoundType)
 		return;
 
-	if (expectStereo != _stereo)
+	if (expectStereo != _caps.isStereo)
 		error("I3MFourToneSynthDriver::feed(): stereo/mono mismatch between sound data and mixer stream");
 
 	const int8 *end = &dst[byteSize];
@@ -823,14 +832,14 @@ void I3MFourToneSynthDriver::feed(int8 *dst, uint32 byteSize, Audio::Mixer::Soun
 			smp = CLIP<int16>(smp, _smpMin, _smpMax);
 			*reinterpret_cast<int16*>(dst) = smp;
 			dst += _smpSize;
-			if (_stereo) {
+			if (_caps.isStereo) {
 				*reinterpret_cast<int16*>(dst) = smp;
 				dst += _smpSize;
 			}
 		} else {
 			smp = CLIP<int16>(smp >> 2, _smpMin, _smpMax);
 			*dst++ = smp;
-			if (_stereo)
+			if (_caps.isStereo)
 				*dst++ = smp;
 		}
 
@@ -1141,10 +1150,6 @@ void I3MPlayer::generateData(int8 *dst, uint32 len, Audio::Mixer::SoundType type
 		(*i)->feed(dst, len, type, expectStereo);
 }
 
-uint32 I3MPlayer::getDriverDeviceRate(uint8 drvID) const {
-	return (drvID < _drivers.size()) ? _drivers[drvID]->getDeviceRate() : 0;
-}
-
 void I3MPlayer::nextTick() {
 	if (_songTimerInternal++ == 29) {
 		_songTimerInternal = 0;
@@ -1161,6 +1166,12 @@ void I3MPlayer::nextTick() {
 	_mixerThread = false;
 }
 
+const I3MSoundDriver::Caps &I3MPlayer::getDriverCaps(uint8 drvID) const {
+	if (drvID >= _drivers.size())
+		error(" I3MPlayer::getDriverCaps(): Invalid driver id %d", drvID);
+	return _drivers[drvID]->getCaps();
+}
+
 void I3MPlayer::startSong(int id) {
 	if (_mdrv == nullptr || id < 0 || id >= _idRangeMax) {
 		warning("I3MPlayer::startSong(): sound id '%d' out of range (0 - 85)", id);




More information about the Scummvm-git-logs mailing list