mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-16 23:17:29 +00:00
cellAudio: Implement application based downmix settings
This commit is contained in:
parent
422246825b
commit
d47f1ef406
@ -1,6 +1,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "AudioBackend.h"
|
||||
#include "Emu/system_config.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu//Cell/Modules/cellAudioOut.h"
|
||||
|
||||
AudioBackend::AudioBackend() {}
|
||||
|
||||
@ -97,3 +99,60 @@ void AudioBackend::normalize(u32 sample_cnt, const f32* src, f32* dst)
|
||||
dst[i] = std::clamp<f32>(src[i], -1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
AudioChannelCnt AudioBackend::get_channel_count(audio_downmix downmix)
|
||||
{
|
||||
switch (downmix)
|
||||
{
|
||||
case audio_downmix::no_downmix: return AudioChannelCnt::SURROUND_7_1;
|
||||
case audio_downmix::downmix_to_5_1: return AudioChannelCnt::SURROUND_5_1;
|
||||
case audio_downmix::downmix_to_stereo: return AudioChannelCnt::STEREO;
|
||||
case audio_downmix::use_application_settings:
|
||||
{
|
||||
audio_out_configuration& audio_out = g_fxo->get<audio_out_configuration>();
|
||||
std::lock_guard lock(audio_out.mtx);
|
||||
ensure(!audio_out.out.empty());
|
||||
audio_out_configuration::audio_out& out = audio_out.out.at(CELL_AUDIO_OUT_PRIMARY);
|
||||
|
||||
switch (out.downmixer)
|
||||
{
|
||||
case CELL_AUDIO_OUT_DOWNMIXER_NONE:
|
||||
{
|
||||
switch (out.channels)
|
||||
{
|
||||
case 2: return AudioChannelCnt::STEREO;
|
||||
case 6: return AudioChannelCnt::SURROUND_5_1;
|
||||
case 8: return AudioChannelCnt::SURROUND_7_1;
|
||||
default:
|
||||
fmt::throw_exception("Unsupported channel count in cellAudioOut config: %d", out.channels);
|
||||
}
|
||||
}
|
||||
case CELL_AUDIO_OUT_DOWNMIXER_TYPE_A:
|
||||
{
|
||||
switch (out.channels)
|
||||
{
|
||||
case 2:
|
||||
return AudioChannelCnt::STEREO;
|
||||
default:
|
||||
fmt::throw_exception("Unsupported channel count for CELL_AUDIO_OUT_DOWNMIXER_TYPE_A in cellAudioOut config: %d", out.channels);
|
||||
}
|
||||
}
|
||||
case CELL_AUDIO_OUT_DOWNMIXER_TYPE_B:
|
||||
{
|
||||
switch (out.channels)
|
||||
{
|
||||
case 6:
|
||||
case 8:
|
||||
return AudioChannelCnt::SURROUND_5_1;
|
||||
default:
|
||||
fmt::throw_exception("Unsupported channel count for CELL_AUDIO_OUT_DOWNMIXER_TYPE_B in cellAudioOut config: %d", out.channels);
|
||||
}
|
||||
}
|
||||
default:
|
||||
fmt::throw_exception("Unknown downmixer in cellAudioOut config: %d", out.downmixer);
|
||||
}
|
||||
}
|
||||
default:
|
||||
fmt::throw_exception("Unknown audio channel mode %s (%d)", downmix, static_cast<int>(downmix));
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ enum class AudioChannelCnt : u32
|
||||
SURROUND_7_1 = 8,
|
||||
};
|
||||
|
||||
enum class audio_downmix;
|
||||
|
||||
class AudioBackend
|
||||
{
|
||||
public:
|
||||
@ -130,6 +132,16 @@ public:
|
||||
*/
|
||||
static void apply_volume_static(f32 vol, u32 sample_cnt, const f32* src, f32* dst);
|
||||
|
||||
/*
|
||||
* Normalize float samples in range from -1.0 to 1.0.
|
||||
*/
|
||||
static void normalize(u32 sample_cnt, const f32* src, f32* dst);
|
||||
|
||||
/*
|
||||
* Returns the channel count based on the downmix mode.
|
||||
*/
|
||||
static AudioChannelCnt get_channel_count(audio_downmix downmix);
|
||||
|
||||
/*
|
||||
* Downmix audio stream.
|
||||
*/
|
||||
@ -188,11 +200,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Normalize float samples in range from -1.0 to 1.0.
|
||||
*/
|
||||
static void normalize(u32 sample_cnt, const f32* src, f32* dst);
|
||||
|
||||
protected:
|
||||
AudioSampleSize m_sample_size = AudioSampleSize::FLOAT;
|
||||
AudioFreq m_sampling_rate = AudioFreq::FREQ_48K;
|
||||
|
@ -66,19 +66,7 @@ void cell_audio_config::reset(bool backend_changed)
|
||||
|
||||
const AudioFreq freq = AudioFreq::FREQ_48K;
|
||||
const AudioSampleSize sample_size = raw.convert_to_s16 ? AudioSampleSize::S16 : AudioSampleSize::FLOAT;
|
||||
const AudioChannelCnt ch_cnt = [&]()
|
||||
{
|
||||
switch (raw.downmix)
|
||||
{
|
||||
case audio_downmix::no_downmix: return AudioChannelCnt::SURROUND_7_1;
|
||||
case audio_downmix::downmix_to_5_1: return AudioChannelCnt::SURROUND_5_1;
|
||||
case audio_downmix::downmix_to_stereo: return AudioChannelCnt::STEREO;
|
||||
case audio_downmix::use_application_settings: return AudioChannelCnt::STEREO; // TODO
|
||||
default:
|
||||
fmt::throw_exception("Unknown audio channel mode %s (%d)", raw.downmix, static_cast<int>(raw.downmix));
|
||||
}
|
||||
}();
|
||||
|
||||
const AudioChannelCnt ch_cnt = AudioBackend::get_channel_count(raw.downmix);
|
||||
const f64 cb_frame_len = backend->Open(freq, sample_size, ch_cnt) ? backend->GetCallbackFrameLen() : 0.0;
|
||||
|
||||
audio_channels = static_cast<u32>(ch_cnt);
|
||||
|
@ -1,7 +1,10 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "cellAudioOut.h"
|
||||
#include "cellAudio.h"
|
||||
#include "Emu/Cell/lv2/sys_rsxaudio.h"
|
||||
|
||||
LOG_CHANNEL(cellSysutil);
|
||||
|
||||
@ -132,8 +135,7 @@ error_code cellAudioOutGetState(u32 audioOut, u32 deviceIndex, vm::ptr<CellAudio
|
||||
return num;
|
||||
}
|
||||
|
||||
CellAudioOutState _state;
|
||||
std::memset(&_state, 0, sizeof(_state));
|
||||
CellAudioOutState _state{};
|
||||
|
||||
if (deviceIndex >= num + 0u)
|
||||
{
|
||||
@ -144,7 +146,7 @@ error_code cellAudioOutGetState(u32 audioOut, u32 deviceIndex, vm::ptr<CellAudio
|
||||
// Although it was constant on my tests so let's write that
|
||||
_state.state = 0x10;
|
||||
_state.soundMode.layout = 0xD00C1680;
|
||||
std::memcpy(state.get_ptr(), &_state, state.size());
|
||||
*state = _state;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -166,12 +168,11 @@ error_code cellAudioOutGetState(u32 audioOut, u32 deviceIndex, vm::ptr<CellAudio
|
||||
_state.soundMode.layout = CELL_AUDIO_OUT_SPEAKER_LAYOUT_8CH_LREClrxy;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
std::memcpy(state.get_ptr(), &_state, state.size());
|
||||
*state = _state;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -187,28 +188,40 @@ error_code cellAudioOutConfigure(u32 audioOut, vm::ptr<CellAudioOutConfiguration
|
||||
switch (audioOut)
|
||||
{
|
||||
case CELL_AUDIO_OUT_PRIMARY:
|
||||
{
|
||||
if (config->channel)
|
||||
{
|
||||
//Emu.GetAudioManager().GetInfo().mode.channel = config->channel;
|
||||
}
|
||||
|
||||
//Emu.GetAudioManager().GetInfo().mode.encoder = config->encoder;
|
||||
|
||||
if (config->downMixer)
|
||||
{
|
||||
//Emu.GetAudioManager().GetInfo().mode.downMixer = config->downMixer;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
break;
|
||||
case CELL_AUDIO_OUT_SECONDARY:
|
||||
return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
|
||||
default: break;
|
||||
default:
|
||||
return CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
return CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
|
||||
audio_out_configuration::audio_out out_old;
|
||||
audio_out_configuration::audio_out out_new;
|
||||
|
||||
{
|
||||
audio_out_configuration& cfg = g_fxo->get<audio_out_configuration>();
|
||||
std::lock_guard lock(cfg.mtx);
|
||||
|
||||
audio_out_configuration::audio_out& out = cfg.out.at(audioOut);
|
||||
out_old = out;
|
||||
|
||||
out.channels = config->channel;
|
||||
out.encoder = config->encoder;
|
||||
out.downmixer = config->downMixer;
|
||||
|
||||
out_new = out;
|
||||
}
|
||||
|
||||
if (g_cfg.audio.audio_channel_downmix == audio_downmix::use_application_settings &&
|
||||
std::memcmp(&out_old, &out_new, sizeof(audio_out_configuration::audio_out)) != 0)
|
||||
{
|
||||
audio::configure_audio();
|
||||
audio::configure_rsxaudio();
|
||||
}
|
||||
|
||||
cellSysutil.notice("cellAudioOutConfigure: channels=%d, encoder=%d, downMixer=%d", config->channel, config->encoder, config->downMixer);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellAudioOutGetConfiguration(u32 audioOut, vm::ptr<CellAudioOutConfiguration> config, vm::ptr<CellAudioOutOption> option)
|
||||
@ -220,26 +233,27 @@ error_code cellAudioOutGetConfiguration(u32 audioOut, vm::ptr<CellAudioOutConfig
|
||||
return CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
CellAudioOutConfiguration _config;
|
||||
std::memset(&_config, 0, sizeof(_config));
|
||||
|
||||
switch (audioOut)
|
||||
{
|
||||
case CELL_AUDIO_OUT_PRIMARY:
|
||||
{
|
||||
_config.channel = CELL_AUDIO_OUT_CHNUM_8;
|
||||
_config.encoder = CELL_AUDIO_OUT_CODING_TYPE_LPCM;
|
||||
_config.downMixer = CELL_AUDIO_OUT_DOWNMIXER_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
case CELL_AUDIO_OUT_SECONDARY:
|
||||
return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
|
||||
default:
|
||||
return CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
std::memcpy(config.get_ptr(), &_config, config.size());
|
||||
audio_out_configuration& cfg = g_fxo->get<audio_out_configuration>();
|
||||
std::lock_guard lock(cfg.mtx);
|
||||
|
||||
CellAudioOutConfiguration _config{};
|
||||
|
||||
audio_out_configuration::audio_out& out = cfg.out.at(audioOut);
|
||||
_config.channel = out.channels;
|
||||
_config.encoder = out.encoder;
|
||||
_config.downMixer = out.downmixer;
|
||||
|
||||
*config = _config;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -281,18 +295,17 @@ error_code cellAudioOutGetDeviceInfo(u32 audioOut, u32 deviceIndex, vm::ptr<Cell
|
||||
if (audioOut == CELL_AUDIO_OUT_SECONDARY)
|
||||
{
|
||||
// Error codes are not returned here
|
||||
std::memset(info.get_ptr(), 0, info.size());
|
||||
*info = {};
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_AUDIO_OUT_ERROR_PARAMETER_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
CellAudioOutDeviceInfo _info;
|
||||
std::memset(&_info, 0, sizeof(_info));
|
||||
CellAudioOutDeviceInfo _info{};
|
||||
|
||||
_info.portType = CELL_AUDIO_OUT_PORT_HDMI;
|
||||
_info.availableModeCount = 2;
|
||||
_info.availableModeCount = 3;
|
||||
_info.state = CELL_AUDIO_OUT_DEVICE_STATE_AVAILABLE;
|
||||
_info.latency = 1000;
|
||||
_info.availableModes[0].type = CELL_AUDIO_OUT_CODING_TYPE_LPCM;
|
||||
@ -303,8 +316,12 @@ error_code cellAudioOutGetDeviceInfo(u32 audioOut, u32 deviceIndex, vm::ptr<Cell
|
||||
_info.availableModes[1].channel = CELL_AUDIO_OUT_CHNUM_2;
|
||||
_info.availableModes[1].fs = CELL_AUDIO_OUT_FS_48KHZ;
|
||||
_info.availableModes[1].layout = CELL_AUDIO_OUT_SPEAKER_LAYOUT_2CH;
|
||||
_info.availableModes[2].type = CELL_AUDIO_OUT_CODING_TYPE_LPCM;
|
||||
_info.availableModes[2].channel = CELL_AUDIO_OUT_CHNUM_6;
|
||||
_info.availableModes[2].fs = CELL_AUDIO_OUT_FS_48KHZ;
|
||||
_info.availableModes[2].layout = CELL_AUDIO_OUT_SPEAKER_LAYOUT_6CH_LREClr;
|
||||
|
||||
std::memcpy(info.get_ptr(), &_info, info.size());
|
||||
*info = _info;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -327,6 +344,11 @@ error_code cellAudioOutSetCopyControl(u32 audioOut, u32 control)
|
||||
return CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
audio_out_configuration& cfg = g_fxo->get<audio_out_configuration>();
|
||||
std::lock_guard lock(cfg.mtx);
|
||||
|
||||
cfg.out.at(audioOut).copy_control = control;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@ enum CellAudioOutError : u32
|
||||
CELL_AUDIO_OUT_ERROR_CONDITION_BUSY = 0x8002b247,
|
||||
};
|
||||
|
||||
|
||||
enum CellAudioOut
|
||||
{
|
||||
CELL_AUDIO_OUT_PRIMARY = 0,
|
||||
@ -187,3 +186,21 @@ struct CellAudioOutDeviceConfiguration
|
||||
{
|
||||
//(Omitted)
|
||||
};
|
||||
|
||||
|
||||
// FXO Object
|
||||
|
||||
struct audio_out_configuration
|
||||
{
|
||||
std::mutex mtx;
|
||||
|
||||
struct audio_out
|
||||
{
|
||||
u32 channels = CELL_AUDIO_OUT_CHNUM_8;
|
||||
u32 encoder = CELL_AUDIO_OUT_CODING_TYPE_LPCM;
|
||||
u32 downmixer = CELL_AUDIO_OUT_DOWNMIXER_NONE;
|
||||
u32 copy_control = CELL_AUDIO_OUT_COPY_CONTROL_COPY_FREE;
|
||||
};
|
||||
|
||||
std::array<audio_out, 2> out;
|
||||
};
|
||||
|
@ -1322,20 +1322,7 @@ void rsxaudio_backend_thread::update_emu_cfg()
|
||||
|
||||
rsxaudio_backend_thread::emu_audio_cfg rsxaudio_backend_thread::get_emu_cfg()
|
||||
{
|
||||
const AudioChannelCnt out_ch_cnt = [&]()
|
||||
{
|
||||
switch (g_cfg.audio.audio_channel_downmix)
|
||||
{
|
||||
case audio_downmix::use_application_settings:
|
||||
case audio_downmix::downmix_to_stereo: return AudioChannelCnt::STEREO;
|
||||
case audio_downmix::downmix_to_5_1: return AudioChannelCnt::SURROUND_5_1;
|
||||
case audio_downmix::no_downmix: return AudioChannelCnt::SURROUND_7_1;
|
||||
default:
|
||||
{
|
||||
fmt::throw_exception("Unsupported downmix level: %u", static_cast<u64>(g_cfg.audio.audio_channel_downmix.get()));
|
||||
}
|
||||
}
|
||||
}();
|
||||
const AudioChannelCnt out_ch_cnt = AudioBackend::get_channel_count(g_cfg.audio.audio_channel_downmix);
|
||||
|
||||
emu_audio_cfg cfg =
|
||||
{
|
||||
|
@ -957,8 +957,6 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
||||
|
||||
m_emu_settings->EnhanceComboBox(ui->combo_audio_downmix, emu_settings_type::AudioChannels);
|
||||
SubscribeTooltip(ui->gb_audio_downmix, tooltips.settings.downmix);
|
||||
// TODO: enable this setting once cellAudioOutConfigure can change downmix on the fly
|
||||
ui->combo_audio_downmix->removeItem(static_cast<int>(audio_downmix::use_application_settings));
|
||||
|
||||
m_emu_settings->EnhanceComboBox(ui->audioProviderBox, emu_settings_type::AudioProvider);
|
||||
SubscribeTooltip(ui->gb_audio_provider, tooltips.settings.audio_provider);
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
const QString audio_avport = tr("Controls which avport is used to sample audio data from.");
|
||||
const QString audio_dump = tr("Saves all audio as a raw wave file. If unsure, leave this unchecked.");
|
||||
const QString convert = tr("Uses 16-bit audio samples instead of default 32-bit floating point.\nUse with buggy audio drivers if you have no sound or completely broken sound.");
|
||||
const QString downmix = tr("Uses chosen audio output instead of default 7.1 surround sound.\nUse downmix to stereo with stereo audio devices. Use 5.1 or higher only if you are using a surround sound audio system.");
|
||||
const QString downmix = tr("Uses chosen audio output instead of default 7.1 surround sound.\nUse downmix to stereo with stereo audio devices.\nUse 5.1 or higher only if you are using a surround sound audio system.\nIf you want to let the game decide choose the application settings.");
|
||||
const QString master_volume = tr("Controls the overall volume of the emulation.\nValues above 100% might reduce the audio quality.");
|
||||
const QString enable_buffering = tr("Enables audio buffering, which reduces crackle/stutter but increases audio latency.");
|
||||
const QString audio_buffer_duration = tr("Target buffer duration in milliseconds.\nHigher values make the buffering algorithm's job easier, but may introduce noticeable audio latency.");
|
||||
|
Loading…
Reference in New Issue
Block a user