1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 // Music class 24 25 #ifndef TINSEL_MUSIC_H 26 #define TINSEL_MUSIC_H 27 28 #include "audio/midiplayer.h" 29 #include "audio/audiostream.h" 30 #include "audio/mixer.h" 31 #include "common/mutex.h" 32 33 class MidiParser; 34 35 namespace Tinsel { 36 37 class Music { 38 public: Music()39 Music() : _currentMidi(0), _currentLoop(false) { 40 _midiBuffer.pDat = nullptr; 41 _midiBuffer.size = 0; 42 } 43 44 bool PlayMidiSequence( // Plays the specified MIDI sequence through the sound driver 45 uint32 dwFileOffset, // handle of MIDI sequence data 46 bool bLoop); // Whether to loop the sequence 47 48 bool MidiPlaying(); // Returns TRUE if a Midi tune is currently playing 49 50 bool StopMidi(); // Stops any currently playing midi 51 52 void SetMidiVolume( // Sets the volume of the MIDI music. Returns the old volume 53 int vol); // new volume - 0..MAXMIDIVOL 54 55 int GetMidiVolume(); 56 57 void OpenMidiFiles(); 58 void DeleteMidiBuffer(); 59 60 void CurrentMidiFacts(SCNHANDLE *pMidi, bool *pLoop); 61 void RestoreMidiFacts(SCNHANDLE Midi, bool Loop); 62 63 int GetTrackNumber(SCNHANDLE hMidi); 64 SCNHANDLE GetTrackOffset(int trackNumber); 65 GetMidiBuffer()66 uint8 *GetMidiBuffer() { return _midiBuffer.pDat; } 67 ResizeMidiBuffer(uint32 newSize)68 uint8* ResizeMidiBuffer(uint32 newSize) { 69 if (_midiBuffer.size < newSize) { 70 _midiBuffer.pDat = (byte*)realloc(_midiBuffer.pDat, newSize); 71 assert(_midiBuffer.pDat); 72 } 73 74 return _midiBuffer.pDat; 75 } 76 77 void dumpMusic(); 78 79 private: 80 // sound buffer structure used for MIDI data and samples 81 struct SOUND_BUFFER { 82 uint8 *pDat; // pointer to actual buffer 83 uint32 size; // size of the buffer 84 }; 85 86 // MIDI buffer 87 SOUND_BUFFER _midiBuffer; 88 89 SCNHANDLE _currentMidi; 90 bool _currentLoop; 91 92 // We allocate 155 entries because that's the maximum, used in the SCN version 93 SCNHANDLE _midiOffsets[155]; 94 }; 95 96 class MidiMusicPlayer : public Audio::MidiPlayer { 97 public: 98 MidiMusicPlayer(TinselEngine *vm); 99 100 void setVolume(int volume) override; 101 102 void playMIDI(uint32 size, bool loop); 103 104 // void stop(); 105 void pause() override; 106 void resume() override; 107 108 // MidiDriver_BASE interface implementation 109 void send(uint32 b) override; 110 111 // The original sets the "sequence timing" to 109 Hz, whatever that 112 // means. The default is 120. getBaseTempo()113 uint32 getBaseTempo() { return _driver ? (109 * _driver->getBaseTempo()) / 120 : 0; } 114 115 bool _milesAudioMode; 116 117 private: 118 void playXMIDI(uint32 size, bool loop); 119 void playSEQ(uint32 size, bool loop); 120 }; 121 122 class PCMMusicPlayer : public Audio::AudioStream { 123 public: 124 PCMMusicPlayer(); 125 ~PCMMusicPlayer() override; 126 127 bool isPlaying() const; 128 129 bool isDimmed() const; 130 131 void getTunePlaying(void *voidPtr, int length); 132 void restoreThatTune(void *voidPtr); 133 134 void setMusicSceneDetails(SCNHANDLE hScript, SCNHANDLE hSegment, const char *fileName); 135 136 void setVolume(int volume); 137 138 void startPlay(int id); 139 void stopPlay(); 140 141 bool getMusicTinselDimmed() const; 142 void dim(bool bTinselDim); 143 void unDim(bool bTinselUnDim); 144 void dimIteration(); 145 146 void startFadeOut(int ticks); 147 void fadeOutIteration(); 148 149 int readBuffer(int16 *buffer, const int numSamples) override; 150 bool isStereo() const override; endOfData()151 bool endOfData() const override { return _end; } endOfStream()152 bool endOfStream() const override { return false; } 153 int getRate() const override; 154 155 protected: 156 enum State { 157 S_IDLE, 158 S_NEW, 159 S_MID, 160 S_END1, 161 S_END2, 162 S_END3, 163 S_NEXT, 164 S_STOP 165 }; 166 167 Audio::SoundHandle _handle; 168 Audio::AudioStream *_curChunk; 169 Common::Mutex _mutex; 170 171 bool _end; 172 173 int _silenceSamples; 174 175 State _state, _mState; 176 bool _forcePlay; 177 int32 _scriptNum; 178 int32 _scriptIndex; 179 SCNHANDLE _hScript; 180 SCNHANDLE _hSegment; 181 Common::String _filename; 182 183 uint8 _volume; 184 185 bool _dimmed; 186 bool _dimmedTinsel; 187 uint8 _dimmedVolume; 188 int _dimIteration; 189 int _dimPosition; 190 191 uint8 _fadeOutVolume; 192 int _fadeOutIteration; 193 194 void play(); 195 void stop(); 196 void setVol(uint8 volume); 197 198 bool getNextChunk(); 199 200 void loadMusicFromSegment(int segmentNum); 201 void loadADPCMMusicFromSegment(int segmentNum); 202 void loadMP3MusicFromSegment(int segmentNum); 203 }; 204 205 } // End of namespace Tinsel 206 207 #endif 208