mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
E.g. in the overlay there's no need to steal cycles for playing empty sample buffer. Also make STMIDI default audio driver for the slim version.
286 lines
7.3 KiB
C++
286 lines
7.3 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "backends/mixer/atari/atari-mixer.h"
|
|
|
|
#include <math.h>
|
|
#include <mint/cookie.h>
|
|
#include <mint/falcon.h>
|
|
#include <mint/osbind.h>
|
|
#include <mint/ostruct.h>
|
|
|
|
#include "common/config-manager.h"
|
|
#include "common/debug.h"
|
|
|
|
#define DEFAULT_OUTPUT_RATE 24585
|
|
|
|
void AtariAudioShutdown() {
|
|
Buffoper(0x00);
|
|
Sndstatus(SND_RESET);
|
|
Unlocksnd();
|
|
}
|
|
|
|
AtariMixerManager::AtariMixerManager() : MixerManager() {
|
|
debug("AtariMixerManager()");
|
|
|
|
_audioSuspended = true;
|
|
|
|
ConfMan.registerDefault("output_rate", DEFAULT_OUTPUT_RATE);
|
|
|
|
_outputRate = ConfMan.getInt("output_rate");
|
|
if (_outputRate <= 0)
|
|
_outputRate = DEFAULT_OUTPUT_RATE;
|
|
|
|
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false);
|
|
}
|
|
|
|
AtariMixerManager::~AtariMixerManager() {
|
|
debug("~AtariMixerManager()");
|
|
|
|
g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
|
|
|
|
AtariAudioShutdown();
|
|
|
|
Mfree(_atariSampleBuffer);
|
|
_atariSampleBuffer = _atariPhysicalSampleBuffer = _atariLogicalSampleBuffer = nullptr;
|
|
|
|
delete[] _samplesBuf;
|
|
}
|
|
|
|
void AtariMixerManager::init() {
|
|
long cookie;
|
|
bool useDevconnectReturnValue = Getcookie(C__SND, &cookie) == C_FOUND && (cookie & SND_EXT) != 0;
|
|
|
|
int clk;
|
|
|
|
if (Locksnd() < 0)
|
|
error("Sound system is locked");
|
|
|
|
// try XBIOS APIs which do not set SND_EXT in _SND
|
|
useDevconnectReturnValue |= (Getcookie(C_STFA, &cookie) == C_FOUND); // STFA
|
|
useDevconnectReturnValue |= (Getcookie(C_McSn, &cookie) == C_FOUND); // X-SOUND, MacSound
|
|
|
|
// reset connection matrix (and other settings)
|
|
Sndstatus(SND_RESET);
|
|
|
|
int diff50, diff33, diff25, diff20, diff16, diff12, diff10, diff8, diff6;
|
|
diff50 = abs(49170 - (int)_outputRate);
|
|
diff33 = abs(32780 - (int)_outputRate);
|
|
diff25 = abs(24585 - (int)_outputRate);
|
|
diff20 = abs(19668 - (int)_outputRate);
|
|
diff16 = abs(16390 - (int)_outputRate);
|
|
diff12 = abs(12292 - (int)_outputRate);
|
|
diff10 = abs(9834 - (int)_outputRate);
|
|
diff8 = abs(8195 - (int)_outputRate);
|
|
|
|
if (diff50 < diff33) {
|
|
_outputRate = 49170;
|
|
clk = CLK50K;
|
|
} else if (diff33 < diff25) {
|
|
_outputRate = 32780;
|
|
clk = CLK33K;
|
|
} else if (diff25 < diff20) {
|
|
_outputRate = 24585;
|
|
clk = CLK25K;
|
|
} else if (diff20 < diff16) {
|
|
_outputRate = 19668;
|
|
clk = CLK20K;
|
|
} else if (diff16 < diff12) {
|
|
_outputRate = 16390;
|
|
clk = CLK16K;
|
|
} else if (diff12 < diff10) {
|
|
_outputRate = 12292;
|
|
clk = CLK12K;
|
|
} else if (diff10 < diff8) {
|
|
_outputRate = 9834;
|
|
clk = CLK10K;
|
|
} else {
|
|
_outputRate = 8195;
|
|
clk = CLK8K;
|
|
}
|
|
|
|
// first try to use Devconnect() with a Falcon prescaler
|
|
if (Devconnect(DMAPLAY, DAC, CLK25M, clk, NO_SHAKE) != 0) {
|
|
// the return value is broken on Falcon
|
|
if (useDevconnectReturnValue) {
|
|
if (Devconnect(DMAPLAY, DAC, CLK25M, CLKOLD, NO_SHAKE) == 0) {
|
|
// calculate compatible prescaler
|
|
diff50 = abs(50066 - (int)_outputRate);
|
|
diff25 = abs(25033 - (int)_outputRate);
|
|
diff12 = abs(12517 - (int)_outputRate);
|
|
diff6 = abs(6258 - (int)_outputRate);
|
|
|
|
if (diff50 < diff25) {
|
|
_outputRate = 50066;
|
|
clk = PRE160;
|
|
} else if (diff25 < diff12) {
|
|
_outputRate = 25033;
|
|
clk = PRE320;
|
|
} else if (diff12 < diff6) {
|
|
_outputRate = 12517;
|
|
clk = PRE640;
|
|
} else {
|
|
_outputRate = 6258;
|
|
clk = PRE1280;
|
|
}
|
|
|
|
Soundcmd(SETPRESCALE, clk);
|
|
} else {
|
|
error("Devconnect() failed");
|
|
}
|
|
}
|
|
}
|
|
|
|
ConfMan.setInt("output_rate", _outputRate);
|
|
debug("setting %d Hz mixing frequency", _outputRate);
|
|
|
|
_samples = 8192;
|
|
while (_samples * 16 > _outputRate * 2)
|
|
_samples >>= 1;
|
|
|
|
ConfMan.registerDefault("audio_buffer_size", (int)_samples);
|
|
|
|
int samples = ConfMan.getInt("audio_buffer_size");
|
|
if (samples > 0)
|
|
_samples = samples;
|
|
|
|
ConfMan.setInt("audio_buffer_size", (int)_samples);
|
|
debug("sample buffer size: %d", _samples);
|
|
|
|
ConfMan.flushToDisk();
|
|
|
|
_atariSampleBufferSize = _samples * 4;
|
|
|
|
_atariSampleBuffer = (byte*)Mxalloc(_atariSampleBufferSize * 2, MX_STRAM);
|
|
if (!_atariSampleBuffer)
|
|
error("Failed to allocate memory in ST RAM");
|
|
|
|
_atariPhysicalSampleBuffer = _atariSampleBuffer;
|
|
_atariLogicalSampleBuffer = _atariSampleBuffer + _atariSampleBufferSize;
|
|
|
|
Setmode(MODE_STEREO16);
|
|
Soundcmd(ADDERIN, MATIN);
|
|
Setbuffer(SR_PLAY, _atariSampleBuffer, _atariSampleBuffer + 2 * _atariSampleBufferSize);
|
|
|
|
_samplesBuf = new uint8[_samples * 4];
|
|
|
|
_mixer = new Audio::MixerImpl(_outputRate, _samples);
|
|
_mixer->setReady(true);
|
|
|
|
_audioSuspended = false;
|
|
}
|
|
|
|
void AtariMixerManager::suspendAudio() {
|
|
debug("suspendAudio");
|
|
|
|
stopPlayback(kPlaybackStopped);
|
|
|
|
_audioSuspended = true;
|
|
}
|
|
|
|
int AtariMixerManager::resumeAudio() {
|
|
debug("resumeAudio");
|
|
|
|
update();
|
|
|
|
_audioSuspended = false;
|
|
return 0;
|
|
}
|
|
|
|
bool AtariMixerManager::notifyEvent(const Common::Event &event) {
|
|
switch (event.type) {
|
|
case Common::EVENT_QUIT:
|
|
case Common::EVENT_RETURN_TO_LAUNCHER:
|
|
stopPlayback(kPlaybackStopped);
|
|
debug("silencing the mixer");
|
|
return false;
|
|
default:
|
|
[[fallthrough]];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void AtariMixerManager::startPlayback(PlaybackState playbackState) {
|
|
Buffoper(SB_PLA_ENA | SB_PLA_RPT);
|
|
_playbackState = playbackState;
|
|
debug("playback started");
|
|
}
|
|
|
|
void AtariMixerManager::stopPlayback(PlaybackState playbackState) {
|
|
Buffoper(0x00);
|
|
_playbackState = playbackState;
|
|
debug("playback stopped");
|
|
}
|
|
|
|
void AtariMixerManager::update() {
|
|
if (_audioSuspended) {
|
|
return;
|
|
}
|
|
|
|
assert(_mixer);
|
|
|
|
uint32 processed = 0;
|
|
if (_playbackState == kPlaybackStopped) {
|
|
// playback stopped means that we are not playing anything (DMA
|
|
// pointer is not updating) but the mixer may have something available
|
|
processed = _mixer->mixCallback(_samplesBuf, _samples * 4);
|
|
|
|
if (processed > 0) {
|
|
memcpy(_atariPhysicalSampleBuffer, _samplesBuf, processed * 4);
|
|
startPlayback(kPlayingFromPhysicalBuffer);
|
|
}
|
|
} else {
|
|
SndBufPtr sPtr;
|
|
if (Buffptr(&sPtr) != 0) {
|
|
warning("Buffptr() failed");
|
|
return;
|
|
}
|
|
|
|
byte *buf = nullptr;
|
|
|
|
if (_playbackState == kPlayingFromPhysicalBuffer) {
|
|
if ((byte*)sPtr.play < _atariLogicalSampleBuffer) {
|
|
buf = _atariLogicalSampleBuffer;
|
|
_playbackState = kPlayingFromLogicalBuffer;
|
|
}
|
|
} else if (_playbackState == kPlayingFromLogicalBuffer) {
|
|
if ((byte*)sPtr.play >= _atariLogicalSampleBuffer) {
|
|
buf = _atariPhysicalSampleBuffer;
|
|
_playbackState = kPlayingFromPhysicalBuffer;
|
|
}
|
|
}
|
|
|
|
if (buf) {
|
|
processed = _mixer->mixCallback(_samplesBuf, _samples * 4);
|
|
if (processed > 0) {
|
|
memcpy(buf, _samplesBuf, processed * 4);
|
|
} else {
|
|
stopPlayback(kPlaybackStopped);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (processed > 0 && processed != _samples) {
|
|
warning("processed: %d, _samples: %d", processed, _samples);
|
|
}
|
|
}
|