Add simple channel downmixer to play >8ch files

This commit is contained in:
bnnm 2018-04-29 23:31:52 +02:00
parent fb63ad4aae
commit eebc83a0c8
6 changed files with 67 additions and 3 deletions

View File

@ -23,6 +23,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
//
// Dialog
//
//elements: text, id, x, y, width, height [, style [, extended-style]]
IDD_CONFIG DIALOGEX 0, 0, 187, 156
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
@ -40,6 +41,8 @@ BEGIN
CONTROL "Loop forever",IDC_LOOP_FOREVER,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,70,77,10
CONTROL "Ignore looping",IDC_IGNORE_LOOP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,83,77,10
CONTROL "Disable subsongs",IDC_DISABLE_SUBSONGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,99,87,10
LTEXT "Downmix",IDC_STATIC,7,115,48,12
EDITTEXT IDC_DOWNMIX_CHANNELS,52,112,37,14,ES_AUTOHSCROLL
END

View File

@ -20,6 +20,7 @@ static const GUID guid_cfg_LoopCount = { 0xfc8dfd72, 0xfae8, 0x44cc, { 0xbe, 0x9
static const GUID guid_cfg_FadeLength = { 0x61da7ef1, 0x56a5, 0x4368, { 0xae, 0x6, 0xec, 0x6f, 0xd7, 0xe6, 0x15, 0x5d } };
static const GUID guid_cfg_FadeDelay = { 0x73907787, 0xaf49, 0x4659, { 0x96, 0x8e, 0x9f, 0x70, 0xa1, 0x62, 0x49, 0xc4 } };
static const GUID guid_cfg_DisableSubsongs = { 0xa8cdd664, 0xb32b, 0x4a36, { 0x83, 0x07, 0xa0, 0x4c, 0xcd, 0x52, 0xa3, 0x7c } };
static const GUID guid_cfg_DownmixChannels = { 0x5a0e65dd, 0xeb37, 0x4c67, { 0x9a, 0xb1, 0x3f, 0xb0, 0xc9, 0x7e, 0xb0, 0xe0 } };
static cfg_bool cfg_LoopForever(guid_cfg_LoopForever, DEFAULT_LOOP_FOREVER);
static cfg_bool cfg_IgnoreLoop(guid_cfg_IgnoreLoop, DEFAULT_IGNORE_LOOP);
@ -27,6 +28,7 @@ static cfg_string cfg_LoopCount(guid_cfg_LoopCount, DEFAULT_LOOP_COUNT);
static cfg_string cfg_FadeLength(guid_cfg_FadeLength, DEFAULT_FADE_SECONDS);
static cfg_string cfg_FadeDelay(guid_cfg_FadeDelay, DEFAULT_FADE_DELAY_SECONDS);
static cfg_bool cfg_DisableSubsongs(guid_cfg_DisableSubsongs, DEFAULT_DISABLE_SUBSONGS);
static cfg_string cfg_DownmixChannels(guid_cfg_DownmixChannels, DEFAULT_DOWNMIX_CHANNELS);
// Needs to be here in rder to access the static config
void input_vgmstream::load_settings()
@ -38,6 +40,7 @@ void input_vgmstream::load_settings()
loop_forever = cfg_LoopForever;
ignore_loop = cfg_IgnoreLoop;
disable_subsongs = cfg_DisableSubsongs;
sscanf(cfg_DownmixChannels.get_ptr(),"%d",&downmix_channels);
}
const char * vgmstream_prefs::get_name()
@ -70,6 +73,8 @@ BOOL vgmstreamPreferences::OnInitDialog(CWindow, LPARAM)
CheckDlgButton(IDC_DISABLE_SUBSONGS, cfg_DisableSubsongs?BST_CHECKED:BST_UNCHECKED);
uSetDlgItemText(m_hWnd, IDC_DOWNMIX_CHANNELS, cfg_DownmixChannels);
return TRUE;
}
@ -93,6 +98,8 @@ void vgmstreamPreferences::reset()
uSetDlgItemText(m_hWnd, IDC_FADE_DELAY_SECONDS, DEFAULT_FADE_DELAY_SECONDS);
CheckDlgButton(IDC_DISABLE_SUBSONGS, DEFAULT_DISABLE_SUBSONGS?BST_CHECKED:BST_UNCHECKED);
uSetDlgItemText(m_hWnd, IDC_DOWNMIX_CHANNELS, DEFAULT_DOWNMIX_CHANNELS);
}
@ -107,6 +114,7 @@ void vgmstreamPreferences::apply()
double temp_fade_delay_seconds;
double temp_loop_count;
int consumed;
int temp_downmix_channels;
pfc::string buf;
buf = uGetDlgItemText(m_hWnd, IDC_FADE_SECONDS);
@ -141,6 +149,18 @@ void vgmstreamPreferences::apply()
"Error",MB_OK|MB_ICONERROR);
return;
} else cfg_FadeDelay = buf.get_ptr();
buf = uGetDlgItemText(m_hWnd, IDC_DOWNMIX_CHANNELS);
if (sscanf(buf.get_ptr(),"%d%n",&temp_downmix_channels,&consumed)<1
|| consumed!=strlen(buf.get_ptr()) ||
temp_downmix_channels<0) {
uMessageBox(m_hWnd,
"Invalid value for Downmix Channels\n"
"Must be a number greater than or equal to zero",
"Error",MB_OK|MB_ICONERROR);
return;
} else cfg_DownmixChannels = buf.get_ptr();
}
@ -166,6 +186,9 @@ bool vgmstreamPreferences::HasChanged()
if(FadeDelay != uGetDlgItemText(m_hWnd, IDC_FADE_DELAY_SECONDS)) return true;
if(LoopCount != uGetDlgItemText(m_hWnd, IDC_LOOP_COUNT)) return true;
pfc::string DownmixChannels(cfg_DownmixChannels);
if(DownmixChannels != uGetDlgItemText(m_hWnd, IDC_DOWNMIX_CHANNELS)) return true;
return FALSE;
}

View File

@ -15,6 +15,7 @@
#define DEFAULT_LOOP_FOREVER false
#define DEFAULT_IGNORE_LOOP false
#define DEFAULT_DISABLE_SUBSONGS false
#define DEFAULT_DOWNMIX_CHANNELS "8"
class vgmstreamPreferences : public CDialogImpl<vgmstreamPreferences>, public preferences_page_instance {
public:
@ -42,6 +43,7 @@ public:
COMMAND_HANDLER_EX(IDC_FADE_DELAY_SECONDS, EN_CHANGE, OnEditChange)
COMMAND_HANDLER_EX(IDC_LOOP_COUNT, EN_CHANGE, OnEditChange)
COMMAND_HANDLER_EX(IDC_DISABLE_SUBSONGS, BN_CLICKED, OnEditChange)
COMMAND_HANDLER_EX(IDC_DOWNMIX_CHANNELS, EN_CHANGE, OnEditChange)
END_MSG_MAP()
private:
BOOL OnInitDialog(CWindow, LPARAM);

View File

@ -56,6 +56,7 @@ input_vgmstream::input_vgmstream() {
loop_forever = false;
ignore_loop = 0;
disable_subsongs = false;
downmix_channels = 0;
load_settings();
}
@ -228,8 +229,38 @@ bool input_vgmstream::decode_run(audio_chunk & p_chunk,abort_callback & p_abort)
}
}
bytes = (samples_to_do*vgmstream->channels * sizeof(sample_buffer[0]));
p_chunk.set_data_fixedpoint((char*)sample_buffer, bytes, vgmstream->sample_rate, vgmstream->channels, 16, audio_chunk::g_guess_channel_config(vgmstream->channels));
/* downmix enabled (foobar refuses to do more than 8 channels) */
if (downmix_channels > 0 && downmix_channels < vgmstream->channels) {
short temp_buffer[OUTBUF_SIZE];
int s, ch;
for (s = 0; s < samples_to_do; s++) {
/* copy channels up to max */
for (ch = 0; ch < downmix_channels; ch++) {
temp_buffer[s*downmix_channels + ch] = sample_buffer[s*vgmstream->channels + ch];
}
/* then mix the rest */
for (ch = downmix_channels; ch < vgmstream->channels; ch++) {
int downmix_ch = ch % downmix_channels;
int new_sample = ((int)temp_buffer[s*downmix_channels + downmix_ch] + (int)sample_buffer[s*vgmstream->channels + ch]);
new_sample = (int)(new_sample * 0.7); /* limit clipping without removing too much loudness... hopefully */
if (new_sample > 32767) new_sample = 32767;
else if (new_sample < -32768) new_sample = -32768;
temp_buffer[s*downmix_channels + downmix_ch] = (short)new_sample;
}
}
/* copy back to global buffer... in case of multithreading stuff? */
memcpy(sample_buffer,temp_buffer, samples_to_do*downmix_channels*sizeof(short));
bytes = (samples_to_do*downmix_channels * sizeof(sample_buffer[0]));
p_chunk.set_data_fixedpoint((char*)sample_buffer, bytes, vgmstream->sample_rate, downmix_channels, 16, audio_chunk::g_guess_channel_config(downmix_channels));
}
else {
bytes = (samples_to_do*vgmstream->channels * sizeof(sample_buffer[0]));
p_chunk.set_data_fixedpoint((char*)sample_buffer, bytes, vgmstream->sample_rate, vgmstream->channels, 16, audio_chunk::g_guess_channel_config(vgmstream->channels));
}
decode_pos_samples+=samples_to_do;
decode_pos_ms=decode_pos_samples*1000LL/vgmstream->sample_rate;
@ -407,7 +438,10 @@ void input_vgmstream::get_subsong_info(t_uint32 p_subsong, pfc::string_base & ti
title.set_string(p, e - p);
if (!disable_subsongs && infostream && infostream->num_streams > 1) {
sprintf(temp,"#%d",infostream->stream_index);
int info_subsong = infostream->stream_index;
if (info_subsong==0)
info_subsong = 1;
sprintf(temp,"#%d",info_subsong);
title += temp;
if (infostream->stream_name[0] != '\0') {

View File

@ -61,6 +61,7 @@ class input_vgmstream : public input_stubs {
bool force_ignore_loop;
int ignore_loop;
bool disable_subsongs;
int downmix_channels;
/* helpers */
VGMSTREAM * init_vgmstream_foo(t_uint32 p_subsong, const char * const filename, abort_callback & p_abort);

View File

@ -14,6 +14,7 @@
#define IDC_THREAD_PRIORITY_TEXT 1007
#define IDC_DEFAULT_BUTTON 1008
#define IDC_DISABLE_SUBSONGS 1009
#define IDC_DOWNMIX_CHANNELS 1010
// Next default values for new objects
//