1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef AGI_SOUND_2GS_H 24 #define AGI_SOUND_2GS_H 25 26 #include "common/frac.h" 27 #include "audio/audiostream.h" 28 29 namespace Agi { 30 31 // Sample data in SIERRASTANDARD files is in unsigned 8-bit format. A zero 32 // occurring in the sample data causes the ES5503 wavetable sound chip in 33 // Apple IIGS to halt the corresponding oscillator immediately. We preprocess 34 // the sample data by converting it to signed values and the instruments by 35 // detecting prematurely stopping samples beforehand. 36 // 37 // Note: None of the tested SIERRASTANDARD files have zeroes in them. So in 38 // practice there is no need to check for them. However, they still do exist 39 // in the sample resources. 40 #define ZERO_OFFSET 0x80 41 42 // Apple IIGS envelope update frequency defaults to 100Hz. It can be changed, 43 // so there might be differences per game, for example. 44 #define ENVELOPE_COEF 100 / _sampleRate 45 46 // MIDI player commands 47 #define MIDI_NOTE_OFF 0x8 48 #define MIDI_NOTE_ON 0x9 49 #define MIDI_CONTROLLER 0xB 50 #define MIDI_PROGRAM_CHANGE 0xC 51 #define MIDI_PITCH_WHEEL 0xE 52 53 #define MIDI_STOP_SEQUENCE 0xFC 54 #define MIDI_TIMER_SYNC 0xF8 55 56 // Size of the SIERRASTANDARD file (i.e. the wave file i.e. the sample data used by the instruments). 57 #define SIERRASTANDARD_SIZE 65536 58 59 // Maximum number of instruments in an Apple IIGS instrument set. 60 // Chosen empirically based on Apple IIGS AGI game data, increase if needed. 61 #define MAX_INSTRUMENTS 28 62 63 // The MIDI player allocates one generator for each note it starts to play. 64 // Here the maximum number of generators is defined. Feel free to increase 65 // this if it does not seem to be enough. 66 #define MAX_GENERATORS 16 67 68 #define ENVELOPE_SEGMENT_COUNT 8 69 #define MAX_OSCILLATOR_WAVES 127 // Maximum is one for every MIDI key 70 71 struct IIgsInstrumentHeader { 72 struct { 73 frac_t bp; ///< Envelope segment breakpoint 74 frac_t inc; ///< Envelope segment velocity 75 } env[ENVELOPE_SEGMENT_COUNT]; 76 uint8 seg; ///< Envelope release segment 77 uint8 bend; ///< Maximum range for pitch bend 78 uint8 vibDepth; ///< Vibrato depth 79 uint8 vibSpeed; ///< Vibrato speed 80 uint8 waveCount[2]; ///< Wave count for both generators 81 struct { 82 uint8 key; ///< Highest MIDI key to use this wave 83 uint32 offset; ///< Offset of wave data, relative to base 84 uint32 size; ///< Wave size 85 bool halt; ///< Oscillator halted? 86 bool loop; ///< Loop mode? 87 bool swap; ///< Swap mode? 88 bool rightChannel; ///< Output channel (left / right) 89 int16 tune; ///< Fine tune in semitones (8.8 fixed point) 90 } wave[2][MAX_OSCILLATOR_WAVES]; 91 92 int8 *wavetableBase; ///< Base of wave data 93 94 /** 95 * Read an Apple IIGS instrument header from the given stream. 96 * @param stream The source stream from which to read the data. 97 * @param ignoreAddr Should we ignore wave infos' wave address variable's value? 98 * @return True if successful, false otherwise. 99 */ 100 bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false); 101 bool finalize(int8 *wavetable, uint32 wavetableSize); 102 }; 103 104 struct IIgsSampleHeader { 105 uint16 type; 106 uint8 pitch; ///< Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080) 107 uint8 unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others. 108 uint8 volume; ///< Current guess: Logarithmic in 6 dB steps 109 uint8 unknownByte_Ofs5; ///< 0 in all tested samples. 110 uint16 instrumentSize; ///< 44 in all tested samples. A guess. 111 uint16 sampleSize; ///< Accurate in all tested samples excluding Manhunter I's sound resource 16. 112 IIgsInstrumentHeader instrument; 113 114 /** 115 * Read an Apple IIGS AGI sample header from the given stream. 116 * @param stream The source stream from which to read the data. 117 * @return True if successful, false otherwise. 118 */ 119 bool read(Common::SeekableReadStream &stream); 120 bool finalize(int8 *sampleData); 121 }; 122 123 class IIgsGenerator { 124 public: IIgsGenerator()125 IIgsGenerator() : curInstrument(nullptr), key(-1), channel(-1) { 126 memset(&osc, 0, sizeof(osc)); 127 seg = 0; 128 a = 0; 129 velocity = 0; 130 } 131 132 const IIgsInstrumentHeader *curInstrument; ///< Currently used instrument 133 int key; ///< MIDI key 134 int velocity; ///< MIDI velocity (& channel volume) 135 int channel; ///< MIDI channel 136 struct { 137 int8 *base; ///< Sample base pointer 138 uint size; ///< Sample size 139 frac_t p; ///< Sample pointer 140 frac_t pd; ///< Sample pointer delta 141 bool halt; ///< Is oscillator halted? 142 bool loop; ///< Is looping enabled? 143 bool swap; ///< Is swapping enabled? 144 bool rightChannel; ///< Output channel (left / right) 145 } osc[2]; 146 int seg; ///< Current envelope segment 147 frac_t a; ///< Current envelope amplitude 148 }; 149 150 class IIgsMidi : public AgiSound { 151 public: 152 IIgsMidi(uint8 *data, uint32 len, int resnum); ~IIgsMidi()153 ~IIgsMidi() override { if (_data != NULL) free(_data); } type()154 uint16 type() override { return _type; } getPtr()155 virtual const uint8 *getPtr() { return _ptr; } setPtr(const uint8 * ptr)156 virtual void setPtr(const uint8 *ptr) { _ptr = ptr; } rewind()157 virtual void rewind() { _ptr = _data + 2; _ticks = 0; } 158 protected: 159 uint8 *_data; ///< Raw sound resource data 160 const uint8 *_ptr; ///< Pointer to the current position in the MIDI data 161 uint32 _len; ///< Length of the raw sound resource 162 uint16 _type; ///< Sound resource type 163 public: 164 uint _ticks; ///< MIDI song position in ticks (1/60ths of a second) 165 }; 166 167 class IIgsSample : public AgiSound { 168 public: 169 IIgsSample(uint8 *data, uint32 len, int16 resourceNr); ~IIgsSample()170 ~IIgsSample() override { delete[] _sample; } type()171 uint16 type() override { return _header.type; } getHeader()172 const IIgsSampleHeader &getHeader() const { return _header; } 173 protected: 174 IIgsSampleHeader _header; ///< Apple IIGS AGI sample header 175 int8 *_sample; ///< Sample data (8-bit signed format) 176 }; 177 178 /** Apple IIGS MIDI program change to instrument number mapping. */ 179 struct IIgsMidiProgramMapping { 180 byte midiProgToInst[44]; ///< Lookup table for the MIDI program number to instrument number mapping 181 byte undefinedInst; ///< The undefined instrument number 182 183 // Maps the MIDI program number to an instrument number mapIIgsMidiProgramMapping184 byte map(uint midiProg) const { 185 return midiProg < ARRAYSIZE(midiProgToInst) ? midiProgToInst[midiProg] : undefinedInst; 186 } 187 }; 188 189 /** Apple IIGS AGI instrument set information. */ 190 struct IIgsInstrumentSetInfo { 191 uint byteCount; ///< Length of the whole instrument set in bytes 192 uint instCount; ///< Amount of instrument in the set 193 const char *md5; ///< MD5 hex digest of the whole instrument set 194 const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments) 195 const IIgsMidiProgramMapping *progToInst; ///< Program change to instrument number mapping 196 }; 197 198 /** Apple IIGS AGI executable file information. */ 199 struct IIgsExeInfo { 200 enum AgiGameID gameid; ///< Game ID 201 const char *exePrefix; ///< Prefix of the Apple IIGS AGI executable (e.g. "SQ", "PQ", "KQ4" etc) 202 uint agiVer; ///< Apple IIGS AGI version number, not strictly needed 203 uint exeSize; ///< Size of the Apple IIGS AGI executable file in bytes 204 uint instSetStart; ///< Starting offset of the instrument set inside the executable file 205 const IIgsInstrumentSetInfo *instSet; ///< Information about the used instrument set 206 }; 207 208 class IIgsMidiChannel { 209 public: IIgsMidiChannel()210 IIgsMidiChannel() : _instrument(NULL), _volume(127) {} setInstrument(const IIgsInstrumentHeader * instrument)211 void setInstrument(const IIgsInstrumentHeader *instrument) { _instrument = instrument; } getInstrument()212 const IIgsInstrumentHeader *getInstrument() { return _instrument; } setVolume(int volume)213 void setVolume(int volume) { _volume = volume; } getVolume()214 int getVolume() { return _volume; } 215 private: 216 const IIgsInstrumentHeader *_instrument; ///< Instrument used on this MIDI channel 217 int _volume; ///< MIDI controller number 7 (Volume) 218 }; 219 220 class SoundGen2GS : public SoundGen, public Audio::AudioStream { 221 public: 222 SoundGen2GS(AgiBase *vm, Audio::Mixer *pMixer); 223 ~SoundGen2GS() override; 224 225 void play(int resnum) override; 226 void stop(void) override; 227 228 int readBuffer(int16 *buffer, const int numSamples) override; 229 isStereo()230 bool isStereo() const override { return true; } endOfData()231 bool endOfData() const override { return false; } getRate()232 int getRate() const override { return _sampleRate; } 233 234 private: 235 // Loader methods 236 bool loadInstruments(); 237 bool loadInstrumentHeaders(Common::String &exePath, const IIgsExeInfo &exeInfo); 238 bool loadWaveFile(Common::String &wavePath, const IIgsExeInfo &exeInfo); 239 240 const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const; 241 void setProgramChangeMapping(const IIgsMidiProgramMapping *mapping); 242 243 // Player methods 244 void advancePlayer(); ///< Advance the player 245 void advanceMidiPlayer(); ///< Advance MIDI player 246 uint generateOutput(); ///< Fill the output buffer 247 248 void haltGenerators(); ///< Halt all generators 249 uint activeGenerators(); ///< How many generators are active? 250 251 void midiNoteOff(int channel, int note, int velocity); 252 void midiNoteOn(int channel, int note, int velocity); 253 double midiKeyToFreq(int key, double finetune); getInstrument(uint8 program)254 IIgsInstrumentHeader *getInstrument(uint8 program) { return &_instruments[_progToInst->map(program)]; } allocateGenerator()255 IIgsGenerator *allocateGenerator() { IIgsGenerator *g = &_generators[_nextGen++]; _nextGen %= 16; return g; } 256 257 bool _disableMidi; ///< Disable MIDI if loading instruments fail 258 int _playingSound; ///< Resource number for the currently playing sound 259 bool _playing; ///< True when the resource is still playing 260 261 IIgsGenerator _generators[MAX_GENERATORS]; ///< IIGS sound generators that are used to play single notes 262 uint _nextGen; ///< Next generator available for allocation 263 IIgsMidiChannel _channels[16]; ///< MIDI channels 264 Common::Array<IIgsInstrumentHeader> _instruments; ///< Instrument data 265 const IIgsMidiProgramMapping *_progToInst; ///< MIDI program number to instrument mapping 266 int8 *_wavetable; ///< Sample data used by the instruments 267 uint _ticks; ///< MIDI ticks (60Hz) 268 int16 *_out; ///< Output buffer 269 uint _outSize; ///< Output buffer size 270 271 static const int kSfxMidiChannel = 15; ///< MIDI channel used for playing sample resources 272 }; 273 274 } // End of namespace Agi 275 276 #endif /* AGI_SOUND_2GS_H */ 277