Ticket #8620: kyra_fmt_music.patch
File kyra_fmt_music.patch, 46.1 KB (added by , 17 years ago) |
---|
-
engines/kyra/gui.cpp
38 38 // Most settings already have sensible defaults. This one, however, is 39 39 // specific to the Kyra engine. 40 40 ConfMan.registerDefault("walkspeed", 2); 41 ConfMan.registerDefault("cdaudio", _flags.platform == Common::kPlatformFMTowns); 41 42 } 42 43 43 44 void KyraEngine::readSettings() { … … 55 56 _configTextspeed = 2; // Fast 56 57 57 58 _configWalkspeed = ConfMan.getInt("walkspeed"); 58 _configMusic = ConfMan.getBool("music_mute") ? 0 : 1;59 _configMusic = ConfMan.getBool("music_mute") ? 0 : (ConfMan.getBool("cdaudio") ? 2 : 1); 59 60 _configSounds = ConfMan.getBool("sfx_mute") ? 0 : 1; 60 61 61 62 _sound->enableMusic(_configMusic); … … 96 97 ConfMan.setInt("talkspeed", talkspeed); 97 98 ConfMan.setInt("walkspeed", _configWalkspeed); 98 99 ConfMan.setBool("music_mute", _configMusic == 0); 100 ConfMan.setBool("cdaudio", _configMusic & 2); 99 101 ConfMan.setBool("sfx_mute", _configSounds == 0); 100 102 101 103 switch (_configVoice) { … … 563 565 _textSpeedString = _guiStrings[25 + offsetOptions]; 564 566 _onString = _guiStrings[20 + offsetOn]; 565 567 _offString = _guiStrings[21 + offset]; 568 _onCDString = _guiStrings[21]; 566 569 } 567 570 568 571 int KyraEngine::buttonMenuCallback(Button *caller) { … … 1214 1217 void KyraEngine::gui_setupControls(Menu &menu) { 1215 1218 debugC(9, kDebugLevelGUI, "KyraEngine::gui_setupControls()"); 1216 1219 1217 if (_configMusic) 1218 menu.item[0].itemString = _onString; //"On" 1219 else 1220 menu.item[0].itemString = _offString; //"Off" 1220 switch (_configMusic) { 1221 case 0: 1222 menu.item[0].itemString = _offString; //"Off" 1223 break; 1224 case 1: 1225 menu.item[0].itemString = _onString; //"On" 1226 break; 1227 case 2: 1228 menu.item[0].itemString = _onCDString; //"On + CD" 1229 break; 1230 } 1221 1231 1222 1232 if (_configSounds) 1223 1233 menu.item[1].itemString = _onString; //"On" … … 1299 1309 debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeMusic()"); 1300 1310 processMenuButton(button); 1301 1311 1302 _configMusic = !_configMusic;1312 _configMusic = ++_configMusic % (_flags.platform == Common::kPlatformFMTowns ? 3 : 2); 1303 1313 gui_setupControls(_menu[5]); 1304 1314 return 0; 1305 1315 } -
engines/kyra/sound.cpp
37 37 38 38 Sound::Sound(KyraEngine *engine, Audio::Mixer *mixer) 39 39 : _engine(engine), _mixer(mixer), _currentVocFile(0), _vocHandle(), _compressHandle(), 40 _musicEnabled( true), _sfxEnabled(true), _soundFileList(0), _soundFileListSize(0) {40 _musicEnabled(1), _sfxEnabled(true), _soundFileList(0), _soundFileListSize(0) { 41 41 } 42 42 43 43 Sound::~Sound() { … … 450 450 451 451 void KyraEngine::snd_playSoundEffect(int track) { 452 452 debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playSoundEffect(%d)", track); 453 if (_flags.platform == Common::kPlatformFMTowns) { 454 if (track == 49) { 455 snd_playWanderScoreViaMap(56, 1); 456 return; 457 } else if (track == 0 || track == 1 || track == 10) { 458 // I don't know what's supposed to happen here, but calling playSoundEffect will lead to crash 459 return; 460 } 453 if (_flags.platform == Common::kPlatformFMTowns && track == 49) { 454 snd_playWanderScoreViaMap(56, 1); 455 return; 461 456 } 462 457 _sound->playSoundEffect(track); 463 458 } -
engines/kyra/sound.h
41 41 * 42 42 */ 43 43 44 #ifndef KYRA_SOUND_H45 #define KYRA_SOUND_H44 #ifndef SOUND_H 45 #define SOUND_H 46 46 47 47 #include "common/stdafx.h" 48 48 #include "common/scummsys.h" 49 49 #include "common/file.h" 50 50 #include "common/mutex.h" 51 51 52 #include "sound/mididrv.h"53 52 #include "sound/midiparser.h" 54 53 #include "sound/mixer.h" 54 #include "sound/softsynth/emumidi.h" 55 #include "sound/softsynth/ym2612.h" 55 56 56 57 #include "kyra/kyra.h" 57 58 … … 84 85 85 86 virtual void beginFadeOut() = 0; 86 87 87 void enableMusic( boolenable) { _musicEnabled = enable; }88 boolmusicEnabled() const { return _musicEnabled; }88 void enableMusic(int enable) { _musicEnabled = enable; } 89 int musicEnabled() const { return _musicEnabled; } 89 90 void enableSFX(bool enable) { _sfxEnabled = enable; } 90 91 bool sfxEnabled() const { return _sfxEnabled; } 91 92 … … 93 94 void voiceUnload() {} 94 95 bool voiceIsPlaying(); 95 96 void voiceStop(); 96 97 97 98 protected: 98 99 const char *soundFilename(uint file) { return (file < _soundFileListSize) ? _soundFileList[file] : ""; } 99 bool_musicEnabled;100 int _musicEnabled; 100 101 bool _sfxEnabled; 101 102 102 103 KyraEngine *_engine; … … 129 130 130 131 void setVolume(int volume); 131 132 int getVolume(); 132 133 133 134 void loadSoundFile(uint file); 134 135 135 136 void playTrack(uint8 track); 136 137 void haltTrack(); 137 138 138 139 void playSoundEffect(uint8 track); 139 140 140 141 void beginFadeOut(); 141 142 private: 142 143 void play(uint8 track); … … 231 232 Common::Mutex _mutex; 232 233 }; 233 234 234 class SoundTowns : public Sound { 235 class FMT_EuphonyDriver; 236 class SoundTowns : public MidiDriver, public Sound { 235 237 public: 236 238 SoundTowns(KyraEngine *engine, Audio::Mixer *mixer); 237 239 ~SoundTowns(); … … 249 251 250 252 void playSoundEffect(uint8); 251 253 252 void beginFadeOut() { /* TODO */ } 254 void beginFadeOut(); 255 256 //MidiDriver interface implementation 257 int open(); 258 void close(); 259 void send(uint32 b); 260 void metaEvent(byte type, byte *data, uint16 length) {} 261 262 void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { } 263 uint32 getBaseTempo(void); 264 265 //Channel allocation functions 266 MidiChannel *allocateChannel() { return 0; } 267 MidiChannel *getPercussionChannel() { return 0; } 268 269 static float semitoneAndSampleRate_to_sampleStep(int8 semiTone, int8 semiToneRootkey, 270 uint32 sampleRate, uint32 outputRate, int32 pitchWheel); 253 271 private: 254 void stopSoundEffect();255 void setPitch(uint8 *&data, uint32 &size, int8 sourcePitch, int8 targetPitch);272 bool loadInstruments(); 273 void playEuphonyTrack(uint32 offset, int loop); 256 274 275 static void onTimer(void *data); 276 257 277 int _lastTrack; 258 278 Audio::AudioStream *_currentSFX; 259 279 Audio::SoundHandle _sfxHandle; 260 int _currentTrackTable; 261 bool _sfxIsPlaying;280 281 int _currentTrackTable; 262 282 uint _sfxFileIndex; 263 283 uint8 *_sfxFileData; 264 284 285 FMT_EuphonyDriver * _driver; 286 MidiParser * _parser; 287 uint8 *_musicTrackData; 288 289 Common::Mutex _mutex; 290 265 291 static const char *_sfxFiles[]; 266 292 static const int _sfxFilenum; 267 293 static const uint8 _sfxBTTable[256]; 268 const uint8 *_sfxWDTable; 294 const uint8 *_sfxWDTable; 269 295 }; 270 296 271 297 class MixedSoundDriver : public Sound { … … 300 326 ~SoundDigital(); 301 327 302 328 bool init(); 303 329 304 330 int playSound(Common::File *fileHandle, bool loop = false, bool fadeIn = false, int channel = -1); 305 331 bool isPlaying(int channel); 306 332 void stopSound(int channel); -
engines/kyra/sound_towns.cpp
29 29 #include "sound/audiocd.h" 30 30 #include "sound/audiostream.h" 31 31 32 #include "common/util.h" 33 #include <math.h> 34 32 35 namespace Kyra { 33 36 37 enum EuD_ChannelState { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing }; 38 39 class MidiChannel_EuD : public MidiChannel { 40 public: 41 MidiChannel_EuD() {} 42 ~MidiChannel_EuD() {} 43 44 virtual void nextTick(int32 *outbuf, int buflen) = 0; 45 virtual void rate(uint16 r) = 0; 46 47 protected: 48 uint16 _rate; 49 }; 50 51 class MidiChannel_EuD_FM : public MidiChannel_EuD { 52 public: 53 MidiChannel_EuD_FM(); 54 virtual ~MidiChannel_EuD_FM(); 55 56 void nextTick(int32 *outbuf, int buflen); 57 void rate(uint16 r); 58 59 // MidiChannel interface 60 MidiDriver *device() { return 0; } 61 byte getNumber() { return 0; } 62 void release() { } 63 void send(uint32 b) { } 64 void noteOff(byte note); 65 void noteOn(byte note, byte onVelo); 66 void programChange(byte program) {} 67 void pitchBend(int16 value); 68 void controlChange(byte control, byte value); 69 void pitchBendFactor(byte value) { } 70 void sysEx_customInstrument(uint32 unused, const byte *instr); 71 72 protected: 73 Voice2612 *_voice; 74 }; 75 76 class MidiChannel_EuD_WAVE : public MidiChannel_EuD { 77 public: 78 void nextTick(int32 *outbuf, int buflen); 79 void rate(uint16 r); 80 81 MidiChannel_EuD_WAVE(); 82 virtual ~MidiChannel_EuD_WAVE(); 83 84 // MidiChannel interface 85 MidiDriver *device() { return 0; } 86 byte getNumber() { return 0; } 87 void release() { } 88 void send(uint32 b) { } 89 void noteOff(byte note); 90 void noteOn(byte note, byte onVelo); 91 void programChange(byte program) {} 92 void pitchBend(int16 value); 93 void controlChange(byte control, byte value); 94 void pitchBendFactor(byte value) { } 95 void sysEx_customInstrument(uint32 type, const byte *instr); 96 97 protected: 98 void velocity(int velo); 99 void panPosition(int8 pan); 100 void evpNextTick(); 101 102 int _ctrl7_volume; 103 int16 _velocity; 104 int16 _note; 105 int32 _frequencyOffs; 106 float _phase; 107 int8 _current; 108 109 struct Voice { 110 char name[9]; 111 uint16 split[8]; 112 uint32 id[8]; 113 struct Snd { 114 char name[9]; 115 int32 id; 116 int32 numSamples; 117 int32 loopStart; 118 int32 loopLength; 119 int32 samplingRate; 120 int32 keyOffset; 121 int32 keyNote; 122 int8 *_samples; 123 } * _snd[8]; 124 struct Env { 125 EuD_ChannelState state; 126 int32 currentLevel; 127 int32 rate; 128 int32 tickCount; 129 int32 totalLevel; 130 int32 attackRate; 131 int32 decayRate; 132 int32 sustainLevel; 133 int32 sustainRate; 134 int32 releaseLevel; 135 int32 releaseRate; 136 int32 rootKeyOffset; 137 int32 size; 138 } * _env[8]; 139 } * _voice; 140 }; 141 142 class MidiParser_EuD : public MidiParser { 143 public: 144 MidiParser_EuD::MidiParser_EuD(); 145 MidiParser_EuD::~MidiParser_EuD() {} 146 147 bool loadMusic (byte *data, uint32 unused = 0); 148 void setTempo(uint32 tempo); 149 150 protected: 151 void parseNextEvent (EventInfo &info); 152 void resetTracking(); 153 154 byte * _enable; 155 byte * _mode; 156 byte * _channel; 157 byte * _adjVelo; 158 int8 * _adjNote; 159 160 uint8 _firstBaseTickStep; 161 uint8 _nextBaseTickStep; 162 uint8 _initialTempo; 163 uint32 _baseTick; 164 }; 165 166 class FMT_EuphonyDriver : public MidiDriver_Emulated { 167 public: 168 FMT_EuphonyDriver(Audio::Mixer *mixer); 169 virtual ~FMT_EuphonyDriver(); 170 171 int open(); 172 void close(); 173 void send(uint32 b); 174 void send(byte channel, uint32 b); 175 uint32 property(int prop, uint32 param) { return 0; } 176 177 void setPitchBendRange(byte channel, uint range) { } 178 //void sysEx(const byte *msg, uint16 length); 179 void loadFmInstruments(const byte *instr); 180 void loadWaveInstruments(const byte *instr); 181 182 MidiChannel *allocateChannel() { return 0; } 183 MidiChannel *getPercussionChannel() { return 0; } 184 185 void assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber); 186 void assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber); 187 void removeChannel(uint8 midiChannelNumber); 188 189 // AudioStream API 190 bool isStereo() const { return true; } 191 int getRate() const { return _mixer->getOutputRate(); } 192 193 protected: 194 void nextTick(int16 *buf1, int buflen); 195 int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; } 196 void rate(uint16 r); 197 198 void generateSamples(int16 *buf, int len); 199 200 MidiChannel_EuD_FM *_fChannel[6]; 201 MidiChannel_EuD_WAVE *_wChannel[8]; 202 MidiChannel_EuD * _channel[16]; 203 204 int _volume; 205 206 uint8 *_fmInstruments; 207 uint8 *_waveInstruments; 208 int8 * _waveSounds[10]; 209 }; 210 211 MidiChannel_EuD_FM::MidiChannel_EuD_FM() { 212 _voice = new Voice2612; 213 } 214 215 MidiChannel_EuD_FM::~MidiChannel_EuD_FM() { 216 delete _voice; 217 } 218 219 void MidiChannel_EuD_FM::noteOn(byte note, byte onVelo) { 220 _voice->noteOn(note, onVelo); 221 } 222 223 void MidiChannel_EuD_FM::noteOff(byte note) { 224 _voice->noteOff(note); 225 } 226 227 void MidiChannel_EuD_FM::controlChange(byte control, byte value) { 228 if (control == 121) { 229 // Reset controller 230 delete _voice; 231 _voice = new Voice2612; 232 } else if (control == 10) { 233 // pan position 234 } else { 235 _voice->setControlParameter(control, value); 236 } 237 } 238 239 void MidiChannel_EuD_FM::sysEx_customInstrument(uint32, const byte *fmInst) { 240 _voice->_rate = _rate; 241 _voice->setInstrument(fmInst); 242 } 243 244 void MidiChannel_EuD_FM::pitchBend(int16 value) { 245 _voice->pitchBend(value); 246 } 247 248 void MidiChannel_EuD_FM::nextTick(int32 *outbuf, int buflen) { 249 _voice->nextTick((int*) outbuf, buflen); 250 } 251 252 void MidiChannel_EuD_FM::rate(uint16 r) { 253 _rate = r; 254 _voice->_rate = r; 255 } 256 257 MidiChannel_EuD_WAVE::MidiChannel_EuD_WAVE() { 258 _voice = new Voice; 259 for (uint8 i = 0; i < 8; i++) { 260 _voice->_env[i] = new Voice::Env; 261 _voice->_snd[i] = 0; 262 } 263 264 int _buflen = 0; 265 _ctrl7_volume = 127; 266 velocity(0); 267 _frequencyOffs = 0x2000; 268 _current = -1; 269 } 270 271 MidiChannel_EuD_WAVE::~MidiChannel_EuD_WAVE() { 272 for (uint8 i = 0; i < 8; i++) { 273 if (_voice->_snd[i]) 274 delete _voice->_snd[i]; 275 delete _voice->_env[i]; 276 } 277 delete _voice; 278 } 279 280 void MidiChannel_EuD_WAVE::noteOn(byte note, byte onVelo) { 281 _note = note; 282 velocity(onVelo); 283 _phase = 0; 284 285 for (_current = 0; _current < 7; _current++) { 286 if (note <= _voice->split[_current]) 287 break; 288 } 289 290 _voice->_env[_current]->state = _s_attacking; 291 _voice->_env[_current]->currentLevel = 0; 292 _voice->_env[_current]->rate = _rate; 293 _voice->_env[_current]->tickCount = 0; 294 } 295 296 void MidiChannel_EuD_WAVE::noteOff(byte note) { 297 if (_current == -1) 298 return; 299 if (_voice->_env[_current]->state == _s_ready) 300 return; 301 302 _voice->_env[_current]->state = _s_releasing; 303 _voice->_env[_current]->releaseLevel = _voice->_env[_current]->currentLevel; 304 _voice->_env[_current]->tickCount = 0; 305 } 306 307 void MidiChannel_EuD_WAVE::controlChange(byte control, byte value) { 308 switch (control) { 309 case 0x07: 310 // volume 311 _ctrl7_volume = value; 312 break; 313 case 0x0A: 314 // pan position 315 break; 316 case 0x79: 317 // Reset controller 318 for (uint8 i = 0; i < 8; i++) { 319 if (_voice->_snd[i]) 320 delete _voice->_snd[i]; 321 delete _voice->_env[i]; 322 } 323 delete _voice; 324 _voice = new Voice; 325 for (uint8 i = 0; i < 8; i++) { 326 _voice->_env[i] = new Voice::Env; 327 _voice->_snd[i] = 0; 328 } 329 break; 330 case 0x7B: 331 noteOff(_note); 332 break; 333 default: 334 break; 335 } 336 } 337 338 void MidiChannel_EuD_WAVE::sysEx_customInstrument(uint32 type, const byte *fmInst) { 339 if (type == 0x80) { 340 for (uint8 i = 0; i < 8; i++) { 341 byte ** pos = (byte **) fmInst; 342 for (uint8 ii = 0; ii < 10; ii++) { 343 if (_voice->id[i] == *(pos[ii] + 8)) { 344 if (!_voice->_snd[i]) 345 _voice->_snd[i] = new Voice::Snd; 346 memset (_voice->_snd[i]->name, 0, 9); 347 memcpy (_voice->_snd[i]->name, (const char*) pos[ii], 8); 348 _voice->_snd[i]->id = READ_LE_UINT32(pos[ii] + 8); 349 _voice->_snd[i]->numSamples = READ_LE_UINT32(pos[ii] + 12); 350 _voice->_snd[i]->loopStart = READ_LE_UINT32(pos[ii] + 16); 351 _voice->_snd[i]->loopLength = READ_LE_UINT32(pos[ii] + 20); 352 _voice->_snd[i]->samplingRate = READ_LE_UINT16(pos[ii] + 24); 353 _voice->_snd[i]->keyOffset = READ_LE_UINT16(pos[ii] + 26); 354 _voice->_snd[i]->keyNote = *(uint8*)(pos[ii] + 28); 355 _voice->_snd[i]->_samples = (int8*) (pos[ii] + 32); 356 } 357 } 358 } 359 } else { 360 memset (_voice->name, 0, 9); 361 memcpy (_voice->name, (const char*) fmInst, 8); 362 363 for (uint8 i = 0; i < 8; i++) { 364 _voice->split[i] = READ_LE_UINT16(fmInst + 16 + 2 * i); 365 _voice->id[i] = READ_LE_UINT32(fmInst + 32 + 4 * i); 366 _voice->_snd[i] = 0; 367 _voice->_env[i]->state = _s_ready; 368 _voice->_env[i]->currentLevel = 0; 369 _voice->_env[i]->totalLevel = *(uint8*)(fmInst + 64 + 8 * i); 370 _voice->_env[i]->attackRate = *(uint8*)(fmInst + 65 + 8 * i) * 10; 371 _voice->_env[i]->decayRate = *(uint8*)(fmInst + 66 + 8 * i) * 10; 372 _voice->_env[i]->sustainLevel = *(uint8*)(fmInst + 67 + 8 * i); 373 _voice->_env[i]->sustainRate = *(uint8*)(fmInst + 68 + 8 * i) * 20; 374 _voice->_env[i]->releaseRate = *(uint8*)(fmInst + 69 + 8 * i) * 10; 375 _voice->_env[i]->rootKeyOffset = *(int8*)(fmInst + 70 + 8 * i); 376 } 377 } 378 } 379 380 void MidiChannel_EuD_WAVE::pitchBend(int16 value) { 381 _frequencyOffs = value; 382 } 383 384 void MidiChannel_EuD_WAVE::nextTick(int32 *outbuf, int buflen) { 385 if (_current == -1 || !_voice->_snd[_current] || !_voice->_env[_current]->state || !_velocity) { 386 velocity(0); 387 _current = -1; 388 return; 389 } 390 391 float phaseStep = SoundTowns::semitoneAndSampleRate_to_sampleStep(_note, _voice->_snd[_current]->keyNote - 392 _voice->_env[_current]->rootKeyOffset, _voice->_snd[_current]->samplingRate, _rate, _frequencyOffs); 393 394 int32 looplength = _voice->_snd[_current]->loopLength; 395 int32 numsamples = _voice->_snd[_current]->numSamples; 396 int8 * samples = _voice->_snd[_current]->_samples; 397 398 for (int i = 0; i < buflen; i++) { 399 if (looplength > 0) { 400 while (_phase >= numsamples) 401 _phase -= looplength; 402 } else { 403 if (_phase >= numsamples) { 404 velocity(0); 405 _current = -1; 406 break; 407 } 408 } 409 410 int32 output; 411 412 int32 phase0 = _phase; 413 int32 phase1 = _phase + 1; 414 if (phase1 >= numsamples) 415 phase1 -= looplength; 416 float weight0 = _phase - phase0; 417 float weight1 = phase1 - _phase; 418 output = samples[phase0] * weight0 + samples[phase1] * weight1; 419 420 output *= _velocity; 421 output <<= 1; 422 423 evpNextTick(); 424 output *= _voice->_env[_current]->currentLevel; 425 output >>= 7; 426 output *= _ctrl7_volume; 427 output >>= 7; 428 429 output *= 185; 430 output >>= 8; 431 outbuf[i] += output; 432 _phase += phaseStep; 433 } 434 } 435 436 void MidiChannel_EuD_WAVE::evpNextTick() { 437 switch (_voice->_env[_current]->state) { 438 case _s_ready: 439 _voice->_env[_current]->currentLevel = 0; 440 return; 441 442 case _s_attacking: 443 if (_voice->_env[_current]->attackRate == 0) 444 _voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel; 445 else if (_voice->_env[_current]->attackRate >= 1270) 446 _voice->_env[_current]->currentLevel = 0; 447 else 448 _voice->_env[_current]->currentLevel = (_voice->_env[_current]->totalLevel * 449 _voice->_env[_current]->tickCount++ * 1000) / 450 (_voice->_env[_current]->attackRate * _voice->_env[_current]->rate); 451 452 if (_voice->_env[_current]->currentLevel >= _voice->_env[_current]->totalLevel) { 453 _voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel; 454 _voice->_env[_current]->state = _s_decaying; 455 _voice->_env[_current]->tickCount = 0; 456 } 457 break; 458 459 case _s_decaying: 460 if (_voice->_env[_current]->decayRate == 0) 461 _voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel; 462 else if (_voice->_env[_current]->decayRate >= 1270) 463 _voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel; 464 else { 465 _voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel; 466 _voice->_env[_current]->currentLevel -= ((_voice->_env[_current]->totalLevel - 467 _voice->_env[_current]->sustainLevel) * _voice->_env[_current]->tickCount++ * 1000) / 468 (_voice->_env[_current]->decayRate * _voice->_env[_current]->rate); 469 } 470 471 if (_voice->_env[_current]->currentLevel <= _voice->_env[_current]->sustainLevel) { 472 _voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel; 473 _voice->_env[_current]->state = _s_sustaining; 474 _voice->_env[_current]->tickCount = 0; 475 } 476 break; 477 478 case _s_sustaining: 479 if (_voice->_env[_current]->sustainRate == 0) 480 _voice->_env[_current]->currentLevel = 0; 481 else if (_voice->_env[_current]->sustainRate >= 2540) 482 _voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel; 483 else { 484 _voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel; 485 _voice->_env[_current]->currentLevel -= (_voice->_env[_current]->sustainLevel * 486 _voice->_env[_current]->tickCount++ * 1000) / (_voice->_env[_current]->sustainRate * 487 _voice->_env[_current]->rate); 488 } 489 490 if (_voice->_env[_current]->currentLevel <= 0) { 491 _voice->_env[_current]->currentLevel = 0; 492 _voice->_env[_current]->state = _s_ready; 493 _voice->_env[_current]->tickCount = 0; 494 } 495 break; 496 497 case _s_releasing: 498 if (_voice->_env[_current]->releaseRate == 0) 499 _voice->_env[_current]->currentLevel = 0; 500 else if (_voice->_env[_current]->releaseRate >= 1270) 501 _voice->_env[_current]->currentLevel = _voice->_env[_current]->releaseLevel; 502 else { 503 _voice->_env[_current]->currentLevel = _voice->_env[_current]->releaseLevel; 504 _voice->_env[_current]->currentLevel -= (_voice->_env[_current]->releaseLevel * 505 _voice->_env[_current]->tickCount++ * 1000) / (_voice->_env[_current]->releaseRate * 506 _voice->_env[_current]->rate); 507 } 508 509 if (_voice->_env[_current]->currentLevel <= 0) { 510 _voice->_env[_current]->currentLevel = 0; 511 _voice->_env[_current]->state = _s_ready; 512 } 513 break; 514 515 default: 516 break; 517 } 518 } 519 520 void MidiChannel_EuD_WAVE::rate(uint16 r) { 521 _rate = r; 522 } 523 524 void MidiChannel_EuD_WAVE::velocity(int velo) { 525 _velocity = velo; 526 } 527 528 FMT_EuphonyDriver::FMT_EuphonyDriver(Audio::Mixer *mixer) 529 : MidiDriver_Emulated(mixer) { 530 531 MidiDriver_YM2612::createLookupTables(); 532 533 _volume = 255; 534 for (uint8 i = 0; i < 6; i++) 535 _channel[i] = _fChannel[i] = new MidiChannel_EuD_FM; 536 for (uint8 i = 0; i < 8; i++) 537 _channel[i + 6] = _wChannel[i] = new MidiChannel_EuD_WAVE; 538 _channel[14] = _channel[15] = 0; 539 540 _fmInstruments = _waveInstruments = 0; 541 memset(_waveSounds, 0, sizeof(uint8*) * 10); 542 543 rate(getRate()); 544 } 545 546 FMT_EuphonyDriver::~FMT_EuphonyDriver() { 547 uint8 i; 548 for (i = 0; i < 6; i++) 549 delete _fChannel[i]; 550 for (i = 0; i < 8; i++) 551 delete _wChannel[i]; 552 553 MidiDriver_YM2612::removeLookupTables(); 554 555 if (_fmInstruments) { 556 delete [] _fmInstruments; 557 _fmInstruments = 0; 558 } 559 if (_waveInstruments) { 560 delete [] _waveInstruments; 561 _waveInstruments = 0; 562 } 563 for (int i = 0; i < 10; i++) { 564 if (_waveSounds[i]) { 565 delete [] _waveSounds[i]; 566 _waveSounds[i] = 0; 567 } 568 } 569 } 570 571 int FMT_EuphonyDriver::open() { 572 if (_isOpen) 573 return MERR_ALREADY_OPEN; 574 575 MidiDriver_Emulated::open(); 576 577 _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, 578 this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); 579 return 0; 580 } 581 582 void FMT_EuphonyDriver::close() { 583 if (!_isOpen) 584 return; 585 _isOpen = false; 586 _mixer->stopHandle(_mixerSoundHandle); 587 } 588 589 void FMT_EuphonyDriver::send(uint32 b) { 590 send(b & 0xF, b & 0xFFFFFFF0); 591 } 592 593 void FMT_EuphonyDriver::send(byte chan, uint32 b) { 594 //byte param3 = (byte) ((b >> 24) & 0xFF); 595 596 byte param2 = (byte) ((b >> 16) & 0xFF); 597 byte param1 = (byte) ((b >> 8) & 0xFF); 598 byte cmd = (byte) (b & 0xF0); 599 if (chan > ARRAYSIZE(_channel)) 600 return; 601 602 switch (cmd) { 603 case 0x80:// Note Off 604 if (_channel[chan]) 605 _channel[chan]->noteOff(param1); 606 break; 607 case 0x90: // Note On 608 if (_channel[chan]) 609 _channel[chan]->noteOn(param1, param2); 610 break; 611 case 0xA0: // Aftertouch 612 break; // Not supported. 613 case 0xB0: // Control Change 614 if (param1 == 0x79) { 615 for (int i = 0; i < 15; i++) { 616 if (_channel[i]) { 617 _channel[i]->controlChange(param1, param2); 618 _channel[i]->programChange(0); 619 } 620 } 621 } else if (param1 == 0x7B) { 622 for (int i = 0; i < 15; i++) { 623 if (_channel[i]) 624 _channel[i]->controlChange(param1, param2); 625 } 626 } else { 627 if (_channel[chan]) 628 _channel[chan]->controlChange(param1, param2); 629 } 630 break; 631 case 0xC0: // Program Change 632 for (int i = 0; i < 6; i++) { 633 if (_channel[chan] == _fChannel[i]) { 634 _channel[chan]->sysEx_customInstrument(0, _fmInstruments + param1 * 0x30); 635 break; 636 } 637 } 638 for (int i = 0; i < 8; i++) { 639 if (_channel[chan] == _wChannel[i]) { 640 _channel[chan]->sysEx_customInstrument(0, _waveInstruments + param1 * 0x80); 641 _channel[chan]->sysEx_customInstrument(0x80, (const byte*) _waveSounds); 642 break; 643 } 644 } 645 break; 646 case 0xD0: // Channel Pressure 647 break; // Not supported. 648 case 0xE0: // Pitch Bend 649 if (_channel[chan]) 650 _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000); 651 break; 652 default: 653 warning("FMT_EuphonyDriver: Unknown send() command 0x%02X", cmd); 654 } 655 } 656 657 void FMT_EuphonyDriver::loadFmInstruments(const byte *instr) { 658 if (_fmInstruments) 659 delete [] _fmInstruments; 660 _fmInstruments = new uint8[0x1800]; 661 memcpy(_fmInstruments, instr, 0x1800); 662 } 663 664 void FMT_EuphonyDriver::loadWaveInstruments(const byte *instr) { 665 if (_waveInstruments) 666 delete [] _waveInstruments; 667 _waveInstruments = new uint8[0x1000]; 668 memcpy(_waveInstruments, instr, 0x1000); 669 670 uint8 * pos = (uint8 *)(instr + 0x1000); 671 672 for (uint8 i = 0; i < 10; i++) { 673 if (_waveSounds[i]) 674 delete [] _waveSounds[i]; 675 uint32 numsamples = READ_LE_UINT32(pos + 0x0C); 676 _waveSounds[i] = new int8[numsamples + 0x20]; 677 memcpy(_waveSounds[i], pos, 0x20); 678 pos += 0x20; 679 for (uint32 ii = 0; ii < numsamples; ii++) { 680 uint8 s = *(uint8*)(pos + ii); 681 s = (s < 0x80) ? 0x80 - s : s; 682 _waveSounds[i][ii + 0x20] = s ^ 0x80; 683 } 684 pos += numsamples; 685 } 686 } 687 688 689 void FMT_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) { 690 _channel[midiChannelNumber] = _fChannel[fmChannelNumber]; 691 } 692 693 void FMT_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) { 694 _channel[midiChannelNumber] = _wChannel[waveChannelNumber]; 695 } 696 697 void FMT_EuphonyDriver::removeChannel(uint8 midiChannelNumber) { 698 _channel[midiChannelNumber] = 0; 699 } 700 701 void FMT_EuphonyDriver::generateSamples(int16 *data, int len) { 702 memset(data, 0, 2 * sizeof(int16) * len); 703 nextTick(data, len); 704 } 705 706 void FMT_EuphonyDriver::nextTick(int16 *buf1, int buflen) { 707 int32 *buf0 = (int32 *)buf1; 708 709 for (int i = 0; i < ARRAYSIZE(_channel); i++) { 710 if (_channel[i]) 711 _channel[i]->nextTick(buf0, buflen); 712 } 713 714 for (int i = 0; i < buflen; ++i) { 715 buf1[i*2] = buf1[i*2+1] =((buf0[i] * volume()) >> 9) & 0xffff; 716 } 717 } 718 719 void FMT_EuphonyDriver::rate(uint16 r) 720 { 721 for (uint8 i = 0; i < 16; i++) { 722 if (_channel[i]) 723 _channel[i]->rate(r); 724 } 725 } 726 727 MidiParser_EuD::MidiParser_EuD() : MidiParser() { 728 } 729 730 void MidiParser_EuD::parseNextEvent (EventInfo &info) { 731 byte *pos = _position._play_pos; 732 733 while (true) { 734 byte cmd = *pos; 735 byte evt = (cmd & 0xF0); 736 737 if (evt == 0x90) { 738 byte chan = pos[1]; 739 740 if (_enable[chan]) { 741 uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick; 742 info.start = pos + 6; 743 uint32 last = _position._last_event_tick; 744 info.delta = (tick < last) ? 0 : (tick - last); 745 746 info.event = 0x90 | _channel[chan]; 747 info.length = pos[7] | (pos[8] << 4); 748 749 int8 note = (int8) pos[4]; 750 if (_adjNote[chan]) { 751 note = (note & 0x7f) & _adjNote[chan]; 752 if (note > 0x7c) 753 note -= 0x0c; 754 else if (note < 0) 755 note += 0x0c; 756 } 757 info.basic.param1 = (byte) note; 758 759 uint8 onVelo = (pos[5] & 0x7f) + _adjVelo[chan]; 760 if (onVelo > 0x7f) 761 onVelo = 0x7f; 762 if (onVelo < 1) 763 onVelo = 1; 764 info.basic.param2 = onVelo; 765 766 pos += 12; 767 break; 768 } else { 769 pos += 6; 770 } 771 } else if (evt == 0xB0 || evt == 0xC0 || evt == 0xe0) { 772 byte chan = pos[1]; 773 774 if (_enable[chan]) { 775 info.start = pos; 776 uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick; 777 uint32 last = _position._last_event_tick; 778 info.delta = (tick < last) ? 0 : (tick - last); 779 info.event = evt | _channel[chan]; 780 info.length = 0; 781 info.basic.param1 = pos[4]; 782 info.basic.param2 = pos[5]; 783 pos += 6; 784 break; 785 } else { 786 pos += 6; 787 } 788 } else if (cmd == 0xF2) { 789 static uint16 tickTable [] = { 0x180, 0xC0, 0x80, 0x60, 0x40, 0x30, 0x20, 0x18 }; 790 _baseTick += tickTable[_nextBaseTickStep >> 4] * ((_nextBaseTickStep & 0x0f) + 1); 791 _nextBaseTickStep = pos[1]; 792 pos += 6; 793 } else if (cmd == 0xF8) { 794 uint16 tempo = pos[4] | (pos[5] << 7); 795 setTempo (tempo); 796 pos += 6; 797 } else if (cmd == 0xFD || cmd == 0xFE) { 798 // End of track. 799 if (_autoLoop) 800 pos = info.start = _tracks[0]; 801 else 802 info.start = pos; 803 804 uint32 last = _position._last_event_tick; 805 uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick; 806 info.delta = (tick < last) ? 0 : (tick - last); 807 info.event = 0xFF; 808 info.ext.type = 0x2F; 809 info.ext.data = pos; 810 break; 811 } else { 812 error("Unknown Euphony music event 0x%02X", (int) cmd); 813 memset(&info, 0, sizeof(info)); 814 pos = 0; 815 break; 816 } 817 } 818 _position._play_pos = pos; 819 } 820 821 bool MidiParser_EuD::loadMusic (byte *data, uint32) { 822 unloadMusic(); 823 824 _enable = data + 0x354; 825 _mode = data + 0x374; 826 _channel = data + 0x394; 827 _adjVelo = data + 0x3B4; 828 _adjNote = (int8*) data + 0x3D4; 829 830 _firstBaseTickStep = data[0x804]; 831 _initialTempo = (data[0x805] > 0xfc) ? 0x5a : data[0x805]; 832 833 _num_tracks = 1; 834 _ppqn = 120; 835 _tracks[0] = data + 0x806; 836 837 resetTracking(); 838 setTrack (0); 839 840 return true; 841 } 842 843 void MidiParser_EuD::setTempo(uint32 tempo) { 844 MidiParser::setTempo(60000000 / tempo); 845 } 846 847 void MidiParser_EuD::resetTracking() { 848 MidiParser::resetTracking(); 849 850 _nextBaseTickStep = _firstBaseTickStep; 851 _baseTick = 0; 852 setTempo (_initialTempo); 853 } 854 34 855 SoundTowns::SoundTowns(KyraEngine *engine, Audio::Mixer *mixer) : Sound(engine, mixer), _lastTrack(-1), 35 _currentSFX(0), _sfxFileData(0), _sfxFileIndex((uint)-1), _sfxWDTable(0) { 856 _currentSFX(0), _sfxFileData(0), _sfxFileIndex((uint)-1), _sfxWDTable(0), _parser(0), _musicTrackData(0) { 857 858 _driver = new FMT_EuphonyDriver(_mixer); 859 int ret = open(); 860 if (ret != MERR_ALREADY_OPEN && ret != 0) { 861 error("couldn't open midi driver"); 862 } 36 863 } 37 864 38 865 SoundTowns::~SoundTowns() { 39 866 AudioCD.stop(); 867 haltTrack(); 40 868 delete [] _sfxFileData; 41 stopSoundEffect(); 869 870 Common::StackLock lock(_mutex); 871 _driver->setTimerCallback(0, 0); 872 close(); 873 874 if (_musicTrackData) 875 delete [] _musicTrackData; 876 877 _driver = 0; 42 878 } 43 879 44 880 bool SoundTowns::init() { 45 881 _engine->checkCD(); 46 882 int unused = 0; 47 883 _sfxWDTable = _engine->staticres()->loadRawData(kKyra1TownsSFXTable, unused); 48 return true; 884 885 return loadInstruments(); 49 886 } 50 887 51 888 void SoundTowns::process() { … … 131 968 132 969 int trackNum = tTable[track].track; 133 970 bool loop = tTable[track].loop; 134 // could be that if the trackNum is -1, the music should be stopped 135 // instead of letting the old music play on 136 if (trackNum == -1 || trackNum == _lastTrack) 971 972 if (track == _lastTrack && _musicEnabled) 137 973 return; 138 974 139 975 haltTrack(); 140 AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0);141 AudioCD.updateCD();142 976 143 _lastTrack = trackNum; 977 if (_musicEnabled == 2 && trackNum != -1) { 978 AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0); 979 AudioCD.updateCD(); 980 } else if (_musicEnabled) { 981 playEuphonyTrack(tTable[track].fileOffset, loop); 982 } 983 984 _lastTrack = track; 144 985 } 145 986 146 987 void SoundTowns::haltTrack() { 147 988 _lastTrack = -1; 148 989 AudioCD.stop(); 149 990 AudioCD.updateCD(); 991 if (_parser) { 992 Common::StackLock lock(_mutex); 993 994 _parser->setTrack(0); 995 _parser->jumpToTick(0); 996 _parser->setTempo(0); 997 998 _parser->unloadMusic(); 999 delete _parser; 1000 _parser = 0; 1001 1002 setVolume(255); 1003 } 150 1004 } 151 1005 152 1006 void SoundTowns::loadSoundFile(uint file) { … … 157 1011 _sfxFileData = _engine->resource()->fileData(soundFilename(file), 0); 158 1012 } 159 1013 160 void SoundTowns::stopSoundEffect() {161 _sfxIsPlaying = false;162 _mixer->stopHandle(_sfxHandle);163 }164 165 1014 void SoundTowns::playSoundEffect(uint8 track) { 166 1015 if (!_sfxEnabled || !_sfxFileData) 167 1016 return; 168 1017 169 _sfxIsPlaying = true; 170 171 uint8 pitch = 0x3c; 172 if (_sfxFileIndex == 5) { 1018 if (track == 0 || track == 10) { 1019 _mixer->stopHandle(_sfxHandle); 1020 return; 1021 } else if (track == 1) { 1022 // sfx fadeout 1023 _mixer->stopHandle(_sfxHandle); 1024 return; 1025 } 1026 1027 uint8 note = 0x3c; 1028 if (_sfxFileIndex == 5) { 173 1029 if (track == 0x10) { 174 pitch= 0x3e;1030 note = 0x3e; 175 1031 track = 0x0f; 176 1032 } else if (track == 0x11) { 177 pitch= 0x40;1033 note = 0x40; 178 1034 track = 0x0f; 179 1035 } else if (track == 0x12) { 180 pitch= 0x41;1036 note = 0x41; 181 1037 track = 0x0f; 182 1038 } 183 1039 } … … 194 1050 uint32 outBufferSize; 195 1051 uint32 unused2; 196 1052 uint32 unused3; 197 uint32 unknown1;198 uint32 pitch;1053 uint32 rate; 1054 uint32 rootNoteOffs; 199 1055 } *sfxHeader = (SfxHeader*)(fileBody + offset); 200 1056 201 1057 uint32 sfxHeaderID = TO_LE_32(sfxHeader->id); 202 1058 uint32 sfxHeaderInBufferSize = TO_LE_32(sfxHeader->inBufferSize); 203 1059 uint32 sfxHeaderOutBufferSize = TO_LE_32(sfxHeader->outBufferSize); 204 sfxHeader->pitch = TO_LE_32(sfxHeader->pitch); 1060 uint32 sfxRootNoteOffs = TO_LE_32(sfxHeader->rootNoteOffs); 1061 uint32 sfxRate = TO_LE_32(sfxHeader->rate); 205 1062 206 1063 uint32 playbackBufferSize = (sfxHeaderID == 1) ? sfxHeaderInBufferSize : sfxHeaderOutBufferSize; 207 1064 208 stopSoundEffect();209 1065 uint8 *sfxPlaybackBuffer = (uint8 *)malloc(playbackBufferSize); 210 1066 memset(sfxPlaybackBuffer, 0x80, playbackBufferSize); 211 1067 … … 220 1076 uint32 sfx_BtTable_Offset = 0; 221 1077 uint32 sfx_WdTable_Offset = 0; 222 1078 uint32 sfx_WdTable_Number = 5; 223 1079 224 1080 for (uint32 i = 0; i < sfxHeaderInBufferSize; i++) { 225 1081 sfx_WdTable_Offset = (sfx_WdTable_Number * 3 << 9) + sfxBody[i] * 6; 226 1082 sfx_WdTable_Number = READ_LE_UINT16(_sfxWDTable + sfx_WdTable_Offset); … … 233 1089 } 234 1090 } 235 1091 236 for (uint32 i = 0; i < playbackBufferSize; i++) { 1092 for (uint32 i = 0; i < playbackBufferSize; i++) { 237 1093 if (sfxPlaybackBuffer[i] < 0x80) 238 1094 sfxPlaybackBuffer[i] = 0x80 - sfxPlaybackBuffer[i]; 239 1095 } 240 1096 241 1097 playbackBufferSize -= 0x20; 242 setPitch(sfxPlaybackBuffer, playbackBufferSize, sfxHeader->pitch, pitch); 243 244 _currentSFX = Audio::makeLinearInputStream(sfxPlaybackBuffer, playbackBufferSize, 245 0x2b11, 246 Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 247 0, 0); 1098 uint32 outputRate = 11025 * semitoneAndSampleRate_to_sampleStep(note, sfxRootNoteOffs, sfxRate, 11025, 0x2000); 1099 1100 _currentSFX = Audio::makeLinearInputStream(sfxPlaybackBuffer, playbackBufferSize, 1101 outputRate, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0); 248 1102 _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX); 249 1103 } 250 1104 251 void SoundTowns::setPitch(uint8 *&data, uint32 &size, int8 sourcePitch, int8 targetPitch) { 252 if (sourcePitch == targetPitch) 253 return; 1105 void SoundTowns::beginFadeOut() { 1106 int vol = 255; 1107 haltTrack(); 1108 } 254 1109 255 if (sourcePitch < 0) 256 sourcePitch = 0; 257 if (sourcePitch > 119) 258 sourcePitch = 119; 259 if (targetPitch < 0) 260 targetPitch = 0; 261 if (targetPitch > 119) 262 targetPitch = 119; 263 1110 int SoundTowns::open() { 1111 if (!_driver) 1112 return 255; 1113 1114 int ret = _driver->open(); 1115 if (ret) 1116 return ret; 1117 1118 _driver->setTimerCallback(this, &onTimer); 1119 return 0; 1120 } 1121 1122 void SoundTowns::close() { 1123 if (_driver) 1124 _driver->close(); 1125 } 1126 1127 void SoundTowns::send(uint32 b) { 1128 _driver->send(b); 1129 } 1130 1131 uint32 SoundTowns::getBaseTempo(void) { 1132 return _driver ? _driver->getBaseTempo() : 0; 1133 } 1134 1135 bool SoundTowns::loadInstruments() { 1136 if (!_musicTrackData) 1137 _musicTrackData = new uint8[0xC58A]; 1138 1139 memset(_musicTrackData, 0, 0xC58A); 1140 uint8 * twm = _engine->resource()->fileData("twmusic.pak", 0); 1141 if (!twm) 1142 return false; 1143 Screen::decodeFrame4(twm, _musicTrackData, 0x8BF0); 1144 _driver->loadFmInstruments(_musicTrackData + 8); 1145 1146 memset (_musicTrackData, 0, 0xC58A); 1147 Screen::decodeFrame4(twm + 0x0CA0, _musicTrackData, 0xC58A); 1148 delete [] twm; 1149 _driver->loadWaveInstruments(_musicTrackData + 8); 1150 1151 return true; 1152 } 1153 1154 void SoundTowns::playEuphonyTrack(uint32 offset, int loop) { 1155 if (!_musicTrackData) 1156 _musicTrackData = new uint8[0xC58A]; 1157 1158 memset(_musicTrackData, 0, 0xC58A); 1159 uint8 * twm = _engine->resource()->fileData("twmusic.pak", 0); 1160 Screen::decodeFrame4(twm + 0x4b70 + offset, _musicTrackData, 0xC58A); 1161 delete [] twm; 1162 1163 Common::StackLock lock(_mutex); 1164 1165 uint8 * used = _musicTrackData + 0x374; 1166 uint8 * fchan = _musicTrackData + 0x6d4; 1167 uint8 * wchan = _musicTrackData + 0x6dA; 1168 1169 for (uint8 i = 0; i < 6; i++) { 1170 if (used[fchan[i]]) 1171 _driver->assignFmChannel(fchan[i], i); 1172 } 1173 1174 for (uint8 i = 0; i < 8; i++) { 1175 if (used[wchan[i]]) 1176 _driver->assignWaveChannel(wchan[i], i); 1177 } 1178 1179 for (uint8 i = 0; i < 16; i++) { 1180 if (!used[i]) 1181 _driver->removeChannel(i); 1182 } 1183 _driver->send(0x79B0); 1184 1185 if (_parser) 1186 delete _parser; 1187 1188 _parser = new MidiParser_EuD; 1189 _parser->property(MidiParser::mpAutoLoop, loop); 1190 _parser->loadMusic(_musicTrackData, 0); 1191 _parser->jumpToTick(0); 1192 1193 _parser->setMidiDriver(this); 1194 _parser->setTimerRate(getBaseTempo()); 1195 } 1196 1197 void SoundTowns::onTimer(void * data) { 1198 SoundTowns *music = (SoundTowns *)data; 1199 Common::StackLock lock(music->_mutex); 1200 if (music->_parser) 1201 music->_parser->onTimer(); 1202 } 1203 1204 float SoundTowns::semitoneAndSampleRate_to_sampleStep(int8 semiTone, int8 semiToneRootkey, 1205 uint32 sampleRate, uint32 outputRate, int32 pitchWheel) { 1206 if (semiTone < 0) 1207 semiTone = 0; 1208 if (semiTone > 119) 1209 semiTone = 119; 1210 if (semiTone < 0) 1211 semiTone = 0; 1212 if (semiTone > 119) 1213 semiTone = 119; 1214 264 1215 static const float noteFrq[] = { 265 1216 0004.13f, 0004.40f, 0004.64f, 0004.95f, 0005.16f, 0005.50f, 0005.80f, 0006.19f, 0006.60f, 0006.86f, 266 1217 0007.43f, 0007.73f, 0008.25f, 0008.80f, 0009.28f, 0009.90f, 0010.31f, 0011.00f, 0011.60f, 0012.38f, … … 276 1227 2376.00f, 2534.40f, 2640.00f, 2816.00f, 2970.40f, 3168.00f, 3379.20f, 3520.00f, 3801.60f, 3960.00f 277 1228 }; 278 1229 279 const float inc = noteFrq[targetPitch] / noteFrq[sourcePitch]; 1230 float pwModifier = (pitchWheel - 0x2000) / 0x2000; 1231 int8 d = pwModifier ? (pwModifier < 0 ? -1 : 1) : 0; 1232 float rateshift = (noteFrq[semiTone] - ((noteFrq[semiTone] - 1233 noteFrq[semiTone + d]) * pwModifier * d)) / noteFrq[semiToneRootkey]; 280 1234 281 uint32 estimatedSize = (uint32)(((float) size / inc) + 1); 282 uint32 exactSize = 0; 283 uint8 * tmp = new uint8[estimatedSize]; 284 memset(tmp, 0x80, estimatedSize); 285 286 int last = 0; 287 for (float i = 0; i < size; i += inc) { 288 int cur = (int) i; 289 if (cur == last + 2) 290 tmp[exactSize++] = (data[last] + data[cur - 1] + data[cur]) / 3; 291 else if (cur == last) 292 tmp[exactSize++] = (data[cur] + data[cur + 1]) / 2; 293 else 294 tmp[exactSize++] = data[cur]; 295 last = (int) i; 296 } 297 298 size = MIN(exactSize, estimatedSize); 299 delete[] data; 300 data = tmp; 1235 return (float) sampleRate * 10.0f * rateshift / outputRate; 301 1236 } 302 1237 303 1238 const uint8 SoundTowns::_sfxBTTable[256] = { -
sound/softsynth/ym2612.cpp
28 28 #include <math.h> 29 29 30 30 #include "common/util.h" 31 #include "sound/softsynth/ym2612.h" 31 32 32 33 //////////////////////////////////////// 33 34 // … … 42 43 static int *keyscaleTable = 0; 43 44 static int *attackOut = 0; 44 45 45 ////////////////////////////////////////46 //47 // Class declarations48 //49 ////////////////////////////////////////50 46 51 class Operator2612;52 class Voice2612;53 class MidiChannel_YM2612;54 class MidiDriver_YM2612;55 56 class Operator2612 {57 protected:58 Voice2612 *_owner;59 enum State { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing };60 State _state;61 int32 _currentLevel;62 int _frequency;63 uint32 _phase;64 int _lastOutput;65 int _feedbackLevel;66 int _detune;67 int _multiple;68 int32 _totalLevel;69 int _keyScale;70 int _velocity;71 int _specifiedTotalLevel;72 int _specifiedAttackRate;73 int _specifiedDecayRate;74 int _specifiedSustainLevel;75 int _specifiedSustainRate;76 int _specifiedReleaseRate;77 int _tickCount;78 int _attackTime;79 int32 _decayRate;80 int32 _sustainLevel;81 int32 _sustainRate;82 int32 _releaseRate;83 84 public:85 Operator2612 (Voice2612 *owner);86 ~Operator2612();87 void feedbackLevel(int level);88 void setInstrument(byte const *instrument);89 void velocity(int velo);90 void keyOn();91 void keyOff();92 void frequency(int freq);93 void nextTick(const int *phaseShift, int *outbuf, int buflen);94 bool inUse() { return (_state != _s_ready); }95 };96 97 class Voice2612 {98 public:99 Voice2612 *next;100 uint16 _rate;101 102 protected:103 Operator2612 *_opr[4];104 int _velocity;105 int _control7;106 int _note;107 int _frequencyOffs;108 int _frequency;109 int _algorithm;110 111 int *_buffer;112 int _buflen;113 114 public:115 Voice2612();116 ~Voice2612();117 void setControlParameter(int control, int value);118 void setInstrument(byte const *instrument);119 void velocity(int velo);120 void nextTick(int *outbuf, int buflen);121 void noteOn(int n, int onVelo);122 bool noteOff(int note);123 void pitchBend(int value);124 void recalculateFrequency();125 };126 127 class MidiChannel_YM2612 : public MidiChannel {128 protected:129 uint16 _rate;130 Voice2612 *_voices;131 Voice2612 *_next_voice;132 133 public:134 void removeAllVoices();135 void nextTick(int *outbuf, int buflen);136 void rate(uint16 r);137 138 public:139 MidiChannel_YM2612();140 virtual ~MidiChannel_YM2612();141 142 // MidiChannel interface143 MidiDriver *device() { return 0; }144 byte getNumber() { return 0; }145 void release() { }146 void send(uint32 b) { }147 void noteOff(byte note);148 void noteOn(byte note, byte onVelo);149 void programChange(byte program) { }150 void pitchBend(int16 value);151 void controlChange(byte control, byte value);152 void pitchBendFactor(byte value) { }153 void sysEx_customInstrument(uint32 type, const byte *instr);154 };155 156 class MidiDriver_YM2612 : public MidiDriver_Emulated {157 protected:158 MidiChannel_YM2612 *_channel[16];159 160 int _next_voice;161 int _volume;162 163 protected:164 static void createLookupTables();165 void nextTick(int16 *buf1, int buflen);166 int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; }167 void rate(uint16 r);168 169 void generateSamples(int16 *buf, int len);170 171 public:172 MidiDriver_YM2612(Audio::Mixer *mixer);173 virtual ~MidiDriver_YM2612();174 175 int open();176 void close();177 void send(uint32 b);178 void send(byte channel, uint32 b); // Supports higher than channel 15179 uint32 property(int prop, uint32 param) { return 0; }180 181 void setPitchBendRange(byte channel, uint range) { }182 void sysEx(const byte *msg, uint16 length);183 184 MidiChannel *allocateChannel() { return 0; }185 MidiChannel *getPercussionChannel() { return 0; }186 187 188 // AudioStream API189 bool isStereo() const { return true; }190 int getRate() const { return _mixer->getOutputRate(); }191 };192 193 47 //////////////////////////////////////// 194 48 // 195 49 // Operator2612 implementation … … 726 580 int i; 727 581 for (i = 0; i < ARRAYSIZE(_channel); i++) 728 582 delete _channel[i]; 729 delete sintbl; 730 delete powtbl; 731 delete frequencyTable; 732 delete keycodeTable; 733 delete keyscaleTable; 734 delete attackOut; 735 sintbl = powtbl = frequencyTable = keycodeTable = keyscaleTable = attackOut = 0; 583 removeLookupTables(); 736 584 } 737 585 738 586 int MidiDriver_YM2612::open() { … … 896 744 } 897 745 } 898 746 747 void MidiDriver_YM2612::removeLookupTables() { 748 delete [] sintbl; 749 delete [] powtbl; 750 delete [] frequencyTable; 751 delete [] keycodeTable; 752 delete [] keyscaleTable; 753 delete [] attackOut; 754 sintbl = powtbl = frequencyTable = keycodeTable = keyscaleTable = attackOut = 0; 755 } 756 899 757 //////////////////////////////////////// 900 758 // 901 759 // MidiDriver_YM2612 factory -
sound/softsynth/ym2612.h
1 //////////////////////////////////////// 2 // 3 // Class declarations 4 // 5 //////////////////////////////////////// 6 7 class Voice2612; 8 class Operator2612 { 9 protected: 10 Voice2612 *_owner; 11 enum State { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing }; 12 State _state; 13 int32 _currentLevel; 14 int _frequency; 15 uint32 _phase; 16 int _lastOutput; 17 int _feedbackLevel; 18 int _detune; 19 int _multiple; 20 int32 _totalLevel; 21 int _keyScale; 22 int _velocity; 23 int _specifiedTotalLevel; 24 int _specifiedAttackRate; 25 int _specifiedDecayRate; 26 int _specifiedSustainLevel; 27 int _specifiedSustainRate; 28 int _specifiedReleaseRate; 29 int _tickCount; 30 int _attackTime; 31 int32 _decayRate; 32 int32 _sustainLevel; 33 int32 _sustainRate; 34 int32 _releaseRate; 35 36 public: 37 Operator2612 (Voice2612 *owner); 38 ~Operator2612(); 39 void feedbackLevel(int level); 40 void setInstrument(byte const *instrument); 41 void velocity(int velo); 42 void keyOn(); 43 void keyOff(); 44 void frequency(int freq); 45 void nextTick(const int *phaseShift, int *outbuf, int buflen); 46 bool inUse() { return (_state != _s_ready); } 47 }; 48 49 class Voice2612 { 50 public: 51 Voice2612 *next; 52 uint16 _rate; 53 54 protected: 55 Operator2612 *_opr[4]; 56 int _velocity; 57 int _control7; 58 int _note; 59 int _frequencyOffs; 60 int _frequency; 61 int _algorithm; 62 63 int *_buffer; 64 int _buflen; 65 66 public: 67 Voice2612(); 68 ~Voice2612(); 69 void setControlParameter(int control, int value); 70 void setInstrument(byte const *instrument); 71 void velocity(int velo); 72 void nextTick(int *outbuf, int buflen); 73 void noteOn(int n, int onVelo); 74 bool noteOff(int note); 75 void pitchBend(int value); 76 void recalculateFrequency(); 77 }; 78 79 class MidiChannel_YM2612 : public MidiChannel { 80 protected: 81 uint16 _rate; 82 Voice2612 *_voices; 83 Voice2612 *_next_voice; 84 85 public: 86 void removeAllVoices(); 87 void nextTick(int *outbuf, int buflen); 88 void rate(uint16 r); 89 90 public: 91 MidiChannel_YM2612(); 92 virtual ~MidiChannel_YM2612(); 93 94 // MidiChannel interface 95 MidiDriver *device() { return 0; } 96 byte getNumber() { return 0; } 97 void release() { } 98 void send(uint32 b) { } 99 void noteOff(byte note); 100 void noteOn(byte note, byte onVelo); 101 void programChange(byte program) { } 102 void pitchBend(int16 value); 103 void controlChange(byte control, byte value); 104 void pitchBendFactor(byte value) { } 105 void sysEx_customInstrument(uint32 type, const byte *instr); 106 }; 107 108 class MidiDriver_YM2612 : public MidiDriver_Emulated { 109 protected: 110 MidiChannel_YM2612 *_channel[16]; 111 112 int _next_voice; 113 int _volume; 114 115 protected: 116 void nextTick(int16 *buf1, int buflen); 117 int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; } 118 void rate(uint16 r); 119 120 void generateSamples(int16 *buf, int len); 121 122 public: 123 MidiDriver_YM2612(Audio::Mixer *mixer); 124 virtual ~MidiDriver_YM2612(); 125 126 static void createLookupTables(); 127 static void removeLookupTables(); 128 129 int open(); 130 void close(); 131 void send(uint32 b); 132 void send(byte channel, uint32 b); // Supports higher than channel 15 133 uint32 property(int prop, uint32 param) { return 0; } 134 135 void setPitchBendRange(byte channel, uint range) { } 136 void sysEx(const byte *msg, uint16 length); 137 138 MidiChannel *allocateChannel() { return 0; } 139 MidiChannel *getPercussionChannel() { return 0; } 140 141 142 // AudioStream API 143 bool isStereo() const { return true; } 144 int getRate() const { return _mixer->getOutputRate(); } 145 }; 146 Kein Zeilenvorschub am Ende der Datei