aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorbjörn Andersson2019-01-18 19:19:25 +0100
committerFilippos Karapetis2019-02-10 16:32:02 +0200
commit9785d5007a7754ab988b51a8780d6a3dcc80dce4 (patch)
treec5c3b28c5846c7b65e9ceb0d24b667e9a2641540
parent82a1859ad1105b2ae2cc3b15bfc3a92e3bc8736f (diff)
downloadscummvm-rg350-9785d5007a7754ab988b51a8780d6a3dcc80dce4.tar.gz
scummvm-rg350-9785d5007a7754ab988b51a8780d6a3dcc80dce4.tar.bz2
scummvm-rg350-9785d5007a7754ab988b51a8780d6a3dcc80dce4.zip
ZVISION: Boost volume for MPEG cutscenes
The high-resolution videos play back at much lower volume than the original ones. This adds hard-coded values for how much to amplify each cutscene. It's all done by ear, and it does introduce some clipping, but I think it should be acceptable. Of course, it could also be a problem with the audio decoder, so this may be the wrong approach entirely.
-rw-r--r--audio/decoders/ac3.cpp20
-rw-r--r--audio/decoders/ac3.h2
-rw-r--r--engines/zvision/video/video.cpp95
-rw-r--r--video/mpegps_decoder.cpp9
-rw-r--r--video/mpegps_decoder.h6
5 files changed, 116 insertions, 16 deletions
diff --git a/audio/decoders/ac3.cpp b/audio/decoders/ac3.cpp
index c569179996..1b2a3bff76 100644
--- a/audio/decoders/ac3.cpp
+++ b/audio/decoders/ac3.cpp
@@ -24,6 +24,7 @@
#include "common/ptr.h"
#include "common/stream.h"
#include "common/textconsole.h"
+#include "common/util.h"
#include "audio/audiostream.h"
#include "audio/decoders/ac3.h"
@@ -37,7 +38,7 @@ namespace Audio {
class AC3Stream : public PacketizedAudioStream {
public:
- AC3Stream();
+ AC3Stream(double decibel);
~AC3Stream();
bool init(Common::SeekableReadStream &firstPacket);
@@ -62,9 +63,14 @@ private:
byte *_inBufPtr;
int _flags;
int _sampleRate;
+ double _audioGain;
};
-AC3Stream::AC3Stream() : _a52State(0), _frameSize(0), _inBufPtr(0), _flags(0), _sampleRate(0) {
+AC3Stream::AC3Stream(double decibel = 0.0) : _a52State(0), _frameSize(0), _inBufPtr(0), _flags(0), _sampleRate(0) {
+ if (decibel != 0.0)
+ _audioGain = pow(2, decibel / 6);
+ else
+ _audioGain = 1.0;
}
AC3Stream::~AC3Stream() {
@@ -153,7 +159,7 @@ void AC3Stream::queuePacket(Common::SeekableReadStream *data) {
} else {
// TODO: Eventually support more than just stereo max
int flags = A52_STEREO | A52_ADJUST_LEVEL;
- sample_t level = 32767;
+ sample_t level = 32767 * _audioGain;
if (a52_frame(_a52State, _inBuf, &flags, &level, 0) != 0)
error("Frame fail");
@@ -165,8 +171,8 @@ void AC3Stream::queuePacket(Common::SeekableReadStream *data) {
if (a52_block(_a52State) == 0) {
sample_t *samples = a52_samples(_a52State);
for (int j = 0; j < 256; j++) {
- *outputPtr++ = (int16)samples[j];
- *outputPtr++ = (int16)samples[j + 256];
+ *outputPtr++ = (int16)CLIP<sample_t>(samples[j], -32768, 32767);
+ *outputPtr++ = (int16)CLIP<sample_t>(samples[j + 256], -32768, 32767);
}
outputLength += 1024;
@@ -189,8 +195,8 @@ void AC3Stream::queuePacket(Common::SeekableReadStream *data) {
}
}
-PacketizedAudioStream *makeAC3Stream(Common::SeekableReadStream &firstPacket) {
- Common::ScopedPtr<AC3Stream> stream(new AC3Stream());
+PacketizedAudioStream *makeAC3Stream(Common::SeekableReadStream &firstPacket, double decibel) {
+ Common::ScopedPtr<AC3Stream> stream(new AC3Stream(decibel));
if (!stream->init(firstPacket))
return 0;
diff --git a/audio/decoders/ac3.h b/audio/decoders/ac3.h
index a51107a410..249d1dcfa2 100644
--- a/audio/decoders/ac3.h
+++ b/audio/decoders/ac3.h
@@ -41,7 +41,7 @@ class PacketizedAudioStream;
* @param firstPacket The stream containing the first packet of data
* @return A new PacketizedAudioStream, or NULL on error
*/
-PacketizedAudioStream *makeAC3Stream(Common::SeekableReadStream &firstPacket);
+PacketizedAudioStream *makeAC3Stream(Common::SeekableReadStream &firstPacket, double decibel = 0.0);
} // End of namespace Audio
diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp
index 01e75a4a3d..54c113dc83 100644
--- a/engines/zvision/video/video.cpp
+++ b/engines/zvision/video/video.cpp
@@ -49,8 +49,99 @@ Video::VideoDecoder *ZVision::loadAnimation(const Common::String &fileName) {
else if (tmpFileName.hasSuffix(".avi"))
animation = new ZorkAVIDecoder();
#if defined(USE_MPEG2) && defined(USE_A52)
- else if (tmpFileName.hasSuffix(".vob"))
- animation = new Video::MPEGPSDecoder();
+ else if (tmpFileName.hasSuffix(".vob")) {
+ // For some reason, we get much lower volume in the hi-res
+ // videos than in the low-res ones. So we artificially boost
+ // the volume here. This is an approximation, but I've tried
+ // to match the old volumes reasonably well.
+ //
+ // Some of these will cause audio clipping. Hopefully not
+ // enough to be noticeable.
+ double amplification = 0.0;
+ if (tmpFileName == "em00d011.vob") {
+ // The finale.
+ amplification = 10.0;
+ } else if (tmpFileName == "em00d021.vob") {
+ // Jack's escape and arrival at Flathead Mesa.
+ amplification = 9.0;
+ } else if (tmpFileName == "em00d032.vob") {
+ // The Grand Inquisitor's speech.
+ amplification = 11.0;
+ } else if (tmpFileName == "em00d122.vob") {
+ // Jack orders you to the radio tower.
+ amplification = 17.0;
+ } else if (tmpFileName == "em3ed012.vob") {
+ // The Grand Inquisitor gets the Coconut of Quendor.
+ amplification = 12.0;
+ } else if (tmpFileName == "g000d101.vob") {
+ // Griff gets captured.
+ amplification = 11.0;
+ } else if (tmpFileName == "g000d111.vob") {
+ // Brog gets totemized. The music seems to be mixed
+ // much softer in this than in the low-resolution
+ // version.
+ amplification = 12.0;
+ } else if (tmpFileName == "g000d122.vob") {
+ // Lucy gets captured.
+ amplification = 14.0;
+ } else if (tmpFileName == "g000d302.vob") {
+ // The Grand Inquisitor visits Jack in his cell.
+ amplification = 13.0;
+ } else if (tmpFileName == "g000d312.vob") {
+ // You get captured.
+ amplification = 14.0;
+ } else if (tmpFileName == "g000d411.vob") {
+ // Propaganda On Parade. No need to make it as loud as
+ // the low-resolution version.
+ amplification = 11.0;
+ } else if (tmpFileName == "pe1ed012.vob") {
+ // Jack lets you in with the lantern.
+ amplification = 14.0;
+ } else if (tmpFileName.hasPrefix("pe1ed")) {
+ // Jack answers the door. Several different ways.
+ amplification = 17.0;
+ } else if (tmpFileName == "pe5ed052.vob") {
+ // You get killed by the guards
+ amplification = 12.0;
+ } else if (tmpFileName == "pe6ed012.vob") {
+ // Jack gets captured by the guards
+ amplification = 17.0;
+ } else if (tmpFileName == "pp1ed022.vob") {
+ // Jack examines the lantern
+ amplification = 10.0;
+ } else if (tmpFileName == "qb1ed012.vob") {
+ // Lucy gets invited to the back room
+ amplification = 17.0;
+ } else if (tmpFileName.hasPrefix("qe1ed")) {
+ // Floyd answers the door. Several different ways.
+ amplification = 17.0;
+ } else if (tmpFileName == "qs1ed011.vob") {
+ // Jack explains the rules of the game.
+ amplification = 16.0;
+ } else if (tmpFileName == "qs1ed021.vob") {
+ // Jack loses the game.
+ amplification = 14.0;
+ } else if (tmpFileName == "uc1gd012.vob") {
+ // Y'Gael appears.
+ amplification = 12.0;
+ } else if (tmpFileName == "ue1ud012.vob") {
+ // Jack gets totemized... or what?
+ amplification = 12.0;
+ } else if (tmpFileName == "ue2qd012.vob") {
+ // Jack agrees to totemization.
+ amplification = 10.0;
+ } else if (tmpFileName == "g000d981.vob") {
+ // The Enterprise logo. Has no low-res version. Its
+ // volume is louder than the other logo animations.
+ amplification = 6.2;
+ } else if (tmpFileName.hasPrefix("g000d")) {
+ // The Dolby Digital and Activision logos. They have no
+ // low-res versions, but I've used the low-resolution
+ // Activision logo (slightly different) as reference.
+ amplification = 8.5;
+ }
+ animation = new Video::MPEGPSDecoder(amplification);
+ }
#endif
else
error("Unknown suffix for animation %s", fileName.c_str());
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index 361481b739..9b232ec792 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -50,7 +50,8 @@ enum {
kStartCodePrivateStream2 = 0x1BF
};
-MPEGPSDecoder::MPEGPSDecoder() {
+MPEGPSDecoder::MPEGPSDecoder(double decibel) {
+ _decibel = decibel;
_demuxer = new MPEGPSDemuxer();
}
@@ -104,7 +105,7 @@ MPEGPSDecoder::MPEGStream *MPEGPSDecoder::getStream(uint32 startCode, Common::Se
#ifdef USE_A52
handled = true;
- AC3AudioTrack *ac3Track = new AC3AudioTrack(*packet, getSoundType());
+ AC3AudioTrack *ac3Track = new AC3AudioTrack(*packet, _decibel, getSoundType());
stream = ac3Track;
_streamMap[startCode] = ac3Track;
addTrack(ac3Track);
@@ -704,9 +705,9 @@ Audio::AudioStream *MPEGPSDecoder::MPEGAudioTrack::getAudioStream() const {
#ifdef USE_A52
-MPEGPSDecoder::AC3AudioTrack::AC3AudioTrack(Common::SeekableReadStream &firstPacket, Audio::Mixer::SoundType soundType) :
+MPEGPSDecoder::AC3AudioTrack::AC3AudioTrack(Common::SeekableReadStream &firstPacket, double decibel, Audio::Mixer::SoundType soundType) :
AudioTrack(soundType) {
- _audStream = Audio::makeAC3Stream(firstPacket);
+ _audStream = Audio::makeAC3Stream(firstPacket, decibel);
if (!_audStream)
error("Could not create AC-3 stream");
}
diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h
index bd703a35ff..7960639d78 100644
--- a/video/mpegps_decoder.h
+++ b/video/mpegps_decoder.h
@@ -54,7 +54,7 @@ namespace Video {
*/
class MPEGPSDecoder : public VideoDecoder {
public:
- MPEGPSDecoder();
+ MPEGPSDecoder(double decibel = 0.0);
virtual ~MPEGPSDecoder();
bool loadStream(Common::SeekableReadStream *stream);
@@ -166,7 +166,7 @@ private:
#ifdef USE_A52
class AC3AudioTrack : public AudioTrack, public MPEGStream {
public:
- AC3AudioTrack(Common::SeekableReadStream &firstPacket, Audio::Mixer::SoundType soundType);
+ AC3AudioTrack(Common::SeekableReadStream &firstPacket, double decibel, Audio::Mixer::SoundType soundType);
~AC3AudioTrack();
bool sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts);
@@ -199,6 +199,8 @@ private:
// A map from stream types to stream handlers
typedef Common::HashMap<int, MPEGStream *> StreamMap;
StreamMap _streamMap;
+
+ double _decibel;
};
} // End of namespace Video