Skip to content

Commit

Permalink
Merge pull request #452 from Aleph-One-Marathon/surround-sound-support
Browse files Browse the repository at this point in the history
Add support for surround sounds
  • Loading branch information
treellama authored Jan 19, 2024
2 parents 05c171c + 34a55bb commit 4d830bd
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 61 deletions.
74 changes: 40 additions & 34 deletions Source_Files/Misc/preferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,24 @@ static const uint32 max_saves_values[] = {
20, 100, 500, 0
};

static const std::unordered_map<ChannelType, int> mapping_channel_index = {
{ChannelType::_mono, 0},
{ChannelType::_stereo, 1},
{ChannelType::_quad, 2},
{ChannelType::_5_1, 3},
{ChannelType::_6_1, 4},
{ChannelType::_7_1, 5}
};

static const std::unordered_map<int, ChannelType> mapping_index_channel = {
{0, ChannelType::_mono},
{1, ChannelType::_stereo},
{2, ChannelType::_quad},
{3, ChannelType::_5_1},
{4, ChannelType::_6_1},
{5, ChannelType::_7_1}
};


enum {
iRENDERING_SYSTEM = 1000
Expand Down Expand Up @@ -1486,34 +1504,6 @@ static void graphics_dialog(void *arg)
* Sound dialog
*/

class w_toggle* stereo_w, * dynamic_w;

class w_stereo_toggle : public w_toggle {
public:
w_stereo_toggle(bool selection) : w_toggle(selection) {}

void selection_changed(void)
{
// Turning off stereo turns off dynamic tracking
w_toggle::selection_changed();
if (selection == false)
dynamic_w->set_selection(false);
}
};

class w_dynamic_toggle : public w_toggle {
public:
w_dynamic_toggle(bool selection) : w_toggle(selection) {}

void selection_changed(void)
{
// Turning on dynamic tracking turns on stereo
w_toggle::selection_changed();
if (selection == true)
stereo_w->set_selection(true);
}
};

class w_volume_slider : public w_percentage_slider {
public:
w_volume_slider(int vol) : w_percentage_slider(21, vol) {}
Expand Down Expand Up @@ -1549,12 +1539,14 @@ static void sound_dialog(void *arg)
table_placer *table = new table_placer(2, get_theme_space(ITEM_WIDGET), true);
table->col_flags(0, placeable::kAlignRight);

static const std::vector<std::string> channel_labels = { "Mono", "Stereo", "Quad", "5.1", "6.1", "7.1" };
w_select_popup* channel_w = new w_select_popup();
channel_w->set_labels(channel_labels);
channel_w->set_selection(mapping_channel_index.at(sound_preferences->channel_type));
table->dual_add(channel_w->label("Channels"), d);
table->dual_add(channel_w, d);

stereo_w = new w_stereo_toggle(sound_preferences->flags & _stereo_flag);
table->dual_add(stereo_w->label("Stereo"), d);
table->dual_add(stereo_w, d);

dynamic_w = new w_dynamic_toggle(TEST_FLAG(sound_preferences->flags, _dynamic_tracking_flag));
w_toggle* dynamic_w = new w_toggle(TEST_FLAG(sound_preferences->flags, _dynamic_tracking_flag));
table->dual_add(dynamic_w->label("Active Panning"), d);
table->dual_add(dynamic_w, d);

Expand Down Expand Up @@ -1631,7 +1623,6 @@ static void sound_dialog(void *arg)
if (quality_w->get_selection()) flags |= _16bit_sound_flag;
if (sounds3d_w->get_selection()) flags |= _3d_sounds_flag;
if (hrtf_w->get_selection()) flags |= _hrtf_flag;
if (stereo_w->get_selection()) flags |= _stereo_flag;
if (dynamic_w->get_selection()) flags |= _dynamic_tracking_flag;
if (ambient_w->get_selection()) flags |= _ambient_sound_flag;
if (more_w->get_selection()) flags |= _more_sounds_flag;
Expand Down Expand Up @@ -1662,6 +1653,12 @@ static void sound_dialog(void *arg)
changed = true;
}

auto channel = mapping_index_channel.at(channel_w->get_selection());
if (channel != sound_preferences->channel_type) {
sound_preferences->channel_type = channel;
changed = true;
}

if (changed) {
// set_sound_manager_parameters(sound_preferences);
SoundManager::instance()->SetParameters(*sound_preferences);
Expand Down Expand Up @@ -3844,6 +3841,7 @@ InfoTree sound_preferences_tree()
root.put_attr("rate", sound_preferences->rate);
root.put_attr("samples", sound_preferences->samples);
root.put_attr("video_export_volume_db", sound_preferences->video_export_volume_db);
root.put_attr("channel", static_cast<int>(sound_preferences->channel_type));

return root;
}
Expand Down Expand Up @@ -4814,6 +4812,14 @@ void parse_sound_preferences(InfoTree root, std::string version)
root.read_attr("rate", sound_preferences->rate);
root.read_attr("samples", sound_preferences->samples);
root.read_attr("video_export_volume_db", sound_preferences->video_export_volume_db);

int channel_type = 0;
root.read_attr("channel", channel_type);

if (channel_type)
{
sound_preferences->channel_type = static_cast<ChannelType>(channel_type);
}
}


Expand Down
29 changes: 14 additions & 15 deletions Source_Files/Sound/OpenALManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bool OpenALManager::Init(const AudioParameters& parameters) {

if (instance) { //Don't bother recreating all the OpenAL context if nothing changed for it
if (parameters.hrtf != instance->audio_parameters.hrtf || parameters.rate != instance->audio_parameters.rate
|| parameters.stereo != instance->audio_parameters.stereo || parameters.sample_frame_size != instance->audio_parameters.sample_frame_size) {
|| parameters.channel_type != instance->audio_parameters.channel_type || parameters.sample_frame_size != instance->audio_parameters.sample_frame_size) {

Shutdown();

Expand Down Expand Up @@ -229,15 +229,14 @@ bool OpenALManager::OpenDevice() {
return false;
}

ALCint channelsType = audio_parameters.stereo ? ALC_STEREO_SOFT : ALC_MONO_SOFT;
ALCint format = rendering_format ? rendering_format : GetBestOpenALRenderingFormat(channelsType);

rendering_format = format;
if (!openal_rendering_format) {
openal_rendering_format = GetBestOpenALSupportedFormat();
}

if (format) {
if (openal_rendering_format) {
ALCint attrs[] = {
ALC_FORMAT_TYPE_SOFT, format,
ALC_FORMAT_CHANNELS_SOFT, channelsType,
ALC_FORMAT_TYPE_SOFT, openal_rendering_format,
ALC_FORMAT_CHANNELS_SOFT, mapping_sdl_openal_channel.at(audio_parameters.channel_type),
ALC_FREQUENCY, audio_parameters.rate,
ALC_HRTF_SOFT, audio_parameters.hrtf,
0,
Expand Down Expand Up @@ -339,12 +338,12 @@ OpenALManager::OpenALManager(const AudioParameters& parameters) {
UpdateParameters(parameters);
alListener3i(AL_POSITION, 0, 0, 0);

auto openalFormat = GetBestOpenALRenderingFormat(parameters.stereo ? ALC_STEREO_SOFT : ALC_MONO_SOFT);
auto openalFormat = GetBestOpenALSupportedFormat();
assert(openalFormat && "Audio format not found or not supported");
SDL_AudioSpec desired = {};
desired.freq = parameters.rate;
desired.format = openalFormat ? mapping_openal_sdl.at(openalFormat) : 0;
desired.channels = parameters.stereo ? 2 : 1;
desired.format = mapping_openal_sdl_format.at(openalFormat);
desired.channels = static_cast<int>(parameters.channel_type);
desired.samples = parameters.sample_frame_size;
desired.callback = MixerCallback;
desired.userdata = reinterpret_cast<void*>(this);
Expand All @@ -353,8 +352,8 @@ OpenALManager::OpenALManager(const AudioParameters& parameters) {
CleanEverything();
} else {
audio_parameters.rate = sdl_audio_specs_obtained.freq;
audio_parameters.stereo = sdl_audio_specs_obtained.channels == 2;
rendering_format = mapping_sdl_openal.at(sdl_audio_specs_obtained.format);
audio_parameters.channel_type = static_cast<ChannelType>(sdl_audio_specs_obtained.channels);
openal_rendering_format = mapping_sdl_openal_format.at(sdl_audio_specs_obtained.format);
}
}

Expand Down Expand Up @@ -383,7 +382,7 @@ void OpenALManager::CleanEverything() {
assert(closedDevice && "Could not close audio device");
}

int OpenALManager::GetBestOpenALRenderingFormat(ALCint channelsType) {
int OpenALManager::GetBestOpenALSupportedFormat() {
auto device = p_ALCDevice ? p_ALCDevice : alcLoopbackOpenDeviceSOFT(nullptr);
if (!device) {
logError("Could not open audio loopback device to find best rendering format");
Expand All @@ -395,7 +394,7 @@ int OpenALManager::GetBestOpenALRenderingFormat(ALCint channelsType) {

ALCint attrs[] = {
ALC_FORMAT_TYPE_SOFT, format_type[i],
ALC_FORMAT_CHANNELS_SOFT, channelsType,
ALC_FORMAT_CHANNELS_SOFT, mapping_sdl_openal_channel.at(audio_parameters.channel_type),
ALC_FREQUENCY, audio_parameters.rate
};

Expand Down
30 changes: 24 additions & 6 deletions Source_Files/Sound/OpenALManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const inline std::unordered_map<ALCint, AVSampleFormat> mapping_openal_ffmpeg =
struct AudioParameters {
int rate;
int sample_frame_size;
bool stereo;
ChannelType channel_type;
bool balance_rewind;
bool hrtf;
bool sounds_3d;
Expand Down Expand Up @@ -67,7 +67,7 @@ class OpenALManager {
bool Support_HRTF_Toggling() const;
bool Is_HRTF_Enabled() const;
bool IsBalanceRewindSound() const { return audio_parameters.balance_rewind; }
ALCint GetRenderingFormat() const { return rendering_format; }
ALCint GetRenderingFormat() const { return openal_rendering_format; }
ALuint GetLowPassFilter(float highFrequencyGain) const;
private:
static OpenALManager* instance;
Expand All @@ -91,7 +91,7 @@ class OpenALManager {
std::queue<std::unique_ptr<AudioPlayer::AudioSource>> sources_pool;
std::deque<std::shared_ptr<AudioPlayer>> audio_players_queue; //for audio thread only
boost::lockfree::spsc_queue<std::shared_ptr<AudioPlayer>, boost::lockfree::capacity<256>> audio_players_shared; //pipeline main => audio thread
int GetBestOpenALRenderingFormat(ALCint channelsType);
int GetBestOpenALSupportedFormat();
void RetrieveSource(const std::shared_ptr<AudioPlayer>& player);

/* Loopback device functions */
Expand All @@ -110,7 +110,7 @@ class OpenALManager {
static void MixerCallback(void* usr, uint8* stream, int len);
SDL_AudioSpec sdl_audio_specs_obtained;
AudioParameters audio_parameters;
ALCint rendering_format = 0;
ALCint openal_rendering_format = 0;
ALuint low_pass_filter;

/* format type we supports for mixing / rendering
Expand All @@ -124,19 +124,37 @@ class OpenALManager {
ALC_UNSIGNED_BYTE_SOFT
};

const std::unordered_map<ALCint, int> mapping_openal_sdl = {
const std::unordered_map<ALCint, SDL_AudioFormat> mapping_openal_sdl_format = {
{ALC_FLOAT_SOFT, AUDIO_F32SYS},
{ALC_INT_SOFT, AUDIO_S32SYS},
{ALC_SHORT_SOFT, AUDIO_S16SYS},
{ALC_UNSIGNED_BYTE_SOFT, AUDIO_U8}
};

const std::unordered_map<int, ALCint> mapping_sdl_openal = {
const std::unordered_map<SDL_AudioFormat, ALCint> mapping_sdl_openal_format = {
{AUDIO_F32SYS, ALC_FLOAT_SOFT},
{AUDIO_S32SYS, ALC_INT_SOFT},
{AUDIO_S16SYS, ALC_SHORT_SOFT},
{AUDIO_U8, ALC_UNSIGNED_BYTE_SOFT}
};

const std::unordered_map<ChannelType, ALCint> mapping_sdl_openal_channel = {
{ChannelType::_mono, ALC_MONO_SOFT},
{ChannelType::_stereo, ALC_STEREO_SOFT},
{ChannelType::_quad, ALC_QUAD_SOFT},
{ChannelType::_5_1, ALC_5POINT1_SOFT},
{ChannelType::_6_1, ALC_6POINT1_SOFT},
{ChannelType::_7_1, ALC_7POINT1_SOFT}
};

const std::unordered_map<ALCint, ChannelType> mapping_openal_sdl_channel = {
{ALC_MONO_SOFT, ChannelType::_mono},
{ALC_STEREO_SOFT, ChannelType::_stereo},
{ALC_QUAD_SOFT, ChannelType::_quad},
{ALC_5POINT1_SOFT, ChannelType::_5_1},
{ALC_6POINT1_SOFT, ChannelType::_6_1},
{ALC_7POINT1_SOFT, ChannelType::_7_1}
};
};

#endif
9 changes: 5 additions & 4 deletions Source_Files/Sound/SoundManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -712,11 +712,12 @@ short SoundManager::RandomSoundIndexToSoundIndex(short random_sound_index)

SoundManager::Parameters::Parameters() :
volume_db(DEFAULT_SOUND_LEVEL_DB),
flags(_more_sounds_flag | _stereo_flag | _dynamic_tracking_flag | _ambient_sound_flag | _16bit_sound_flag),
flags(_more_sounds_flag | _dynamic_tracking_flag | _ambient_sound_flag | _16bit_sound_flag),
rate(DEFAULT_RATE),
samples(DEFAULT_SAMPLES),
music_db(DEFAULT_MUSIC_LEVEL_DB),
video_export_volume_db(DEFAULT_VIDEO_EXPORT_VOLUME_DB)
video_export_volume_db(DEFAULT_VIDEO_EXPORT_VOLUME_DB),
channel_type(ChannelType::_stereo)
{
}

Expand Down Expand Up @@ -770,7 +771,7 @@ void SoundManager::SetStatus(bool active)
AudioParameters audio_parameters = {
parameters.rate,
parameters.samples,
static_cast<bool>(parameters.flags & _stereo_flag),
parameters.channel_type,
!(parameters.flags & _lower_restart_delay),
static_cast<bool>(parameters.flags & _hrtf_flag),
static_cast<bool>(parameters.flags & _3d_sounds_flag),
Expand Down Expand Up @@ -891,7 +892,7 @@ float SoundManager::CalculatePitchModifier(short sound_index, _fixed pitch_modif

void SoundManager::AngleAndVolumeToStereoVolume(angle delta, short volume, short *right_volume, short *left_volume)
{
if (parameters.flags & _stereo_flag)
if (parameters.channel_type != ChannelType::_mono)
{
short fraction = delta & ((1<<(ANGULAR_BITS-2))-1);
short maximum_volume = volume + (volume >> 1);
Expand Down
4 changes: 3 additions & 1 deletion Source_Files/Sound/SoundManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class SoundManager
static const int DEFAULT_RATE = 44100;
static const int DEFAULT_SAMPLES = 1024;
float volume_db; // db
uint16 flags; // stereo, dynamic_tracking, etc.
uint16 flags; // dynamic_tracking, etc.

uint16 rate; // in Hz
uint16 samples; // size of buffer
Expand All @@ -110,6 +110,8 @@ class SoundManager

float video_export_volume_db;

ChannelType channel_type;

Parameters();
bool Verify();
} parameters;
Expand Down
11 changes: 10 additions & 1 deletion Source_Files/Sound/SoundManagerEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,18 @@ enum class AudioFormat
_32_float
};

enum class ChannelType
{
_mono = 1,
_stereo = 2,
_quad = 4,
_5_1 = 6,
_6_1 = 7,
_7_1 = 8
};

enum // initialization flags (some of these are used by the prefs, which fixes them)
{
_stereo_flag= 0x0001, /* play sounds in stereo [prefs] */
_dynamic_tracking_flag = 0x0002, /* tracks sound sources during idle_proc [prefs] */
_doppler_shift_flag= 0x0004, /* adjusts sound pitch during idle_proc */
_ambient_sound_flag= 0x0008, /* plays and tracks ambient sounds [prefs] */
Expand Down

0 comments on commit 4d830bd

Please sign in to comment.