foobar2000 SDK  2015-01-14
audio_chunk_channel_config.cpp
Go to the documentation of this file.
1 #include "foobar2000.h"
2 
3 #ifdef _WIN32
4 #include <ks.h>
5 #include <ksmedia.h>
6 
7 #if 0
8 #define SPEAKER_FRONT_LEFT 0x1
9 #define SPEAKER_FRONT_RIGHT 0x2
10 #define SPEAKER_FRONT_CENTER 0x4
11 #define SPEAKER_LOW_FREQUENCY 0x8
12 #define SPEAKER_BACK_LEFT 0x10
13 #define SPEAKER_BACK_RIGHT 0x20
14 #define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
15 #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
16 #define SPEAKER_BACK_CENTER 0x100
17 #define SPEAKER_SIDE_LEFT 0x200
18 #define SPEAKER_SIDE_RIGHT 0x400
19 #define SPEAKER_TOP_CENTER 0x800
20 #define SPEAKER_TOP_FRONT_LEFT 0x1000
21 #define SPEAKER_TOP_FRONT_CENTER 0x2000
22 #define SPEAKER_TOP_FRONT_RIGHT 0x4000
23 #define SPEAKER_TOP_BACK_LEFT 0x8000
24 #define SPEAKER_TOP_BACK_CENTER 0x10000
25 #define SPEAKER_TOP_BACK_RIGHT 0x20000
26 
27 static struct {DWORD m_wfx; unsigned m_native; } const g_translation_table[] =
28 {
29  {SPEAKER_FRONT_LEFT, audio_chunk::channel_front_left},
30  {SPEAKER_FRONT_RIGHT, audio_chunk::channel_front_right},
31  {SPEAKER_FRONT_CENTER, audio_chunk::channel_front_center},
32  {SPEAKER_LOW_FREQUENCY, audio_chunk::channel_lfe},
33  {SPEAKER_BACK_LEFT, audio_chunk::channel_back_left},
34  {SPEAKER_BACK_RIGHT, audio_chunk::channel_back_right},
35  {SPEAKER_FRONT_LEFT_OF_CENTER, audio_chunk::channel_front_center_left},
36  {SPEAKER_FRONT_RIGHT_OF_CENTER, audio_chunk::channel_front_center_right},
37  {SPEAKER_BACK_CENTER, audio_chunk::channel_back_center},
38  {SPEAKER_SIDE_LEFT, audio_chunk::channel_side_left},
39  {SPEAKER_SIDE_RIGHT, audio_chunk::channel_side_right},
40  {SPEAKER_TOP_CENTER, audio_chunk::channel_top_center},
41  {SPEAKER_TOP_FRONT_LEFT, audio_chunk::channel_top_front_left},
42  {SPEAKER_TOP_FRONT_CENTER, audio_chunk::channel_top_front_center},
43  {SPEAKER_TOP_FRONT_RIGHT, audio_chunk::channel_top_front_right},
44  {SPEAKER_TOP_BACK_LEFT, audio_chunk::channel_top_back_left},
45  {SPEAKER_TOP_BACK_CENTER, audio_chunk::channel_top_back_center},
46  {SPEAKER_TOP_BACK_RIGHT, audio_chunk::channel_top_back_right},
47 };
48 
49 #endif
50 #endif
51 
52 // foobar2000 channel flags are 1:1 identical to Windows WFX ones.
53 uint32_t audio_chunk::g_channel_config_to_wfx(unsigned p_config)
54 {
55  return p_config;
56 #if 0
57  DWORD ret = 0;
58  unsigned n;
59  for(n=0;n<PFC_TABSIZE(g_translation_table);n++)
60  {
61  if (p_config & g_translation_table[n].m_native) ret |= g_translation_table[n].m_wfx;
62  }
63  return ret;
64 #endif
65 }
66 
68 {
69  return p_wfx;
70 #if 0
71  unsigned ret = 0;
72  unsigned n;
73  for(n=0;n<PFC_TABSIZE(g_translation_table);n++)
74  {
75  if (p_wfx & g_translation_table[n].m_wfx) ret |= g_translation_table[n].m_native;
76  }
77  return ret;
78 #endif
79 }
80 
81 
82 static const unsigned g_audio_channel_config_table[] =
83 {
84  0,
93 };
94 
95 static const unsigned g_audio_channel_config_table_xiph[] =
96 {
97  0,
106 };
107 
108 unsigned audio_chunk::g_guess_channel_config(unsigned count)
109 {
110  if (count >= PFC_TABSIZE(g_audio_channel_config_table)) return 0;
111  return g_audio_channel_config_table[count];
112 }
113 
115  if (count == 0 || count >= PFC_TABSIZE(g_audio_channel_config_table_xiph)) throw exception_io_data();
116  return g_audio_channel_config_table_xiph[count];
117 }
118 
119 unsigned audio_chunk::g_channel_index_from_flag(unsigned p_config,unsigned p_flag) {
120  unsigned index = 0;
121  for(unsigned walk = 0; walk < 32; walk++) {
122  unsigned query = 1 << walk;
123  if (p_flag & query) return index;
124  if (p_config & query) index++;
125  }
126  return ~0;
127 }
128 
129 unsigned audio_chunk::g_extract_channel_flag(unsigned p_config,unsigned p_index)
130 {
131  unsigned toskip = p_index;
132  unsigned flag = 1;
133  while(flag)
134  {
135  if (p_config & flag)
136  {
137  if (toskip == 0) break;
138  toskip--;
139  }
140  flag <<= 1;
141  }
142  return flag;
143 }
144 
145 unsigned audio_chunk::g_count_channels(unsigned p_config)
146 {
147  return pfc::countBits32(p_config);
148 }
149 
150 static const char * const chanNames[] = {
151  "FL", //channel_front_left = 1<<0,
152  "FR", //channel_front_right = 1<<1,
153  "FC", //channel_front_center = 1<<2,
154  "LFE", //channel_lfe = 1<<3,
155  "BL", //channel_back_left = 1<<4,
156  "BR", //channel_back_right = 1<<5,
157  "FCL", //channel_front_center_left = 1<<6,
158  "FCR", //channel_front_center_right = 1<<7,
159  "BC", //channel_back_center = 1<<8,
160  "SL", //channel_side_left = 1<<9,
161  "SR", //channel_side_right = 1<<10,
162  "TC", //channel_top_center = 1<<11,
163  "TFL", //channel_top_front_left = 1<<12,
164  "TFC", //channel_top_front_center = 1<<13,
165  "TFR", //channel_top_front_right = 1<<14,
166  "TBL", //channel_top_back_left = 1<<15,
167  "TBC", //channel_top_back_center = 1<<16,
168  "TBR", //channel_top_back_right = 1<<17,
169 };
170 
171 unsigned audio_chunk::g_find_channel_idx(unsigned p_flag) {
172  unsigned rv = 0;
173  if ((p_flag & 0xFFFF) == 0) {
174  rv += 16; p_flag >>= 16;
175  }
176  if ((p_flag & 0xFF) == 0) {
177  rv += 8; p_flag >>= 8;
178  }
179  if ((p_flag & 0xF) == 0) {
180  rv += 4; p_flag >>= 4;
181  }
182  if ((p_flag & 0x3) == 0) {
183  rv += 2; p_flag >>= 2;
184  }
185  if ((p_flag & 0x1) == 0) {
186  rv += 1; p_flag >>= 1;
187  }
188  PFC_ASSERT( p_flag & 1 );
189  return rv;
190 }
191 
192 const char * audio_chunk::g_channel_name(unsigned p_flag) {
194 }
195 
196 const char * audio_chunk::g_channel_name_byidx(unsigned p_index) {
197  if (p_index < PFC_TABSIZE(chanNames)) return chanNames[p_index];
198  else return "?";
199 }
200 
202  out.reset();
203  unsigned idx = 0;
204  while(flags) {
205  if (flags & 1) {
206  if (!out.is_empty()) out << " ";
207  out << g_channel_name_byidx(idx);
208  }
209  flags >>= 1;
210  ++idx;
211  }
212 }
static const char *const chanNames[]
static void g_formatChannelMaskDesc(unsigned flags, pfc::string_base &out)
static const unsigned g_audio_channel_config_table[]
static const char * g_channel_name_byidx(unsigned p_index)
static unsigned g_channel_config_from_wfx(uint32_t p_wfx)
Helper function; translates WAVEFORMATEXTENSIBLE channel map to audio_chunk channel map...
static unsigned g_find_channel_idx(unsigned p_flag)
unsigned countBits32(uint32_t i)
Definition: primitives.h:850
static unsigned g_count_channels(unsigned p_config)
Counts channels specified by channel map.
static unsigned g_extract_channel_flag(unsigned p_config, unsigned p_index)
Extracts flag describing Nth channel from specified map. Usable to figure what specific channel in a ...
bool is_empty() const
Definition: string_base.h:212
static unsigned g_channel_index_from_flag(unsigned p_config, unsigned p_flag)
Calculates index of a channel specified by p_flag in a stream where channel map is described by p_con...
static unsigned g_guess_channel_config(unsigned count)
Helper function; guesses default channel map for the specified channel count. Returns 0 on failure...
static const unsigned g_audio_channel_config_table_xiph[]
static struct @29 g_translation_table[]
static const char * g_channel_name(unsigned p_flag)
static unsigned g_guess_channel_config_xiph(unsigned count)
Helper function; determines channel map for the specified channel count according to Xiph specs...
static uint32_t g_channel_config_to_wfx(unsigned p_config)
Helper function; translates audio_chunk channel map to WAVEFORMATEXTENSIBLE channel map...