mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-11 19:54:03 +00:00
0245ae15b0
This adds a convenience function to reset the source volume to the source neutral volume.
284 lines
8.1 KiB
C++
284 lines
8.1 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "common/config-manager.h"
|
|
|
|
#include "audio/mididrv_ms.h"
|
|
|
|
const uint8 MidiDriver_Multisource::MAXIMUM_SOURCES;
|
|
const uint16 MidiDriver_Multisource::DEFAULT_SOURCE_NEUTRAL_VOLUME;
|
|
const uint16 MidiDriver_Multisource::FADING_DELAY;
|
|
|
|
MidiDriver_Multisource::MidiSource::MidiSource() :
|
|
type(SOURCE_TYPE_UNDEFINED),
|
|
volume(DEFAULT_SOURCE_NEUTRAL_VOLUME),
|
|
neutralVolume(DEFAULT_SOURCE_NEUTRAL_VOLUME),
|
|
fadeStartVolume(0),
|
|
fadeEndVolume(0),
|
|
fadePassedTime(0),
|
|
fadeDuration(0) { }
|
|
|
|
MidiDriver_Multisource::MidiDriver_Multisource() :
|
|
_userVolumeScaling(false),
|
|
_userMusicVolume(192),
|
|
_userSfxVolume(192),
|
|
_userMute(false),
|
|
_timerRate(0),
|
|
_fadeDelay(0),
|
|
_timer_param(0),
|
|
_timer_proc(0) {
|
|
for (int i = 0; i < MAXIMUM_SOURCES; ++i) {
|
|
// Default source type: 0 = music, 1+ = SFX
|
|
_sources[i].type = (i == 0 ? SOURCE_TYPE_MUSIC : SOURCE_TYPE_SFX);
|
|
}
|
|
}
|
|
|
|
void MidiDriver_Multisource::send(uint32 b) {
|
|
send(-1, b);
|
|
}
|
|
|
|
uint32 MidiDriver_Multisource::property(int prop, uint32 param) {
|
|
switch (prop) {
|
|
case PROP_USER_VOLUME_SCALING:
|
|
if (param == 0xFFFF)
|
|
return _userVolumeScaling ? 1 : 0;
|
|
_userVolumeScaling = param > 0;
|
|
break;
|
|
default:
|
|
return MidiDriver::property(prop, param);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void MidiDriver_Multisource::startFade(uint16 duration, uint16 targetVolume) {
|
|
for (int i = 0; i < MAXIMUM_SOURCES; ++i) {
|
|
startFade(i, duration, targetVolume);
|
|
}
|
|
}
|
|
|
|
void MidiDriver_Multisource::startFade(uint8 source, uint16 duration, uint16 targetVolume) {
|
|
Common::StackLock lock(_fadingMutex);
|
|
|
|
assert(source < MAXIMUM_SOURCES);
|
|
|
|
// Reset the number of microseconds which have passed since the start of
|
|
// the fade.
|
|
_sources[source].fadePassedTime = 0;
|
|
// Set start volume to current volume.
|
|
_sources[source].fadeStartVolume = _sources[source].volume;
|
|
_sources[source].fadeEndVolume = targetVolume;
|
|
// Convert to microseconds and set the duration. A duration > 0 will cause
|
|
// the fade to be processed by updateFading.
|
|
_sources[source].fadeDuration = duration * 1000;
|
|
}
|
|
|
|
void MidiDriver_Multisource::abortFade(FadeAbortType abortType) {
|
|
for (int i = 0; i < MAXIMUM_SOURCES; ++i) {
|
|
abortFade(i, abortType);
|
|
}
|
|
}
|
|
|
|
void MidiDriver_Multisource::abortFade(uint8 source, FadeAbortType abortType) {
|
|
Common::StackLock lock(_fadingMutex);
|
|
|
|
assert(source < MAXIMUM_SOURCES);
|
|
|
|
if (!isFading(source)) {
|
|
// Nothing to abort.
|
|
return;
|
|
}
|
|
|
|
// Set the fade duration to 0. This will stop the fade from being processed
|
|
// by updateFading.
|
|
_sources[source].fadeDuration = 0;
|
|
|
|
// Now set the intended end volume.
|
|
uint16 newSourceVolume;
|
|
switch (abortType) {
|
|
case FADE_ABORT_TYPE_END_VOLUME:
|
|
newSourceVolume = _sources[source].fadeEndVolume;
|
|
break;
|
|
case FADE_ABORT_TYPE_START_VOLUME:
|
|
newSourceVolume = _sources[source].fadeStartVolume;
|
|
break;
|
|
case FADE_ABORT_TYPE_CURRENT_VOLUME:
|
|
default:
|
|
return;
|
|
}
|
|
setSourceVolume(source, newSourceVolume);
|
|
}
|
|
|
|
bool MidiDriver_Multisource::isFading() {
|
|
for (int i = 0; i < MAXIMUM_SOURCES; ++i) {
|
|
if (isFading(i))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool MidiDriver_Multisource::isFading(uint8 source) {
|
|
assert(source < MAXIMUM_SOURCES);
|
|
|
|
return _sources[source].fadeDuration > 0;
|
|
}
|
|
|
|
void MidiDriver_Multisource::updateFading() {
|
|
Common::StackLock lock(_fadingMutex);
|
|
|
|
// Decrease the fade delay by the time that has passed since the last
|
|
// fading update.
|
|
_fadeDelay -= (_fadeDelay < _timerRate ? _fadeDelay : _timerRate);
|
|
|
|
bool updatedVolume = false;
|
|
for (int i = 0; i < MAXIMUM_SOURCES; ++i) {
|
|
|
|
if (_sources[i].fadeDuration > 0) {
|
|
// This source has an active fade.
|
|
|
|
// Update the time that has passed since the start of the fade.
|
|
_sources[i].fadePassedTime += _timerRate;
|
|
|
|
if (_sources[i].fadePassedTime >= _sources[i].fadeDuration) {
|
|
// The fade has finished.
|
|
|
|
// Set the end volume.
|
|
setSourceVolume(i, _sources[i].fadeEndVolume);
|
|
updatedVolume = true;
|
|
|
|
// Stop further processing of this fade.
|
|
_sources[i].fadeDuration = 0;
|
|
} else if (_fadeDelay == 0) {
|
|
// The fade has not yet finished and the fade delay has run
|
|
// down. Waiting for the fade delay prevents sending out volume
|
|
// updates on every updateFading call, which can overflow
|
|
// slower MIDI hardware.
|
|
|
|
// Set the new volume value.
|
|
setSourceVolume(i, ((_sources[i].fadePassedTime * (_sources[i].fadeEndVolume - _sources[i].fadeStartVolume)) /
|
|
_sources[i].fadeDuration) + _sources[i].fadeStartVolume);
|
|
updatedVolume = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (updatedVolume)
|
|
// Set the fade delay to delay the next volume update.
|
|
_fadeDelay = FADING_DELAY;
|
|
}
|
|
|
|
void MidiDriver_Multisource::deinitSource(uint8 source) {
|
|
abortFade(source, FADE_ABORT_TYPE_END_VOLUME);
|
|
|
|
// Stop all active notes for this source.
|
|
stopAllNotes(source, 0xFF);
|
|
}
|
|
|
|
void MidiDriver_Multisource::setSourceType(SourceType type) {
|
|
for (int i = 0; i < MAXIMUM_SOURCES; ++i) {
|
|
setSourceType(i, type);
|
|
}
|
|
}
|
|
|
|
void MidiDriver_Multisource::setSourceType(uint8 source, SourceType type) {
|
|
assert(source < MAXIMUM_SOURCES);
|
|
|
|
_sources[source].type = type;
|
|
|
|
// A changed source type can mean a different user volume level should be
|
|
// used for this source. Calling applySourceVolume will apply the user
|
|
// volume.
|
|
applySourceVolume(source);
|
|
}
|
|
|
|
void MidiDriver_Multisource::setSourceVolume(uint16 volume) {
|
|
for (int i = 0; i < MAXIMUM_SOURCES; ++i) {
|
|
setSourceVolume(i, volume);
|
|
}
|
|
}
|
|
|
|
void MidiDriver_Multisource::setSourceVolume(uint8 source, uint16 volume) {
|
|
assert(source < MAXIMUM_SOURCES);
|
|
|
|
_sources[source].volume = volume;
|
|
|
|
// Set the volume for active notes and/or MIDI channels for this source.
|
|
applySourceVolume(source);
|
|
}
|
|
|
|
void MidiDriver_Multisource::resetSourceVolume() {
|
|
for (int i = 0; i < MAXIMUM_SOURCES; ++i) {
|
|
resetSourceVolume(i);
|
|
}
|
|
}
|
|
|
|
void MidiDriver_Multisource::resetSourceVolume(uint8 source) {
|
|
assert(source < MAXIMUM_SOURCES);
|
|
|
|
setSourceVolume(source, _sources[source].neutralVolume);
|
|
}
|
|
|
|
void MidiDriver_Multisource::setSourceNeutralVolume(uint16 volume) {
|
|
for (int i = 0; i < MAXIMUM_SOURCES; ++i) {
|
|
setSourceNeutralVolume(i, volume);
|
|
}
|
|
}
|
|
|
|
void MidiDriver_Multisource::setSourceNeutralVolume(uint8 source, uint16 volume) {
|
|
assert(source < MAXIMUM_SOURCES);
|
|
|
|
_sources[source].neutralVolume = volume;
|
|
}
|
|
|
|
void MidiDriver_Multisource::syncSoundSettings() {
|
|
// Get user volume settings.
|
|
_userMusicVolume = MIN(256, ConfMan.getInt("music_volume"));
|
|
_userSfxVolume = MIN(256, ConfMan.getInt("sfx_volume"));
|
|
_userMute = ConfMan.getBool("mute");
|
|
|
|
// Calling applySourceVolume will apply the user volume.
|
|
applySourceVolume(0xFF);
|
|
}
|
|
|
|
void MidiDriver_Multisource::onTimer() {
|
|
updateFading();
|
|
|
|
if (_timer_proc && _timer_param)
|
|
_timer_proc(_timer_param);
|
|
}
|
|
|
|
MidiDriver_NULL_Multisource::~MidiDriver_NULL_Multisource() {
|
|
g_system->getTimerManager()->removeTimerProc(timerCallback);
|
|
}
|
|
|
|
int MidiDriver_NULL_Multisource::open() {
|
|
// Setup a timer callback so "fades" will end after the specified time
|
|
// (effectively becoming timers, because there is no audio).
|
|
_timerRate = getBaseTempo();
|
|
g_system->getTimerManager()->installTimerProc(timerCallback, _timerRate, this, "MidiDriver_NULL_Multisource");
|
|
return 0;
|
|
}
|
|
|
|
void MidiDriver_NULL_Multisource::timerCallback(void *data) {
|
|
MidiDriver_NULL_Multisource *driver = (MidiDriver_NULL_Multisource *)data;
|
|
driver->onTimer();
|
|
}
|