aboutsummaryrefslogtreecommitdiff
path: root/audio
diff options
context:
space:
mode:
Diffstat (limited to 'audio')
-rw-r--r--audio/audiostream.cpp4
-rw-r--r--audio/audiostream.h4
-rw-r--r--audio/decoders/adpcm.cpp489
-rw-r--r--audio/decoders/adpcm.h13
-rw-r--r--audio/decoders/adpcm_intern.h242
-rw-r--r--audio/decoders/aiff.cpp4
-rw-r--r--audio/decoders/aiff.h4
-rw-r--r--audio/decoders/flac.cpp1
-rw-r--r--audio/decoders/flac.h3
-rw-r--r--audio/decoders/iff_sound.cpp1
-rw-r--r--audio/decoders/iff_sound.h2
-rw-r--r--audio/decoders/mac_snd.cpp3
-rw-r--r--audio/decoders/mac_snd.h4
-rw-r--r--audio/decoders/mp3.cpp1
-rw-r--r--audio/decoders/mp3.h3
-rw-r--r--audio/decoders/raw.cpp3
-rw-r--r--audio/decoders/raw.h6
-rw-r--r--audio/decoders/vag.h3
-rw-r--r--audio/decoders/voc.cpp2
-rw-r--r--audio/decoders/voc.h6
-rw-r--r--audio/decoders/vorbis.cpp6
-rw-r--r--audio/decoders/vorbis.h3
-rw-r--r--audio/decoders/wave.cpp3
-rw-r--r--audio/decoders/wave.h4
-rw-r--r--audio/fmopl.cpp1
-rw-r--r--audio/mididrv.cpp4
-rw-r--r--audio/mididrv.h113
-rw-r--r--audio/midiparser.cpp3
-rw-r--r--audio/midiparser.h7
-rw-r--r--audio/midiparser_smf.cpp2
-rw-r--r--audio/midiparser_xmidi.cpp2
-rw-r--r--audio/midiplayer.cpp198
-rw-r--r--audio/midiplayer.h191
-rw-r--r--audio/mixer.cpp83
-rw-r--r--audio/mixer.h23
-rw-r--r--audio/mixer_intern.h16
-rw-r--r--audio/mods/infogrames.cpp1
-rw-r--r--audio/mods/infogrames.h5
-rw-r--r--audio/mods/maxtrax.cpp2
-rw-r--r--audio/mods/module.cpp4
-rw-r--r--audio/mods/module.h6
-rw-r--r--audio/mods/protracker.cpp2
-rw-r--r--audio/mods/protracker.h4
-rw-r--r--audio/mods/rjp1.cpp8
-rw-r--r--audio/mods/rjp1.h4
-rw-r--r--audio/mods/soundfx.cpp3
-rw-r--r--audio/mods/soundfx.h4
-rw-r--r--audio/mods/tfmx.cpp2
-rw-r--r--audio/module.mk2
-rw-r--r--audio/mpu401.cpp14
-rw-r--r--audio/mpu401.h31
-rw-r--r--audio/musicplugin.h4
-rw-r--r--audio/null.cpp1
-rw-r--r--audio/null.h1
-rw-r--r--audio/rate.cpp1
-rw-r--r--audio/rate.h6
-rw-r--r--audio/rate_arm.cpp178
-rw-r--r--audio/softsynth/adlib.cpp7
-rw-r--r--audio/softsynth/eas.cpp486
-rw-r--r--audio/softsynth/emumidi.h45
-rw-r--r--audio/softsynth/fluidsynth.cpp8
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_audio.cpp1
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_euphony.cpp13
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp1
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp4
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h2
-rw-r--r--audio/softsynth/mt32.cpp12
-rw-r--r--audio/softsynth/mt32/part.cpp4
-rw-r--r--audio/softsynth/mt32/part.h1
-rw-r--r--audio/softsynth/mt32/synth.cpp8
-rw-r--r--audio/softsynth/mt32/synth.h1
-rw-r--r--audio/softsynth/opl/dbopl.cpp10
-rw-r--r--audio/softsynth/opl/dosbox.cpp1
-rw-r--r--audio/softsynth/opl/mame.cpp9
-rw-r--r--audio/softsynth/opl/mame.h1
-rw-r--r--audio/softsynth/pcspk.cpp2
-rw-r--r--audio/softsynth/pcspk.h1
-rw-r--r--audio/softsynth/sid.cpp29
-rw-r--r--audio/softsynth/sid.h12
-rw-r--r--audio/softsynth/ym2612.cpp8
80 files changed, 1626 insertions, 780 deletions
diff --git a/audio/audiostream.cpp b/audio/audiostream.cpp
index 0c41a38254..776f904e77 100644
--- a/audio/audiostream.cpp
+++ b/audio/audiostream.cpp
@@ -24,14 +24,14 @@
*/
#include "common/debug.h"
-#include "common/endian.h"
#include "common/file.h"
+#include "common/mutex.h"
+#include "common/textconsole.h"
#include "common/queue.h"
#include "common/util.h"
#include "audio/audiostream.h"
#include "audio/decoders/flac.h"
-#include "audio/mixer.h"
#include "audio/decoders/mp3.h"
#include "audio/decoders/raw.h"
#include "audio/decoders/vorbis.h"
diff --git a/audio/audiostream.h b/audio/audiostream.h
index cd6456cc70..22de21cb34 100644
--- a/audio/audiostream.h
+++ b/audio/audiostream.h
@@ -26,16 +26,14 @@
#ifndef SOUND_AUDIOSTREAM_H
#define SOUND_AUDIOSTREAM_H
-#include "common/util.h"
#include "common/scummsys.h"
+#include "common/str.h"
#include "common/types.h"
#include "audio/timestamp.h"
namespace Audio {
-class SeekableAudioStream;
-
/**
* Generic audio input stream. Subclasses of this are used to feed arbitrary
* sampled audio data into ScummVM's audio mixer.
diff --git a/audio/decoders/adpcm.cpp b/audio/decoders/adpcm.cpp
index 7def89b688..a9284973d5 100644
--- a/audio/decoders/adpcm.cpp
+++ b/audio/decoders/adpcm.cpp
@@ -23,47 +23,16 @@
*
*/
-#include "common/endian.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
+#include "common/util.h"
#include "audio/decoders/adpcm.h"
-#include "audio/audiostream.h"
+#include "audio/decoders/adpcm_intern.h"
namespace Audio {
-class ADPCMStream : public RewindableAudioStream {
-protected:
- Common::SeekableReadStream *_stream;
- const DisposeAfterUse::Flag _disposeAfterUse;
- const int32 _startpos;
- const int32 _endpos;
- const int _channels;
- const uint32 _blockAlign;
- uint32 _blockPos[2];
- const int _rate;
-
- struct {
- // OKI/IMA
- struct {
- int32 last;
- int32 stepIndex;
- } ima_ch[2];
- } _status;
-
- virtual void reset();
- int16 stepAdjust(byte);
-
-public:
- ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign);
- ~ADPCMStream();
-
- virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); }
- virtual bool isStereo() const { return _channels == 2; }
- virtual int getRate() const { return _rate; }
-
- virtual bool rewind();
-};
-
// Routines to convert 12 bit linear samples to the
// Dialogic or Oki ADPCM coding format aka VOX.
// See also <http://www.comptek.ru/telephony/tnotes/tt1-13.html>
@@ -107,17 +76,6 @@ bool ADPCMStream::rewind() {
#pragma mark -
-class Oki_ADPCMStream : public ADPCMStream {
-public:
- Oki_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-
-protected:
- int16 decodeOKI(byte);
-};
-
int Oki_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
int samples;
byte data;
@@ -153,7 +111,7 @@ int16 Oki_ADPCMStream::decodeOKI(byte code) {
samp = CLIP<int16>(samp, -2048, 2047);
_status.ima_ch[0].last = samp;
- _status.ima_ch[0].stepIndex += stepAdjust(code);
+ _status.ima_ch[0].stepIndex += _stepAdjustTable[code];
_status.ima_ch[0].stepIndex = CLIP<int32>(_status.ima_ch[0].stepIndex, 0, ARRAYSIZE(okiStepSize) - 1);
// * 16 effectively converts 12-bit input to 16-bit output
@@ -164,20 +122,7 @@ int16 Oki_ADPCMStream::decodeOKI(byte code) {
#pragma mark -
-class Ima_ADPCMStream : public ADPCMStream {
-protected:
- int16 decodeIMA(byte code, int channel = 0); // Default to using the left channel/using one channel
-
-public:
- Ima_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
- memset(&_status, 0, sizeof(_status));
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-};
-
-int Ima_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
+int DVI_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
int samples;
byte data;
@@ -194,34 +139,6 @@ int Ima_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
#pragma mark -
-class Apple_ADPCMStream : public Ima_ADPCMStream {
-protected:
- // Apple QuickTime IMA ADPCM
- int32 _streamPos[2];
- int16 _buffer[2][2];
- uint8 _chunkPos[2];
-
- void reset() {
- Ima_ADPCMStream::reset();
- _chunkPos[0] = 0;
- _chunkPos[1] = 0;
- _streamPos[0] = 0;
- _streamPos[1] = _blockAlign;
- }
-
-public:
- Apple_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
- _chunkPos[0] = 0;
- _chunkPos[1] = 0;
- _streamPos[0] = 0;
- _streamPos[1] = _blockAlign;
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-
-};
-
int Apple_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
// Need to write at least one samples per channel
assert((numSamples % _channels) == 0);
@@ -285,82 +202,49 @@ int Apple_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
return samples[0] + samples[1];
}
-#pragma mark -
+#pragma mark -
-class MSIma_ADPCMStream : public Ima_ADPCMStream {
-public:
- MSIma_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign, bool invertSamples = false)
- : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign), _invertSamples(invertSamples) {
- if (blockAlign == 0)
- error("ADPCMStream(): blockAlign isn't specified for MS IMA ADPCM");
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples) {
- if (_channels == 1)
- return readBufferMSIMA1(buffer, numSamples);
- else
- return readBufferMSIMA2(buffer, numSamples);
- }
-
- int readBufferMSIMA1(int16 *buffer, const int numSamples);
- int readBufferMSIMA2(int16 *buffer, const int numSamples);
-private:
- bool _invertSamples; // Some implementations invert the way samples are decoded
-};
+int MSIma_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
+ // Need to write at least one sample per channel
+ assert((numSamples % _channels) == 0);
-int MSIma_ADPCMStream::readBufferMSIMA1(int16 *buffer, const int numSamples) {
int samples = 0;
- byte data;
-
- assert(numSamples % 2 == 0);
while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
if (_blockPos[0] == _blockAlign) {
- // read block header
- _status.ima_ch[0].last = _stream->readSint16LE();
- _status.ima_ch[0].stepIndex = _stream->readSint16LE();
- _blockPos[0] = 4;
- }
+ for (int i = 0; i < _channels; i++) {
+ // read block header
+ _status.ima_ch[i].last = _stream->readSint16LE();
+ _status.ima_ch[i].stepIndex = _stream->readSint16LE();
+ }
- for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2) {
- data = _stream->readByte();
- _blockPos[0]++;
- buffer[samples] = decodeIMA(_invertSamples ? (data >> 4) & 0x0f : data & 0x0f);
- buffer[samples + 1] = decodeIMA(_invertSamples ? data & 0x0f : (data >> 4) & 0x0f);
+ _blockPos[0] = _channels * 4;
}
- }
- return samples;
-}
+ // Decode a set of samples
+ for (int i = 0; i < _channels; i++) {
+ // The stream encodes four bytes per channel at a time
+ for (int j = 0; j < 4; j++) {
+ byte data = _stream->readByte();
+ _blockPos[0]++;
+ _buffer[i][j * 2] = decodeIMA(data & 0x0f, i);
+ _buffer[i][j * 2 + 1] = decodeIMA((data >> 4) & 0x0f, i);
+ _samplesLeft[i] += 2;
+ }
+ }
-// Microsoft as usual tries to implement it differently. This method
-// is used for stereo data.
-int MSIma_ADPCMStream::readBufferMSIMA2(int16 *buffer, const int numSamples) {
- int samples;
- uint32 data;
- int nibble;
- byte k;
-
- // TODO: Currently this implementation only supports
- // reading a multiple of 16 samples at once. We might
- // consider changing that so it could read an arbitrary
- // sample pair count.
- assert(numSamples % 16 == 0);
-
- for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos;) {
- for (int channel = 0; channel < 2; channel++) {
- data = _stream->readUint32LE();
-
- for (nibble = 0; nibble < 8; nibble++) {
- k = ((data & 0xf0000000) >> 28);
- buffer[samples + channel + nibble * 2] = decodeIMA(k);
- data <<= 4;
+ while (samples < numSamples && _samplesLeft[0] != 0) {
+ for (int i = 0; i < _channels; i++) {
+ buffer[samples] = _buffer[i][8 - _samplesLeft[i]];
+ _samplesLeft[i]--;
}
+
+ samples += _channels;
}
- samples += 16;
}
+
return samples;
}
@@ -382,41 +266,6 @@ static const int MSADPCMAdaptationTable[] = {
};
-class MS_ADPCMStream : public ADPCMStream {
-protected:
- struct ADPCMChannelStatus {
- byte predictor;
- int16 delta;
- int16 coeff1;
- int16 coeff2;
- int16 sample1;
- int16 sample2;
- };
-
- struct {
- // MS ADPCM
- ADPCMChannelStatus ch[2];
- } _status;
-
- void reset() {
- ADPCMStream::reset();
- memset(&_status, 0, sizeof(_status));
- }
-
-public:
- MS_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
- if (blockAlign == 0)
- error("MS_ADPCMStream(): blockAlign isn't specified for MS ADPCM");
- memset(&_status, 0, sizeof(_status));
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-
-protected:
- int16 decodeMS(ADPCMChannelStatus *c, byte);
-};
-
int16 MS_ADPCMStream::decodeMS(ADPCMChannelStatus *c, byte code) {
int32 predictor;
@@ -478,246 +327,9 @@ int MS_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
}
-
#pragma mark -
-class Tinsel_ADPCMStream : public ADPCMStream {
-protected:
- struct {
- // Tinsel
- double predictor;
- double K0, K1;
- double d0, d1;
- } _status;
-
- void reset() {
- ADPCMStream::reset();
- memset(&_status, 0, sizeof(_status));
- }
-
- int16 decodeTinsel(int16, double);
- void readBufferTinselHeader();
-
-public:
- Tinsel_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
-
- if (blockAlign == 0)
- error("Tinsel_ADPCMStream(): blockAlign isn't specified");
-
- if (channels != 1)
- error("Tinsel_ADPCMStream(): Tinsel ADPCM only supports mono");
-
- memset(&_status, 0, sizeof(_status));
- }
-
-};
-
-static const double TinselFilterTable[4][2] = {
- {0, 0 },
- {0.9375, 0},
- {1.796875, -0.8125},
- {1.53125, -0.859375}
-};
-
-void Tinsel_ADPCMStream::readBufferTinselHeader() {
- uint8 start = _stream->readByte();
- uint8 filterVal = (start & 0xC0) >> 6;
-
- if ((start & 0x20) != 0) {
- //Lower 6 bit are negative
-
- // Negate
- start = ~(start | 0xC0) + 1;
-
- _status.predictor = 1 << start;
- } else {
- // Lower 6 bit are positive
-
- // Truncate
- start &= 0x1F;
-
- _status.predictor = ((double) 1.0) / (1 << start);
- }
-
- _status.K0 = TinselFilterTable[filterVal][0];
- _status.K1 = TinselFilterTable[filterVal][1];
-}
-
-int16 Tinsel_ADPCMStream::decodeTinsel(int16 code, double eVal) {
- double sample;
-
- sample = (double) code;
- sample *= eVal * _status.predictor;
- sample += (_status.d0 * _status.K0) + (_status.d1 * _status.K1);
-
- _status.d1 = _status.d0;
- _status.d0 = sample;
-
- return (int16) CLIP<double>(sample, -32768.0, 32767.0);
-}
-
-class Tinsel4_ADPCMStream : public Tinsel_ADPCMStream {
-public:
- Tinsel4_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-};
-
-int Tinsel4_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples;
- uint16 data;
- const double eVal = 1.142822265;
-
- samples = 0;
-
- assert(numSamples % 2 == 0);
-
- while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
- if (_blockPos[0] == _blockAlign) {
- readBufferTinselHeader();
- _blockPos[0] = 0;
- }
-
- for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2, _blockPos[0]++) {
- // Read 1 byte = 8 bits = two 4 bit blocks
- data = _stream->readByte();
- buffer[samples] = decodeTinsel((data << 8) & 0xF000, eVal);
- buffer[samples+1] = decodeTinsel((data << 12) & 0xF000, eVal);
- }
- }
-
- return samples;
-}
-
-class Tinsel6_ADPCMStream : public Tinsel_ADPCMStream {
-protected:
- uint8 _chunkPos;
- uint16 _chunkData;
-
- void reset() {
- ADPCMStream::reset();
- _chunkPos = 0;
- _chunkData = 0;
- }
-
-public:
- Tinsel6_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
- _chunkPos = 0;
- _chunkData = 0;
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-};
-
-int Tinsel6_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples;
- const double eVal = 1.032226562;
-
- samples = 0;
-
- while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
- if (_blockPos[0] == _blockAlign) {
- readBufferTinselHeader();
- _blockPos[0] = 0;
- _chunkPos = 0;
- }
-
- for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples++, _chunkPos = (_chunkPos + 1) % 4) {
-
- switch (_chunkPos) {
- case 0:
- _chunkData = _stream->readByte();
- buffer[samples] = decodeTinsel((_chunkData << 8) & 0xFC00, eVal);
- break;
- case 1:
- _chunkData = (_chunkData << 8) | (_stream->readByte());
- buffer[samples] = decodeTinsel((_chunkData << 6) & 0xFC00, eVal);
- _blockPos[0]++;
- break;
- case 2:
- _chunkData = (_chunkData << 8) | (_stream->readByte());
- buffer[samples] = decodeTinsel((_chunkData << 4) & 0xFC00, eVal);
- _blockPos[0]++;
- break;
- case 3:
- _chunkData = (_chunkData << 8);
- buffer[samples] = decodeTinsel((_chunkData << 2) & 0xFC00, eVal);
- _blockPos[0]++;
- break;
- }
-
- }
-
- }
-
- return samples;
-}
-
-class Tinsel8_ADPCMStream : public Tinsel_ADPCMStream {
-public:
- Tinsel8_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-};
-
-int Tinsel8_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples;
- byte data;
- const double eVal = 1.007843258;
-
- samples = 0;
-
- while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
- if (_blockPos[0] == _blockAlign) {
- readBufferTinselHeader();
- _blockPos[0] = 0;
- }
-
- for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples++, _blockPos[0]++) {
- // Read 1 byte = 8 bits = one 8 bit block
- data = _stream->readByte();
- buffer[samples] = decodeTinsel(data << 8, eVal);
- }
- }
-
- return samples;
-}
-
-
-#pragma mark -
-
-// Duck DK3 IMA ADPCM Decoder
-// Based on FFmpeg's decoder and http://wiki.multimedia.cx/index.php?title=Duck_DK3_IMA_ADPCM
-
-class DK3_ADPCMStream : public Ima_ADPCMStream {
-protected:
-
- void reset() {
- Ima_ADPCMStream::reset();
- _topNibble = false;
- }
-
-public:
- DK3_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
-
- // DK3 only works as a stereo stream
- assert(channels == 2);
- _topNibble = false;
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-
-private:
- byte _nibble, _lastByte;
- bool _topNibble;
-};
-
#define DK3_READ_NIBBLE() \
do { \
if (_topNibble) { \
@@ -782,14 +394,15 @@ int DK3_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
#pragma mark -
-// adjust the step for use on the next sample.
-int16 ADPCMStream::stepAdjust(byte code) {
- static const int16 adjusts[] = {-1, -1, -1, -1, 2, 4, 6, 8};
-
- return adjusts[code & 0x07];
-}
+// This table is used to adjust the step for use on the next sample.
+// We could half the table, but since the lookup index used is always
+// a 4-bit nibble, it's more efficient to just keep it as it is.
+const int16 ADPCMStream::_stepAdjustTable[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+};
-static const uint16 imaStepTable[89] = {
+const int16 Ima_ADPCMStream::_imaTable[89] = {
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66,
@@ -805,13 +418,13 @@ static const uint16 imaStepTable[89] = {
};
int16 Ima_ADPCMStream::decodeIMA(byte code, int channel) {
- int32 E = (2 * (code & 0x7) + 1) * imaStepTable[_status.ima_ch[channel].stepIndex] / 8;
+ int32 E = (2 * (code & 0x7) + 1) * _imaTable[_status.ima_ch[channel].stepIndex] / 8;
int32 diff = (code & 0x08) ? -E : E;
int32 samp = CLIP<int32>(_status.ima_ch[channel].last + diff, -32768, 32767);
_status.ima_ch[channel].last = samp;
- _status.ima_ch[channel].stepIndex += stepAdjust(code);
- _status.ima_ch[channel].stepIndex = CLIP<int32>(_status.ima_ch[channel].stepIndex, 0, ARRAYSIZE(imaStepTable) - 1);
+ _status.ima_ch[channel].stepIndex += _stepAdjustTable[code];
+ _status.ima_ch[channel].stepIndex = CLIP<int32>(_status.ima_ch[channel].stepIndex, 0, ARRAYSIZE(_imaTable) - 1);
return samp;
}
@@ -826,18 +439,10 @@ RewindableAudioStream *makeADPCMStream(Common::SeekableReadStream *stream, Dispo
return new Oki_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
case kADPCMMSIma:
return new MSIma_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMMSImaLastExpress:
- return new MSIma_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign, true);
case kADPCMMS:
return new MS_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMTinsel4:
- return new Tinsel4_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMTinsel6:
- return new Tinsel6_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMTinsel8:
- return new Tinsel8_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMIma:
- return new Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
+ case kADPCMDVI:
+ return new DVI_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
case kADPCMApple:
return new Apple_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
case kADPCMDK3:
diff --git a/audio/decoders/adpcm.h b/audio/decoders/adpcm.h
index 38ec870a27..10344101e2 100644
--- a/audio/decoders/adpcm.h
+++ b/audio/decoders/adpcm.h
@@ -38,12 +38,15 @@
#define SOUND_ADPCM_H
#include "common/scummsys.h"
-#include "common/stream.h"
+#include "common/types.h"
+
+namespace Common {
+class SeekableReadStream;
+}
namespace Audio {
-class AudioStream;
class RewindableAudioStream;
// There are several types of ADPCM encoding, only some are supported here
@@ -54,12 +57,8 @@ class RewindableAudioStream;
enum typesADPCM {
kADPCMOki, // Dialogic/Oki ADPCM (aka VOX)
kADPCMMSIma, // Microsoft IMA ADPCM
- kADPCMMSImaLastExpress, // Microsoft IMA ADPCM (with inverted samples)
kADPCMMS, // Microsoft ADPCM
- kADPCMTinsel4, // 4-bit ADPCM used by the Tinsel engine
- kADPCMTinsel6, // 6-bit ADPCM used by the Tinsel engine
- kADPCMTinsel8, // 8-bit ADPCM used by the Tinsel engine
- kADPCMIma, // Standard IMA ADPCM
+ kADPCMDVI, // Intel DVI IMA ADPCM
kADPCMApple, // Apple QuickTime IMA ADPCM
kADPCMDK3 // Duck DK3 IMA ADPCM
};
diff --git a/audio/decoders/adpcm_intern.h b/audio/decoders/adpcm_intern.h
new file mode 100644
index 0000000000..f875bd88c7
--- /dev/null
+++ b/audio/decoders/adpcm_intern.h
@@ -0,0 +1,242 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/**
+ * Internal interfaces to the ADPCM decoders.
+ *
+ * These can be used to make custom ADPCM decoder subclasses,
+ * or to at least share some common data tables between various
+ * ADPCM decoder implementations.
+ */
+
+#ifndef SOUND_ADPCM_INTERN_H
+#define SOUND_ADPCM_INTERN_H
+
+#include "audio/audiostream.h"
+#include "common/endian.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
+
+
+namespace Audio {
+
+class ADPCMStream : public RewindableAudioStream {
+protected:
+ Common::SeekableReadStream *_stream;
+ const DisposeAfterUse::Flag _disposeAfterUse;
+ const int32 _startpos;
+ const int32 _endpos;
+ const int _channels;
+ const uint32 _blockAlign;
+ uint32 _blockPos[2];
+ const int _rate;
+
+ struct ADPCMStatus {
+ // OKI/IMA
+ struct {
+ int32 last;
+ int32 stepIndex;
+ } ima_ch[2];
+ } _status;
+
+ virtual void reset();
+
+public:
+ ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign);
+ ~ADPCMStream();
+
+ virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); }
+ virtual bool isStereo() const { return _channels == 2; }
+ virtual int getRate() const { return _rate; }
+
+ virtual bool rewind();
+
+
+ /**
+ * This table is used by some ADPCM variants (IMA and OKI) to adjust the
+ * step for use on the next sample.
+ * The first 8 entries are identical to the second 8 entries. Hence, we
+ * could half the table in size. But since the lookup index is always a
+ * 4-bit nibble, it is more efficient to just keep it as it is.
+ */
+ static const int16 _stepAdjustTable[16];
+};
+
+class Oki_ADPCMStream : public ADPCMStream {
+public:
+ Oki_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+
+protected:
+ int16 decodeOKI(byte);
+};
+
+class Ima_ADPCMStream : public ADPCMStream {
+protected:
+ int16 decodeIMA(byte code, int channel = 0); // Default to using the left channel/using one channel
+
+public:
+ Ima_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+ memset(&_status, 0, sizeof(_status));
+ }
+
+ /**
+ * This table is used by decodeIMA.
+ */
+ static const int16 _imaTable[89];
+};
+
+class DVI_ADPCMStream : public Ima_ADPCMStream {
+public:
+ DVI_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+};
+
+class Apple_ADPCMStream : public Ima_ADPCMStream {
+protected:
+ // Apple QuickTime IMA ADPCM
+ int32 _streamPos[2];
+ int16 _buffer[2][2];
+ uint8 _chunkPos[2];
+
+ void reset() {
+ Ima_ADPCMStream::reset();
+ _chunkPos[0] = 0;
+ _chunkPos[1] = 0;
+ _streamPos[0] = 0;
+ _streamPos[1] = _blockAlign;
+ }
+
+public:
+ Apple_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+ _chunkPos[0] = 0;
+ _chunkPos[1] = 0;
+ _streamPos[0] = 0;
+ _streamPos[1] = _blockAlign;
+ }
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+
+};
+
+class MSIma_ADPCMStream : public Ima_ADPCMStream {
+public:
+ MSIma_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+
+ if (blockAlign == 0)
+ error("MSIma_ADPCMStream(): blockAlign isn't specified");
+
+ if (blockAlign % (_channels * 4))
+ error("MSIma_ADPCMStream(): invalid blockAlign");
+
+ _samplesLeft[0] = 0;
+ _samplesLeft[1] = 0;
+ }
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+
+ void reset() {
+ Ima_ADPCMStream::reset();
+ _samplesLeft[0] = 0;
+ _samplesLeft[1] = 0;
+ }
+
+private:
+ int16 _buffer[2][8];
+ int _samplesLeft[2];
+};
+
+class MS_ADPCMStream : public ADPCMStream {
+protected:
+ struct ADPCMChannelStatus {
+ byte predictor;
+ int16 delta;
+ int16 coeff1;
+ int16 coeff2;
+ int16 sample1;
+ int16 sample2;
+ };
+
+ struct {
+ // MS ADPCM
+ ADPCMChannelStatus ch[2];
+ } _status;
+
+ void reset() {
+ ADPCMStream::reset();
+ memset(&_status, 0, sizeof(_status));
+ }
+
+public:
+ MS_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+ if (blockAlign == 0)
+ error("MS_ADPCMStream(): blockAlign isn't specified for MS ADPCM");
+ memset(&_status, 0, sizeof(_status));
+ }
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+
+protected:
+ int16 decodeMS(ADPCMChannelStatus *c, byte);
+};
+
+// Duck DK3 IMA ADPCM Decoder
+// Based on FFmpeg's decoder and http://wiki.multimedia.cx/index.php?title=Duck_DK3_IMA_ADPCM
+
+class DK3_ADPCMStream : public Ima_ADPCMStream {
+protected:
+
+ void reset() {
+ Ima_ADPCMStream::reset();
+ _topNibble = false;
+ }
+
+public:
+ DK3_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
+ : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
+
+ // DK3 only works as a stereo stream
+ assert(channels == 2);
+ _topNibble = false;
+ }
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+
+private:
+ byte _nibble, _lastByte;
+ bool _topNibble;
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/decoders/aiff.cpp b/audio/decoders/aiff.cpp
index 0f947752f6..957fb13638 100644
--- a/audio/decoders/aiff.cpp
+++ b/audio/decoders/aiff.cpp
@@ -32,12 +32,10 @@
*/
#include "common/endian.h"
-#include "common/util.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#include "audio/decoders/aiff.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
#include "audio/decoders/raw.h"
namespace Audio {
diff --git a/audio/decoders/aiff.h b/audio/decoders/aiff.h
index 06c56ecd38..dddbffb520 100644
--- a/audio/decoders/aiff.h
+++ b/audio/decoders/aiff.h
@@ -37,7 +37,9 @@
#include "common/scummsys.h"
#include "common/types.h"
-namespace Common { class SeekableReadStream; }
+namespace Common {
+class SeekableReadStream;
+}
namespace Audio {
diff --git a/audio/decoders/flac.cpp b/audio/decoders/flac.cpp
index 76b6d35419..fe15877ac6 100644
--- a/audio/decoders/flac.cpp
+++ b/audio/decoders/flac.cpp
@@ -32,6 +32,7 @@
#include "common/debug.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "audio/audiostream.h"
diff --git a/audio/decoders/flac.h b/audio/decoders/flac.h
index 17f95ec1fb..69222f22a1 100644
--- a/audio/decoders/flac.h
+++ b/audio/decoders/flac.h
@@ -49,12 +49,11 @@
#ifdef USE_FLAC
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
namespace Audio {
-class AudioStream;
class SeekableAudioStream;
/**
diff --git a/audio/decoders/iff_sound.cpp b/audio/decoders/iff_sound.cpp
index 2ec189c586..8efe017e75 100644
--- a/audio/decoders/iff_sound.cpp
+++ b/audio/decoders/iff_sound.cpp
@@ -25,7 +25,6 @@
#include "audio/decoders/iff_sound.h"
#include "audio/audiostream.h"
-#include "audio/mixer.h"
#include "audio/decoders/raw.h"
#include "common/iff_container.h"
#include "common/func.h"
diff --git a/audio/decoders/iff_sound.h b/audio/decoders/iff_sound.h
index 4e53059380..4d26b32e71 100644
--- a/audio/decoders/iff_sound.h
+++ b/audio/decoders/iff_sound.h
@@ -33,7 +33,7 @@
#define SOUND_IFF_H
namespace Common {
- class ReadStream;
+class ReadStream;
}
namespace Audio {
diff --git a/audio/decoders/mac_snd.cpp b/audio/decoders/mac_snd.cpp
index 7c1a2f75f0..fc69988860 100644
--- a/audio/decoders/mac_snd.cpp
+++ b/audio/decoders/mac_snd.cpp
@@ -30,11 +30,10 @@
* We implement both type 1 and type 2 snd resources, but only those that are sampled
*/
-#include "common/util.h"
+#include "common/textconsole.h"
#include "common/stream.h"
#include "audio/decoders/mac_snd.h"
-#include "audio/audiostream.h"
#include "audio/decoders/raw.h"
namespace Audio {
diff --git a/audio/decoders/mac_snd.h b/audio/decoders/mac_snd.h
index 198a61333e..bf6331a265 100644
--- a/audio/decoders/mac_snd.h
+++ b/audio/decoders/mac_snd.h
@@ -35,7 +35,9 @@
#include "common/scummsys.h"
#include "common/types.h"
-namespace Common { class SeekableReadStream; }
+namespace Common {
+class SeekableReadStream;
+}
namespace Audio {
diff --git a/audio/decoders/mp3.cpp b/audio/decoders/mp3.cpp
index 53d68fa9db..91bd49873a 100644
--- a/audio/decoders/mp3.cpp
+++ b/audio/decoders/mp3.cpp
@@ -29,6 +29,7 @@
#include "common/debug.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "audio/audiostream.h"
diff --git a/audio/decoders/mp3.h b/audio/decoders/mp3.h
index 72bc6e1b3e..d3a5b70d45 100644
--- a/audio/decoders/mp3.h
+++ b/audio/decoders/mp3.h
@@ -50,12 +50,11 @@
#ifdef USE_MAD
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
namespace Audio {
-class AudioStream;
class SeekableAudioStream;
/**
diff --git a/audio/decoders/raw.cpp b/audio/decoders/raw.cpp
index 8b833c7838..cf787f9b12 100644
--- a/audio/decoders/raw.cpp
+++ b/audio/decoders/raw.cpp
@@ -25,9 +25,10 @@
#include "common/endian.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
+#include "common/util.h"
#include "audio/audiostream.h"
-#include "audio/mixer.h"
#include "audio/decoders/raw.h"
namespace Audio {
diff --git a/audio/decoders/raw.h b/audio/decoders/raw.h
index 3e9426012c..23ed02182d 100644
--- a/audio/decoders/raw.h
+++ b/audio/decoders/raw.h
@@ -32,12 +32,12 @@
#include "common/list.h"
-namespace Common { class SeekableReadStream; }
-
+namespace Common {
+class SeekableReadStream;
+}
namespace Audio {
-class AudioStream;
class SeekableAudioStream;
/**
diff --git a/audio/decoders/vag.h b/audio/decoders/vag.h
index cdf91a8ea1..4adc1d3dde 100644
--- a/audio/decoders/vag.h
+++ b/audio/decoders/vag.h
@@ -35,12 +35,11 @@
#define SOUND_VAG_H
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
namespace Audio {
-class AudioStream;
class RewindableAudioStream;
/**
diff --git a/audio/decoders/voc.cpp b/audio/decoders/voc.cpp
index b811a640ec..9c2dc4f337 100644
--- a/audio/decoders/voc.cpp
+++ b/audio/decoders/voc.cpp
@@ -27,9 +27,9 @@
#include "common/endian.h"
#include "common/util.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#include "audio/audiostream.h"
-#include "audio/mixer.h"
#include "audio/decoders/raw.h"
#include "audio/decoders/voc.h"
diff --git a/audio/decoders/voc.h b/audio/decoders/voc.h
index 82cc261f2c..38250dcf7a 100644
--- a/audio/decoders/voc.h
+++ b/audio/decoders/voc.h
@@ -41,8 +41,10 @@
#include "common/scummsys.h"
#include "common/types.h"
-namespace Common { class ReadStream; }
-namespace Common { class SeekableReadStream; }
+namespace Common {
+class ReadStream;
+class SeekableReadStream;
+}
namespace Audio {
diff --git a/audio/decoders/vorbis.cpp b/audio/decoders/vorbis.cpp
index dc37e852d3..63f7ba8207 100644
--- a/audio/decoders/vorbis.cpp
+++ b/audio/decoders/vorbis.cpp
@@ -32,15 +32,15 @@
#ifdef USE_VORBIS
-#include "common/debug.h"
#include "common/stream.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "audio/audiostream.h"
#ifdef USE_TREMOR
-#if defined(__GP32__) // custom libtremor locations
-#include <ivorbisfile.h>
+#ifdef USE_TREMOLO
+#include <tremolo/ivorbisfile.h>
#else
#include <tremor/ivorbisfile.h>
#endif
diff --git a/audio/decoders/vorbis.h b/audio/decoders/vorbis.h
index 7cc395cccb..51d0b82d5f 100644
--- a/audio/decoders/vorbis.h
+++ b/audio/decoders/vorbis.h
@@ -49,12 +49,11 @@
#ifdef USE_VORBIS
namespace Common {
- class SeekableReadStream;
+class SeekableReadStream;
}
namespace Audio {
-class AudioStream;
class SeekableAudioStream;
/**
diff --git a/audio/decoders/wave.cpp b/audio/decoders/wave.cpp
index 1f0ddd8ceb..a64874887a 100644
--- a/audio/decoders/wave.cpp
+++ b/audio/decoders/wave.cpp
@@ -24,11 +24,10 @@
*/
#include "common/debug.h"
-#include "common/util.h"
+#include "common/textconsole.h"
#include "common/stream.h"
#include "audio/audiostream.h"
-#include "audio/mixer.h"
#include "audio/decoders/wave.h"
#include "audio/decoders/adpcm.h"
#include "audio/decoders/raw.h"
diff --git a/audio/decoders/wave.h b/audio/decoders/wave.h
index 2bdbe8f0b6..33c3e798a0 100644
--- a/audio/decoders/wave.h
+++ b/audio/decoders/wave.h
@@ -43,7 +43,9 @@
#include "common/scummsys.h"
#include "common/types.h"
-namespace Common { class SeekableReadStream; }
+namespace Common {
+class SeekableReadStream;
+}
namespace Audio {
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index 1f61e16101..5952a987a7 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -28,6 +28,7 @@
#include "audio/softsynth/opl/mame.h"
#include "common/config-manager.h"
+#include "common/textconsole.h"
#include "common/translation.h"
namespace OPL {
diff --git a/audio/mididrv.cpp b/audio/mididrv.cpp
index a1487ff69d..6cc3366847 100644
--- a/audio/mididrv.cpp
+++ b/audio/mididrv.cpp
@@ -23,14 +23,14 @@
*
*/
-#include "engines/engine.h"
#include "common/config-manager.h"
+#include "common/error.h"
#include "common/str.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "common/util.h"
#include "audio/mididrv.h"
#include "audio/musicplugin.h"
-#include "common/translation.h"
const byte MidiDriver::_mt32ToGm[128] = {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
diff --git a/audio/mididrv.h b/audio/mididrv.h
index 9e649cba3d..c6c5179051 100644
--- a/audio/mididrv.h
+++ b/audio/mididrv.h
@@ -27,24 +27,10 @@
#define SOUND_MIDIDRV_H
#include "common/scummsys.h"
+#include "common/str.h"
#include "common/timer.h"
class MidiChannel;
-class MusicDevice;
-
-namespace Audio {
- class Mixer;
-}
-namespace Common { class String; }
-
-/**
- * Music Driver Types, used to uniquely identify each music driver.
- *
- * The pseudo drivers are listed first, then all native drivers,
- * then all other MIDI drivers, and finally the non-MIDI drivers.
- *
- * @todo Rename MidiDriverType to MusicDriverType
- */
/**
* Music types that music drivers can implement and engines can rely on.
@@ -71,16 +57,21 @@ enum MusicType {
* A set of flags to be passed to detectDevice() which can be used to
* specify what kind of music driver is preferred / accepted.
*
- * The flags (except for MDT_PREFER_MT32 and MDT_PREFER_GM) indicate whether a given driver
- * type is acceptable. E.g. the TOWNS music driver could be returned by
- * detectDevice if and only if MDT_TOWNS is specified.
+ * The flags (except for MDT_PREFER_MT32 and MDT_PREFER_GM) indicate whether a
+ * given driver type is acceptable. E.g. the TOWNS music driver could be
+ * returned by detectDevice if and only if MDT_TOWNS is specified.
+ *
+ * MDT_PREFER_MT32 and MDT_PREFER_GM indicate the MIDI device type to use when
+ * no device is selected in the music options, or when the MIDI device selected
+ * does not match the requirements of a game engine. With these flags, more
+ * priority is given to an MT-32 device, or a GM device respectively.
*
* @todo Rename MidiDriverFlags to MusicDriverFlags
*/
enum MidiDriverFlags {
MDT_NONE = 0,
- MDT_PCSPK = 1 << 0, // PC Speaker: Maps to MD_PCSPK and MD_PCJR
- MDT_CMS = 1 << 1, // Creative Music System / Gameblaster: Maps to MD_CMS
+ MDT_PCSPK = 1 << 0, // PC Speaker: Maps to MT_PCSPK and MT_PCJR
+ MDT_CMS = 1 << 1, // Creative Music System / Gameblaster: Maps to MT_CMS
MDT_PCJR = 1 << 2, // Tandy/PC Junior driver
MDT_ADLIB = 1 << 3, // AdLib: Maps to MT_ADLIB
MDT_C64 = 1 << 4,
@@ -94,19 +85,53 @@ enum MidiDriverFlags {
};
/**
- * Abstract description of a MIDI driver. Used by the config file and command
- * line parsing code, and also to be able to give the user a list of available
- * drivers.
- *
- * @todo Rename MidiDriverType to MusicDriverType
+ * TODO: Document this, give it a better name.
*/
+class MidiDriver_BASE {
+public:
+ virtual ~MidiDriver_BASE() { }
+
+ /**
+ * Output a packed midi command to the midi stream.
+ * The 'lowest' byte (i.e. b & 0xFF) is the status
+ * code, then come (if used) the first and second
+ * opcode.
+ */
+ virtual void send(uint32 b) = 0;
+
+ /**
+ * Output a midi command to the midi stream. Convenience wrapper
+ * around the usual 'packed' send method.
+ *
+ * Do NOT use this for sysEx transmission; instead, use the sysEx()
+ * method below.
+ */
+ void send(byte status, byte firstOp, byte secondOp) {
+ send(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+ }
+
+ /**
+ * Transmit a sysEx to the midi device.
+ *
+ * The given msg MUST NOT contain the usual SysEx frame, i.e.
+ * do NOT include the leading 0xF0 and the trailing 0xF7.
+ *
+ * Furthermore, the maximal supported length of a SysEx
+ * is 264 bytes. Passing longer buffers can lead to
+ * undefined behavior (most likely, a crash).
+ */
+ virtual void sysEx(const byte *msg, uint16 length) { }
+
+ // TODO: Document this.
+ virtual void metaEvent(byte type, byte *data, uint16 length) { }
+};
/**
* Abstract MIDI Driver Class
*
* @todo Rename MidiDriver to MusicDriver
*/
-class MidiDriver {
+class MidiDriver : public MidiDriver_BASE {
public:
/**
* The device handle.
@@ -177,27 +202,13 @@ public:
*/
virtual int open() = 0;
- /** Close the midi driver. */
- virtual void close() = 0;
-
/**
- * Output a packed midi command to the midi stream.
- * The 'lowest' byte (i.e. b & 0xFF) is the status
- * code, then come (if used) the first and second
- * opcode.
+ * Check whether the midi driver has already been opened.
*/
- virtual void send(uint32 b) = 0;
+ virtual bool isOpen() const = 0;
- /**
- * Output a midi command to the midi stream. Convenience wrapper
- * around the usual 'packed' send method.
- *
- * Do NOT use this for sysEx transmission; instead, use the sysEx()
- * method below.
- */
- void send(byte status, byte firstOp, byte secondOp) {
- send(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
- }
+ /** Close the midi driver. */
+ virtual void close() = 0;
/** Get or set a property. */
virtual uint32 property(int prop, uint32 param) { return 0; }
@@ -225,22 +236,8 @@ public:
*/
void sendGMReset();
- /**
- * Transmit a sysEx to the midi device.
- *
- * The given msg MUST NOT contain the usual SysEx frame, i.e.
- * do NOT include the leading 0xF0 and the trailing 0xF7.
- *
- * Furthermore, the maximal supported length of a SysEx
- * is 264 bytes. Passing longer buffers can lead to
- * undefined behavior (most likely, a crash).
- */
- virtual void sysEx(const byte *msg, uint16 length) { }
-
virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { }
- virtual void metaEvent(byte type, byte *data, uint16 length) { }
-
// Timing functions - MidiDriver now operates timers
virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) = 0;
diff --git a/audio/midiparser.cpp b/audio/midiparser.cpp
index e01b8a7fc6..a1399d0c30 100644
--- a/audio/midiparser.cpp
+++ b/audio/midiparser.cpp
@@ -25,6 +25,7 @@
#include "audio/midiparser.h"
#include "audio/mididrv.h"
+#include "common/textconsole.h"
#include "common/util.h"
//////////////////////////////////////////////////
@@ -350,7 +351,7 @@ void MidiParser::hangAllActiveNotes() {
if (_next_event.command() == 0x8) {
if (temp_active[_next_event.basic.param1] & (1 << _next_event.channel())) {
hangingNote(_next_event.channel(), _next_event.basic.param1, (advance_tick - _position._last_event_tick) * _psec_per_tick, false);
- temp_active[_next_event.basic.param1] &= ~ (1 << _next_event.channel());
+ temp_active[_next_event.basic.param1] &= ~(1 << _next_event.channel());
}
} else if (_next_event.event == 0xFF && _next_event.ext.type == 0x2F) {
// warning("MidiParser::hangAllActiveNotes(): Hit End of Track with active notes left");
diff --git a/audio/midiparser.h b/audio/midiparser.h
index 0b18a19a5b..24f2ba7963 100644
--- a/audio/midiparser.h
+++ b/audio/midiparser.h
@@ -31,8 +31,7 @@
#include "common/scummsys.h"
#include "common/endian.h"
-class MidiParser;
-class MidiDriver;
+class MidiDriver_BASE;
@@ -273,7 +272,7 @@ protected:
///< Used for "Smart Jump" and MIDI formats that do not include explicit Note Off events.
byte _hanging_notes_count; ///< Count of hanging notes, used to optimize expiration.
- MidiDriver *_driver; ///< The device to which all events will be transmitted.
+ MidiDriver_BASE *_driver; ///< The device to which all events will be transmitted.
uint32 _timer_rate; ///< The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
uint32 _ppqn; ///< Pulses Per Quarter Note. (We refer to "pulses" as "ticks".)
uint32 _tempo; ///< Microseconds per quarter note.
@@ -380,7 +379,7 @@ public:
virtual void unloadMusic();
virtual void property(int prop, int value);
- void setMidiDriver(MidiDriver *driver) { _driver = driver; }
+ void setMidiDriver(MidiDriver_BASE *driver) { _driver = driver; }
void setTimerRate(uint32 rate) { _timer_rate = rate; }
void setTempo(uint32 tempo);
void onTimer();
diff --git a/audio/midiparser_smf.cpp b/audio/midiparser_smf.cpp
index 9e4e8ed293..8ead95de4c 100644
--- a/audio/midiparser_smf.cpp
+++ b/audio/midiparser_smf.cpp
@@ -24,7 +24,7 @@
*/
#include "audio/midiparser.h"
-#include "audio/mididrv.h"
+#include "common/textconsole.h"
#include "common/util.h"
/**
diff --git a/audio/midiparser_xmidi.cpp b/audio/midiparser_xmidi.cpp
index edc7c7a943..1146084cde 100644
--- a/audio/midiparser_xmidi.cpp
+++ b/audio/midiparser_xmidi.cpp
@@ -24,7 +24,7 @@
*/
#include "audio/midiparser.h"
-#include "audio/mididrv.h"
+#include "common/textconsole.h"
#include "common/util.h"
/**
diff --git a/audio/midiplayer.cpp b/audio/midiplayer.cpp
new file mode 100644
index 0000000000..f4a13a0438
--- /dev/null
+++ b/audio/midiplayer.cpp
@@ -0,0 +1,198 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "audio/midiplayer.h"
+#include "audio/midiparser.h"
+
+#include "common/config-manager.h"
+
+namespace Audio {
+
+MidiPlayer::MidiPlayer() :
+ _driver(0),
+ _parser(0),
+ _midiData(0),
+ _isLooping(false),
+ _isPlaying(false),
+ _masterVolume(0),
+ _nativeMT32(false) {
+
+ memset(_channelsTable, 0, sizeof(_channelsTable));
+ memset(_channelsVolume, 127, sizeof(_channelsVolume));
+
+// TODO
+}
+
+MidiPlayer::~MidiPlayer() {
+ // FIXME/TODO: In some engines, stop() was called first;
+ // in others, _driver->setTimerCallback(NULL, NULL) came first.
+ // Hopefully, this make no real difference, but we should
+ // watch out for regressions.
+ stop();
+
+ // Unhook & unload the driver
+ if (_driver) {
+ _driver->setTimerCallback(0, 0);
+ _driver->close();
+ delete _driver;
+ _driver = 0;
+ }
+}
+
+void MidiPlayer::createDriver(int flags) {
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(flags);
+ _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
+
+ _driver = MidiDriver::createMidi(dev);
+ assert(_driver);
+ if (_nativeMT32)
+ _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+}
+
+
+void MidiPlayer::setVolume(int volume) {
+ volume = CLIP(volume, 0, 255);
+ if (_masterVolume == volume)
+ return;
+
+ Common::StackLock lock(_mutex);
+
+ _masterVolume = volume;
+ for (int i = 0; i < kNumChannels; ++i) {
+ if (_channelsTable[i]) {
+ _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
+ }
+ }
+}
+
+void MidiPlayer::syncVolume() {
+ int volume = ConfMan.getInt("music_volume");
+ if (ConfMan.getBool("mute")) {
+ volume = -1;
+ }
+ setVolume(volume);
+}
+
+
+void MidiPlayer::send(uint32 b) {
+ byte ch = (byte)(b & 0x0F);
+ if ((b & 0xFFF0) == 0x07B0) {
+ // Adjust volume changes by master volume
+ byte volume = (byte)((b >> 16) & 0x7F);
+ _channelsVolume[ch] = volume;
+ volume = volume * _masterVolume / 255;
+ b = (b & 0xFF00FFFF) | (volume << 16);
+ } else if ((b & 0xFFF0) == 0x007BB0) {
+ // Only respond to All Notes Off if this channel
+ // has currently been allocated
+ if (!_channelsTable[ch])
+ return;
+ }
+
+ sendToChannel(ch, b);
+}
+
+void MidiPlayer::sendToChannel(byte ch, uint32 b) {
+ if (!_channelsTable[ch]) {
+ _channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ // TODO: Some engines overload this method to insert code at this
+ // point which calls the channel's volume() method.
+ // Does this make sense, and should we maybe do it in general?
+ }
+ if (_channelsTable[ch]) {
+ _channelsTable[ch]->send(b);
+ }
+}
+
+void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
+ switch (type) {
+ case 0x2F: // End of Track
+ endOfTrack();
+ break;
+ default:
+ //warning("Unhandled meta event: %02x", type);
+ break;
+ }
+}
+
+void MidiPlayer::endOfTrack() {
+ if (_isLooping) {
+ assert(_parser);
+ _parser->jumpToTick(0);
+ } else
+ stop();
+}
+
+void MidiPlayer::timerCallback(void *data) {
+ assert(data);
+ ((MidiPlayer *)data)->onTimer();
+}
+
+void MidiPlayer::onTimer() {
+ Common::StackLock lock(_mutex);
+
+ // TODO: Maybe we can replace _isPlaying
+ // by a simple check for "_parser != 0" ?
+
+ if (_isPlaying && _parser) {
+ _parser->onTimer();
+ }
+}
+
+
+void MidiPlayer::stop() {
+ Common::StackLock lock(_mutex);
+
+ _isPlaying = false;
+ if (_parser) {
+ _parser->unloadMusic();
+
+ // FIXME/TODO: The MidiParser destructor calls allNotesOff()
+ // but unloadMusic also does. To suppress double notes-off,
+ // we reset the midi driver of _parser before deleting it.
+ // This smells very fishy, in any case.
+ _parser->setMidiDriver(0);
+
+ delete _parser;
+ _parser = NULL;
+ }
+
+ free(_midiData);
+ _midiData = 0;
+}
+
+void MidiPlayer::pause() {
+// debugC(2, kDraciSoundDebugLevel, "Pausing track %d", _track);
+ _isPlaying = false;
+ setVolume(-1); // FIXME: This should be 0, shouldn't it?
+}
+
+void MidiPlayer::resume() {
+// debugC(2, kDraciSoundDebugLevel, "Resuming track %d", _track);
+ syncVolume();
+ _isPlaying = true;
+}
+
+} // End of namespace Audio
diff --git a/audio/midiplayer.h b/audio/midiplayer.h
new file mode 100644
index 0000000000..0cf373d646
--- /dev/null
+++ b/audio/midiplayer.h
@@ -0,0 +1,191 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SOUND_MIDIPLAYER_H
+#define SOUND_MIDIPLAYER_H
+
+#include "common/scummsys.h"
+#include "common/mutex.h"
+#include "audio/mididrv.h"
+
+class MidiParser;
+
+namespace Audio {
+
+/**
+ * Simple MIDI playback class.
+ *
+ * @note Currently incomplete, as it lacks play() methods. This is just a
+ * start of the real thing, which tries to include code replicated between
+ * several of our engines.
+ *
+ * Eventually, this should offer ways to start playback of SMF and XMIDI
+ * data (and possibly make it easy to add further playback methods),
+ * should be able to automatically instantiate _driver as needed,
+ * should perform memory management on the MidiParser object(s) being
+ * used, and possibly more.
+ *
+ * Also, pause/resume handling should be unified (we provide an implementation,
+ * but several subclasses use different ones).
+ *
+ * Also, care should be taken to ensure that mutex locking is done right.
+ *
+ * @todo Document origin of this class. It is based on code shared by
+ * several engines (e.g. DRACI says it copied it from MADE, which took
+ * it from SAGE).
+ */
+class MidiPlayer : public MidiDriver_BASE {
+public:
+ MidiPlayer();
+ ~MidiPlayer();
+
+ // TODO: Implement ways to actually play stuff
+ //virtual void play(TODO);
+
+ // TODO: Document these
+ virtual void stop();
+ virtual void pause();
+ virtual void resume();
+
+ /**
+ * Return whether there is currently any MIDI music playing.
+ *
+ * @todo There is a subtle difference between the semantics of this in
+ * various subclasses, related to paused music: Namely, should this
+ * function return true or false if a MIDI song is currently loaded,
+ * but paused? In the base implementation of pause/resume, "false"
+ * will be returned (that is, it is not possible to distinguish between
+ * nothing being played, and an active but paused MIDI tune).
+ * But in several subclasses (e.g. in HUGO), there is a separate _paused
+ * variable, which is used to pause playback, and for these, "true"
+ * will be returned.
+ * And in SAGA, isPlaying is overwritten to return the value
+ * of _parser->isPlaying() (which should amount to "true" in the
+ * described situation).
+ * We really should unify this and clearly define the desired
+ * semantics of this method.
+ */
+ bool isPlaying() const { return _isPlaying; }
+
+ /**
+ * Return the currently active master volume, in the range 0-255.
+ */
+ int getVolume() const { return _masterVolume; }
+
+ /**
+ * Set the master volume to the specified value in the range 0-255.
+ * (values outside this range are automatically clipped).
+ * This may cause suitable MIDI events to be sent to active channels.
+ *
+ * @todo This method currently does not do anything if the new volume
+ * matches the old volume. But some engines always update the
+ * volume (Parallaction, Tinsel, Touche, ...). This is why
+ * this method is currently virtual. We really should figure
+ * which way to do it, and then make this the default, and make
+ * this method non-virtual again.
+ */
+ virtual void setVolume(int volume);
+
+ /**
+ * Update the volume according to the ConfMan's 'music_volume'
+ * setting. also respects the 'mute' setting.
+ */
+ void syncVolume();
+
+ // TODO: Document this
+ bool hasNativeMT32() const { return _nativeMT32; }
+
+ // MidiDriver_BASE implementation
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
+
+protected:
+ /**
+ * This method is invoked by the default send() implementation,
+ * after suitably filtering the message b.
+ */
+ virtual void sendToChannel(byte ch, uint32 b);
+
+ /**
+ * This method is invoked by metaEvent when an end-of-track
+ * event arrives. By default, this tells the parser
+ * to jump to the start (if looping is enabled) resp.
+ * invokes stope():
+ * Overload this to customize behavior.
+ */
+ virtual void endOfTrack();
+
+ // TODO: Document this
+ virtual void onTimer();
+
+ static void timerCallback(void *data);
+
+ void createDriver(int flags = MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+
+protected:
+ enum {
+ /**
+ * The number of MIDI channels supported.
+ */
+ kNumChannels = 16
+ };
+
+ Common::Mutex _mutex;
+ MidiDriver *_driver;
+
+ /**
+ * A MidiParser instances, to be created by methods of a MidiPlayer
+ * subclass.
+ * @note The stop() method (and hence the destructor) invoke the
+ * unloadMusic() method of _parser and then delete it.
+ */
+ MidiParser *_parser;
+
+ /**
+ * This is an (optional) pointer to a malloc'ed buffer containing
+ * MIDI data used by _parser. The stop() method (and hence the
+ * destructor) will free this if set.
+ * Subclasses of this class may use _midiData, but don't have to
+ */
+ byte *_midiData;
+
+ MidiChannel *_channelsTable[kNumChannels];
+ uint8 _channelsVolume[kNumChannels];
+
+ bool _isLooping;
+ bool _isPlaying;
+
+ /**
+ * The master volume, in the range 0-255.
+ */
+ int _masterVolume; // FIXME: byte or int ?
+
+ bool _nativeMT32;
+};
+
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/mixer.cpp b/audio/mixer.cpp
index c2271b1059..4d23487e71 100644
--- a/audio/mixer.cpp
+++ b/audio/mixer.cpp
@@ -25,6 +25,7 @@
#include "common/util.h"
#include "common/system.h"
+#include "common/textconsole.h"
#include "audio/mixer_intern.h"
#include "audio/rate.h"
@@ -54,8 +55,9 @@ public:
* @param len number of sample *pairs*. So a value of
* 10 means that the buffer contains twice 10 sample, each
* 16 bits, for a total of 40 bytes.
+ * @return number of sample pairs processed (which can still be silence!)
*/
- void mix(int16 *data, uint len);
+ int mix(int16 *data, uint len);
/**
* Queries whether the channel is still playing or not.
@@ -161,16 +163,11 @@ private:
MixerImpl::MixerImpl(OSystem *system, uint sampleRate)
- : _syst(system), _sampleRate(sampleRate), _mixerReady(false), _handleSeed(0) {
+ : _syst(system), _mutex(), _sampleRate(sampleRate), _mixerReady(false), _handleSeed(0), _soundTypeSettings() {
assert(sampleRate > 0);
- int i;
-
- for (i = 0; i < ARRAYSIZE(_volumeForSoundType); i++)
- _volumeForSoundType[i] = kMaxMixerVolume;
-
- for (i = 0; i != NUM_CHANNELS; i++)
+ for (int i = 0; i != NUM_CHANNELS; i++)
_channels[i] = 0;
}
@@ -257,7 +254,7 @@ void MixerImpl::playStream(
insertChannel(handle, chan);
}
-void MixerImpl::mixCallback(byte *samples, uint len) {
+int MixerImpl::mixCallback(byte *samples, uint len) {
assert(samples);
Common::StackLock lock(_mutex);
@@ -272,14 +269,21 @@ void MixerImpl::mixCallback(byte *samples, uint len) {
memset(buf, 0, 2 * len * sizeof(int16));
// mix all channels
+ int res = 0, tmp;
for (int i = 0; i != NUM_CHANNELS; i++)
if (_channels[i]) {
if (_channels[i]->isFinished()) {
delete _channels[i];
_channels[i] = 0;
- } else if (!_channels[i]->isPaused())
- _channels[i]->mix(buf, len);
+ } else if (!_channels[i]->isPaused()) {
+ tmp = _channels[i]->mix(buf, len);
+
+ if (tmp > res)
+ res = tmp;
+ }
}
+
+ return res;
}
void MixerImpl::stopAll() {
@@ -314,6 +318,21 @@ void MixerImpl::stopHandle(SoundHandle handle) {
_channels[index] = 0;
}
+void MixerImpl::muteSoundType(SoundType type, bool mute) {
+ assert(0 <= type && type < ARRAYSIZE(_soundTypeSettings));
+ _soundTypeSettings[type].mute = mute;
+
+ for (int i = 0; i != NUM_CHANNELS; ++i) {
+ if (_channels[i] && _channels[i]->getType() == type)
+ _channels[i]->notifyGlobalVolChange();
+ }
+}
+
+bool MixerImpl::isSoundTypeMuted(SoundType type) const {
+ assert(0 <= type && type < ARRAYSIZE(_soundTypeSettings));
+ return _soundTypeSettings[type].mute;
+}
+
void MixerImpl::setChannelVolume(SoundHandle handle, byte volume) {
Common::StackLock lock(_mutex);
@@ -409,7 +428,7 @@ bool MixerImpl::hasActiveChannelOfType(SoundType type) {
}
void MixerImpl::setVolumeForSoundType(SoundType type, int volume) {
- assert(0 <= type && type < ARRAYSIZE(_volumeForSoundType));
+ assert(0 <= type && type < ARRAYSIZE(_soundTypeSettings));
// Check range
if (volume > kMaxMixerVolume)
@@ -421,7 +440,7 @@ void MixerImpl::setVolumeForSoundType(SoundType type, int volume) {
// scaling? See also Player_V2::setMasterVolume
Common::StackLock lock(_mutex);
- _volumeForSoundType[type] = volume;
+ _soundTypeSettings[type].volume = volume;
for (int i = 0; i != NUM_CHANNELS; ++i) {
if (_channels[i] && _channels[i]->getType() == type)
@@ -430,9 +449,9 @@ void MixerImpl::setVolumeForSoundType(SoundType type, int volume) {
}
int MixerImpl::getVolumeForSoundType(SoundType type) const {
- assert(0 <= type && type < ARRAYSIZE(_volumeForSoundType));
+ assert(0 <= type && type < ARRAYSIZE(_soundTypeSettings));
- return _volumeForSoundType[type];
+ return _soundTypeSettings[type].volume;
}
@@ -478,17 +497,21 @@ void Channel::updateChannelVolumes() {
// volume is in the range 0 - kMaxMixerVolume.
// Hence, the vol_l/vol_r values will be in that range, too
- int vol = _mixer->getVolumeForSoundType(_type) * _volume;
-
- if (_balance == 0) {
- _volL = vol / Mixer::kMaxChannelVolume;
- _volR = vol / Mixer::kMaxChannelVolume;
- } else if (_balance < 0) {
- _volL = vol / Mixer::kMaxChannelVolume;
- _volR = ((127 + _balance) * vol) / (Mixer::kMaxChannelVolume * 127);
+ if (!_mixer->isSoundTypeMuted(_type)) {
+ int vol = _mixer->getVolumeForSoundType(_type) * _volume;
+
+ if (_balance == 0) {
+ _volL = vol / Mixer::kMaxChannelVolume;
+ _volR = vol / Mixer::kMaxChannelVolume;
+ } else if (_balance < 0) {
+ _volL = vol / Mixer::kMaxChannelVolume;
+ _volR = ((127 + _balance) * vol) / (Mixer::kMaxChannelVolume * 127);
+ } else {
+ _volL = ((127 - _balance) * vol) / (Mixer::kMaxChannelVolume * 127);
+ _volR = vol / Mixer::kMaxChannelVolume;
+ }
} else {
- _volL = ((127 - _balance) * vol) / (Mixer::kMaxChannelVolume * 127);
- _volR = vol / Mixer::kMaxChannelVolume;
+ _volL = _volR = 0;
}
}
@@ -538,19 +561,23 @@ Timestamp Channel::getElapsedTime() {
return ts;
}
-void Channel::mix(int16 *data, uint len) {
+int Channel::mix(int16 *data, uint len) {
assert(_stream);
+ int res = 0;
+
if (_stream->endOfData()) {
// TODO: call drain method
} else {
assert(_converter);
-
_samplesConsumed = _samplesDecoded;
_mixerTimeStamp = g_system->getMillis();
_pauseTime = 0;
- _samplesDecoded += _converter->flow(*_stream, data, len, _volL, _volR);
+ res = _converter->flow(*_stream, data, len, _volL, _volR);
+ _samplesDecoded += res;
}
+
+ return res;
}
} // End of namespace Audio
diff --git a/audio/mixer.h b/audio/mixer.h
index a048124ca3..5802abdd6b 100644
--- a/audio/mixer.h
+++ b/audio/mixer.h
@@ -27,20 +27,13 @@
#define SOUND_MIXER_H
#include "common/types.h"
-#include "common/mutex.h"
#include "common/noncopyable.h"
-#include "audio/timestamp.h"
-
-class OSystem;
-
-
namespace Audio {
class AudioStream;
class Channel;
-class Mixer;
-class MixerImpl;
+class Timestamp;
/**
* A SoundHandle instances corresponds to a specific sound
@@ -197,6 +190,20 @@ public:
virtual bool isSoundHandleActive(SoundHandle handle) = 0;
+ /**
+ * Set the mute state for a given sound type.
+ *
+ * @param type the sound type
+ * @param mute Whether to mute (= true) or not (= false).
+ */
+ virtual void muteSoundType(SoundType type, bool mute) = 0;
+
+ /**
+ * Query the mute state for a given sound type.
+ *
+ * @param type the sound type
+ */
+ virtual bool isSoundTypeMuted(SoundType type) const = 0;
/**
* Set the channel volume for the given handle.
diff --git a/audio/mixer_intern.h b/audio/mixer_intern.h
index c8df9a594d..d7764e50d9 100644
--- a/audio/mixer_intern.h
+++ b/audio/mixer_intern.h
@@ -64,7 +64,14 @@ private:
bool _mixerReady;
uint32 _handleSeed;
- int _volumeForSoundType[4];
+ struct SoundTypeSettings {
+ SoundTypeSettings() : mute(false), volume(kMaxMixerVolume) {}
+
+ bool mute;
+ int volume;
+ };
+
+ SoundTypeSettings _soundTypeSettings[4];
Channel *_channels[NUM_CHANNELS];
@@ -97,6 +104,9 @@ public:
virtual bool isSoundHandleActive(SoundHandle handle);
+ virtual void muteSoundType(SoundType type, bool mute);
+ virtual bool isSoundTypeMuted(SoundType type) const;
+
virtual void setChannelVolume(SoundHandle handle, byte volume);
virtual void setChannelBalance(SoundHandle handle, int8 balance);
@@ -118,8 +128,10 @@ public:
* The mixer callback function, to be called at regular intervals by
* the backend (e.g. from an audio mixing thread). All the actual mixing
* work is done from here.
+ *
+ * @return number of sample pairs processed (which can still be silence!)
*/
- void mixCallback(byte *samples, uint len);
+ int mixCallback(byte *samples, uint len);
/**
* Set the internal 'is ready' flag of the mixer.
diff --git a/audio/mods/infogrames.cpp b/audio/mods/infogrames.cpp
index 27e42c637b..8bfffeacb6 100644
--- a/audio/mods/infogrames.cpp
+++ b/audio/mods/infogrames.cpp
@@ -27,6 +27,7 @@
#include "common/endian.h"
#include "common/file.h"
#include "common/memstream.h"
+#include "common/textconsole.h"
namespace Audio {
diff --git a/audio/mods/infogrames.h b/audio/mods/infogrames.h
index c7abebf24e..9787210e82 100644
--- a/audio/mods/infogrames.h
+++ b/audio/mods/infogrames.h
@@ -33,7 +33,10 @@
#define SOUND_MODS_INFOGRAMES_H
#include "audio/mods/paula.h"
-#include "common/stream.h"
+
+namespace Common {
+class SeekableReadStream;
+}
namespace Audio {
diff --git a/audio/mods/maxtrax.cpp b/audio/mods/maxtrax.cpp
index a577c72eed..0738966dab 100644
--- a/audio/mods/maxtrax.cpp
+++ b/audio/mods/maxtrax.cpp
@@ -24,10 +24,10 @@
*/
#include "common/scummsys.h"
-#include "common/endian.h"
#include "common/stream.h"
#include "common/util.h"
#include "common/debug.h"
+#include "common/textconsole.h"
#include "audio/mods/maxtrax.h"
diff --git a/audio/mods/module.cpp b/audio/mods/module.cpp
index 0da6923b5d..987b17bc8d 100644
--- a/audio/mods/module.cpp
+++ b/audio/mods/module.cpp
@@ -27,6 +27,8 @@
#include "common/util.h"
#include "common/endian.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
namespace Modules {
@@ -113,7 +115,7 @@ const int16 Module::periods[16][60] = {
108 , 101 , 96 , 90 , 85 , 80 , 76 , 72 , 68 , 64 , 60 , 57 }};
const uint32 Module::signatures[] = {
- MKID_BE('M.K.'), MKID_BE('M!K!'), MKID_BE('FLT4')
+ MKTAG('M','.','K','.'), MKTAG('M','!','K','!'), MKTAG('F','L','T','4')
};
bool Module::load(Common::SeekableReadStream &st, int offs) {
diff --git a/audio/mods/module.h b/audio/mods/module.h
index 550b63617e..c9b72bd2d6 100644
--- a/audio/mods/module.h
+++ b/audio/mods/module.h
@@ -26,7 +26,11 @@
#ifndef SOUND_MODS_MODULE_H
#define SOUND_MODS_MODULE_H
-#include "common/stream.h"
+#include "common/scummsys.h"
+
+namespace Common {
+class SeekableReadStream;
+}
namespace Modules {
diff --git a/audio/mods/protracker.cpp b/audio/mods/protracker.cpp
index 6051338900..f781920505 100644
--- a/audio/mods/protracker.cpp
+++ b/audio/mods/protracker.cpp
@@ -29,6 +29,8 @@
#include "audio/audiostream.h"
+#include "common/textconsole.h"
+
namespace Modules {
class ProtrackerStream : public ::Audio::Paula {
diff --git a/audio/mods/protracker.h b/audio/mods/protracker.h
index af722637c7..fa9895b81f 100644
--- a/audio/mods/protracker.h
+++ b/audio/mods/protracker.h
@@ -33,7 +33,9 @@
#ifndef SOUND_MODS_PROTRACKER_H
#define SOUND_MODS_PROTRACKER_H
-#include "common/stream.h"
+namespace Common {
+class SeekableReadStream;
+}
namespace Audio {
diff --git a/audio/mods/rjp1.cpp b/audio/mods/rjp1.cpp
index 7423abb668..eaa99e6928 100644
--- a/audio/mods/rjp1.cpp
+++ b/audio/mods/rjp1.cpp
@@ -25,10 +25,12 @@
#include "common/debug.h"
#include "common/endian.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
+#include "common/util.h"
#include "audio/mods/paula.h"
#include "audio/mods/rjp1.h"
-#include "audio/audiostream.h"
namespace Audio {
@@ -138,7 +140,7 @@ Rjp1::~Rjp1() {
}
bool Rjp1::load(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData) {
- if (songData->readUint32BE() == MKID_BE('RJP1') && songData->readUint32BE() == MKID_BE('SMOD')) {
+ if (songData->readUint32BE() == MKTAG('R','J','P','1') && songData->readUint32BE() == MKTAG('S','M','O','D')) {
for (int i = 0; i < 7; ++i) {
uint32 size = songData->readUint32BE();
_vars.songData[i] = (uint8 *)malloc(size);
@@ -167,7 +169,7 @@ bool Rjp1::load(Common::SeekableReadStream *songData, Common::SeekableReadStream
}
}
- if (instrumentsData->readUint32BE() == MKID_BE('RJP1')) {
+ if (instrumentsData->readUint32BE() == MKTAG('R','J','P','1')) {
uint32 size = instrumentsData->size() - 4;
_vars.instData = (int8 *)malloc(size);
if (!_vars.instData)
diff --git a/audio/mods/rjp1.h b/audio/mods/rjp1.h
index e1960921b2..e3cb0b853d 100644
--- a/audio/mods/rjp1.h
+++ b/audio/mods/rjp1.h
@@ -32,7 +32,9 @@
#ifndef SOUND_MODS_RJP1_H
#define SOUND_MODS_RJP1_H
-#include "common/stream.h"
+namespace Common {
+class SeekableReadStream;
+}
namespace Audio {
diff --git a/audio/mods/soundfx.cpp b/audio/mods/soundfx.cpp
index 06a1e29514..44fdd65986 100644
--- a/audio/mods/soundfx.cpp
+++ b/audio/mods/soundfx.cpp
@@ -24,10 +24,11 @@
*/
#include "common/endian.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
#include "audio/mods/paula.h"
#include "audio/mods/soundfx.h"
-#include "audio/audiostream.h"
namespace Audio {
diff --git a/audio/mods/soundfx.h b/audio/mods/soundfx.h
index 089c19d292..9dd5240160 100644
--- a/audio/mods/soundfx.h
+++ b/audio/mods/soundfx.h
@@ -32,7 +32,9 @@
#ifndef SOUND_MODS_SOUNDFX_H
#define SOUND_MODS_SOUNDFX_H
-#include "common/stream.h"
+namespace Common {
+class SeekableReadStream;
+}
namespace Audio {
diff --git a/audio/mods/tfmx.cpp b/audio/mods/tfmx.cpp
index 8c69a75ebd..f7cfc50c10 100644
--- a/audio/mods/tfmx.cpp
+++ b/audio/mods/tfmx.cpp
@@ -26,8 +26,8 @@
#include "common/scummsys.h"
#include "common/endian.h"
#include "common/stream.h"
-#include "common/util.h"
#include "common/debug.h"
+#include "common/textconsole.h"
#include "audio/mods/tfmx.h"
diff --git a/audio/module.mk b/audio/module.mk
index 5b93c80d57..a9d9bfc869 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
midiparser_smf.o \
midiparser_xmidi.o \
midiparser.o \
+ midiplayer.o \
mixer.o \
mpu401.o \
musicplugin.o \
@@ -44,6 +45,7 @@ MODULE_OBJS := \
softsynth/ym2612.o \
softsynth/fluidsynth.o \
softsynth/mt32.o \
+ softsynth/eas.o \
softsynth/pcspk.o \
softsynth/sid.o \
softsynth/wave6581.o
diff --git a/audio/mpu401.cpp b/audio/mpu401.cpp
index 4f62de930c..4834772c07 100644
--- a/audio/mpu401.cpp
+++ b/audio/mpu401.cpp
@@ -101,12 +101,18 @@ MidiDriver_MPU401::MidiDriver_MPU401() :
}
}
+MidiDriver_MPU401::~MidiDriver_MPU401() {
+}
+
void MidiDriver_MPU401::close() {
- if (_timer_proc)
+ if (_timer_proc) {
g_system->getTimerManager()->removeTimerProc(_timer_proc);
- _timer_proc = 0;
- for (int i = 0; i < 16; ++i)
- send(0x7B << 8 | 0xB0 | i);
+ _timer_proc = 0;
+ }
+ if (isOpen()) {
+ for (int i = 0; i < 16; ++i)
+ send(0x7B << 8 | 0xB0 | i);
+ }
}
uint32 MidiDriver_MPU401::property(int prop, uint32 param) {
diff --git a/audio/mpu401.h b/audio/mpu401.h
index 070eaf636a..5f1a5108ac 100644
--- a/audio/mpu401.h
+++ b/audio/mpu401.h
@@ -34,8 +34,6 @@
//
////////////////////////////////////////
-class MidiDriver_MPU401;
-
class MidiChannel_MPU401 : public MidiChannel {
private:
@@ -46,22 +44,22 @@ private:
public:
MidiDriver *device();
byte getNumber() { return _channel; }
- void release() { _allocated = false; }
+ virtual void release() { _allocated = false; }
- void send(uint32 b);
+ virtual void send(uint32 b);
// Regular messages
- void noteOff(byte note);
- void noteOn(byte note, byte velocity);
- void programChange(byte program);
- void pitchBend(int16 bend);
+ virtual void noteOff(byte note);
+ virtual void noteOn(byte note, byte velocity);
+ virtual void programChange(byte program);
+ virtual void pitchBend(int16 bend);
// Control Change messages
- void controlChange(byte control, byte value);
- void pitchBendFactor(byte value);
+ virtual void controlChange(byte control, byte value);
+ virtual void pitchBendFactor(byte value);
// SysEx messages
- void sysEx_customInstrument(uint32 type, const byte *instr);
+ virtual void sysEx_customInstrument(uint32 type, const byte *instr);
// Only to be called by the owner
void init(MidiDriver *owner, byte channel);
@@ -78,14 +76,15 @@ private:
public:
MidiDriver_MPU401();
+ virtual ~MidiDriver_MPU401();
virtual void close();
- void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
- uint32 getBaseTempo(void) { return 10000; }
- uint32 property(int prop, uint32 param);
+ virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
+ virtual uint32 getBaseTempo(void) { return 10000; }
+ virtual uint32 property(int prop, uint32 param);
- MidiChannel *allocateChannel();
- MidiChannel *getPercussionChannel() { return &_midi_channels[9]; }
+ virtual MidiChannel *allocateChannel();
+ virtual MidiChannel *getPercussionChannel() { return &_midi_channels[9]; }
};
diff --git a/audio/musicplugin.h b/audio/musicplugin.h
index da0e0ff816..53a2ae426d 100644
--- a/audio/musicplugin.h
+++ b/audio/musicplugin.h
@@ -29,6 +29,10 @@
#include "audio/mididrv.h"
#include "common/list.h"
+namespace Common {
+class Error;
+}
+
class MusicPluginObject;
/**
diff --git a/audio/null.cpp b/audio/null.cpp
index 152f5da03e..2066a6d048 100644
--- a/audio/null.cpp
+++ b/audio/null.cpp
@@ -22,6 +22,7 @@
* $Id$
*/
+#include "common/error.h"
#include "audio/null.h"
Common::Error NullMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
diff --git a/audio/null.h b/audio/null.h
index 5df7493a06..8570d4d293 100644
--- a/audio/null.h
+++ b/audio/null.h
@@ -33,6 +33,7 @@
class MidiDriver_NULL : public MidiDriver_MPU401 {
public:
int open() { return 0; }
+ bool isOpen() const { return true; }
void send(uint32 b) { }
};
diff --git a/audio/rate.cpp b/audio/rate.cpp
index 1fcf0ade2e..fd52503b8c 100644
--- a/audio/rate.cpp
+++ b/audio/rate.cpp
@@ -35,6 +35,7 @@
#include "audio/rate.h"
#include "audio/mixer.h"
#include "common/frac.h"
+#include "common/textconsole.h"
#include "common/util.h"
namespace Audio {
diff --git a/audio/rate.h b/audio/rate.h
index fb231e4c4a..af37994d02 100644
--- a/audio/rate.h
+++ b/audio/rate.h
@@ -27,13 +27,11 @@
#define SOUND_RATE_H
#include "common/scummsys.h"
-#include "engines/engine.h"
-
-class AudioStream;
-
namespace Audio {
+class AudioStream;
+
typedef int16 st_sample_t;
typedef uint16 st_volume_t;
typedef uint32 st_size_t;
diff --git a/audio/rate_arm.cpp b/audio/rate_arm.cpp
index 41944ef698..1eb55d0dc3 100644
--- a/audio/rate_arm.cpp
+++ b/audio/rate_arm.cpp
@@ -48,6 +48,7 @@
#include "audio/rate.h"
#include "audio/mixer.h"
#include "common/util.h"
+#include "common/textconsole.h"
//#define DEBUG_RATECONV
@@ -60,7 +61,7 @@ namespace Audio {
* ARM routine we call doesn't respect those definitions.
*/
#define FRAC_BITS 16
-#define FRAC_ONE (1<<FRAC_BITS)
+#define FRAC_ONE (1 << FRAC_BITS)
/**
* The size of the intermediate input cache. Bigger values may increase
@@ -129,43 +130,40 @@ SimpleRateConverter<stereo, reverseStereo>::SimpleRateConverter(st_rate_t inrate
sr.inLen = 0;
}
-extern "C" {
#ifndef IPHONE
#define ARM_SimpleRate_M _ARM_SimpleRate_M
#define ARM_SimpleRate_S _ARM_SimpleRate_S
#define ARM_SimpleRate_R _ARM_SimpleRate_R
#endif
-}
extern "C" st_sample_t *ARM_SimpleRate_M(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- SimpleRateDetails *sr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ SimpleRateDetails *sr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
extern "C" st_sample_t *ARM_SimpleRate_S(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- SimpleRateDetails *sr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ SimpleRateDetails *sr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
extern "C" st_sample_t *ARM_SimpleRate_R(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- SimpleRateDetails *sr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
-
-extern "C" int SimpleRate_readFudge(Audio::AudioStream &input,
- int16 *a, int b)
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ SimpleRateDetails *sr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
+
+extern "C" int SimpleRate_readFudge(Audio::AudioStream &input, int16 *a, int b)
{
#ifdef DEBUG_RATECONV
debug("Reading ptr=%x n%d", a, b);
@@ -183,21 +181,22 @@ int SimpleRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
if (!stereo) {
obuf = ARM_SimpleRate_M(input,
- &SimpleRate_readFudge,
- &sr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &sr,
+ obuf, osamp, vol_l, vol_r);
} else if (reverseStereo) {
obuf = ARM_SimpleRate_R(input,
- &SimpleRate_readFudge,
- &sr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &sr,
+ obuf, osamp, vol_l, vol_r);
} else {
obuf = ARM_SimpleRate_S(input,
- &SimpleRate_readFudge,
- &sr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &sr,
+ obuf, osamp, vol_l, vol_r);
}
- return (obuf-ostart)/2;
+
+ return (obuf - ostart) / 2;
}
/**
@@ -240,31 +239,31 @@ extern "C" {
}
extern "C" st_sample_t *ARM_LinearRate_M(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- LinearRateDetails *lr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ LinearRateDetails *lr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
extern "C" st_sample_t *ARM_LinearRate_S(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- LinearRateDetails *lr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ LinearRateDetails *lr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
extern "C" st_sample_t *ARM_LinearRate_R(
- AudioStream &input,
- int (*fn)(Audio::AudioStream&,int16*,int),
- LinearRateDetails *lr,
- st_sample_t *obuf,
- st_size_t osamp,
- st_volume_t vol_l,
- st_volume_t vol_r);
+ AudioStream &input,
+ int (*fn)(Audio::AudioStream&,int16*,int),
+ LinearRateDetails *lr,
+ st_sample_t *obuf,
+ st_size_t osamp,
+ st_volume_t vol_l,
+ st_volume_t vol_r);
template<bool stereo, bool reverseStereo>
class LinearRateConverter : public RateConverter {
@@ -320,23 +319,29 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
#endif
st_sample_t *ostart = obuf;
+ if (vol_l > 0xff)
+ vol_l = 0xff;
+
+ if (vol_r > 0xff)
+ vol_r = 0xff;
+
if (!stereo) {
obuf = ARM_LinearRate_M(input,
- &SimpleRate_readFudge,
- &lr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &lr,
+ obuf, osamp, vol_l, vol_r);
} else if (reverseStereo) {
obuf = ARM_LinearRate_R(input,
- &SimpleRate_readFudge,
- &lr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &lr,
+ obuf, osamp, vol_l, vol_r);
} else {
obuf = ARM_LinearRate_S(input,
- &SimpleRate_readFudge,
- &lr,
- obuf, osamp, vol_l, vol_r);
+ &SimpleRate_readFudge,
+ &lr,
+ obuf, osamp, vol_l, vol_r);
}
- return (obuf-ostart)/2;
+ return (obuf - ostart) / 2;
}
@@ -355,31 +360,32 @@ extern "C" {
}
extern "C" st_sample_t *ARM_CopyRate_M(
- st_size_t len,
- st_sample_t *obuf,
- st_volume_t vol_l,
- st_volume_t vol_r,
- st_sample_t *_buffer);
+ st_size_t len,
+ st_sample_t *obuf,
+ st_volume_t vol_l,
+ st_volume_t vol_r,
+ st_sample_t *_buffer);
extern "C" st_sample_t *ARM_CopyRate_S(
- st_size_t len,
- st_sample_t *obuf,
- st_volume_t vol_l,
- st_volume_t vol_r,
- st_sample_t *_buffer);
+ st_size_t len,
+ st_sample_t *obuf,
+ st_volume_t vol_l,
+ st_volume_t vol_r,
+ st_sample_t *_buffer);
extern "C" st_sample_t *ARM_CopyRate_R(
- st_size_t len,
- st_sample_t *obuf,
- st_volume_t vol_l,
- st_volume_t vol_r,
- st_sample_t *_buffer);
+ st_size_t len,
+ st_sample_t *obuf,
+ st_volume_t vol_l,
+ st_volume_t vol_r,
+ st_sample_t *_buffer);
template<bool stereo, bool reverseStereo>
class CopyRateConverter : public RateConverter {
st_sample_t *_buffer;
st_size_t _bufferSize;
+
public:
CopyRateConverter() : _buffer(0), _bufferSize(0) {}
~CopyRateConverter() {
@@ -393,7 +399,7 @@ public:
debug("Copy st=%d rev=%d", stereo, reverseStereo);
#endif
st_size_t len;
- st_sample_t *ostart = obuf;
+ st_sample_t *ostart = obuf;
if (stereo)
osamp *= 2;
@@ -418,8 +424,9 @@ public:
else
obuf = ARM_CopyRate_M(len, obuf, vol_l, vol_r, _buffer);
- return (obuf-ostart)/2;
+ return (obuf - ostart) / 2;
}
+
virtual int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) {
return (ST_SUCCESS);
}
@@ -463,3 +470,4 @@ RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stere
}
} // End of namespace Audio
+
diff --git a/audio/softsynth/adlib.cpp b/audio/softsynth/adlib.cpp
index 4a9ce54c75..0b5215e5d6 100644
--- a/audio/softsynth/adlib.cpp
+++ b/audio/softsynth/adlib.cpp
@@ -24,6 +24,11 @@
#include "audio/softsynth/emumidi.h"
#include "common/debug.h"
+#include "common/error.h"
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+#include "common/types.h"
#include "common/util.h"
#include "audio/fmopl.h"
#include "audio/musicplugin.h"
@@ -118,7 +123,7 @@ public:
byte getNumber() { return _channel; }
void release() { _allocated = false; }
- void send (uint32 b);
+ void send(uint32 b);
// Regular messages
void noteOff(byte note);
diff --git a/audio/softsynth/eas.cpp b/audio/softsynth/eas.cpp
new file mode 100644
index 0000000000..7d17655d20
--- /dev/null
+++ b/audio/softsynth/eas.cpp
@@ -0,0 +1,486 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "common/scummsys.h"
+
+#if defined(__ANDROID__)
+
+#include <dlfcn.h>
+
+#include "common/debug.h"
+#include "common/endian.h"
+#include "common/textconsole.h"
+#include "common/error.h"
+#include "common/file.h"
+#include "common/config-manager.h"
+#include "common/system.h"
+#include "audio/audiostream.h"
+#include "audio/mpu401.h"
+#include "audio/musicplugin.h"
+#include "audio/mixer.h"
+
+//#define EAS_DUMPSTREAM
+
+// NOTE:
+// EAS's render function *only* accepts one mix buffer size. it's defined at
+// compile time of the library and can be retrieved via EASLibConfig.bufSize
+// (seen: 128 bytes).
+// to avoid local intermediate buffers, this implementation insists on a fixed
+// buffer size of the calling rate converter, which in return must be a
+// multiple of EAS's. that may change if there're hickups because slower
+// devices can't render fast enough
+
+// from rate_arm.cpp
+#define INTERMEDIATE_BUFFER_SIZE 512
+
+// so far all android versions have the very same library version
+#define EAS_LIBRARY "libsonivox.so"
+#define EAS_KNOWNVERSION 0x03060a0e
+
+#define EAS_REVERB 2
+#define EAS_REVERB_BYPASS 0
+#define EAS_REVERB_PRESET 1
+#define EAS_REVERB_CHAMBER 2
+
+class MidiDriver_EAS : public MidiDriver_MPU401, Audio::AudioStream {
+public:
+ MidiDriver_EAS();
+ virtual ~MidiDriver_EAS();
+
+ // MidiDriver
+ virtual int open();
+ virtual bool isOpen() const;
+ virtual void close();
+ virtual void send(uint32 b);
+ virtual void sysEx(const byte *msg, uint16 length);
+ virtual void setTimerCallback(void *timerParam,
+ Common::TimerManager::TimerProc timerProc);
+ virtual uint32 getBaseTempo();
+
+ // AudioStream
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+ virtual bool isStereo() const;
+ virtual int getRate() const;
+ virtual bool endOfData() const;
+
+private:
+ struct EASLibConfig {
+ uint32 version;
+ uint32 debug;
+ int32 voices;
+ int32 channels;
+ int32 rate;
+ int32 bufSize;
+ uint32 filter;
+ uint32 timeStamp;
+ char *GUID;
+ };
+
+ struct EASFile {
+ const char *path;
+ int fd;
+ long long offset;
+ long long length;
+ };
+
+ typedef void * EASDataHandle;
+ typedef void * EASHandle;
+
+ typedef EASLibConfig *(*ConfigFunc)();
+ typedef int32 (*InitFunc)(EASDataHandle *);
+ typedef int32 (*ShutdownFunc)(EASDataHandle);
+ typedef int32 (*LoadDLSFunc)(EASDataHandle, EASHandle, EASFile *);
+ typedef int32 (*SetParameterFunc)(EASDataHandle, int32, int32, int32);
+ typedef int32 (*SetVolumeFunc)(EASDataHandle, EASHandle, int32);
+ typedef int32 (*OpenStreamFunc)(EASDataHandle, EASHandle *, EASHandle);
+ typedef int32 (*WriteStreamFunc)(EASDataHandle, EASHandle, byte *, int32);
+ typedef int32 (*CloseStreamFunc)(EASDataHandle, EASHandle);
+ typedef int32 (*RenderFunc)(EASDataHandle, int16 *, int32, int32 *);
+
+ template<typename T>
+ void sym(T &t, const char *symbol) {
+ union {
+ void *v;
+ T t;
+ } u;
+
+ assert(sizeof(u.v) == sizeof(u.t));
+
+ u.v = dlsym(_dlHandle, symbol);
+
+ if (!u.v)
+ warning("couldn't resolve %s from " EAS_LIBRARY, symbol);
+
+ t = u.t;
+ }
+
+ void *_dlHandle;
+
+ ConfigFunc _configFunc;
+ InitFunc _initFunc;
+ ShutdownFunc _shutdownFunc;
+ LoadDLSFunc _loadDLSFunc;
+ SetParameterFunc _setParameterFunc;
+ SetVolumeFunc _setVolumeFunc;
+ OpenStreamFunc _openStreamFunc;
+ WriteStreamFunc _writeStreamFunc;
+ CloseStreamFunc _closeStreamFunc;
+ RenderFunc _renderFunc;
+
+ const EASLibConfig *_config;
+ EASDataHandle _EASHandle;
+ EASHandle _midiStream;
+
+ Common::TimerManager::TimerProc _timerProc;
+ void *_timerParam;
+ uint32 _baseTempo;
+ uint _rounds;
+ Audio::SoundHandle _soundHandle;
+
+ Common::DumpFile _dump;
+};
+
+MidiDriver_EAS::MidiDriver_EAS() :
+ MidiDriver_MPU401(),
+ _dlHandle(0),
+ _configFunc(0),
+ _initFunc(0),
+ _shutdownFunc(0),
+ _loadDLSFunc(0),
+ _setParameterFunc(0),
+ _setVolumeFunc(0),
+ _openStreamFunc(0),
+ _writeStreamFunc(0),
+ _closeStreamFunc(0),
+ _renderFunc(0),
+ _config(0),
+ _EASHandle(0),
+ _midiStream(0),
+ _timerProc(0),
+ _timerParam(0),
+ _baseTempo(0),
+ _rounds(0),
+ _soundHandle(),
+ _dump() {
+}
+
+MidiDriver_EAS::~MidiDriver_EAS() {
+}
+
+int MidiDriver_EAS::open() {
+ if (isOpen())
+ return MERR_ALREADY_OPEN;
+
+ _dlHandle = dlopen(EAS_LIBRARY, RTLD_LAZY);
+ if (!_dlHandle) {
+ warning("error opening " EAS_LIBRARY ": %s", dlerror());
+ return MERR_DEVICE_NOT_AVAILABLE;
+ }
+
+ sym(_configFunc, "EAS_Config");
+ if (!_configFunc) {
+ close();
+ return -1;
+ }
+
+ _config = _configFunc();
+ if (!_config) {
+ close();
+ warning("error retrieving EAS library configuration");
+ return -1;
+ }
+
+ if (_config->version != EAS_KNOWNVERSION) {
+ close();
+ warning("unknown EAS library version: 0x%08x", _config->version);
+ return -1;
+ }
+
+ if (_config->channels > 2) {
+ close();
+ warning("unsupported number of EAS channels: %d", _config->channels);
+ return -1;
+ }
+
+ // see note at top of this file
+ if (INTERMEDIATE_BUFFER_SIZE % (_config->bufSize * _config->channels)) {
+ close();
+ warning("unsupported EAS buffer size: %d", _config->bufSize);
+ return -1;
+ }
+
+ sym(_initFunc, "EAS_Init");
+ sym(_shutdownFunc, "EAS_Shutdown");
+ sym(_loadDLSFunc, "EAS_LoadDLSCollection");
+ sym(_setParameterFunc, "EAS_SetParameter");
+ sym(_setVolumeFunc, "EAS_SetVolume");
+ sym(_openStreamFunc, "EAS_OpenMIDIStream");
+ sym(_writeStreamFunc, "EAS_WriteMIDIStream");
+ sym(_closeStreamFunc, "EAS_CloseMIDIStream");
+ sym(_renderFunc, "EAS_Render");
+
+ if (!_initFunc || !_shutdownFunc || !_loadDLSFunc || !_setParameterFunc ||
+ !_openStreamFunc || !_writeStreamFunc || !_closeStreamFunc ||
+ !_renderFunc) {
+ close();
+ return -1;
+ }
+
+ int32 res = _initFunc(&_EASHandle);
+ if (res) {
+ close();
+ warning("error initializing the EAS library: %d", res);
+ return -1;
+ }
+
+ res = _setParameterFunc(_EASHandle, EAS_REVERB, EAS_REVERB_PRESET,
+ EAS_REVERB_CHAMBER);
+ if (res)
+ warning("error setting reverb preset: %d", res);
+
+ res = _setParameterFunc(_EASHandle, EAS_REVERB, EAS_REVERB_BYPASS, 0);
+ if (res)
+ warning("error disabling reverb bypass: %d", res);
+
+ // 90 is EAS's default, max is 100
+ // so the option slider will only work from 0.1 to 1.1
+ res = _setVolumeFunc(_EASHandle, 0, ConfMan.getInt("midi_gain") - 10);
+ if (res)
+ warning("error setting EAS master volume: %d", res);
+
+ res = _openStreamFunc(_EASHandle, &_midiStream, 0);
+ if (res) {
+ close();
+ warning("error opening EAS MIDI stream: %d", res);
+ return -1;
+ }
+
+ // set the timer frequency to match a single buffer size
+ _baseTempo = (1000000 * _config->bufSize) / _config->rate;
+
+ // number of buffer fills per readBuffer()
+ _rounds = INTERMEDIATE_BUFFER_SIZE / (_config->bufSize * _config->channels);
+
+ debug("EAS initialized (voices:%d channels:%d rate:%d buffer:%d) "
+ "tempo:%u rounds:%u", _config->voices, _config->channels,
+ _config->rate, _config->bufSize, _baseTempo, _rounds);
+
+ // TODO doesn't seem to work with midi streams?
+ if (ConfMan.hasKey("soundfont")) {
+ const Common::String dls = ConfMan.get("soundfont");
+
+ debug("loading DLS file '%s'", dls.c_str());
+
+ EASFile f;
+ memset(&f, 0, sizeof(EASFile));
+ f.path = dls.c_str();
+
+ res = _loadDLSFunc(_EASHandle, 0, &f);
+ if (res)
+ warning("error loading DLS file '%s': %d", dls.c_str(), res);
+ else
+ debug("DLS file loaded");
+ }
+
+#ifdef EAS_DUMPSTREAM
+ if (!_dump.open("/sdcard/eas.dump"))
+ warning("error opening EAS dump file");
+#endif
+
+ g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType,
+ &_soundHandle, this, -1,
+ Audio::Mixer::kMaxChannelVolume, 0,
+ DisposeAfterUse::NO, true);
+
+ return 0;
+}
+
+bool MidiDriver_EAS::isOpen() const {
+ return _dlHandle != 0;
+}
+
+void MidiDriver_EAS::close() {
+ MidiDriver_MPU401::close();
+
+ if (!isOpen())
+ return;
+
+ g_system->getMixer()->stopHandle(_soundHandle);
+
+#ifdef EAS_DUMPSTREAM
+ if (_dump.isOpen())
+ _dump.close();
+#endif
+
+ // not pretty, but better than a mutex
+ g_system->delayMillis((_baseTempo * _rounds) / 1000);
+
+ if (_midiStream) {
+ int32 res = _closeStreamFunc(_EASHandle, _midiStream);
+ if (res)
+ warning("error closing EAS MIDI stream: %d", res);
+
+ _midiStream = 0;
+ }
+
+ if (_EASHandle) {
+ int32 res = _shutdownFunc(_EASHandle);
+ if (res)
+ warning("error shutting down the EAS library: %d", res);
+
+ _EASHandle = 0;
+ }
+
+ if (dlclose(_dlHandle))
+ warning("error closing " EAS_LIBRARY ": %s", dlerror());
+
+ _dlHandle = 0;
+}
+
+void MidiDriver_EAS::send(uint32 b) {
+ byte buf[4];
+
+ WRITE_LE_UINT32(buf, b);
+
+ int32 len = 3;
+ if ((buf[0] >> 4) == 0xC || (buf[0] >> 4) == 0xD)
+ len = 2;
+
+ int32 res = _writeStreamFunc(_EASHandle, _midiStream, buf, len);
+ if (res)
+ warning("error writing to EAS MIDI stream: %d", res);
+}
+
+void MidiDriver_EAS::sysEx(const byte *msg, uint16 length) {
+ byte buf[266];
+
+ assert(length + 2 <= ARRAYSIZE(buf));
+
+ buf[0] = 0xF0;
+ memcpy(buf + 1, msg, length);
+ buf[length + 1] = 0xF7;
+
+ int32 res = _writeStreamFunc(_EASHandle, _midiStream, buf, length + 2);
+ if (res)
+ warning("error writing to EAS MIDI stream: %d", res);
+}
+
+void MidiDriver_EAS::setTimerCallback(void *timerParam,
+ Common::TimerManager::TimerProc timerProc) {
+ _timerParam = timerParam;
+ _timerProc = timerProc;
+}
+
+uint32 MidiDriver_EAS::getBaseTempo() {
+ return _baseTempo;
+}
+
+int MidiDriver_EAS::readBuffer(int16 *buffer, const int numSamples) {
+ // see note at top of this file
+ assert(numSamples == INTERMEDIATE_BUFFER_SIZE);
+
+ int32 res, c;
+
+ for (uint i = 0; i < _rounds; ++i) {
+ // pull in MIDI events for exactly one buffer size
+ if (_timerProc)
+ (*_timerProc)(_timerParam);
+
+ // if there are no MIDI events, this just renders silence
+ res = _renderFunc(_EASHandle, buffer, _config->bufSize, &c);
+ if (res) {
+ warning("error rendering EAS samples: %d", res);
+ return -1;
+ }
+
+#ifdef EAS_DUMPSTREAM
+ if (_dump.isOpen())
+ _dump.write(buffer, c * _config->channels * 2);
+#endif
+
+ buffer += c * _config->channels;
+ }
+
+ return numSamples;
+}
+
+bool MidiDriver_EAS::isStereo() const {
+ return _config->channels == 2;
+}
+
+int MidiDriver_EAS::getRate() const {
+ return _config->rate;
+}
+
+bool MidiDriver_EAS::endOfData() const {
+ return false;
+}
+
+class EASMusicPlugin : public MusicPluginObject {
+public:
+ EASMusicPlugin();
+ virtual ~EASMusicPlugin();
+
+ const char *getName() const;
+ const char *getId() const;
+ MusicDevices getDevices() const;
+ Common::Error createInstance(MidiDriver **mididriver,
+ MidiDriver::DeviceHandle = 0) const;
+};
+
+EASMusicPlugin::EASMusicPlugin() {
+}
+
+EASMusicPlugin::~EASMusicPlugin() {
+}
+
+const char *EASMusicPlugin::getName() const {
+ return "Embedded Audio Synthesis";
+}
+
+const char *EASMusicPlugin::getId() const {
+ return "eas";
+}
+
+MusicDevices EASMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ devices.push_back(MusicDevice(this, "", MT_GM));
+
+ return devices;
+}
+
+Common::Error EASMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
+ *mididriver = new MidiDriver_EAS();
+
+ return Common::kNoError;
+}
+
+//#if PLUGIN_ENABLED_DYNAMIC(EAS)
+ //REGISTER_PLUGIN_DYNAMIC(EAS, PLUGIN_TYPE_MUSIC, EASMusicPlugin);
+//#else
+ REGISTER_PLUGIN_STATIC(EAS, PLUGIN_TYPE_MUSIC, EASMusicPlugin);
+//#endif
+
+#endif
+
diff --git a/audio/softsynth/emumidi.h b/audio/softsynth/emumidi.h
index 35c81490e4..190b70c392 100644
--- a/audio/softsynth/emumidi.h
+++ b/audio/softsynth/emumidi.h
@@ -45,25 +45,24 @@ private:
int _samplesPerTick;
protected:
+ int _baseFreq;
+
virtual void generateSamples(int16 *buf, int len) = 0;
virtual void onTimer() {}
- int _baseFreq;
-
public:
- MidiDriver_Emulated(Audio::Mixer *mixer) : _mixer(mixer) {
- _isOpen = false;
-
- _timerProc = 0;
- _timerParam = 0;
-
- _nextTick = 0;
- _samplesPerTick = 0;
-
- _baseFreq = 250;
+ MidiDriver_Emulated(Audio::Mixer *mixer) :
+ _mixer(mixer),
+ _isOpen(false),
+ _timerProc(0),
+ _timerParam(0),
+ _nextTick(0),
+ _samplesPerTick(0),
+ _baseFreq(250) {
}
- int open() {
+ // MidiDriver API
+ virtual int open() {
_isOpen = true;
int d = getRate() / _baseFreq;
@@ -73,19 +72,23 @@ public:
// but less prone to arithmetic overflow.
_samplesPerTick = (d << FIXP_SHIFT) + (r << FIXP_SHIFT) / _baseFreq;
+
return 0;
}
- void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
+ bool isOpen() const { return _isOpen; }
+
+ virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
_timerProc = timer_proc;
_timerParam = timer_param;
}
- uint32 getBaseTempo() { return 1000000 / _baseFreq; }
-
+ virtual uint32 getBaseTempo() {
+ return 1000000 / _baseFreq;
+ }
// AudioStream API
- int readBuffer(int16 *data, const int numSamples) {
+ virtual int readBuffer(int16 *data, const int numSamples) {
const int stereoFactor = isStereo() ? 2 : 1;
int len = numSamples / stereoFactor;
int step;
@@ -101,16 +104,22 @@ public:
if (!(_nextTick >> FIXP_SHIFT)) {
if (_timerProc)
(*_timerProc)(_timerParam);
+
onTimer();
+
_nextTick += _samplesPerTick;
}
+
data += step * stereoFactor;
len -= step;
} while (len);
return numSamples;
}
- bool endOfData() const { return false; }
+
+ virtual bool endOfData() const {
+ return false;
+ }
};
#endif
diff --git a/audio/softsynth/fluidsynth.cpp b/audio/softsynth/fluidsynth.cpp
index bd016548ec..a4877a4ec1 100644
--- a/audio/softsynth/fluidsynth.cpp
+++ b/audio/softsynth/fluidsynth.cpp
@@ -27,6 +27,9 @@
#ifdef USE_FLUIDSYNTH
#include "common/config-manager.h"
+#include "common/error.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include "audio/softsynth/emumidi.h"
@@ -40,7 +43,6 @@ private:
fluid_synth_t *_synth;
int _soundFont;
int _outputRate;
- Audio::SoundHandle _handle;
protected:
// Because GCC complains about casting from const to non-const...
@@ -144,7 +146,7 @@ int MidiDriver_FluidSynth::open() {
MidiDriver_Emulated::open();
// The MT-32 emulator uses kSFXSoundType here. I don't know why.
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
@@ -153,7 +155,7 @@ void MidiDriver_FluidSynth::close() {
return;
_isOpen = false;
- _mixer->stopHandle(_handle);
+ _mixer->stopHandle(_mixerSoundHandle);
if (_soundFont != -1)
fluid_synth_sfunload(_synth, _soundFont, 1);
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
index e019aa2481..7b6658ab3a 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -25,6 +25,7 @@
#include "audio/softsynth/fmtowns_pc98/towns_audio.h"
#include "common/endian.h"
+#include "common/util.h"
#include "backends/audiocd/audiocd.h"
diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
index 7c071c43fb..cd3a348b85 100644
--- a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
@@ -25,6 +25,8 @@
#include "audio/softsynth/fmtowns_pc98/towns_euphony.h"
#include "common/endian.h"
+#include "common/util.h"
+#include "common/textconsole.h"
TownsEuphonyDriver::TownsEuphonyDriver(Audio::Mixer *mixer) : _activeChannels(0), _sustainChannels(0),
_assignedChannels(0), _paraCount(0), _command(0), _tEnable(0), _tMode(0), _tOrdr(0), _tLevel(0),
@@ -40,6 +42,7 @@ TownsEuphonyDriver::~TownsEuphonyDriver() {
delete[] _activeChannels;
delete[] _sustainChannels;
delete[] _assignedChannels;
+ delete[] _eventBuffer;
delete[] _tEnable;
delete[] _tMode;
delete[] _tOrdr;
@@ -51,6 +54,16 @@ bool TownsEuphonyDriver::init() {
if (!_intf->init())
return false;
+ delete[] _activeChannels;
+ delete[] _sustainChannels;
+ delete[] _assignedChannels;
+ delete[] _eventBuffer;
+ delete[] _tEnable;
+ delete[] _tMode;
+ delete[] _tOrdr;
+ delete[] _tLevel;
+ delete[] _tTranspose;
+
_activeChannels = new int8[16];
_sustainChannels = new int8[16];
_assignedChannels = new ActiveChannel[128];
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
index 79fd95ea0d..a551276ab1 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
@@ -25,6 +25,7 @@
#include "audio/softsynth/fmtowns_pc98/towns_pc98_driver.h"
#include "common/endian.h"
+#include "common/textconsole.h"
class TownsPC98_MusicChannel {
public:
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
index f84fd841a6..9d3751a0cc 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -25,6 +25,8 @@
#include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
#include "common/endian.h"
+#include "common/textconsole.h"
+#include "common/util.h"
class TownsPC98_FmSynthOperator {
public:
@@ -1253,7 +1255,7 @@ void TownsPC98_FmSynth::generateTables() {
delete[] _oprSinTbl;
_oprSinTbl = new uint32[1024];
for (int i = 0; i < 1024; i++) {
- double val = sin((double)(((i << 1) + 1) * PI / 1024.0));
+ double val = sin((double)(((i << 1) + 1) * M_PI / 1024.0));
double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0;
int32 i_dcb = (int32)(2.0 * d_dcb);
i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1);
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
index 18cca56e29..2b916b2cdc 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
@@ -28,7 +28,7 @@
#include "audio/audiostream.h"
#include "audio/mixer.h"
-#include "common/list.h"
+#include "common/mutex.h"
#ifdef __DS__
/* This disables the rhythm channel when emulating the PC-98 type 86 sound card.
diff --git a/audio/softsynth/mt32.cpp b/audio/softsynth/mt32.cpp
index a980b564fc..5371be60b3 100644
--- a/audio/softsynth/mt32.cpp
+++ b/audio/softsynth/mt32.cpp
@@ -34,15 +34,20 @@
#include "common/config-manager.h"
#include "common/debug.h"
+#include "common/error.h"
#include "common/events.h"
#include "common/file.h"
#include "common/system.h"
#include "common/util.h"
#include "common/archive.h"
+#include "common/textconsole.h"
#include "common/translation.h"
#include "graphics/fontman.h"
#include "graphics/surface.h"
+#include "graphics/pixelformat.h"
+#include "graphics/palette.h"
+#include "graphics/font.h"
class MidiChannel_MT32 : public MidiChannel_MPU401 {
void effectLevel(byte value) { }
@@ -51,7 +56,6 @@ class MidiChannel_MT32 : public MidiChannel_MPU401 {
class MidiDriver_MT32 : public MidiDriver_Emulated {
private:
- Audio::SoundHandle _handle;
MidiChannel_MT32 _midiChannels[16];
uint16 _channelMask;
MT32Emu::Synth *_synth;
@@ -336,7 +340,7 @@ int MidiDriver_MT32::open() {
g_system->updateScreen();
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
@@ -347,7 +351,7 @@ void MidiDriver_MT32::send(uint32 b) {
void MidiDriver_MT32::setPitchBendRange(byte channel, uint range) {
if (range > 24) {
- printf("setPitchBendRange() called with range > 24: %d", range);
+ warning("setPitchBendRange() called with range > 24: %d", range);
}
byte benderRangeSysex[9];
benderRangeSysex[0] = 0x41; // Roland
@@ -378,7 +382,7 @@ void MidiDriver_MT32::close() {
// Detach the player callback handler
setTimerCallback(NULL, NULL);
// Detach the mixer callback handler
- _mixer->stopHandle(_handle);
+ _mixer->stopHandle(_mixerSoundHandle);
_synth->close();
delete _synth;
diff --git a/audio/softsynth/mt32/part.cpp b/audio/softsynth/mt32/part.cpp
index eb087f7ea0..9f9269cba5 100644
--- a/audio/softsynth/mt32/part.cpp
+++ b/audio/softsynth/mt32/part.cpp
@@ -100,7 +100,7 @@ void RhythmPart::setBend(unsigned int midiBend) {
}
void Part::setBend(unsigned int midiBend) {
- // FIXME:KG: Slightly unbalanced increments, but I wanted min -1.0, centre 0.0 and max 1.0
+ // FIXME:KG: Slightly unbalanced increments, but I wanted min -1.0, center 0.0 and max 1.0
if (midiBend <= 0x2000) {
bend = ((signed int)midiBend - 0x2000) / (float)0x2000;
} else {
@@ -413,7 +413,7 @@ void RhythmPart::setPan(unsigned int midiPan)
}
void Part::setPan(unsigned int midiPan) {
- // FIXME:KG: Tweaked this a bit so that we have a left 100%, centre and right 100%
+ // FIXME:KG: Tweaked this a bit so that we have a left 100%, center and right 100%
// (But this makes the range somewhat skewed)
// Check against the real thing
// NOTE: Panning is inverted compared to GM.
diff --git a/audio/softsynth/mt32/part.h b/audio/softsynth/mt32/part.h
index 54c4999653..967298258c 100644
--- a/audio/softsynth/mt32/part.h
+++ b/audio/softsynth/mt32/part.h
@@ -24,7 +24,6 @@
namespace MT32Emu {
-class PartialManager;
class Synth;
class Part {
diff --git a/audio/softsynth/mt32/synth.cpp b/audio/softsynth/mt32/synth.cpp
index 16460795a5..112527cc71 100644
--- a/audio/softsynth/mt32/synth.cpp
+++ b/audio/softsynth/mt32/synth.cpp
@@ -19,14 +19,18 @@
* IN THE SOFTWARE.
*/
+// FIXME: Avoid using printf
+#define FORBIDDEN_SYMBOL_EXCEPTION_printf
+
+// FIXME: Avoid using vprintf
+#define FORBIDDEN_SYMBOL_EXCEPTION_vprintf
+
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "mt32emu.h"
-#include "common/str.h"
-
#if defined(MACOSX) || defined(SOLARIS) || defined(__MINGW32__)
// Older versions of Mac OS X didn't supply a powf function, so using it
// will cause a binary incompatibility when trying to run a binary built
diff --git a/audio/softsynth/mt32/synth.h b/audio/softsynth/mt32/synth.h
index 3fc303d322..edda446287 100644
--- a/audio/softsynth/mt32/synth.h
+++ b/audio/softsynth/mt32/synth.h
@@ -29,7 +29,6 @@ class revmodel;
namespace MT32Emu {
class File;
-class TableInitialiser;
class Partial;
class PartialManager;
class Part;
diff --git a/audio/softsynth/opl/dbopl.cpp b/audio/softsynth/opl/dbopl.cpp
index 47e263b6b9..2c46cfee75 100644
--- a/audio/softsynth/opl/dbopl.cpp
+++ b/audio/softsynth/opl/dbopl.cpp
@@ -41,10 +41,6 @@
namespace OPL {
namespace DOSBox {
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
namespace DBOPL {
#define OPLRATE ((double)(14318180.0 / 288.0))
@@ -1392,7 +1388,7 @@ void InitTables( void ) {
//Add 0.5 for the trunc rounding of the integer cast
//Do a PI sinetable instead of the original 0.5 PI
for ( int i = 0; i < 512; i++ ) {
- SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
+ SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (M_PI / 512.0) ) ) / log10(2.0)*256 );
}
#endif
#if ( DBOPL_WAVE == WAVE_TABLEMUL )
@@ -1406,7 +1402,7 @@ void InitTables( void ) {
//Sine Wave Base
for ( int i = 0; i < 512; i++ ) {
- WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084);
+ WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (M_PI / 512.0) ) * 4084);
WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
}
//Exponential wave
@@ -1418,7 +1414,7 @@ void InitTables( void ) {
#if ( DBOPL_WAVE == WAVE_TABLELOG )
//Sine Wave Base
for ( int i = 0; i < 512; i++ ) {
- WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
+ WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (M_PI / 512.0) ) ) / log10(2.0)*256 );
WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i];
}
//Exponential wave
diff --git a/audio/softsynth/opl/dosbox.cpp b/audio/softsynth/opl/dosbox.cpp
index 29993ce3d8..7a494d70ec 100644
--- a/audio/softsynth/opl/dosbox.cpp
+++ b/audio/softsynth/opl/dosbox.cpp
@@ -36,6 +36,7 @@
#include "common/system.h"
#include "common/scummsys.h"
+#include "common/util.h"
#include <math.h>
#include <string.h>
diff --git a/audio/softsynth/opl/mame.cpp b/audio/softsynth/opl/mame.cpp
index c875080e8f..5d790f924f 100644
--- a/audio/softsynth/opl/mame.cpp
+++ b/audio/softsynth/opl/mame.cpp
@@ -33,6 +33,9 @@
#include "mame.h"
+#include "common/textconsole.h"
+#include "common/util.h"
+
#if defined (_WIN32_WCE) || defined (__SYMBIAN32__) || defined(__GP32__) || defined(GP2X) || defined (__MAEMO__) || defined(__DS__) || defined (__MINT__) || defined(__N64__)
#include "common/config-manager.h"
#endif
@@ -708,7 +711,7 @@ static int OPLOpenTable(void) {
/* degree 0 = degree 180 = off */
SIN_TABLE[0] = SIN_TABLE[SIN_ENT /2 ] = &TL_TABLE[EG_ENT - 1];
for (s = 1;s <= SIN_ENT / 4; s++) {
- pom = sin(2 * PI * s / SIN_ENT); /* sin */
+ pom = sin(2 * M_PI * s / SIN_ENT); /* sin */
pom = 20 * log10(1 / pom); /* decibel */
j = int(pom / EG_STEP); /* TL_TABLE steps */
@@ -739,14 +742,14 @@ static int OPLOpenTable(void) {
ENV_CURVE[EG_OFF >> ENV_BITS]= EG_ENT - 1;
/* make LFO ams table */
for (i=0; i < AMS_ENT; i++) {
- pom = (1.0 + sin(2 * PI * i / AMS_ENT)) / 2; /* sin */
+ pom = (1.0 + sin(2 * M_PI * i / AMS_ENT)) / 2; /* sin */
AMS_TABLE[i] = (int)((1.0 / EG_STEP) * pom); /* 1dB */
AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */
}
/* make LFO vibrate table */
for (i=0; i < VIB_ENT; i++) {
/* 100cent = 1seminote = 6% ?? */
- pom = (double)VIB_RATE * 0.06 * sin(2 * PI * i / VIB_ENT); /* +-100sect step */
+ pom = (double)VIB_RATE * 0.06 * sin(2 * M_PI * i / VIB_ENT); /* +-100sect step */
VIB_TABLE[i] = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */
VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */
}
diff --git a/audio/softsynth/opl/mame.h b/audio/softsynth/opl/mame.h
index 58ef5f18dc..4314aa6dba 100644
--- a/audio/softsynth/opl/mame.h
+++ b/audio/softsynth/opl/mame.h
@@ -30,7 +30,6 @@
#define SOUND_SOFTSYNTH_OPL_MAME_H
#include "common/scummsys.h"
-#include "common/util.h"
#include "common/random.h"
#include "audio/fmopl.h"
diff --git a/audio/softsynth/pcspk.cpp b/audio/softsynth/pcspk.cpp
index 69ba113c8b..947c142b73 100644
--- a/audio/softsynth/pcspk.cpp
+++ b/audio/softsynth/pcspk.cpp
@@ -109,7 +109,7 @@ int8 PCSpeaker::generateSine(uint32 x, uint32 oscLength) {
return 0;
// TODO: Maybe using a look-up-table would be better?
- return CLIP<int16>((int16) (128 * sin(2.0 * PI * x / oscLength)), -128, 127);
+ return CLIP<int16>((int16) (128 * sin(2.0 * M_PI * x / oscLength)), -128, 127);
}
int8 PCSpeaker::generateSaw(uint32 x, uint32 oscLength) {
diff --git a/audio/softsynth/pcspk.h b/audio/softsynth/pcspk.h
index c0d85bbceb..8f01fa852b 100644
--- a/audio/softsynth/pcspk.h
+++ b/audio/softsynth/pcspk.h
@@ -26,7 +26,6 @@
#define SOUND_SOFTSYNTH_PCSPK_H
#include "audio/audiostream.h"
-#include "audio/mixer.h"
#include "common/mutex.h"
namespace Audio {
diff --git a/audio/softsynth/sid.cpp b/audio/softsynth/sid.cpp
index 241766fa0a..40dc50e972 100644
--- a/audio/softsynth/sid.cpp
+++ b/audio/softsynth/sid.cpp
@@ -32,7 +32,6 @@
#include "sid.h"
#include "audio/null.h"
-#include <math.h>
namespace Resid {
@@ -110,7 +109,7 @@ void WaveformGenerator::reset() {
msb_rising = false;
}
-RESID_INLINE void WaveformGenerator::clock(cycle_count delta_t) {
+RESID_INLINE void WaveformGenerator::updateClock(cycle_count delta_t) {
// No operation if test bit is set.
if (test) {
return;
@@ -165,10 +164,10 @@ RESID_INLINE void WaveformGenerator::clock(cycle_count delta_t) {
/**
* Synchronize oscillators.
- * This must be done after all the oscillators have been clock()'ed since the
+ * This must be done after all the oscillators have been updateClock()'ed since the
* oscillators operate in parallel.
* Note that the oscillators must be clocked exactly on the cycle when the
- * MSB is set high for hard sync to operate correctly. See SID::clock().
+ * MSB is set high for hard sync to operate correctly. See SID::updateClock().
*/
RESID_INLINE void WaveformGenerator::synchronize() {
// A special case occurs when a sync source is synced itself on the same
@@ -592,7 +591,7 @@ void Filter::set_Q() {
_1024_div_Q = static_cast<sound_sample>(1024.0/(0.707 + 1.0*res/0x0f));
}
-RESID_INLINE void Filter::clock(cycle_count delta_t,
+RESID_INLINE void Filter::updateClock(cycle_count delta_t,
sound_sample voice1,
sound_sample voice2,
sound_sample voice3)
@@ -888,7 +887,7 @@ reg8 EnvelopeGenerator::readENV() {
return output();
}
-RESID_INLINE void EnvelopeGenerator::clock(cycle_count delta_t) {
+RESID_INLINE void EnvelopeGenerator::updateClock(cycle_count delta_t) {
// Check for ADSR delay bug.
// If the rate counter comparison value is set below the current value of the
// rate counter, the counter will continue counting up until it wraps around
@@ -1027,7 +1026,7 @@ void ExternalFilter::reset() {
Vo = 0;
}
-RESID_INLINE void ExternalFilter::clock(cycle_count delta_t, sound_sample Vi) {
+RESID_INLINE void ExternalFilter::updateClock(cycle_count delta_t, sound_sample Vi) {
// This is handy for testing.
if (!enabled) {
// Remove maximum DC level since there is no filter to do it.
@@ -1317,7 +1316,7 @@ bool SID::set_sampling_parameters(double clock_freq,
return true;
}
-void SID::clock(cycle_count delta_t) {
+void SID::updateClock(cycle_count delta_t) {
int i;
if (delta_t <= 0) {
@@ -1333,7 +1332,7 @@ void SID::clock(cycle_count delta_t) {
// Clock amplitude modulators.
for (i = 0; i < 3; i++) {
- voice[i].envelope.clock(delta_t);
+ voice[i].envelope.updateClock(delta_t);
}
// Clock and synchronize oscillators.
@@ -1373,7 +1372,7 @@ void SID::clock(cycle_count delta_t) {
// Clock oscillators.
for (i = 0; i < 3; i++) {
- voice[i].wave.clock(delta_t_min);
+ voice[i].wave.updateClock(delta_t_min);
}
// Synchronize oscillators.
@@ -1385,11 +1384,11 @@ void SID::clock(cycle_count delta_t) {
}
// Clock filter.
- filter.clock(delta_t,
+ filter.updateClock(delta_t,
voice[0].output(), voice[1].output(), voice[2].output());
// Clock external filter.
- extfilt.clock(delta_t, filter.output());
+ extfilt.updateClock(delta_t, filter.output());
}
@@ -1397,7 +1396,7 @@ void SID::clock(cycle_count delta_t) {
* SID clocking with audio sampling.
* Fixpoint arithmetics is used.
*/
-int SID::clock(cycle_count& delta_t, short* buf, int n, int interleave) {
+int SID::updateClock(cycle_count& delta_t, short* buf, int n, int interleave) {
int s = 0;
for (;;) {
@@ -1409,13 +1408,13 @@ int SID::clock(cycle_count& delta_t, short* buf, int n, int interleave) {
if (s >= n) {
return s;
}
- clock(delta_t_sample);
+ updateClock(delta_t_sample);
delta_t -= delta_t_sample;
sample_offset = (next_sample_offset & FIXP_MASK) - (1 << (FIXP_SHIFT - 1));
buf[s++*interleave] = output();
}
- clock(delta_t);
+ updateClock(delta_t);
sample_offset -= delta_t << FIXP_SHIFT;
delta_t = 0;
return s;
diff --git a/audio/softsynth/sid.h b/audio/softsynth/sid.h
index c78f538441..d6e402dc3b 100644
--- a/audio/softsynth/sid.h
+++ b/audio/softsynth/sid.h
@@ -60,7 +60,7 @@ public:
void set_sync_source(WaveformGenerator*);
- void clock(cycle_count delta_t);
+ void updateClock(cycle_count delta_t);
void synchronize();
void reset();
@@ -133,7 +133,7 @@ public:
void enable_filter(bool enable);
- void clock(cycle_count delta_t,
+ void updateClock(cycle_count delta_t,
sound_sample voice1, sound_sample voice2, sound_sample voice3);
void reset();
@@ -201,7 +201,7 @@ public:
enum State { ATTACK, DECAY_SUSTAIN, RELEASE };
- void clock(cycle_count delta_t);
+ void updateClock(cycle_count delta_t);
void reset();
void writeCONTROL_REG(reg8);
@@ -246,7 +246,7 @@ public:
void enable_filter(bool enable);
void set_sampling_parameter(double pass_freq);
- void clock(cycle_count delta_t, sound_sample Vi);
+ void updateClock(cycle_count delta_t, sound_sample Vi);
void reset();
// Audio output (20 bits).
@@ -312,8 +312,8 @@ public:
double sample_freq, double pass_freq = -1,
double filter_scale = 0.97);
- void clock(cycle_count delta_t);
- int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1);
+ void updateClock(cycle_count delta_t);
+ int updateClock(cycle_count& delta_t, short* buf, int n, int interleave = 1);
void reset();
// Read/write registers.
diff --git a/audio/softsynth/ym2612.cpp b/audio/softsynth/ym2612.cpp
index 94fcfb97db..162c92f05a 100644
--- a/audio/softsynth/ym2612.cpp
+++ b/audio/softsynth/ym2612.cpp
@@ -27,7 +27,11 @@
#include "audio/softsynth/ym2612.h"
#include "common/util.h"
#include "audio/musicplugin.h"
+#include "common/error.h"
+#include "common/system.h"
+#include "common/textconsole.h"
#include "common/translation.h"
+#include "common/types.h"
////////////////////////////////////////
//
@@ -677,14 +681,14 @@ void MidiDriver_YM2612::createLookupTables() {
int i;
sintbl = new int [2048];
for (i = 0; i < 2048; i++)
- sintbl[i] = (int)(0xffff * sin(i/2048.0*2.0*PI));
+ sintbl[i] = (int)(0xffff * sin(i/2048.0 * 2.0 * M_PI));
}
{
int i;
powtbl = new int [1025];
for (i = 0; i <= 1024; i++)
- powtbl[i] = (int)(0x10000 * pow(2.0, (i-512)/512.0));
+ powtbl[i] = (int)(0x10000 * pow(2.0, (i - 512) / 512.0));
}
{