ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

emumidi.h

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #ifndef AUDIO_SOFTSYNTH_EMUMIDI_H
00024 #define AUDIO_SOFTSYNTH_EMUMIDI_H
00025 
00026 #include "audio/audiostream.h"
00027 #include "audio/mididrv.h"
00028 #include "audio/mixer.h"
00029 
00030 class MidiDriver_Emulated : public Audio::AudioStream, public MidiDriver {
00031 protected:
00032     bool _isOpen;
00033     Audio::Mixer *_mixer;
00034     Audio::SoundHandle _mixerSoundHandle;
00035 
00036 private:
00037     Common::TimerManager::TimerProc _timerProc;
00038     void *_timerParam;
00039 
00040     enum {
00041         FIXP_SHIFT = 16
00042     };
00043 
00044     int _nextTick;
00045     int _samplesPerTick;
00046 
00047 protected:
00048     int _baseFreq;
00049 
00050     virtual void generateSamples(int16 *buf, int len) = 0;
00051     virtual void onTimer() {}
00052 
00053 public:
00054     MidiDriver_Emulated(Audio::Mixer *mixer) :
00055         _mixer(mixer),
00056         _isOpen(false),
00057         _timerProc(0),
00058         _timerParam(0),
00059         _nextTick(0),
00060         _samplesPerTick(0),
00061         _baseFreq(250) {
00062     }
00063 
00064     // MidiDriver API
00065     virtual int open() {
00066         _isOpen = true;
00067 
00068         int d = getRate() / _baseFreq;
00069         int r = getRate() % _baseFreq;
00070 
00071         // This is equivalent to (getRate() << FIXP_SHIFT) / BASE_FREQ
00072         // but less prone to arithmetic overflow.
00073 
00074         _samplesPerTick = (d << FIXP_SHIFT) + (r << FIXP_SHIFT) / _baseFreq;
00075 
00076         return 0;
00077     }
00078 
00079     bool isOpen() const { return _isOpen; }
00080 
00081     virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
00082         _timerProc = timer_proc;
00083         _timerParam = timer_param;
00084     }
00085 
00086     virtual uint32 getBaseTempo() {
00087         return 1000000 / _baseFreq;
00088     }
00089 
00090     // AudioStream API
00091     virtual int readBuffer(int16 *data, const int numSamples) {
00092         const int stereoFactor = isStereo() ? 2 : 1;
00093         int len = numSamples / stereoFactor;
00094         int step;
00095 
00096         do {
00097             step = len;
00098             if (step > (_nextTick >> FIXP_SHIFT))
00099                 step = (_nextTick >> FIXP_SHIFT);
00100 
00101             generateSamples(data, step);
00102 
00103             _nextTick -= step << FIXP_SHIFT;
00104             if (!(_nextTick >> FIXP_SHIFT)) {
00105                 if (_timerProc)
00106                     (*_timerProc)(_timerParam);
00107 
00108                 onTimer();
00109 
00110                 _nextTick += _samplesPerTick;
00111             }
00112 
00113             data += step * stereoFactor;
00114             len -= step;
00115         } while (len);
00116 
00117         return numSamples;
00118     }
00119 
00120     virtual bool endOfData() const {
00121         return false;
00122     }
00123 };
00124 
00125 #endif


Generated on Sat Apr 20 2019 05:02:33 for ResidualVM by doxygen 1.7.1
curved edge   curved edge