blob: 84f96763e887f05d09b78175e1e44da74cf05e49 [file] [log] [blame]
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001/* Copyright (c) 2011 Xiph.Org Foundation
2 Written by Jean-Marc Valin */
3/*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "opus_multistream.h"
33#include "opus.h"
34#include "opus_private.h"
35#include "stack_alloc.h"
36#include <stdarg.h>
37#include "float_cast.h"
38#include "os_support.h"
Jean-Marc Valin49587512013-07-07 02:50:18 -040039#include "mathops.h"
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040040#include "mdct.h"
41#include "modes.h"
42#include "bands.h"
43#include "quant_bands.h"
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050044
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -040045typedef struct {
46 int nb_streams;
47 int nb_coupled_streams;
48 unsigned char mapping[8];
49} VorbisLayout;
50
51/* Index is nb_channel-1*/
52static const VorbisLayout vorbis_mappings[8] = {
53 {1, 0, {0}}, /* 1: mono */
54 {1, 1, {0, 1}}, /* 2: stereo */
55 {2, 1, {0, 2, 1}}, /* 3: 1-d surround */
56 {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */
57 {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */
58 {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */
59 {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */
60 {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
61};
62
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040063typedef void (*opus_copy_channel_in_func)(
64 opus_val16 *dst,
65 int dst_stride,
66 const void *src,
67 int src_stride,
68 int src_channel,
69 int frame_size
70);
71
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050072struct OpusMSEncoder {
73 ChannelLayout layout;
Jean-Marc Valin1b723862013-04-25 21:34:04 -040074 int lfe_stream;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -040075 int application;
Jean-Marc Valin74483662012-12-17 16:23:42 -050076 int variable_duration;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -040077 int surround;
Jean-Marc Valin74483662012-12-17 16:23:42 -050078 opus_int32 bitrate_bps;
79 opus_val32 subframe_mem[3];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050080 /* Encoder states go here */
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040081 /* then opus_val32 window_mem[channels*120]; */
82 /* then opus_val32 preemph_mem[channels]; */
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050083};
84
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040085static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
86{
87 int s;
88 char *ptr;
89 int coupled_size, mono_size;
90
91 coupled_size = opus_encoder_get_size(2);
92 mono_size = opus_encoder_get_size(1);
93 ptr = (char*)st + align(sizeof(OpusMSEncoder));
94 for (s=0;s<st->layout.nb_streams;s++)
95 {
96 if (s < st->layout.nb_coupled_streams)
97 ptr += align(coupled_size);
98 else
99 ptr += align(mono_size);
100 }
101 return (opus_val32*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
102}
103
104static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
105{
106 int s;
107 char *ptr;
108 int coupled_size, mono_size;
109
110 coupled_size = opus_encoder_get_size(2);
111 mono_size = opus_encoder_get_size(1);
112 ptr = (char*)st + align(sizeof(OpusMSEncoder));
113 for (s=0;s<st->layout.nb_streams;s++)
114 {
115 if (s < st->layout.nb_coupled_streams)
116 ptr += align(coupled_size);
117 else
118 ptr += align(mono_size);
119 }
120 return (opus_val32*)ptr;
121}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500122
123static int validate_encoder_layout(const ChannelLayout *layout)
124{
125 int s;
126 for (s=0;s<layout->nb_streams;s++)
127 {
128 if (s < layout->nb_coupled_streams)
129 {
130 if (get_left_channel(layout, s, -1)==-1)
131 return 0;
132 if (get_right_channel(layout, s, -1)==-1)
133 return 0;
134 } else {
135 if (get_mono_channel(layout, s, -1)==-1)
136 return 0;
137 }
138 }
139 return 1;
140}
141
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400142static void channel_pos(int channels, int pos[8])
143{
144 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
145 if (channels==4)
146 {
147 pos[0]=1;
148 pos[1]=3;
149 pos[2]=1;
150 pos[3]=3;
151 } else if (channels==3||channels==5||channels==6)
152 {
153 pos[0]=1;
154 pos[1]=2;
155 pos[2]=3;
156 pos[3]=1;
157 pos[4]=3;
158 pos[5]=0;
159 } else if (channels==7)
160 {
161 pos[0]=1;
162 pos[1]=2;
163 pos[2]=3;
164 pos[3]=1;
165 pos[4]=3;
166 pos[5]=2;
167 pos[6]=0;
168 } else if (channels==8)
169 {
170 pos[0]=1;
171 pos[1]=2;
172 pos[2]=3;
173 pos[3]=1;
174 pos[4]=3;
175 pos[5]=1;
176 pos[6]=3;
177 pos[7]=0;
178 }
179}
180
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400181#if 1
182/* Computes a rough approximation of log2(2^a + 2^b) */
183static opus_val16 logSum(opus_val16 a, opus_val16 b)
184{
185 opus_val16 max;
186 opus_val32 diff;
187 opus_val16 frac;
188 static const opus_val16 diff_table[17] = {
189 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
190 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
191 QCONST16(0.0028123f, DB_SHIFT)
192 };
193 int low;
194 if (a>b)
195 {
196 max = a;
197 diff = SUB32(EXTEND32(a),EXTEND32(b));
198 } else {
199 max = b;
200 diff = SUB32(EXTEND32(b),EXTEND32(a));
201 }
202 if (diff >= QCONST16(8.f, DB_SHIFT))
203 return max;
204#ifdef FIXED_POINT
205 low = SHR32(diff, DB_SHIFT-1);
206 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
207#else
208 low = floor(2*diff);
209 frac = 2*diff - low;
210#endif
211 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
212}
213#else
214opus_val16 logSum(opus_val16 a, opus_val16 b)
215{
216 return log2(pow(4, a)+ pow(4, b))/2;
217}
218#endif
219
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400220void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
221 int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in
222)
223{
224 int c;
225 int i;
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400226 int LM;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400227 int pos[8] = {0};
228 int upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400229 int frame_size;
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400230 opus_val16 channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400231 opus_val32 bandE[21];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400232 opus_val16 maskLogE[3][21];
233 VARDECL(opus_val32, in);
234 VARDECL(opus_val16, x);
235 VARDECL(opus_val32, out);
Jean-Marc Valine8e5ecb2013-10-01 17:16:33 -0400236 VARDECL(opus_val32, freq);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400237 SAVE_STACK;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400238
239 upsample = resampling_factor(rate);
240 frame_size = len*upsample;
241
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400242 for (LM=0;LM<=celt_mode->maxLM;LM++)
243 if (celt_mode->shortMdctSize<<LM==frame_size)
244 break;
245
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400246 ALLOC(in, frame_size+overlap, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400247 ALLOC(x, len, opus_val16);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400248 ALLOC(freq, frame_size, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400249
250 channel_pos(channels, pos);
251
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400252 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400253 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400254 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400255
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400256 for (c=0;c<channels;c++)
257 {
258 OPUS_COPY(in, mem+c*overlap, overlap);
259 (*copy_channel_in)(x, 1, pcm, channels, c, len);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400260 preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400261 clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1);
262 if (upsample != 1)
263 {
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400264 int bound = len;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400265 for (i=0;i<bound;i++)
266 freq[i] *= upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400267 for (;i<frame_size;i++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400268 freq[i] = 0;
269 }
270
271 compute_band_energies(celt_mode, freq, bandE, 21, 1, 1<<LM);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400272 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400273 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
274 for (i=1;i<21;i++)
275 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
276 for (i=19;i>=0;i--)
277 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400278 if (pos[c]==1)
279 {
280 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400281 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400282 } else if (pos[c]==3)
283 {
284 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400285 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400286 } else if (pos[c]==2)
287 {
288 for (i=0;i<21;i++)
289 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400290 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
291 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400292 }
293 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400294#if 0
295 for (i=0;i<21;i++)
296 printf("%f ", bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400297 float sum=0;
298 for (i=0;i<21;i++)
299 sum += bandLogE[21*c+i];
300 printf("%f ", sum/21);
301#endif
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400302 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400303 }
304 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400305 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400306 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400307 for (c=0;c<3;c++)
308 for (i=0;i<21;i++)
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400309 maskLogE[c][i] += channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400310#if 0
311 for (c=0;c<3;c++)
312 {
313 for (i=0;i<21;i++)
314 printf("%f ", maskLogE[c][i]);
315 }
316#endif
317 for (c=0;c<channels;c++)
318 {
319 opus_val16 *mask;
320 if (pos[c]!=0)
321 {
322 mask = &maskLogE[pos[c]-1][0];
323 for (i=0;i<21;i++)
324 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
325 } else {
326 for (i=0;i<21;i++)
327 bandLogE[21*c+i] = 0;
328 }
329#if 0
330 for (i=0;i<21;i++)
331 printf("%f ", bandLogE[21*c+i]);
332 printf("\n");
333#endif
334#if 0
335 float sum=0;
336 for (i=0;i<21;i++)
337 sum += bandLogE[21*c+i];
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400338 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400339 printf("\n");
340#endif
341 }
342 RESTORE_STACK;
343}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500344
345opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
346{
347 int coupled_size;
348 int mono_size;
349
350 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
351 coupled_size = opus_encoder_get_size(2);
352 mono_size = opus_encoder_get_size(1);
353 return align(sizeof(OpusMSEncoder))
354 + nb_coupled_streams * align(coupled_size)
355 + (nb_streams-nb_coupled_streams) * align(mono_size);
356}
357
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400358opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
359{
360 int nb_streams;
361 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400362 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400363
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400364 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400365 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400366 if (channels==1)
367 {
368 nb_streams=1;
369 nb_coupled_streams=0;
370 } else if (channels==2)
371 {
372 nb_streams=1;
373 nb_coupled_streams=1;
374 } else
375 return 0;
376 } else if (mapping_family==1 && channels<=8 && channels>=1)
377 {
378 nb_streams=vorbis_mappings[channels-1].nb_streams;
379 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
380 } else if (mapping_family==255)
381 {
382 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400383 nb_coupled_streams=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400384 } else
385 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400386 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
387 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400388 {
389 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
390 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400391 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400392}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500393
394
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400395static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500396 OpusMSEncoder *st,
397 opus_int32 Fs,
398 int channels,
399 int streams,
400 int coupled_streams,
401 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400402 int application,
403 int surround
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500404)
405{
406 int coupled_size;
407 int mono_size;
408 int i, ret;
409 char *ptr;
410
411 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
412 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
413 return OPUS_BAD_ARG;
414
415 st->layout.nb_channels = channels;
416 st->layout.nb_streams = streams;
417 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400418 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400419 if (!surround)
420 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500421 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400422 st->application = application;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500423 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500424 for (i=0;i<st->layout.nb_channels;i++)
425 st->layout.mapping[i] = mapping[i];
426 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
427 return OPUS_BAD_ARG;
428 ptr = (char*)st + align(sizeof(OpusMSEncoder));
429 coupled_size = opus_encoder_get_size(2);
430 mono_size = opus_encoder_get_size(1);
431
432 for (i=0;i<st->layout.nb_coupled_streams;i++)
433 {
434 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400435 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400436 if (i==st->lfe_stream)
437 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500438 ptr += align(coupled_size);
439 }
440 for (;i<st->layout.nb_streams;i++)
441 {
442 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400443 if (i==st->lfe_stream)
444 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500445 if(ret!=OPUS_OK)return ret;
446 ptr += align(mono_size);
447 }
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400448 if (surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400449 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400450 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
451 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400452 }
453 st->surround = surround;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500454 return OPUS_OK;
455}
456
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400457int opus_multistream_encoder_init(
458 OpusMSEncoder *st,
459 opus_int32 Fs,
460 int channels,
461 int streams,
462 int coupled_streams,
463 const unsigned char *mapping,
464 int application
465)
466{
467 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
468}
469
470int opus_multistream_surround_encoder_init(
471 OpusMSEncoder *st,
472 opus_int32 Fs,
473 int channels,
474 int mapping_family,
475 int *streams,
476 int *coupled_streams,
477 unsigned char *mapping,
478 int application
479)
480{
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400481 if ((channels>255) || (channels<1))
482 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400483 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400484 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400485 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400486 if (channels==1)
487 {
488 *streams=1;
489 *coupled_streams=0;
490 mapping[0]=0;
491 } else if (channels==2)
492 {
493 *streams=1;
494 *coupled_streams=1;
495 mapping[0]=0;
496 mapping[1]=1;
497 } else
498 return OPUS_UNIMPLEMENTED;
499 } else if (mapping_family==1 && channels<=8 && channels>=1)
500 {
501 int i;
502 *streams=vorbis_mappings[channels-1].nb_streams;
503 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
504 for (i=0;i<channels;i++)
505 mapping[i] = vorbis_mappings[channels-1].mapping[i];
506 if (channels>=6)
507 st->lfe_stream = *streams-1;
508 } else if (mapping_family==255)
509 {
510 int i;
511 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400512 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400513 for(i=0;i<channels;i++)
514 mapping[i] = i;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400515 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400516 return OPUS_UNIMPLEMENTED;
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400517 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400518 mapping, application, channels>2&&mapping_family==1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400519}
520
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500521OpusMSEncoder *opus_multistream_encoder_create(
522 opus_int32 Fs,
523 int channels,
524 int streams,
525 int coupled_streams,
526 const unsigned char *mapping,
527 int application,
528 int *error
529)
530{
531 int ret;
532 OpusMSEncoder *st;
533 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
534 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
535 {
536 if (error)
537 *error = OPUS_BAD_ARG;
538 return NULL;
539 }
540 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
541 if (st==NULL)
542 {
543 if (error)
544 *error = OPUS_ALLOC_FAIL;
545 return NULL;
546 }
547 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
548 if (ret != OPUS_OK)
549 {
550 opus_free(st);
551 st = NULL;
552 }
553 if (error)
554 *error = ret;
555 return st;
556}
557
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400558OpusMSEncoder *opus_multistream_surround_encoder_create(
559 opus_int32 Fs,
560 int channels,
561 int mapping_family,
562 int *streams,
563 int *coupled_streams,
564 unsigned char *mapping,
565 int application,
566 int *error
567)
568{
569 int ret;
570 OpusMSEncoder *st;
571 if ((channels>255) || (channels<1))
572 {
573 if (error)
574 *error = OPUS_BAD_ARG;
575 return NULL;
576 }
577 st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
578 if (st==NULL)
579 {
580 if (error)
581 *error = OPUS_ALLOC_FAIL;
582 return NULL;
583 }
584 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
585 if (ret != OPUS_OK)
586 {
587 opus_free(st);
588 st = NULL;
589 }
590 if (error)
591 *error = ret;
592 return st;
593}
594
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400595static void surround_rate_allocation(
596 OpusMSEncoder *st,
597 opus_int32 *rate,
598 int frame_size
599 )
600{
601 int i;
602 opus_int32 channel_rate;
603 opus_int32 Fs;
604 char *ptr;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400605 int stream_offset;
606 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400607 int coupled_ratio; /* Q8 */
608 int lfe_ratio; /* Q8 */
609
610 ptr = (char*)st + align(sizeof(OpusMSEncoder));
611 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
612
Jean-Marc Valin49587512013-07-07 02:50:18 -0400613 if (st->bitrate_bps > st->layout.nb_channels*40000)
614 stream_offset = 20000;
615 else
616 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400617 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
618 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400619 /* The LFE stream is an exception to the above and gets fewer bits. */
620 lfe_offset = 3500;
621 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
622 coupled_ratio = 512;
623 /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400624 lfe_ratio = 32;
625
626 /* Compute bitrate allocation between streams */
627 if (st->bitrate_bps==OPUS_AUTO)
628 {
629 channel_rate = Fs+60*Fs/frame_size;
630 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
631 {
632 channel_rate = 300000;
633 } else {
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400634 int nb_lfe;
635 int nb_uncoupled;
636 int nb_coupled;
637 int total;
638 nb_lfe = (st->lfe_stream!=-1);
639 nb_coupled = st->layout.nb_coupled_streams;
640 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
641 total = (nb_uncoupled<<8) /* mono */
642 + coupled_ratio*nb_coupled /* stereo */
643 + nb_lfe*lfe_ratio;
644 channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400645 }
646#ifndef FIXED_POINT
647 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
648 {
649 opus_int32 bonus;
650 bonus = 60*(Fs/frame_size-50);
651 channel_rate += bonus;
652 }
653#endif
654
655 for (i=0;i<st->layout.nb_streams;i++)
656 {
657 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400658 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400659 else if (i!=st->lfe_stream)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400660 rate[i] = stream_offset+channel_rate;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400661 else
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400662 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400663 }
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400664}
665
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500666/* Max size in case the encoder decides to return three frames */
667#define MS_FRAME_TMP (3*1275+7)
668static int opus_multistream_encode_native
669(
670 OpusMSEncoder *st,
671 opus_copy_channel_in_func copy_channel_in,
672 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400673 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500674 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500675 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400676 int lsb_depth,
677 downmix_func downmix
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500678)
679{
680 opus_int32 Fs;
681 int coupled_size;
682 int mono_size;
683 int s;
684 char *ptr;
685 int tot_size;
686 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400687 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500688 unsigned char tmp_data[MS_FRAME_TMP];
689 OpusRepacketizer rp;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500690 opus_int32 complexity;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500691 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400692 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400693 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400694 opus_val32 *mem = NULL;
695 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400696 int frame_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500697 ALLOC_STACK;
698
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400699 if (st->surround)
700 {
701 preemph_mem = ms_get_preemph_mem(st);
702 mem = ms_get_window_mem(st);
703 }
704
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500705 ptr = (char*)st + align(sizeof(OpusMSEncoder));
706 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500707 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
708 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500709
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400710 {
711 opus_int32 delay_compensation;
712 int channels;
713
714 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
715 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
716 delay_compensation -= Fs/400;
717 frame_size = compute_frame_size(pcm, analysis_frame_size,
718 st->variable_duration, channels, Fs, st->bitrate_bps,
719 delay_compensation, downmix, st->subframe_mem);
720 }
721
Jean-Marc Valin74483662012-12-17 16:23:42 -0500722 if (400*frame_size < Fs)
723 {
724 RESTORE_STACK;
725 return OPUS_BAD_ARG;
726 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500727 /* Validate frame_size before using it to allocate stack space.
728 This mirrors the checks in opus_encode[_float](). */
729 if (400*frame_size != Fs && 200*frame_size != Fs &&
730 100*frame_size != Fs && 50*frame_size != Fs &&
731 25*frame_size != Fs && 50*frame_size != 3*Fs)
732 {
733 RESTORE_STACK;
734 return OPUS_BAD_ARG;
735 }
736 ALLOC(buf, 2*frame_size, opus_val16);
737 coupled_size = opus_encoder_get_size(2);
738 mono_size = opus_encoder_get_size(1);
739
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400740 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400741 if (st->surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400742 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400743 surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400744 }
745
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500746 if (max_data_bytes < 4*st->layout.nb_streams-1)
747 {
748 RESTORE_STACK;
749 return OPUS_BUFFER_TOO_SMALL;
750 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500751
752 /* Compute bitrate allocation between streams (this could be a lot better) */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400753 surround_rate_allocation(st, bitrates, frame_size);
754
Jean-Marc Valin74483662012-12-17 16:23:42 -0500755 ptr = (char*)st + align(sizeof(OpusMSEncoder));
756 for (s=0;s<st->layout.nb_streams;s++)
757 {
758 OpusEncoder *enc;
759 enc = (OpusEncoder*)ptr;
760 if (s < st->layout.nb_coupled_streams)
761 ptr += align(coupled_size);
762 else
763 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400764 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400765 if (st->surround)
766 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400767 opus_int32 equiv_rate;
768 equiv_rate = st->bitrate_bps;
769 if (frame_size*50 < Fs)
770 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
771 if (equiv_rate > 112000)
772 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
773 else if (equiv_rate > 76000)
774 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
775 else if (equiv_rate > 48000)
776 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
777 else
778 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400779 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400780 {
781 /* To preserve the spatial image, force stereo CELT on coupled streams */
782 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400783 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400784 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400785 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500786 }
787
788 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500789 /* Counting ToC */
790 tot_size = 0;
791 for (s=0;s<st->layout.nb_streams;s++)
792 {
793 OpusEncoder *enc;
794 int len;
795 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400796 int c1, c2;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500797
798 opus_repacketizer_init(&rp);
799 enc = (OpusEncoder*)ptr;
800 if (s < st->layout.nb_coupled_streams)
801 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400802 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500803 int left, right;
804 left = get_left_channel(&st->layout, s, -1);
805 right = get_right_channel(&st->layout, s, -1);
806 (*copy_channel_in)(buf, 2,
807 pcm, st->layout.nb_channels, left, frame_size);
808 (*copy_channel_in)(buf+1, 2,
809 pcm, st->layout.nb_channels, right, frame_size);
810 ptr += align(coupled_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400811 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400812 {
813 for (i=0;i<21;i++)
814 {
815 bandLogE[i] = bandSMR[21*left+i];
816 bandLogE[21+i] = bandSMR[21*right+i];
817 }
818 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400819 c1 = left;
820 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500821 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400822 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500823 int chan = get_mono_channel(&st->layout, s, -1);
824 (*copy_channel_in)(buf, 1,
825 pcm, st->layout.nb_channels, chan, frame_size);
826 ptr += align(mono_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400827 if (st->surround)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400828 {
829 for (i=0;i<21;i++)
830 bandLogE[i] = bandSMR[21*chan+i];
831 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400832 c1 = chan;
833 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500834 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400835 if (st->surround)
836 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500837 /* number of bytes left (+Toc) */
838 curr_max = max_data_bytes - tot_size;
839 /* Reserve three bytes for the last stream and four for the others */
840 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
841 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400842 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
843 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500844 if (len<0)
845 {
846 RESTORE_STACK;
847 return len;
848 }
849 /* We need to use the repacketizer to add the self-delimiting lengths
850 while taking into account the fact that the encoder can now return
851 more than one frame at a time (e.g. 60 ms CELT-only) */
852 opus_repacketizer_cat(&rp, tmp_data, len);
853 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), data, max_data_bytes-tot_size, s != st->layout.nb_streams-1);
854 data += len;
855 tot_size += len;
856 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400857 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500858 RESTORE_STACK;
859 return tot_size;
860
861}
862
Pedro Becerra1af7f952013-07-11 00:00:47 -0400863#if !defined(DISABLE_FLOAT_API)
864static void opus_copy_channel_in_float(
865 opus_val16 *dst,
866 int dst_stride,
867 const void *src,
868 int src_stride,
869 int src_channel,
870 int frame_size
871)
872{
873 const float *float_src;
874 opus_int32 i;
875 float_src = (const float *)src;
876 for (i=0;i<frame_size;i++)
877#if defined(FIXED_POINT)
878 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
879#else
880 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
881#endif
882}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500883#endif
884
885static void opus_copy_channel_in_short(
886 opus_val16 *dst,
887 int dst_stride,
888 const void *src,
889 int src_stride,
890 int src_channel,
891 int frame_size
892)
893{
894 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700895 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500896 short_src = (const opus_int16 *)src;
897 for (i=0;i<frame_size;i++)
898#if defined(FIXED_POINT)
899 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
900#else
901 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
902#endif
903}
904
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400905
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500906#ifdef FIXED_POINT
907int opus_multistream_encode(
908 OpusMSEncoder *st,
909 const opus_val16 *pcm,
910 int frame_size,
911 unsigned char *data,
912 opus_int32 max_data_bytes
913)
914{
915 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400916 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500917}
918
919#ifndef DISABLE_FLOAT_API
920int opus_multistream_encode_float(
921 OpusMSEncoder *st,
922 const float *pcm,
923 int frame_size,
924 unsigned char *data,
925 opus_int32 max_data_bytes
926)
927{
928 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400929 pcm, frame_size, data, max_data_bytes, 16, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500930}
931#endif
932
933#else
934
935int opus_multistream_encode_float
936(
937 OpusMSEncoder *st,
938 const opus_val16 *pcm,
939 int frame_size,
940 unsigned char *data,
941 opus_int32 max_data_bytes
942)
943{
944 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400945 pcm, frame_size, data, max_data_bytes, 24, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500946}
947
948int opus_multistream_encode(
949 OpusMSEncoder *st,
950 const opus_int16 *pcm,
951 int frame_size,
952 unsigned char *data,
953 opus_int32 max_data_bytes
954)
955{
956 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400957 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500958}
959#endif
960
961int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
962{
963 va_list ap;
964 int coupled_size, mono_size;
965 char *ptr;
966 int ret = OPUS_OK;
967
968 va_start(ap, request);
969
970 coupled_size = opus_encoder_get_size(2);
971 mono_size = opus_encoder_get_size(1);
972 ptr = (char*)st + align(sizeof(OpusMSEncoder));
973 switch (request)
974 {
975 case OPUS_SET_BITRATE_REQUEST:
976 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500977 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700978 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
979 {
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500980 goto bad_arg;
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700981 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500982 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500983 }
984 break;
985 case OPUS_GET_BITRATE_REQUEST:
986 {
987 int s;
988 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700989 if (!value)
990 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700991 goto bad_arg;
992 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500993 *value = 0;
994 for (s=0;s<st->layout.nb_streams;s++)
995 {
996 opus_int32 rate;
997 OpusEncoder *enc;
998 enc = (OpusEncoder*)ptr;
999 if (s < st->layout.nb_coupled_streams)
1000 ptr += align(coupled_size);
1001 else
1002 ptr += align(mono_size);
1003 opus_encoder_ctl(enc, request, &rate);
1004 *value += rate;
1005 }
1006 }
1007 break;
1008 case OPUS_GET_LSB_DEPTH_REQUEST:
1009 case OPUS_GET_VBR_REQUEST:
1010 case OPUS_GET_APPLICATION_REQUEST:
1011 case OPUS_GET_BANDWIDTH_REQUEST:
1012 case OPUS_GET_COMPLEXITY_REQUEST:
1013 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1014 case OPUS_GET_DTX_REQUEST:
1015 case OPUS_GET_VOICE_RATIO_REQUEST:
1016 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1017 case OPUS_GET_SIGNAL_REQUEST:
1018 case OPUS_GET_LOOKAHEAD_REQUEST:
1019 case OPUS_GET_SAMPLE_RATE_REQUEST:
1020 case OPUS_GET_INBAND_FEC_REQUEST:
1021 case OPUS_GET_FORCE_CHANNELS_REQUEST:
1022 {
1023 OpusEncoder *enc;
1024 /* For int32* GET params, just query the first stream */
1025 opus_int32 *value = va_arg(ap, opus_int32*);
1026 enc = (OpusEncoder*)ptr;
1027 ret = opus_encoder_ctl(enc, request, value);
1028 }
1029 break;
1030 case OPUS_GET_FINAL_RANGE_REQUEST:
1031 {
1032 int s;
1033 opus_uint32 *value = va_arg(ap, opus_uint32*);
1034 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001035 if (!value)
1036 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001037 goto bad_arg;
1038 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001039 *value=0;
1040 for (s=0;s<st->layout.nb_streams;s++)
1041 {
1042 OpusEncoder *enc;
1043 enc = (OpusEncoder*)ptr;
1044 if (s < st->layout.nb_coupled_streams)
1045 ptr += align(coupled_size);
1046 else
1047 ptr += align(mono_size);
1048 ret = opus_encoder_ctl(enc, request, &tmp);
1049 if (ret != OPUS_OK) break;
1050 *value ^= tmp;
1051 }
1052 }
1053 break;
1054 case OPUS_SET_LSB_DEPTH_REQUEST:
1055 case OPUS_SET_COMPLEXITY_REQUEST:
1056 case OPUS_SET_VBR_REQUEST:
1057 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001058 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001059 case OPUS_SET_BANDWIDTH_REQUEST:
1060 case OPUS_SET_SIGNAL_REQUEST:
1061 case OPUS_SET_APPLICATION_REQUEST:
1062 case OPUS_SET_INBAND_FEC_REQUEST:
1063 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1064 case OPUS_SET_DTX_REQUEST:
1065 case OPUS_SET_FORCE_MODE_REQUEST:
1066 case OPUS_SET_FORCE_CHANNELS_REQUEST:
1067 {
1068 int s;
1069 /* This works for int32 params */
1070 opus_int32 value = va_arg(ap, opus_int32);
1071 for (s=0;s<st->layout.nb_streams;s++)
1072 {
1073 OpusEncoder *enc;
1074
1075 enc = (OpusEncoder*)ptr;
1076 if (s < st->layout.nb_coupled_streams)
1077 ptr += align(coupled_size);
1078 else
1079 ptr += align(mono_size);
1080 ret = opus_encoder_ctl(enc, request, value);
1081 if (ret != OPUS_OK)
1082 break;
1083 }
1084 }
1085 break;
1086 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1087 {
1088 int s;
1089 opus_int32 stream_id;
1090 OpusEncoder **value;
1091 stream_id = va_arg(ap, opus_int32);
1092 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1093 ret = OPUS_BAD_ARG;
1094 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001095 if (!value)
1096 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001097 goto bad_arg;
1098 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001099 for (s=0;s<stream_id;s++)
1100 {
1101 if (s < st->layout.nb_coupled_streams)
1102 ptr += align(coupled_size);
1103 else
1104 ptr += align(mono_size);
1105 }
1106 *value = (OpusEncoder*)ptr;
1107 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001108 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001109 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001110 {
1111 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001112 st->variable_duration = value;
1113 }
1114 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001115 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001116 {
1117 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001118 if (!value)
1119 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001120 goto bad_arg;
1121 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001122 *value = st->variable_duration;
1123 }
1124 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001125 default:
1126 ret = OPUS_UNIMPLEMENTED;
1127 break;
1128 }
1129
1130 va_end(ap);
1131 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001132bad_arg:
1133 va_end(ap);
1134 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001135}
1136
1137void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1138{
1139 opus_free(st);
1140}