ScummVM API documentation
sound_2gs.h
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 modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (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, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef AGI_SOUND_2GS_H
23 #define AGI_SOUND_2GS_H
24 
25 #include "common/frac.h"
26 #include "audio/audiostream.h"
27 
28 namespace Agi {
29 
30 // Sample data in SIERRASTANDARD files is in unsigned 8-bit format. A zero
31 // occurring in the sample data causes the ES5503 wavetable sound chip in
32 // Apple IIGS to halt the corresponding oscillator immediately. We preprocess
33 // the sample data by converting it to signed values and the instruments by
34 // detecting prematurely stopping samples beforehand.
35 //
36 // Note: None of the tested SIERRASTANDARD files have zeroes in them. So in
37 // practice there is no need to check for them. However, they still do exist
38 // in the sample resources.
39 #define ZERO_OFFSET 0x80
40 
41 // Apple IIGS envelope update frequency defaults to 100Hz. It can be changed,
42 // so there might be differences per game, for example.
43 #define ENVELOPE_COEF 100 / _sampleRate
44 
45 // MIDI player commands
46 #define MIDI_NOTE_OFF 0x8
47 #define MIDI_NOTE_ON 0x9
48 #define MIDI_CONTROLLER 0xB
49 #define MIDI_PROGRAM_CHANGE 0xC
50 #define MIDI_PITCH_WHEEL 0xE
51 
52 #define MIDI_STOP_SEQUENCE 0xFC
53 #define MIDI_TIMER_SYNC 0xF8
54 
55 // Size of the SIERRASTANDARD file (i.e. the wave file i.e. the sample data used by the instruments).
56 #define SIERRASTANDARD_SIZE 65536
57 
58 // Maximum number of instruments in an Apple IIGS instrument set.
59 // Chosen empirically based on Apple IIGS AGI game data, increase if needed.
60 #define MAX_INSTRUMENTS 28
61 
62 // The MIDI player allocates one generator for each note it starts to play.
63 // Here the maximum number of generators is defined. Feel free to increase
64 // this if it does not seem to be enough.
65 #define MAX_GENERATORS 16
66 
67 #define ENVELOPE_SEGMENT_COUNT 8
68 #define MAX_OSCILLATOR_WAVES 127 // Maximum is one for every MIDI key
69 
71  struct {
74  } env[ENVELOPE_SEGMENT_COUNT];
75  uint8 seg;
76  uint8 bend;
77  uint8 vibDepth;
78  uint8 vibSpeed;
79  uint8 waveCount[2];
80  struct {
81  uint8 key;
82  uint32 offset;
83  uint32 size;
84  bool halt;
85  bool loop;
86  bool swap;
87  bool rightChannel;
88  int16 tune;
89  } wave[2][MAX_OSCILLATOR_WAVES];
90 
91  int8 *wavetableBase;
92 
99  bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false);
100  bool finalize(int8 *wavetable, uint32 wavetableSize);
101 };
102 
104  uint16 type;
105  uint8 pitch;
106  uint8 unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others.
107  uint8 volume;
109  uint16 instrumentSize;
110  uint16 sampleSize;
111  IIgsInstrumentHeader instrument;
112 
118  bool read(Common::SeekableReadStream &stream);
119  bool finalize(int8 *sampleData);
120 };
121 
123 public:
124  IIgsGenerator() : curInstrument(nullptr), key(-1), channel(-1) {
125  memset(&osc, 0, sizeof(osc));
126  seg = 0;
127  a = 0;
128  velocity = 0;
129  }
130 
132  int key;
133  int velocity;
134  int channel;
135  struct {
136  int8 *base;
137  uint size;
140  bool halt;
141  bool loop;
142  bool swap;
144  } osc[2];
145  int seg;
147 };
148 
149 class IIgsMidi : public AgiSound {
150 public:
151  IIgsMidi(byte resourceNr, byte *data, uint32 length, uint16 type);
152  virtual const uint8 *getPtr() { return _ptr; }
153  virtual void setPtr(const uint8 *ptr) { _ptr = ptr; }
154  virtual void rewind() { _ptr = _data + 2; _ticks = 0; }
155 protected:
156  const uint8 *_ptr;
157 public:
158  uint _ticks;
159 };
160 
161 class IIgsSample : public AgiSound {
162 public:
163  IIgsSample(byte resourceNr, byte *data, uint32 length, uint16 type);
164  ~IIgsSample() override { delete[] _sample; }
165  uint16 type() override { return _header.type; }
166  const IIgsSampleHeader &getHeader() const { return _header; }
167  bool isValid() override { return _isValid; }
168 protected:
170  int8 *_sample;
171  bool _isValid;
172 };
173 
176  byte midiProgToInst[44];
178 
179  // Maps the MIDI program number to an instrument number
180  byte map(uint midiProg) const {
181  return midiProg < ARRAYSIZE(midiProgToInst) ? midiProgToInst[midiProg] : undefinedInst;
182  }
183 };
184 
187  uint byteCount;
188  uint instCount;
189  const char *md5;
190  const char *waveFileMd5;
192 };
193 
195 struct IIgsExeInfo {
196  enum AgiGameID gameid;
197  const char *exePrefix;
198  uint agiVer;
199  uint exeSize;
202 };
203 
205 public:
206  IIgsMidiChannel() : _instrument(NULL), _volume(127) {}
207  void setInstrument(const IIgsInstrumentHeader *instrument) { _instrument = instrument; }
208  const IIgsInstrumentHeader *getInstrument() { return _instrument; }
209  void setVolume(int volume) { _volume = volume; }
210  int getVolume() { return _volume; }
211 private:
212  const IIgsInstrumentHeader *_instrument;
213  int _volume;
214 };
215 
216 class SoundGen2GS : public SoundGen, public Audio::AudioStream {
217 public:
218  SoundGen2GS(AgiBase *vm, Audio::Mixer *pMixer);
219  ~SoundGen2GS() override;
220 
221  void play(int resnum) override;
222  void stop() override;
223 
224  int readBuffer(int16 *buffer, const int numSamples) override;
225 
226  bool isStereo() const override { return true; }
227  bool endOfData() const override { return false; }
228  int getRate() const override { return _sampleRate; }
229 
230 private:
231  // Loader methods
232  bool loadInstruments();
233  bool loadInstrumentHeaders(const Common::Path &exePath, const IIgsExeInfo &exeInfo);
234  bool loadWaveFile(const Common::Path &wavePath, const IIgsExeInfo &exeInfo);
235 
236  const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const;
237  void setProgramChangeMapping(const IIgsMidiProgramMapping *mapping);
238 
239  // Player methods
240  void advancePlayer();
241  void advanceMidiPlayer();
242  uint generateOutput();
243 
244  void haltGenerators();
245  uint activeGenerators();
246 
247  void midiNoteOff(int channel, int note, int velocity);
248  void midiNoteOn(int channel, int note, int velocity);
249  double midiKeyToFreq(int key, double finetune);
250  IIgsInstrumentHeader *getInstrument(uint8 program) { return &_instruments[_progToInst->map(program)]; }
251  IIgsGenerator *allocateGenerator() { IIgsGenerator *g = &_generators[_nextGen++]; _nextGen %= 16; return g; }
252 
253  bool _disableMidi;
254  int _playingSound;
255  bool _playing;
256 
257  IIgsGenerator _generators[MAX_GENERATORS];
258  uint _nextGen;
259  IIgsMidiChannel _channels[16];
261  const IIgsMidiProgramMapping *_progToInst;
262  int8 *_wavetable;
263  uint _ticks;
264  int16 *_out;
265  uint _outSize;
266 
267  static const int kSfxMidiChannel = 15;
268 };
269 
270 } // End of namespace Agi
271 
272 #endif /* AGI_SOUND_2GS_H */
#define ARRAYSIZE(x)
Definition: util.h:91
int getRate() const override
Definition: sound_2gs.h:228
uint byteCount
Length of the whole instrument set in bytes.
Definition: sound_2gs.h:187
int8 * base
Sample base pointer.
Definition: sound_2gs.h:136
Definition: agi.h:713
const char * waveFileMd5
MD5 hex digest of the wave file (i.e. the sample data used by the instruments)
Definition: sound_2gs.h:190
uint8 seg
Envelope release segment.
Definition: sound_2gs.h:75
uint size
Sample size.
Definition: sound_2gs.h:137
Definition: sound.h:57
Definition: sound_2gs.h:70
Definition: array.h:52
Definition: sound_2gs.h:149
uint8 key
Highest MIDI key to use this wave.
Definition: sound_2gs.h:81
uint8 unknownByte_Ofs5
0 in all tested samples.
Definition: sound_2gs.h:108
bool loop
Is looping enabled?
Definition: sound_2gs.h:141
Definition: path.h:52
bool loop
Loop mode?
Definition: sound_2gs.h:85
uint8 waveCount[2]
Wave count for both generators.
Definition: sound_2gs.h:79
Definition: sound_2gs.h:175
Definition: stream.h:745
bool endOfData() const override
Definition: sound_2gs.h:227
const char * md5
MD5 hex digest of the whole instrument set.
Definition: sound_2gs.h:189
uint16 instrumentSize
44 in all tested samples. A guess.
Definition: sound_2gs.h:109
int8 * wavetableBase
Base of wave data.
Definition: sound_2gs.h:91
Definition: sound_2gs.h:122
uint8 pitch
Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080)
Definition: sound_2gs.h:105
const IIgsMidiProgramMapping * progToInst
Program change to instrument number mapping.
Definition: sound_2gs.h:191
uint agiVer
Apple IIGS AGI version number, not strictly needed.
Definition: sound_2gs.h:198
int seg
Current envelope segment.
Definition: sound_2gs.h:145
uint8 vibDepth
Vibrato depth.
Definition: sound_2gs.h:77
Definition: sound_2gs.h:204
frac_t inc
Envelope segment velocity.
Definition: sound_2gs.h:73
Definition: mixer.h:59
byte undefinedInst
The undefined instrument number.
Definition: sound_2gs.h:177
uint32 size
Wave size.
Definition: sound_2gs.h:83
const IIgsInstrumentSetInfo * instSet
Information about the used instrument set.
Definition: sound_2gs.h:201
Definition: sound.h:76
uint instSetStart
Starting offset of the instrument set inside the executable file.
Definition: sound_2gs.h:200
int16 tune
Fine tune in semitones (8.8 fixed point)
Definition: sound_2gs.h:88
uint _ticks
MIDI song position in ticks (1/60ths of a second)
Definition: sound_2gs.h:158
uint32 offset
Offset of wave data, relative to base.
Definition: sound_2gs.h:82
const char * exePrefix
Prefix of the Apple IIGS AGI executable (e.g. "SQ", "PQ", "KQ4" etc)
Definition: sound_2gs.h:197
uint8 vibSpeed
Vibrato speed.
Definition: sound_2gs.h:78
bool swap
Swap mode?
Definition: sound_2gs.h:86
bool halt
Is oscillator halted?
Definition: sound_2gs.h:140
Definition: audiostream.h:50
int key
MIDI key.
Definition: sound_2gs.h:132
uint exeSize
Size of the Apple IIGS AGI executable file in bytes.
Definition: sound_2gs.h:199
uint8 bend
Maximum range for pitch bend.
Definition: sound_2gs.h:76
Definition: sound_2gs.h:186
frac_t bp
Envelope segment breakpoint.
Definition: sound_2gs.h:72
int channel
MIDI channel.
Definition: sound_2gs.h:134
bool read(Common::SeekableReadStream &stream, bool ignoreAddr=false)
bool isStereo() const override
Definition: sound_2gs.h:226
bool rightChannel
Output channel (left / right)
Definition: sound_2gs.h:87
uint16 sampleSize
Accurate in all tested samples excluding Manhunter I&#39;s sound resource 16.
Definition: sound_2gs.h:110
Definition: sound_2gs.h:216
int8 * _sample
Sample data (8-bit signed format)
Definition: sound_2gs.h:170
const uint8 * _ptr
Pointer to the current position in the MIDI data.
Definition: sound_2gs.h:156
bool rightChannel
Output channel (left / right)
Definition: sound_2gs.h:143
int velocity
MIDI velocity (& channel volume)
Definition: sound_2gs.h:133
IIgsSampleHeader _header
Apple IIGS AGI sample header.
Definition: sound_2gs.h:169
uint instCount
Amount of instrument in the set.
Definition: sound_2gs.h:188
Definition: sound_2gs.h:103
bool swap
Is swapping enabled?
Definition: sound_2gs.h:142
bool halt
Oscillator halted?
Definition: sound_2gs.h:84
Definition: sound_2gs.h:195
int32 frac_t
Definition: frac.h:52
frac_t pd
Sample pointer delta.
Definition: sound_2gs.h:139
Definition: sound_2gs.h:161
const IIgsInstrumentHeader * curInstrument
Currently used instrument.
Definition: sound_2gs.h:131
Definition: agi.h:63
frac_t a
Current envelope amplitude.
Definition: sound_2gs.h:146
frac_t p
Sample pointer.
Definition: sound_2gs.h:138
uint8 volume
Current guess: Logarithmic in 6 dB steps.
Definition: sound_2gs.h:107