cellAudio: implement downmix to 5.1

This commit is contained in:
Megamouse 2020-06-01 20:36:45 +02:00
parent 987ede2e6c
commit bb0aaea92d
13 changed files with 133 additions and 45 deletions

View file

@ -142,7 +142,7 @@ void audio_ringbuffer::enqueue(const float* in_buffer)
}
// Enqueue audio
bool success = backend->AddData(buf, AUDIO_BUFFER_SAMPLES * cfg.audio_channels);
const bool success = backend->AddData(buf, AUDIO_BUFFER_SAMPLES * cfg.audio_channels);
if (!success)
{
cellAudio.error("Could not enqueue buffer onto audio backend. Attempting to recover...");
@ -311,8 +311,8 @@ void audio_port::tag(s32 offset)
// We use -0.0f in case games check if the buffer is empty. -0.0f == 0.0f evaluates to true, but std::signbit can be used to distinguish them
const f32 tag = -0.0f;
const u32 tag_first_pos = num_channels == 2 ? PORT_BUFFER_TAG_FIRST_2CH : PORT_BUFFER_TAG_FIRST_8CH;
const u32 tag_delta = num_channels == 2 ? PORT_BUFFER_TAG_DELTA_2CH : PORT_BUFFER_TAG_DELTA_8CH;
const u32 tag_first_pos = num_channels == 2 ? PORT_BUFFER_TAG_FIRST_2CH : num_channels == 6 ? PORT_BUFFER_TAG_FIRST_6CH : PORT_BUFFER_TAG_FIRST_8CH;
const u32 tag_delta = num_channels == 2 ? PORT_BUFFER_TAG_DELTA_2CH : num_channels == 6 ? PORT_BUFFER_TAG_DELTA_6CH : PORT_BUFFER_TAG_DELTA_8CH;
for (u32 tag_pos = tag_first_pos, tag_nr = 0; tag_nr < PORT_BUFFER_TAG_COUNT; tag_pos += tag_delta, tag_nr++)
{
@ -341,8 +341,8 @@ std::tuple<u32, u32, u32, u32> cell_audio_thread::count_port_buffer_tags()
u32 port_pos = port.position();
// Find the last tag that has been touched
const u32 tag_first_pos = port.num_channels == 2 ? PORT_BUFFER_TAG_FIRST_2CH : PORT_BUFFER_TAG_FIRST_8CH;
const u32 tag_delta = port.num_channels == 2 ? PORT_BUFFER_TAG_DELTA_2CH : PORT_BUFFER_TAG_DELTA_8CH;
const u32 tag_first_pos = port.num_channels == 2 ? PORT_BUFFER_TAG_FIRST_2CH : port.num_channels == 6 ? PORT_BUFFER_TAG_FIRST_6CH : PORT_BUFFER_TAG_FIRST_8CH;
const u32 tag_delta = port.num_channels == 2 ? PORT_BUFFER_TAG_DELTA_2CH : port.num_channels == 6 ? PORT_BUFFER_TAG_DELTA_6CH : PORT_BUFFER_TAG_DELTA_8CH;
u32 last_touched_tag_nr = port.prev_touched_tag_nr;
bool retouched = false;
@ -742,16 +742,19 @@ void cell_audio_thread::operator()()
// Mix
float *buf = ringbuffer->get_current_buffer();
if (cfg.audio_channels == 2)
{
mix<true>(buf);
}
else if (cfg.audio_channels == 8)
{
mix<false>(buf);
}
else
switch (cfg.audio_channels)
{
case 2:
mix<audio_channels::downmix_to_stereo>(buf);
break;
case 6:
mix<audio_channels::downmix_to_5_1>(buf);
break;
case 8:
mix<audio_channels::surround_7_1>(buf);
break;
default:
fmt::throw_exception("Unsupported number of audio channels: %u", cfg.audio_channels);
}
@ -766,12 +769,12 @@ void cell_audio_thread::operator()()
ringbuffer.reset();
}
template <bool DownmixToStereo>
template <audio_channels downmix>
void cell_audio_thread::mix(float *out_buffer, s32 offset)
{
AUDIT(out_buffer != nullptr);
constexpr u32 channels = DownmixToStereo ? 2 : 8;
constexpr u32 channels = downmix == audio_channels::surround_7_1 ? 8 : downmix == audio_channels::downmix_to_5_1 ? 6 : 2;
constexpr u32 out_buffer_sz = channels * AUDIO_BUFFER_SAMPLES;
bool first_mix = true;
@ -823,14 +826,18 @@ void cell_audio_thread::mix(float *out_buffer, s32 offset)
out_buffer[out + 0] = left;
out_buffer[out + 1] = right;
if constexpr (!DownmixToStereo)
if constexpr (downmix != audio_channels::downmix_to_stereo)
{
out_buffer[out + 2] = 0.0f;
out_buffer[out + 3] = 0.0f;
out_buffer[out + 4] = 0.0f;
out_buffer[out + 5] = 0.0f;
out_buffer[out + 6] = 0.0f;
out_buffer[out + 7] = 0.0f;
if constexpr (downmix != audio_channels::downmix_to_5_1)
{
out_buffer[out + 6] = 0.0f;
out_buffer[out + 7] = 0.0f;
}
}
}
first_mix = false;
@ -866,13 +873,22 @@ void cell_audio_thread::mix(float *out_buffer, s32 offset)
const float side_left = buf[in + 6] * m;
const float side_right = buf[in + 7] * m;
if constexpr (DownmixToStereo)
if constexpr (downmix == audio_channels::downmix_to_stereo)
{
// Don't mix in the lfe as per dolby specification and based on documentation
const float mid = center * 0.5;
out_buffer[out + 0] = left * minus_3db + mid + side_left * 0.5 + rear_left * 0.5;
out_buffer[out + 1] = right * minus_3db + mid + side_right * 0.5 + rear_right * 0.5;
}
else if constexpr (downmix == audio_channels::downmix_to_5_1)
{
out_buffer[out + 0] = left;
out_buffer[out + 1] = right;
out_buffer[out + 2] = center;
out_buffer[out + 3] = low_freq;
out_buffer[out + 4] = side_left + rear_left;
out_buffer[out + 5] = side_right + rear_right;
}
else
{
out_buffer[out + 0] = left;
@ -902,13 +918,22 @@ void cell_audio_thread::mix(float *out_buffer, s32 offset)
const float side_left = buf[in + 6] * m;
const float side_right = buf[in + 7] * m;
if constexpr (DownmixToStereo)
if constexpr (downmix == audio_channels::downmix_to_stereo)
{
// Don't mix in the lfe as per dolby specification and based on documentation
const float mid = center * 0.5;
out_buffer[out + 0] += left * minus_3db + mid + side_left * 0.5 + rear_left * 0.5;
out_buffer[out + 1] += right * minus_3db + mid + side_right * 0.5 + rear_right * 0.5;
}
else if constexpr (downmix == audio_channels::downmix_to_5_1)
{
out_buffer[out + 0] += left;
out_buffer[out + 1] += right;
out_buffer[out + 2] += center;
out_buffer[out + 3] += low_freq;
out_buffer[out + 4] += side_left + rear_left;
out_buffer[out + 5] += side_right + rear_right;
}
else
{
out_buffer[out + 0] += left;