WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / audio_remap.c
blobd1efcc3e6c385d4a7826ea3dbab0b74cad39cc14
1 /* audio_remap.c
3 * Copyright (c) 2003-2015 HandBrake Team
4 * This file is part of the HandBrake source code
5 * Homepage: <http://handbrake.fr/>
6 * It may be used under the terms of the GNU General Public License v2.
7 * For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
10 #include "common.h"
11 #include "hbffmpeg.h"
12 #include "audio_remap.h"
14 // source: libavutil/channel_layout.h
15 hb_chan_map_t hb_libav_chan_map =
18 AV_CH_FRONT_LEFT,
19 AV_CH_FRONT_RIGHT,
20 AV_CH_FRONT_CENTER,
21 AV_CH_LOW_FREQUENCY,
22 AV_CH_BACK_LEFT,
23 AV_CH_BACK_RIGHT,
24 AV_CH_FRONT_LEFT_OF_CENTER,
25 AV_CH_FRONT_RIGHT_OF_CENTER,
26 AV_CH_BACK_CENTER,
27 AV_CH_SIDE_LEFT,
28 AV_CH_SIDE_RIGHT,
33 // source: liba52 documentation
34 hb_chan_map_t hb_liba52_chan_map =
37 AV_CH_LOW_FREQUENCY,
38 AV_CH_FRONT_LEFT,
39 AV_CH_FRONT_CENTER,
40 AV_CH_FRONT_RIGHT,
41 AV_CH_BACK_CENTER,
42 AV_CH_SIDE_LEFT,
43 AV_CH_SIDE_RIGHT,
48 // source: http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
49 hb_chan_map_t hb_vorbis_chan_map =
52 AV_CH_FRONT_LEFT,
53 AV_CH_FRONT_CENTER,
54 AV_CH_FRONT_RIGHT,
55 AV_CH_SIDE_LEFT,
56 AV_CH_SIDE_RIGHT,
57 AV_CH_BACK_LEFT,
58 AV_CH_BACK_CENTER,
59 AV_CH_BACK_RIGHT,
60 AV_CH_LOW_FREQUENCY,
65 // source: https://developer.apple.com/library/mac/#documentation/musicaudio/reference/CoreAudioDataTypesRef/Reference/reference.html
66 hb_chan_map_t hb_aac_chan_map =
69 AV_CH_FRONT_CENTER,
70 AV_CH_FRONT_LEFT_OF_CENTER,
71 AV_CH_FRONT_RIGHT_OF_CENTER,
72 AV_CH_FRONT_LEFT,
73 AV_CH_FRONT_RIGHT,
74 AV_CH_SIDE_LEFT,
75 AV_CH_SIDE_RIGHT,
76 AV_CH_BACK_LEFT,
77 AV_CH_BACK_RIGHT,
78 AV_CH_BACK_CENTER,
79 AV_CH_LOW_FREQUENCY,
84 static void remap_planar(uint8_t **samples, int nsamples,
85 int nchannels, int *remap_table)
87 int ii;
88 uint8_t *tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
89 memcpy(tmp_buf, samples, nchannels * sizeof(uint8_t*));
90 for (ii = 0; ii < nchannels; ii++)
92 samples[ii] = tmp_buf[remap_table[ii]];
96 static void remap_u8_interleaved(uint8_t **samples, int nsamples,
97 int nchannels, int *remap_table)
99 int ii, jj;
100 uint8_t *samples_u8 = (*samples);
101 uint8_t tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
102 for (ii = 0; ii < nsamples; ii++)
104 memcpy(tmp_buf, samples_u8, nchannels * sizeof(uint8_t));
105 for (jj = 0; jj < nchannels; jj++)
107 samples_u8[jj] = tmp_buf[remap_table[jj]];
109 samples_u8 += nchannels;
113 static void remap_s16_interleaved(uint8_t **samples, int nsamples,
114 int nchannels, int *remap_table)
116 int ii, jj;
117 int16_t *samples_s16 = (int16_t*)(*samples);
118 int16_t tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
119 for (ii = 0; ii < nsamples; ii++)
121 memcpy(tmp_buf, samples_s16, nchannels * sizeof(int16_t));
122 for (jj = 0; jj < nchannels; jj++)
124 samples_s16[jj] = tmp_buf[remap_table[jj]];
126 samples_s16 += nchannels;
130 static void remap_s32_interleaved(uint8_t **samples, int nsamples,
131 int nchannels, int *remap_table)
133 int ii, jj;
134 int32_t *samples_s32 = (int32_t*)(*samples);
135 int32_t tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
136 for (ii = 0; ii < nsamples; ii++)
138 memcpy(tmp_buf, samples_s32, nchannels * sizeof(int32_t));
139 for (jj = 0; jj < nchannels; jj++)
141 samples_s32[jj] = tmp_buf[remap_table[jj]];
143 samples_s32 += nchannels;
147 static void remap_flt_interleaved(uint8_t **samples, int nsamples,
148 int nchannels, int *remap_table)
150 int ii, jj;
151 float *samples_flt = (float*)(*samples);
152 float tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
153 for (ii = 0; ii < nsamples; ii++)
155 memcpy(tmp_buf, samples_flt, nchannels * sizeof(float));
156 for (jj = 0; jj < nchannels; jj++)
158 samples_flt[jj] = tmp_buf[remap_table[jj]];
160 samples_flt += nchannels;
164 static void remap_dbl_interleaved(uint8_t **samples, int nsamples,
165 int nchannels, int *remap_table)
167 int ii, jj;
168 double *samples_dbl = (double*)(*samples);
169 double tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
170 for (ii = 0; ii < nsamples; ii++)
172 memcpy(tmp_buf, samples_dbl, nchannels * sizeof(double));
173 for (jj = 0; jj < nchannels; jj++)
175 samples_dbl[jj] = tmp_buf[remap_table[jj]];
177 samples_dbl += nchannels;
181 hb_audio_remap_t* hb_audio_remap_init(enum AVSampleFormat sample_fmt,
182 hb_chan_map_t *channel_map_out,
183 hb_chan_map_t *channel_map_in)
185 hb_audio_remap_t *remap = calloc(1, sizeof(hb_audio_remap_t));
186 if (remap == NULL)
188 hb_error("hb_audio_remap_init: failed to allocate remap");
189 goto fail;
192 // sample format
193 switch (sample_fmt)
195 case AV_SAMPLE_FMT_U8P:
196 case AV_SAMPLE_FMT_S16P:
197 case AV_SAMPLE_FMT_S32P:
198 case AV_SAMPLE_FMT_FLTP:
199 case AV_SAMPLE_FMT_DBLP:
200 remap->remap = &remap_planar;
201 break;
203 case AV_SAMPLE_FMT_U8:
204 remap->remap = &remap_u8_interleaved;
205 break;
207 case AV_SAMPLE_FMT_S16:
208 remap->remap = &remap_s16_interleaved;
209 break;
211 case AV_SAMPLE_FMT_S32:
212 remap->remap = &remap_s32_interleaved;
213 break;
215 case AV_SAMPLE_FMT_FLT:
216 remap->remap = &remap_flt_interleaved;
217 break;
219 case AV_SAMPLE_FMT_DBL:
220 remap->remap = &remap_dbl_interleaved;
221 break;
223 default:
224 hb_error("hb_audio_remap_init: unsupported sample format '%s'",
225 av_get_sample_fmt_name(sample_fmt));
226 goto fail;
229 // input/output channel order
230 if (channel_map_in == NULL || channel_map_out == NULL)
232 hb_error("hb_audio_remap_init: invalid channel map(s)");
233 goto fail;
235 remap->channel_map_in = channel_map_in;
236 remap->channel_map_out = channel_map_out;
238 // remap can't be done until the channel layout has been set
239 remap->remap_needed = 0;
241 return remap;
243 fail:
244 hb_audio_remap_free(remap);
245 return NULL;
248 void hb_audio_remap_set_channel_layout(hb_audio_remap_t *remap,
249 uint64_t channel_layout)
251 if (remap != NULL)
253 int ii;
254 remap->remap_needed = 0;
256 // sanitize the layout
257 if (channel_layout == AV_CH_LAYOUT_STEREO_DOWNMIX)
259 channel_layout = AV_CH_LAYOUT_STEREO;
261 remap->nchannels = av_get_channel_layout_nb_channels(channel_layout);
263 // in some cases, remapping is not necessary and/or supported
264 if (remap->nchannels > HB_AUDIO_REMAP_MAX_CHANNELS)
266 hb_log("hb_audio_remap_set_channel_layout: too many channels (%d)",
267 remap->nchannels);
268 return;
270 if (remap->channel_map_in == remap->channel_map_out)
272 return;
275 // build the table and check whether remapping is necessary
276 hb_audio_remap_build_table(remap->channel_map_out,
277 remap->channel_map_in, channel_layout,
278 remap->table);
279 for (ii = 0; ii < remap->nchannels; ii++)
281 if (remap->table[ii] != ii)
283 remap->remap_needed = 1;
284 break;
291 void hb_audio_remap_free(hb_audio_remap_t *remap)
293 if (remap != NULL)
295 free(remap);
299 void hb_audio_remap(hb_audio_remap_t *remap, uint8_t **samples, int nsamples)
301 if (remap != NULL && remap->remap_needed)
303 remap->remap(samples, nsamples, remap->nchannels, remap->table);
307 void hb_audio_remap_build_table(hb_chan_map_t *channel_map_out,
308 hb_chan_map_t *channel_map_in,
309 uint64_t channel_layout,
310 int *remap_table)
312 int ii, jj, nchannels, out_chan_idx, remap_idx;
313 uint64_t *channels_in, *channels_out;
315 if (channel_layout == AV_CH_LAYOUT_STEREO_DOWNMIX)
317 // Dolby Surround is Stereo when it comes to remapping
318 channel_layout = AV_CH_LAYOUT_STEREO;
320 nchannels = av_get_channel_layout_nb_channels(channel_layout);
322 // clear remap table before (re-)building it
323 memset(remap_table, 0, nchannels * sizeof(int));
325 out_chan_idx = 0;
326 channels_in = channel_map_in ->channel_order_map;
327 channels_out = channel_map_out->channel_order_map;
328 for (ii = 0; channels_out[ii] && out_chan_idx < nchannels; ii++)
330 if (channel_layout & channels_out[ii])
332 remap_idx = 0;
333 for (jj = 0; channels_in[jj] && remap_idx < nchannels; jj++)
335 if (channels_out[ii] == channels_in[jj])
337 remap_table[out_chan_idx++] = remap_idx++;
338 break;
340 else if (channel_layout & channels_in[jj])
342 remap_idx++;