mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-27 20:28:27 +00:00
aed02365ec
svn-id: r47541
226 lines
5.1 KiB
C++
226 lines
5.1 KiB
C++
/* 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$
|
|
*
|
|
*/
|
|
|
|
// see if all engines using this class are DISABLED
|
|
#if !defined(ENABLE_KYRA)
|
|
|
|
// normal Header Guard
|
|
#elif !defined SOUND_MODS_MAXTRAX_H
|
|
#define SOUND_MODS_MAXTRAX_H
|
|
|
|
// #define MAXTRAX_HAS_MODULATION
|
|
// #define MAXTRAX_HAS_MICROTONAL
|
|
|
|
#include "sound/mods/paula.h"
|
|
|
|
namespace Audio {
|
|
|
|
class MaxTrax : public Paula {
|
|
public:
|
|
MaxTrax(int rate, bool stereo, uint16 vBlankFreq = 50, uint16 maxScores = 128);
|
|
virtual ~MaxTrax();
|
|
|
|
bool load(Common::SeekableReadStream &musicData, bool loadScores = true, bool loadSamples = true);
|
|
bool playSong(int songIndex, bool loop = false);
|
|
void advanceSong(int advance = 1);
|
|
int playNote(byte note, byte patch, uint16 duration, uint16 volume, bool rightSide);
|
|
void setVolume(const byte volume) { Common::StackLock lock(_mutex); _playerCtx.volume = volume; }
|
|
void setTempo(const uint16 tempo);
|
|
void stopMusic();
|
|
/**
|
|
* Set a callback function for sync-events.
|
|
* @param callback Callback function, will be called synchronously, so DONT modify the player
|
|
* directly in response
|
|
*/
|
|
void setSignalCallback(void (*callback) (int));
|
|
|
|
protected:
|
|
void interrupt();
|
|
|
|
private:
|
|
enum { kNumPatches = 64, kNumVoices = 4, kNumChannels = 16, kNumExtraChannels = 1 };
|
|
enum { kPriorityScore, kPriorityNote, kPrioritySound };
|
|
|
|
#ifdef MAXTRAX_HAS_MICROTONAL
|
|
int16 _microtonal[128];
|
|
#endif
|
|
|
|
struct Event {
|
|
uint16 startTime;
|
|
uint16 stopTime;
|
|
byte command;
|
|
byte parameter;
|
|
};
|
|
|
|
const struct Score {
|
|
const Event *events;
|
|
uint32 numEvents;
|
|
} *_scores;
|
|
|
|
int _numScores;
|
|
|
|
struct {
|
|
uint32 sineValue;
|
|
uint16 vBlankFreq;
|
|
int32 ticks;
|
|
int32 tickUnit;
|
|
uint16 frameUnit;
|
|
|
|
uint16 maxScoreNum;
|
|
uint16 tempo;
|
|
uint16 tempoInitial;
|
|
uint16 tempoStart;
|
|
int16 tempoDelta;
|
|
int32 tempoTime;
|
|
int32 tempoTicks;
|
|
|
|
byte volume;
|
|
|
|
bool filterOn;
|
|
bool handleVolume;
|
|
bool musicLoop;
|
|
|
|
int scoreIndex;
|
|
const Event *nextEvent;
|
|
int32 nextEventTime;
|
|
|
|
void (*syncCallBack) (int);
|
|
const Event *repeatPoint[4];
|
|
byte repeatCount[4];
|
|
} _playerCtx;
|
|
|
|
struct Envelope {
|
|
uint16 duration;
|
|
uint16 volume;
|
|
};
|
|
|
|
struct Patch {
|
|
const Envelope *attackPtr;
|
|
//Envelope *releasePtr;
|
|
uint16 attackLen;
|
|
uint16 releaseLen;
|
|
|
|
int16 tune;
|
|
uint16 volume;
|
|
|
|
// this was the SampleData struct in the assembler source
|
|
const int8 *samplePtr;
|
|
uint32 sampleTotalLen;
|
|
uint32 sampleAttackLen;
|
|
uint16 sampleOctaves;
|
|
} _patch[kNumPatches];
|
|
|
|
struct ChannelContext {
|
|
const Patch *patch;
|
|
uint16 regParamNumber;
|
|
|
|
uint16 modulation;
|
|
uint16 modulationTime;
|
|
|
|
int16 microtonal;
|
|
|
|
uint16 portamentoTime;
|
|
|
|
int16 pitchBend;
|
|
int16 pitchReal;
|
|
int8 pitchBendRange;
|
|
|
|
uint8 volume;
|
|
// uint8 voicesActive;
|
|
|
|
enum {
|
|
kFlagRightChannel = 1 << 0,
|
|
kFlagPortamento = 1 << 1,
|
|
kFlagDamper = 1 << 2,
|
|
kFlagMono = 1 << 3,
|
|
kFlagMicrotonal = 1 << 4,
|
|
kFlagModVolume = 1 << 5
|
|
};
|
|
byte flags;
|
|
bool isAltered;
|
|
|
|
uint8 lastNote;
|
|
// uint8 program;
|
|
|
|
} _channelCtx[kNumChannels + kNumExtraChannels];
|
|
|
|
struct VoiceContext {
|
|
ChannelContext *channel;
|
|
const Patch *patch;
|
|
const Envelope *envelope;
|
|
// uint32 uinqueId;
|
|
int32 preCalcNote;
|
|
uint32 ticksLeft;
|
|
int32 portaTicks;
|
|
int32 incrVolume;
|
|
// int32 periodOffset;
|
|
uint16 envelopeLeft;
|
|
uint16 noteVolume;
|
|
uint16 baseVolume;
|
|
uint16 lastPeriod;
|
|
byte baseNote;
|
|
byte endNote;
|
|
byte octave;
|
|
// byte number;
|
|
// byte link;
|
|
enum {
|
|
kStatusFree,
|
|
kStatusHalt,
|
|
kStatusDecay,
|
|
kStatusRelease,
|
|
kStatusSustain,
|
|
kStatusAttack,
|
|
kStatusStart
|
|
};
|
|
uint8 isBlocked;
|
|
uint8 priority;
|
|
byte status;
|
|
byte lastVolume;
|
|
byte tieBreak;
|
|
bool hasDamper;
|
|
bool hasPortamento;
|
|
byte dmaOff;
|
|
|
|
int32 stopEventTime;
|
|
} _voiceCtx[kNumVoices];
|
|
|
|
void controlCh(ChannelContext &channel, byte command, byte data);
|
|
void freePatches();
|
|
void freeScores();
|
|
void resetChannel(ChannelContext &chan, bool rightChannel);
|
|
void resetPlayer();
|
|
|
|
int8 pickvoice(uint pick, int16 pri);
|
|
uint16 calcNote(const VoiceContext &voice);
|
|
int8 noteOn(ChannelContext &channel, byte note, uint16 volume, uint16 pri);
|
|
void killVoice(byte num);
|
|
|
|
static void outPutEvent(const Event &ev, int num = -1);
|
|
static void outPutScore(const Score &sc, int num = -1);
|
|
};
|
|
} // End of namespace Audio
|
|
|
|
#endif // !defined SOUND_MODS_MAXTRAX_H
|