diff options
Diffstat (limited to 'audio/fmopl.h')
-rw-r--r-- | audio/fmopl.h | 154 |
1 files changed, 129 insertions, 25 deletions
diff --git a/audio/fmopl.h b/audio/fmopl.h index 85ac606c7a..ba0872d87b 100644 --- a/audio/fmopl.h +++ b/audio/fmopl.h @@ -23,8 +23,16 @@ #ifndef AUDIO_FMOPL_H #define AUDIO_FMOPL_H +#include "audio/audiostream.h" + +#include "common/func.h" +#include "common/ptr.h" #include "common/scummsys.h" +namespace Audio { +class SoundHandle; +} + namespace Common { class String; } @@ -71,6 +79,12 @@ public: static DriverId parse(const Common::String &name); /** + * @return The driver description for the given id or 0 in case it is not + * available. + */ + static const EmulatorDescription *findDriver(DriverId id); + + /** * Detects a driver for the specific type. * * @return Returns a valid driver id on success, -1 otherwise. @@ -92,6 +106,14 @@ private: static const EmulatorDescription _drivers[]; }; +/** + * The type of the OPL timer callback functor. + */ +typedef Common::Functor0<void> TimerCallback; + +/** + * A representation of a Yamaha OPL chip. + */ class OPL { private: static bool _hasInstance; @@ -102,10 +124,9 @@ public: /** * Initializes the OPL emulator. * - * @param rate output sample rate * @return true on success, false on failure */ - virtual bool init(int rate) = 0; + virtual bool init() = 0; /** * Reinitializes the OPL emulator @@ -140,6 +161,101 @@ public: virtual void writeReg(int r, int v) = 0; /** + * Start the OPL with callbacks. + */ + void start(TimerCallback *callback, int timerFrequency = kDefaultCallbackFrequency); + + /** + * Stop the OPL + */ + void stop(); + + /** + * Change the callback frequency. This must only be called from a + * timer proc. + */ + virtual void setCallbackFrequency(int timerFrequency) = 0; + + enum { + /** + * The default callback frequency that start() uses + */ + kDefaultCallbackFrequency = 250 + }; + +protected: + /** + * Start the callbacks. + */ + virtual void startCallbacks(int timerFrequency) = 0; + + /** + * Stop the callbacks. + */ + virtual void stopCallbacks() = 0; + + /** + * The functor for callbacks. + */ + Common::ScopedPtr<TimerCallback> _callback; +}; + +/** + * An OPL that represents a real OPL, as opposed to an emulated one. + * + * This will use an actual timer instead of using one calculated from + * the number of samples in an AudioStream::readBuffer call. + */ +class RealOPL : public OPL { +public: + RealOPL(); + virtual ~RealOPL(); + + // OPL API + void setCallbackFrequency(int timerFrequency); + +protected: + // OPL API + void startCallbacks(int timerFrequency); + void stopCallbacks(); + +private: + static void timerProc(void *refCon); + void onTimer(); + + uint _baseFreq; + uint _remainingTicks; + + enum { + kMaxFreq = 100 + }; +}; + +/** + * An OPL that represents an emulated OPL. + * + * This will send callbacks based on the number of samples + * decoded in readBuffer(). + */ +class EmulatedOPL : public OPL, protected Audio::AudioStream { +public: + EmulatedOPL(); + virtual ~EmulatedOPL(); + + // OPL API + void setCallbackFrequency(int timerFrequency); + + // AudioStream API + int readBuffer(int16 *buffer, const int numSamples); + int getRate() const; + bool endOfData() const { return false; } + +protected: + // OPL API + void startCallbacks(int timerFrequency); + void stopCallbacks(); + + /** * Read up to 'length' samples. * * Data will be in native endianess, 16 bit per sample, signed. @@ -149,33 +265,21 @@ public: * So if you request 4 samples from a stereo OPL, you will get * a total of two left channel and two right channel samples. */ - virtual void readBuffer(int16 *buffer, int length) = 0; - - /** - * Returns whether the setup OPL mode is stereo or not - */ - virtual bool isStereo() const = 0; -}; + virtual void generateSamples(int16 *buffer, int numSamples) = 0; -} // End of namespace OPL +private: + int _baseFreq; -// Legacy API -// !You should not write any new code using the legacy API! -typedef OPL::OPL FM_OPL; + enum { + FIXP_SHIFT = 16 + }; -void OPLDestroy(FM_OPL *OPL); + int _nextTick; + int _samplesPerTick; -void OPLResetChip(FM_OPL *OPL); -void OPLWrite(FM_OPL *OPL, int a, int v); -unsigned char OPLRead(FM_OPL *OPL, int a); -void OPLWriteReg(FM_OPL *OPL, int r, int v); -void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length); + Audio::SoundHandle *_handle; +}; -/** - * Legacy factory to create an AdLib (OPL2) chip. - * - * !You should not write any new code using the legacy API! - */ -FM_OPL *makeAdLibOPL(int rate); +} // End of namespace OPL #endif |