diff options
| author | Matthew Hoops | 2015-05-14 21:07:46 -0400 | 
|---|---|---|
| committer | Matthew Hoops | 2015-07-07 20:19:47 -0400 | 
| commit | 4d5658511228328a9e56d32448f9b598ecda696c (patch) | |
| tree | 164d68f9ca5a6bed5e7c0b4526045067a0bd8c5e /audio/fmopl.cpp | |
| parent | bed9da8b9dbbaa19d317f71663e42875c1717fda (diff) | |
| download | scummvm-rg350-4d5658511228328a9e56d32448f9b598ecda696c.tar.gz scummvm-rg350-4d5658511228328a9e56d32448f9b598ecda696c.tar.bz2 scummvm-rg350-4d5658511228328a9e56d32448f9b598ecda696c.zip  | |
AUDIO: Add a class representing a real OPL
Diffstat (limited to 'audio/fmopl.cpp')
| -rw-r--r-- | audio/fmopl.cpp | 58 | 
1 files changed, 58 insertions, 0 deletions
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp index 4bc902eba0..b0b3273e82 100644 --- a/audio/fmopl.cpp +++ b/audio/fmopl.cpp @@ -29,6 +29,7 @@  #include "common/config-manager.h"  #include "common/system.h"  #include "common/textconsole.h" +#include "common/timer.h"  #include "common/translation.h"  namespace OPL { @@ -185,6 +186,63 @@ void OPL::stop() {  bool OPL::_hasInstance = false; +RealOPL::RealOPL() : _baseFreq(0), _remainingTicks(0) { +} + +RealOPL::~RealOPL() { +	// Stop callbacks, just in case. If it's still playing at this +	// point, there's probably a bigger issue, though. The subclass +	// needs to call stop() or the pointer can still use be used in +	// the mixer thread at the same time. +	stop(); +} + +void RealOPL::setCallbackFrequency(int timerFrequency) { +	stopCallbacks(); +	startCallbacks(timerFrequency); +} + +void RealOPL::startCallbacks(int timerFrequency) { +	_baseFreq = timerFrequency; +	assert(_baseFreq > 0); + +	// We can't request more a timer faster than 100Hz. We'll handle this by calling +	// the proc multiple times in onTimer() later on. +	if (timerFrequency > kMaxFreq) +		timerFrequency = kMaxFreq; + +	_remainingTicks = 0; +	g_system->getTimerManager()->installTimerProc(timerProc, 1000000 / timerFrequency, this, "RealOPL"); +} + +void RealOPL::stopCallbacks() { +	g_system->getTimerManager()->removeTimerProc(timerProc); +	_baseFreq = 0; +	_remainingTicks = 0; +} + +void RealOPL::timerProc(void *refCon) { +	static_cast<RealOPL *>(refCon)->onTimer(); +} + +void RealOPL::onTimer() { +	uint callbacks = 1; + +	if (_baseFreq > kMaxFreq) { +		// We run faster than our max, so run the callback multiple +		// times to approximate the actual timer callback frequency. +		uint totalTicks = _baseFreq + _remainingTicks;		 +		callbacks = totalTicks / kMaxFreq; +		_remainingTicks = totalTicks % kMaxFreq; +	} + +	// Call the callback multiple times. The if is on the inside of the +	// loop in case the callback removes itself. +	for (uint i = 0; i < callbacks; i++) +		if (_callback && _callback->isValid()) +			(*_callback)(); +} +  EmulatedOPL::EmulatedOPL() :  	_nextTick(0),  	_samplesPerTick(0),  | 
