Mercurial > foo_out_sdl
diff foosdk/sdk/foobar2000/SDK/audio_chunk_channel_config.cpp @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/foobar2000/SDK/audio_chunk_channel_config.cpp Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,233 @@ +#include "foobar2000-sdk-pch.h" +#include "audio_chunk.h" + +#ifdef _WIN32 +#include <ks.h> +#include <ksmedia.h> + +#if 0 +#define SPEAKER_FRONT_LEFT 0x1 +#define SPEAKER_FRONT_RIGHT 0x2 +#define SPEAKER_FRONT_CENTER 0x4 +#define SPEAKER_LOW_FREQUENCY 0x8 +#define SPEAKER_BACK_LEFT 0x10 +#define SPEAKER_BACK_RIGHT 0x20 +#define SPEAKER_FRONT_LEFT_OF_CENTER 0x40 +#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80 +#define SPEAKER_BACK_CENTER 0x100 +#define SPEAKER_SIDE_LEFT 0x200 +#define SPEAKER_SIDE_RIGHT 0x400 +#define SPEAKER_TOP_CENTER 0x800 +#define SPEAKER_TOP_FRONT_LEFT 0x1000 +#define SPEAKER_TOP_FRONT_CENTER 0x2000 +#define SPEAKER_TOP_FRONT_RIGHT 0x4000 +#define SPEAKER_TOP_BACK_LEFT 0x8000 +#define SPEAKER_TOP_BACK_CENTER 0x10000 +#define SPEAKER_TOP_BACK_RIGHT 0x20000 + +static struct {DWORD m_wfx; unsigned m_native; } const g_translation_table[] = +{ + {SPEAKER_FRONT_LEFT, audio_chunk::channel_front_left}, + {SPEAKER_FRONT_RIGHT, audio_chunk::channel_front_right}, + {SPEAKER_FRONT_CENTER, audio_chunk::channel_front_center}, + {SPEAKER_LOW_FREQUENCY, audio_chunk::channel_lfe}, + {SPEAKER_BACK_LEFT, audio_chunk::channel_back_left}, + {SPEAKER_BACK_RIGHT, audio_chunk::channel_back_right}, + {SPEAKER_FRONT_LEFT_OF_CENTER, audio_chunk::channel_front_center_left}, + {SPEAKER_FRONT_RIGHT_OF_CENTER, audio_chunk::channel_front_center_right}, + {SPEAKER_BACK_CENTER, audio_chunk::channel_back_center}, + {SPEAKER_SIDE_LEFT, audio_chunk::channel_side_left}, + {SPEAKER_SIDE_RIGHT, audio_chunk::channel_side_right}, + {SPEAKER_TOP_CENTER, audio_chunk::channel_top_center}, + {SPEAKER_TOP_FRONT_LEFT, audio_chunk::channel_top_front_left}, + {SPEAKER_TOP_FRONT_CENTER, audio_chunk::channel_top_front_center}, + {SPEAKER_TOP_FRONT_RIGHT, audio_chunk::channel_top_front_right}, + {SPEAKER_TOP_BACK_LEFT, audio_chunk::channel_top_back_left}, + {SPEAKER_TOP_BACK_CENTER, audio_chunk::channel_top_back_center}, + {SPEAKER_TOP_BACK_RIGHT, audio_chunk::channel_top_back_right}, +}; + +#endif +#endif + + + +static constexpr unsigned g_audio_channel_config_table[] = +{ + 0, + audio_chunk::channel_config_mono, + audio_chunk::channel_config_stereo, + audio_chunk::channel_front_left | audio_chunk::channel_front_right | audio_chunk::channel_lfe, + audio_chunk::channel_front_left | audio_chunk::channel_front_right | audio_chunk::channel_back_left | audio_chunk::channel_back_right, + audio_chunk::channel_front_left | audio_chunk::channel_front_right | audio_chunk::channel_back_left | audio_chunk::channel_back_right | audio_chunk::channel_lfe, + audio_chunk::channel_config_5point1, + audio_chunk::channel_config_5point1_side | audio_chunk::channel_back_center, + audio_chunk::channel_config_7point1, + 0, + audio_chunk::channel_config_7point1 | audio_chunk::channel_front_center_right | audio_chunk::channel_front_center_left, +}; + +unsigned audio_chunk::g_guess_channel_config(unsigned count) +{ + if (count == 0) return 0; + if (count > 32) throw exception_io_data(); + unsigned ret = 0; + if (count < PFC_TABSIZE(g_audio_channel_config_table)) ret = g_audio_channel_config_table[count]; + if (ret == 0) { + // Warning: 1u<<32u behaves stupidly + ret = (unsigned)( (1ull << count) - 1 ); + } + PFC_ASSERT(g_count_channels(ret) == count); + return ret; +} + +unsigned audio_chunk::g_guess_channel_config_xiph(unsigned count) { + switch (count) { + case 3: + return audio_chunk::channel_front_left | audio_chunk::channel_front_center | audio_chunk::channel_front_right; + case 5: + return audio_chunk::channel_front_left | audio_chunk::channel_front_center | audio_chunk::channel_front_right | audio_chunk::channel_back_left | audio_chunk::channel_back_right; + case 7: + return audio_chunk::channel_config_5point1 | audio_chunk::channel_back_center; + default: + return g_guess_channel_config(count); + } +} + +unsigned audio_chunk::g_channel_index_from_flag(unsigned p_config,unsigned p_flag) { + if (p_config & p_flag) { + unsigned index = 0; + + for (unsigned walk = 0; walk < 32; walk++) { + unsigned query = 1 << walk; + if (p_flag & query) return index; + if (p_config & query) index++; + } + } + return (unsigned)(-1); +} + +unsigned audio_chunk::g_extract_channel_flag(unsigned p_config,unsigned p_index) +{ + unsigned toskip = p_index; + unsigned flag = 1; + while(flag) + { + if (p_config & flag) + { + if (toskip == 0) break; + toskip--; + } + flag <<= 1; + } + return flag; +} + + +static const char * const chanNames[] = { + "FL", //channel_front_left = 1<<0, + "FR", //channel_front_right = 1<<1, + "FC", //channel_front_center = 1<<2, + "LFE", //channel_lfe = 1<<3, + "BL", //channel_back_left = 1<<4, + "BR", //channel_back_right = 1<<5, + "FCL", //channel_front_center_left = 1<<6, + "FCR", //channel_front_center_right = 1<<7, + "BC", //channel_back_center = 1<<8, + "SL", //channel_side_left = 1<<9, + "SR", //channel_side_right = 1<<10, + "TC", //channel_top_center = 1<<11, + "TFL", //channel_top_front_left = 1<<12, + "TFC", //channel_top_front_center = 1<<13, + "TFR", //channel_top_front_right = 1<<14, + "TBL", //channel_top_back_left = 1<<15, + "TBC", //channel_top_back_center = 1<<16, + "TBR", //channel_top_back_right = 1<<17, +}; + +unsigned audio_chunk::g_find_channel_idx(unsigned p_flag) { + unsigned rv = 0; + if ((p_flag & 0xFFFF) == 0) { + rv += 16; p_flag >>= 16; + } + if ((p_flag & 0xFF) == 0) { + rv += 8; p_flag >>= 8; + } + if ((p_flag & 0xF) == 0) { + rv += 4; p_flag >>= 4; + } + if ((p_flag & 0x3) == 0) { + rv += 2; p_flag >>= 2; + } + if ((p_flag & 0x1) == 0) { + rv += 1; p_flag >>= 1; + } + PFC_ASSERT( p_flag & 1 ); + return rv; +} + +const char * audio_chunk::g_channel_name(unsigned p_flag) { + return g_channel_name_byidx(g_find_channel_idx(p_flag)); +} + +const char * audio_chunk::g_channel_name_byidx(unsigned p_index) { + if (p_index < PFC_TABSIZE(chanNames)) return chanNames[p_index]; + else return "?"; +} + +pfc::string8 audio_chunk::g_formatChannelMaskDesc(unsigned flags) { + pfc::string8 temp; g_formatChannelMaskDesc(flags, temp); return temp; +} +void audio_chunk::g_formatChannelMaskDesc(unsigned flags, pfc::string_base & out) { + out.reset(); + unsigned idx = 0; + while(flags) { + if (flags & 1) { + if (!out.is_empty()) out << " "; + out << g_channel_name_byidx(idx); + } + flags >>= 1; + ++idx; + } +} + +namespace { + struct maskDesc_t { + const char* name; + unsigned mask; + }; + static constexpr maskDesc_t maskDesc[] = { + {"mono", audio_chunk::channel_config_mono}, + {"stereo", audio_chunk::channel_config_stereo}, + {"stereo (rear)", audio_chunk::channel_back_left | audio_chunk::channel_back_right}, + {"stereo (side)", audio_chunk::channel_side_left | audio_chunk::channel_side_right}, + {"2.1", audio_chunk::channel_config_2point1}, + {"3.0", audio_chunk::channel_config_3point0}, + {"4.0", audio_chunk::channel_config_4point0}, + {"4.1", audio_chunk::channel_config_4point1}, + {"5.0", audio_chunk::channel_config_5point0}, + {"5.1", audio_chunk::channel_config_5point1}, + {"5.1 (side)", audio_chunk::channel_config_5point1_side}, + {"6.1", audio_chunk::channel_config_5point1 | audio_chunk::channel_back_center}, + {"6.1 (side)", audio_chunk::channel_config_5point1_side | audio_chunk::channel_back_center}, + {"7.1", audio_chunk::channel_config_7point1}, + }; +} + +const char* audio_chunk::g_channelMaskName(unsigned flags) { + for (auto& walk : maskDesc) { + if (flags == walk.mask) return walk.name; + } + return nullptr; +} + +static_assert( pfc::countBits32(audio_chunk::channel_config_mono) == 1 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_stereo) == 2 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_4point0) == 4 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_4point0_side) == 4 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_4point1) == 5 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_5point0) == 5 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_5point1) == 6 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_5point1_side) == 6 ); +static_assert( pfc::countBits32(audio_chunk::channel_config_6point0) == 6); +static_assert( pfc::countBits32(audio_chunk::channel_config_7point1) == 8 );
