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