blob: ed93c898927545b3bdb58e7a5186fe049b32134a [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 Valin7c49ad02015-10-07 09:17:50 -040044#include "pitch.h"
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050045
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -040046typedef struct {
47 int nb_streams;
48 int nb_coupled_streams;
49 unsigned char mapping[8];
50} VorbisLayout;
51
52/* Index is nb_channel-1*/
53static const VorbisLayout vorbis_mappings[8] = {
54 {1, 0, {0}}, /* 1: mono */
55 {1, 1, {0, 1}}, /* 2: stereo */
56 {2, 1, {0, 2, 1}}, /* 3: 1-d surround */
57 {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */
58 {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */
59 {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */
60 {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */
61 {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
62};
63
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040064typedef void (*opus_copy_channel_in_func)(
65 opus_val16 *dst,
66 int dst_stride,
67 const void *src,
68 int src_stride,
69 int src_channel,
70 int frame_size
71);
72
Michael Graczyk39256682016-05-02 21:42:18 -070073typedef enum {
74 MAPPING_TYPE_NONE,
Michael Graczykd6642d62016-06-29 20:30:19 -070075 MAPPING_TYPE_SURROUND
Michael Graczyk39256682016-05-02 21:42:18 -070076#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
Michael Graczykd6642d62016-06-29 20:30:19 -070077 , /* Do not include comma at end of enumerator list */
78 MAPPING_TYPE_AMBISONICS
Michael Graczyk39256682016-05-02 21:42:18 -070079#endif
80} MappingType;
81
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050082struct OpusMSEncoder {
83 ChannelLayout layout;
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -050084 int arch;
Jean-Marc Valin1b723862013-04-25 21:34:04 -040085 int lfe_stream;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -040086 int application;
Jean-Marc Valin74483662012-12-17 16:23:42 -050087 int variable_duration;
Michael Graczyk39256682016-05-02 21:42:18 -070088 MappingType mapping_type;
Jean-Marc Valin74483662012-12-17 16:23:42 -050089 opus_int32 bitrate_bps;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050090 /* Encoder states go here */
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040091 /* then opus_val32 window_mem[channels*120]; */
92 /* then opus_val32 preemph_mem[channels]; */
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050093};
94
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040095static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
96{
97 int s;
98 char *ptr;
99 int coupled_size, mono_size;
100
101 coupled_size = opus_encoder_get_size(2);
102 mono_size = opus_encoder_get_size(1);
103 ptr = (char*)st + align(sizeof(OpusMSEncoder));
104 for (s=0;s<st->layout.nb_streams;s++)
105 {
106 if (s < st->layout.nb_coupled_streams)
107 ptr += align(coupled_size);
108 else
109 ptr += align(mono_size);
110 }
Mark Harris4feb0df2015-08-07 01:24:48 -0700111 /* void* cast avoids clang -Wcast-align warning */
112 return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400113}
114
115static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
116{
117 int s;
118 char *ptr;
119 int coupled_size, mono_size;
120
121 coupled_size = opus_encoder_get_size(2);
122 mono_size = opus_encoder_get_size(1);
123 ptr = (char*)st + align(sizeof(OpusMSEncoder));
124 for (s=0;s<st->layout.nb_streams;s++)
125 {
126 if (s < st->layout.nb_coupled_streams)
127 ptr += align(coupled_size);
128 else
129 ptr += align(mono_size);
130 }
Mark Harris4feb0df2015-08-07 01:24:48 -0700131 /* void* cast avoids clang -Wcast-align warning */
132 return (opus_val32*)(void*)ptr;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400133}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500134
135static int validate_encoder_layout(const ChannelLayout *layout)
136{
137 int s;
138 for (s=0;s<layout->nb_streams;s++)
139 {
140 if (s < layout->nb_coupled_streams)
141 {
142 if (get_left_channel(layout, s, -1)==-1)
143 return 0;
144 if (get_right_channel(layout, s, -1)==-1)
145 return 0;
146 } else {
147 if (get_mono_channel(layout, s, -1)==-1)
148 return 0;
149 }
150 }
151 return 1;
152}
153
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400154static void channel_pos(int channels, int pos[8])
155{
156 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
157 if (channels==4)
158 {
159 pos[0]=1;
160 pos[1]=3;
161 pos[2]=1;
162 pos[3]=3;
163 } else if (channels==3||channels==5||channels==6)
164 {
165 pos[0]=1;
166 pos[1]=2;
167 pos[2]=3;
168 pos[3]=1;
169 pos[4]=3;
170 pos[5]=0;
171 } else if (channels==7)
172 {
173 pos[0]=1;
174 pos[1]=2;
175 pos[2]=3;
176 pos[3]=1;
177 pos[4]=3;
178 pos[5]=2;
179 pos[6]=0;
180 } else if (channels==8)
181 {
182 pos[0]=1;
183 pos[1]=2;
184 pos[2]=3;
185 pos[3]=1;
186 pos[4]=3;
187 pos[5]=1;
188 pos[6]=3;
189 pos[7]=0;
190 }
191}
192
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400193#if 1
194/* Computes a rough approximation of log2(2^a + 2^b) */
195static opus_val16 logSum(opus_val16 a, opus_val16 b)
196{
197 opus_val16 max;
198 opus_val32 diff;
199 opus_val16 frac;
200 static const opus_val16 diff_table[17] = {
201 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
202 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
203 QCONST16(0.0028123f, DB_SHIFT)
204 };
205 int low;
206 if (a>b)
207 {
208 max = a;
209 diff = SUB32(EXTEND32(a),EXTEND32(b));
210 } else {
211 max = b;
212 diff = SUB32(EXTEND32(b),EXTEND32(a));
213 }
Mark Harrisa6595e62015-10-07 09:21:23 -0400214 if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400215 return max;
216#ifdef FIXED_POINT
217 low = SHR32(diff, DB_SHIFT-1);
218 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
219#else
Jean-Marc Valina71c9ad2013-11-13 12:07:01 -0500220 low = (int)floor(2*diff);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400221 frac = 2*diff - low;
222#endif
223 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
224}
225#else
226opus_val16 logSum(opus_val16 a, opus_val16 b)
227{
228 return log2(pow(4, a)+ pow(4, b))/2;
229}
230#endif
231
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400232void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500233 int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in, int arch
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400234)
235{
236 int c;
237 int i;
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400238 int LM;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400239 int pos[8] = {0};
240 int upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400241 int frame_size;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400242 int freq_size;
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400243 opus_val16 channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400244 opus_val32 bandE[21];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400245 opus_val16 maskLogE[3][21];
246 VARDECL(opus_val32, in);
247 VARDECL(opus_val16, x);
Jean-Marc Valine8e5ecb2013-10-01 17:16:33 -0400248 VARDECL(opus_val32, freq);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400249 SAVE_STACK;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400250
251 upsample = resampling_factor(rate);
252 frame_size = len*upsample;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400253 freq_size = IMIN(960, frame_size);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400254
Michael Graczyk39256682016-05-02 21:42:18 -0700255 /* LM = log2(frame_size / 120) */
Jean-Marc Valin2e653a72013-10-14 17:47:18 -0400256 for (LM=0;LM<celt_mode->maxLM;LM++)
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400257 if (celt_mode->shortMdctSize<<LM==frame_size)
258 break;
259
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400260 ALLOC(in, frame_size+overlap, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400261 ALLOC(x, len, opus_val16);
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400262 ALLOC(freq, freq_size, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400263
264 channel_pos(channels, pos);
265
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400266 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400267 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400268 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400269
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400270 for (c=0;c<channels;c++)
271 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400272 int frame;
273 int nb_frames = frame_size/freq_size;
274 celt_assert(nb_frames*freq_size == frame_size);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400275 OPUS_COPY(in, mem+c*overlap, overlap);
276 (*copy_channel_in)(x, 1, pcm, channels, c, len);
Jean-Marc Valin2dc27df2013-11-13 19:35:43 -0500277 celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400278#ifndef FIXED_POINT
279 {
280 opus_val32 sum;
281 sum = celt_inner_prod(in, in, frame_size+overlap, 0);
282 /* This should filter out both NaNs and ridiculous signals that could
283 cause NaNs further down. */
284 if (!(sum < 1e9f) || celt_isnan(sum))
285 {
286 OPUS_CLEAR(in, frame_size+overlap);
287 preemph_mem[c] = 0;
288 }
289 }
290#endif
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400291 OPUS_CLEAR(bandE, 21);
292 for (frame=0;frame<nb_frames;frame++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400293 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400294 opus_val32 tmpE[21];
295 clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window,
296 overlap, celt_mode->maxLM-LM, 1, arch);
297 if (upsample != 1)
298 {
299 int bound = freq_size/upsample;
300 for (i=0;i<bound;i++)
301 freq[i] *= upsample;
302 for (;i<freq_size;i++)
303 freq[i] = 0;
304 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400305
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400306 compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM);
307 /* If we have multiple frames, take the max energy. */
308 for (i=0;i<21;i++)
309 bandE[i] = MAX32(bandE[i], tmpE[i]);
310 }
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400311 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400312 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
313 for (i=1;i<21;i++)
314 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
315 for (i=19;i>=0;i--)
316 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 -0400317 if (pos[c]==1)
318 {
319 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400320 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400321 } else if (pos[c]==3)
322 {
323 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400324 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400325 } else if (pos[c]==2)
326 {
327 for (i=0;i<21;i++)
328 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400329 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
330 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400331 }
332 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400333#if 0
334 for (i=0;i<21;i++)
335 printf("%f ", bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400336 float sum=0;
337 for (i=0;i<21;i++)
338 sum += bandLogE[21*c+i];
339 printf("%f ", sum/21);
340#endif
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400341 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400342 }
343 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400344 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400345 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400346 for (c=0;c<3;c++)
347 for (i=0;i<21;i++)
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400348 maskLogE[c][i] += channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400349#if 0
350 for (c=0;c<3;c++)
351 {
352 for (i=0;i<21;i++)
353 printf("%f ", maskLogE[c][i]);
354 }
355#endif
356 for (c=0;c<channels;c++)
357 {
358 opus_val16 *mask;
359 if (pos[c]!=0)
360 {
361 mask = &maskLogE[pos[c]-1][0];
362 for (i=0;i<21;i++)
363 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
364 } else {
365 for (i=0;i<21;i++)
366 bandLogE[21*c+i] = 0;
367 }
368#if 0
369 for (i=0;i<21;i++)
370 printf("%f ", bandLogE[21*c+i]);
371 printf("\n");
372#endif
373#if 0
374 float sum=0;
375 for (i=0;i<21;i++)
376 sum += bandLogE[21*c+i];
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400377 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400378 printf("\n");
379#endif
380 }
381 RESTORE_STACK;
382}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500383
384opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
385{
386 int coupled_size;
387 int mono_size;
388
389 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
390 coupled_size = opus_encoder_get_size(2);
391 mono_size = opus_encoder_get_size(1);
392 return align(sizeof(OpusMSEncoder))
393 + nb_coupled_streams * align(coupled_size)
394 + (nb_streams-nb_coupled_streams) * align(mono_size);
395}
396
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400397opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
398{
399 int nb_streams;
400 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400401 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400402
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400403 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400404 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400405 if (channels==1)
406 {
407 nb_streams=1;
408 nb_coupled_streams=0;
409 } else if (channels==2)
410 {
411 nb_streams=1;
412 nb_coupled_streams=1;
413 } else
414 return 0;
415 } else if (mapping_family==1 && channels<=8 && channels>=1)
416 {
417 nb_streams=vorbis_mappings[channels-1].nb_streams;
418 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
419 } else if (mapping_family==255)
420 {
421 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400422 nb_coupled_streams=0;
Michael Graczyk39256682016-05-02 21:42:18 -0700423#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
424 } else if (mapping_family==254)
425 {
426 nb_streams=channels;
427 nb_coupled_streams=0;
428#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400429 } else
430 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400431 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
432 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400433 {
434 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
435 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400436 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400437}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500438
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400439static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500440 OpusMSEncoder *st,
441 opus_int32 Fs,
442 int channels,
443 int streams,
444 int coupled_streams,
445 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400446 int application,
Michael Graczyk39256682016-05-02 21:42:18 -0700447 MappingType mapping_type
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500448)
449{
450 int coupled_size;
451 int mono_size;
452 int i, ret;
453 char *ptr;
454
455 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800456 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500457 return OPUS_BAD_ARG;
458
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500459 st->arch = opus_select_arch();
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500460 st->layout.nb_channels = channels;
461 st->layout.nb_streams = streams;
462 st->layout.nb_coupled_streams = coupled_streams;
Michael Graczyk39256682016-05-02 21:42:18 -0700463 if (mapping_type != MAPPING_TYPE_SURROUND)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400464 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500465 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400466 st->application = application;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500467 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500468 for (i=0;i<st->layout.nb_channels;i++)
469 st->layout.mapping[i] = mapping[i];
470 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
471 return OPUS_BAD_ARG;
472 ptr = (char*)st + align(sizeof(OpusMSEncoder));
473 coupled_size = opus_encoder_get_size(2);
474 mono_size = opus_encoder_get_size(1);
475
476 for (i=0;i<st->layout.nb_coupled_streams;i++)
477 {
478 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400479 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400480 if (i==st->lfe_stream)
481 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500482 ptr += align(coupled_size);
483 }
484 for (;i<st->layout.nb_streams;i++)
485 {
486 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400487 if (i==st->lfe_stream)
488 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500489 if(ret!=OPUS_OK)return ret;
490 ptr += align(mono_size);
491 }
Michael Graczyk39256682016-05-02 21:42:18 -0700492 if (mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400493 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400494 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
495 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400496 }
Michael Graczyk39256682016-05-02 21:42:18 -0700497 st->mapping_type = mapping_type;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500498 return OPUS_OK;
499}
500
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400501int opus_multistream_encoder_init(
502 OpusMSEncoder *st,
503 opus_int32 Fs,
504 int channels,
505 int streams,
506 int coupled_streams,
507 const unsigned char *mapping,
508 int application
509)
510{
Michael Graczyk39256682016-05-02 21:42:18 -0700511 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
512 coupled_streams, mapping,
513 application, MAPPING_TYPE_NONE);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400514}
515
516int opus_multistream_surround_encoder_init(
517 OpusMSEncoder *st,
518 opus_int32 Fs,
519 int channels,
520 int mapping_family,
521 int *streams,
522 int *coupled_streams,
523 unsigned char *mapping,
524 int application
525)
526{
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700527 MappingType mapping_type;
528
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400529 if ((channels>255) || (channels<1))
530 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400531 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400532 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400533 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400534 if (channels==1)
535 {
536 *streams=1;
537 *coupled_streams=0;
538 mapping[0]=0;
539 } else if (channels==2)
540 {
541 *streams=1;
542 *coupled_streams=1;
543 mapping[0]=0;
544 mapping[1]=1;
545 } else
546 return OPUS_UNIMPLEMENTED;
547 } else if (mapping_family==1 && channels<=8 && channels>=1)
548 {
549 int i;
550 *streams=vorbis_mappings[channels-1].nb_streams;
551 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
552 for (i=0;i<channels;i++)
553 mapping[i] = vorbis_mappings[channels-1].mapping[i];
554 if (channels>=6)
555 st->lfe_stream = *streams-1;
556 } else if (mapping_family==255)
557 {
558 int i;
559 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400560 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400561 for(i=0;i<channels;i++)
562 mapping[i] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700563#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
564 } else if (mapping_family==254)
565 {
566 int i;
567 *streams=channels;
568 *coupled_streams=0;
569 for(i=0;i<channels;i++)
570 mapping[i] = i;
571#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400572 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400573 return OPUS_UNIMPLEMENTED;
Michael Graczyk39256682016-05-02 21:42:18 -0700574
575 if (channels>2 && mapping_family==1) {
576 mapping_type = MAPPING_TYPE_SURROUND;
577#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
578 } else if (mapping_family==254)
579 {
580 mapping_type = MAPPING_TYPE_AMBISONICS;
581#endif
582 } else
583 {
584 mapping_type = MAPPING_TYPE_NONE;
585 }
586 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
587 *coupled_streams, mapping,
588 application, mapping_type);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400589}
590
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500591OpusMSEncoder *opus_multistream_encoder_create(
592 opus_int32 Fs,
593 int channels,
594 int streams,
595 int coupled_streams,
596 const unsigned char *mapping,
597 int application,
598 int *error
599)
600{
601 int ret;
602 OpusMSEncoder *st;
603 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800604 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500605 {
606 if (error)
607 *error = OPUS_BAD_ARG;
608 return NULL;
609 }
610 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
611 if (st==NULL)
612 {
613 if (error)
614 *error = OPUS_ALLOC_FAIL;
615 return NULL;
616 }
617 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
618 if (ret != OPUS_OK)
619 {
620 opus_free(st);
621 st = NULL;
622 }
623 if (error)
624 *error = ret;
625 return st;
626}
627
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400628OpusMSEncoder *opus_multistream_surround_encoder_create(
629 opus_int32 Fs,
630 int channels,
631 int mapping_family,
632 int *streams,
633 int *coupled_streams,
634 unsigned char *mapping,
635 int application,
636 int *error
637)
638{
639 int ret;
Mark Harris25b27a92014-11-27 08:48:09 -0800640 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400641 OpusMSEncoder *st;
642 if ((channels>255) || (channels<1))
643 {
644 if (error)
645 *error = OPUS_BAD_ARG;
646 return NULL;
647 }
Mark Harris25b27a92014-11-27 08:48:09 -0800648 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
649 if (!size)
650 {
651 if (error)
652 *error = OPUS_UNIMPLEMENTED;
653 return NULL;
654 }
655 st = (OpusMSEncoder *)opus_alloc(size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400656 if (st==NULL)
657 {
658 if (error)
659 *error = OPUS_ALLOC_FAIL;
660 return NULL;
661 }
662 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
663 if (ret != OPUS_OK)
664 {
665 opus_free(st);
666 st = NULL;
667 }
668 if (error)
669 *error = ret;
670 return st;
671}
672
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700673static void surround_rate_allocation(
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400674 OpusMSEncoder *st,
675 opus_int32 *rate,
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700676 int frame_size,
677 opus_int32 Fs
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400678 )
679{
680 int i;
681 opus_int32 channel_rate;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400682 int stream_offset;
683 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400684 int coupled_ratio; /* Q8 */
685 int lfe_ratio; /* Q8 */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400686 int nb_lfe;
687 int nb_uncoupled;
688 int nb_coupled;
689 int nb_normal;
690 opus_int32 channel_offset;
691 opus_int32 bitrate;
692 int total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400693
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400694 nb_lfe = (st->lfe_stream!=-1);
695 nb_coupled = st->layout.nb_coupled_streams;
696 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
697 nb_normal = 2*nb_coupled + nb_uncoupled;
698
699 /* Give each non-LFE channel enough bits per channel for coding band energy. */
700 channel_offset = 40*IMAX(50, Fs/frame_size);
701
702 if (st->bitrate_bps==OPUS_AUTO)
703 {
704 bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
705 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
706 {
707 bitrate = nb_normal*300000 + nb_lfe*128000;
708 } else {
709 bitrate = st->bitrate_bps;
710 }
711
712 /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
713 total rate for the non-energy part to avoid problems at really low rate. */
714 lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
715
716 /* We give each stream (coupled or uncoupled) a starting bitrate.
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400717 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400718 stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
719 stream_offset = IMAX(0, IMIN(20000, stream_offset));
720
721 /* Coupled streams get twice the mono rate after the offset is allocated. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400722 coupled_ratio = 512;
723 /* 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 -0400724 lfe_ratio = 32;
725
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400726 total = (nb_uncoupled<<8) /* mono */
727 + coupled_ratio*nb_coupled /* stereo */
728 + nb_lfe*lfe_ratio;
729 channel_rate = 256*(opus_int64)(bitrate - lfe_offset*nb_lfe - stream_offset*(nb_coupled+nb_uncoupled) - channel_offset*nb_normal)/total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400730
731 for (i=0;i<st->layout.nb_streams;i++)
732 {
733 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400734 rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400735 else if (i!=st->lfe_stream)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400736 rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400737 else
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400738 rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700739 }
740}
741
742#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
743static void ambisonics_rate_allocation(
744 OpusMSEncoder *st,
745 opus_int32 *rate,
746 int frame_size,
747 opus_int32 Fs
748 )
749{
750 int i;
751 int non_mono_rate;
752 int total_rate;
753
754 /* The mono channel gets (rate_ratio_num / rate_ratio_den) times as many bits
755 * as all other channels */
756 const int rate_ratio_num = 4;
757 const int rate_ratio_den = 3;
758 const int num_channels = st->layout.nb_streams;
759
760 if (st->bitrate_bps==OPUS_AUTO)
761 {
Michael Graczykfa2578b2016-09-07 15:26:51 -0700762 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
763 (Fs+60*Fs/frame_size) + st->layout.nb_streams * 15000;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700764 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
765 {
766 total_rate = num_channels * 320000;
767 } else {
768 total_rate = st->bitrate_bps;
769 }
770
771 /* Let y be the non-mono rate and let p, q be integers such that the mono
772 * channel rate is (p/q) * y.
773 * Also let T be the total bitrate to allocate. Then
774 * (n - 1) y + (p/q) y = T
775 * y = (T q) / (qn - q + p)
776 */
777 non_mono_rate =
778 total_rate * rate_ratio_den
779 / (rate_ratio_den*num_channels + rate_ratio_num - rate_ratio_den);
780
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700781 rate[0] = total_rate - (num_channels - 1) * non_mono_rate;
782 for (i=1;i<st->layout.nb_streams;i++)
783 {
784 rate[i] = non_mono_rate;
785 }
786}
787#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
788
789static opus_int32 rate_allocation(
790 OpusMSEncoder *st,
791 opus_int32 *rate,
792 int frame_size
793 )
794{
795 int i;
796 opus_int32 rate_sum=0;
797 opus_int32 Fs;
798 char *ptr;
799
800 ptr = (char*)st + align(sizeof(OpusMSEncoder));
801 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
802
803#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
804 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
805 ambisonics_rate_allocation(st, rate, frame_size, Fs);
806 } else
807#endif
808 {
809 surround_rate_allocation(st, rate, frame_size, Fs);
810 }
811
812 for (i=0;i<st->layout.nb_streams;i++)
813 {
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400814 rate[i] = IMAX(rate[i], 500);
815 rate_sum += rate[i];
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400816 }
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400817 return rate_sum;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400818}
819
Felicia Lim0962cbe2016-10-27 17:03:36 -0700820/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
821#define MS_FRAME_TMP (6*1275+12)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500822static int opus_multistream_encode_native
823(
824 OpusMSEncoder *st,
825 opus_copy_channel_in_func copy_channel_in,
826 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400827 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500828 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500829 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400830 int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500831 downmix_func downmix,
832 int float_api
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500833)
834{
835 opus_int32 Fs;
836 int coupled_size;
837 int mono_size;
838 int s;
839 char *ptr;
840 int tot_size;
841 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400842 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500843 unsigned char tmp_data[MS_FRAME_TMP];
844 OpusRepacketizer rp;
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400845 opus_int32 vbr;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500846 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400847 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400848 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400849 opus_val32 *mem = NULL;
850 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400851 int frame_size;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400852 opus_int32 rate_sum;
853 opus_int32 smallest_packet;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500854 ALLOC_STACK;
855
Michael Graczyk39256682016-05-02 21:42:18 -0700856 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400857 {
858 preemph_mem = ms_get_preemph_mem(st);
859 mem = ms_get_window_mem(st);
860 }
861
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500862 ptr = (char*)st + align(sizeof(OpusMSEncoder));
863 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400864 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500865 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500866
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400867 {
868 opus_int32 delay_compensation;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400869
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400870 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
871 delay_compensation -= Fs/400;
Jean-Marc Valin132ed592016-11-04 11:41:13 -0400872 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400873 }
874
Jean-Marc Valin74483662012-12-17 16:23:42 -0500875 if (400*frame_size < Fs)
876 {
877 RESTORE_STACK;
878 return OPUS_BAD_ARG;
879 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500880 /* Validate frame_size before using it to allocate stack space.
881 This mirrors the checks in opus_encode[_float](). */
Felicia Lim0962cbe2016-10-27 17:03:36 -0700882 if (400*frame_size != Fs && 200*frame_size != Fs &&
883 100*frame_size != Fs && 50*frame_size != Fs &&
884 25*frame_size != Fs && 50*frame_size != 3*Fs &&
885 50*frame_size != 4*Fs && 50*frame_size != 5*Fs &&
886 50*frame_size != 6*Fs)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500887 {
888 RESTORE_STACK;
889 return OPUS_BAD_ARG;
890 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400891
892 /* Smallest packet the encoder can produce. */
893 smallest_packet = st->layout.nb_streams*2-1;
Felicia Limbcfe0f62016-10-28 11:11:18 -0700894 /* 100 ms needs an extra byte per stream for the ToC. */
895 if (Fs/frame_size == 10)
896 smallest_packet += st->layout.nb_streams;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400897 if (max_data_bytes < smallest_packet)
898 {
899 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400900 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400901 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500902 ALLOC(buf, 2*frame_size, opus_val16);
903 coupled_size = opus_encoder_get_size(2);
904 mono_size = opus_encoder_get_size(1);
905
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400906 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700907 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400908 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500909 surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400910 }
911
Jean-Marc Valin74483662012-12-17 16:23:42 -0500912 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700913 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400914
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400915 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400916 {
917 if (st->bitrate_bps == OPUS_AUTO)
918 {
919 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
920 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
921 {
922 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
923 3*st->bitrate_bps/(3*8*Fs/frame_size)));
924 }
925 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500926 ptr = (char*)st + align(sizeof(OpusMSEncoder));
927 for (s=0;s<st->layout.nb_streams;s++)
928 {
929 OpusEncoder *enc;
930 enc = (OpusEncoder*)ptr;
931 if (s < st->layout.nb_coupled_streams)
932 ptr += align(coupled_size);
933 else
934 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400935 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700936 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400937 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400938 opus_int32 equiv_rate;
939 equiv_rate = st->bitrate_bps;
940 if (frame_size*50 < Fs)
941 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500942 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400943 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500944 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400945 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500946 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400947 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
948 else
949 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400950 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400951 {
952 /* To preserve the spatial image, force stereo CELT on coupled streams */
953 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400954 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400955 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400956 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700957#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
958 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
959 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
960 }
961#endif
Jean-Marc Valin74483662012-12-17 16:23:42 -0500962 }
963
964 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500965 /* Counting ToC */
966 tot_size = 0;
967 for (s=0;s<st->layout.nb_streams;s++)
968 {
969 OpusEncoder *enc;
970 int len;
971 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400972 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -0400973 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500974
975 opus_repacketizer_init(&rp);
976 enc = (OpusEncoder*)ptr;
977 if (s < st->layout.nb_coupled_streams)
978 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400979 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500980 int left, right;
981 left = get_left_channel(&st->layout, s, -1);
982 right = get_right_channel(&st->layout, s, -1);
983 (*copy_channel_in)(buf, 2,
984 pcm, st->layout.nb_channels, left, frame_size);
985 (*copy_channel_in)(buf+1, 2,
986 pcm, st->layout.nb_channels, right, frame_size);
987 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -0700988 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400989 {
990 for (i=0;i<21;i++)
991 {
992 bandLogE[i] = bandSMR[21*left+i];
993 bandLogE[21+i] = bandSMR[21*right+i];
994 }
995 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400996 c1 = left;
997 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500998 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400999 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001000 int chan = get_mono_channel(&st->layout, s, -1);
1001 (*copy_channel_in)(buf, 1,
1002 pcm, st->layout.nb_channels, chan, frame_size);
1003 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001004 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001005 {
1006 for (i=0;i<21;i++)
1007 bandLogE[i] = bandSMR[21*chan+i];
1008 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001009 c1 = chan;
1010 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001011 }
Michael Graczyk39256682016-05-02 21:42:18 -07001012 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001013 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001014 /* number of bytes left (+Toc) */
1015 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001016 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -04001017 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Felicia Lim8fec4162016-10-31 11:58:26 -07001018 /* For 100 ms, reserve an extra byte per stream for the ToC */
Felicia Limbcfe0f62016-10-28 11:11:18 -07001019 if (Fs/frame_size == 10)
Felicia Lim8fec4162016-10-31 11:58:26 -07001020 curr_max -= st->layout.nb_streams-s-1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001021 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001022 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -04001023 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -04001024 if (!vbr && s == st->layout.nb_streams-1)
1025 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04001026 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001027 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001028 if (len<0)
1029 {
1030 RESTORE_STACK;
1031 return len;
1032 }
1033 /* We need to use the repacketizer to add the self-delimiting lengths
1034 while taking into account the fact that the encoder can now return
1035 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001036 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1037 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1038 with the encoder. */
1039 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001040 {
1041 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001042 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001043 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001044 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1045 data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001046 data += len;
1047 tot_size += len;
1048 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001049 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001050 RESTORE_STACK;
1051 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001052}
1053
Pedro Becerra1af7f952013-07-11 00:00:47 -04001054#if !defined(DISABLE_FLOAT_API)
1055static void opus_copy_channel_in_float(
1056 opus_val16 *dst,
1057 int dst_stride,
1058 const void *src,
1059 int src_stride,
1060 int src_channel,
1061 int frame_size
1062)
1063{
1064 const float *float_src;
1065 opus_int32 i;
1066 float_src = (const float *)src;
1067 for (i=0;i<frame_size;i++)
1068#if defined(FIXED_POINT)
1069 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1070#else
1071 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1072#endif
1073}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001074#endif
1075
1076static void opus_copy_channel_in_short(
1077 opus_val16 *dst,
1078 int dst_stride,
1079 const void *src,
1080 int src_stride,
1081 int src_channel,
1082 int frame_size
1083)
1084{
1085 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001086 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001087 short_src = (const opus_int16 *)src;
1088 for (i=0;i<frame_size;i++)
1089#if defined(FIXED_POINT)
1090 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1091#else
1092 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1093#endif
1094}
1095
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001096
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001097#ifdef FIXED_POINT
1098int opus_multistream_encode(
1099 OpusMSEncoder *st,
1100 const opus_val16 *pcm,
1101 int frame_size,
1102 unsigned char *data,
1103 opus_int32 max_data_bytes
1104)
1105{
1106 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001107 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001108}
1109
1110#ifndef DISABLE_FLOAT_API
1111int opus_multistream_encode_float(
1112 OpusMSEncoder *st,
1113 const float *pcm,
1114 int frame_size,
1115 unsigned char *data,
1116 opus_int32 max_data_bytes
1117)
1118{
1119 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001120 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001121}
1122#endif
1123
1124#else
1125
1126int opus_multistream_encode_float
1127(
1128 OpusMSEncoder *st,
1129 const opus_val16 *pcm,
1130 int frame_size,
1131 unsigned char *data,
1132 opus_int32 max_data_bytes
1133)
1134{
1135 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001136 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001137}
1138
1139int opus_multistream_encode(
1140 OpusMSEncoder *st,
1141 const opus_int16 *pcm,
1142 int frame_size,
1143 unsigned char *data,
1144 opus_int32 max_data_bytes
1145)
1146{
1147 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001148 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001149}
1150#endif
1151
1152int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1153{
1154 va_list ap;
1155 int coupled_size, mono_size;
1156 char *ptr;
1157 int ret = OPUS_OK;
1158
1159 va_start(ap, request);
1160
1161 coupled_size = opus_encoder_get_size(2);
1162 mono_size = opus_encoder_get_size(1);
1163 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1164 switch (request)
1165 {
1166 case OPUS_SET_BITRATE_REQUEST:
1167 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001168 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001169 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001170 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001171 if (value <= 0)
1172 goto bad_arg;
1173 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001174 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001175 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001176 }
1177 break;
1178 case OPUS_GET_BITRATE_REQUEST:
1179 {
1180 int s;
1181 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001182 if (!value)
1183 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001184 goto bad_arg;
1185 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001186 *value = 0;
1187 for (s=0;s<st->layout.nb_streams;s++)
1188 {
1189 opus_int32 rate;
1190 OpusEncoder *enc;
1191 enc = (OpusEncoder*)ptr;
1192 if (s < st->layout.nb_coupled_streams)
1193 ptr += align(coupled_size);
1194 else
1195 ptr += align(mono_size);
1196 opus_encoder_ctl(enc, request, &rate);
1197 *value += rate;
1198 }
1199 }
1200 break;
1201 case OPUS_GET_LSB_DEPTH_REQUEST:
1202 case OPUS_GET_VBR_REQUEST:
1203 case OPUS_GET_APPLICATION_REQUEST:
1204 case OPUS_GET_BANDWIDTH_REQUEST:
1205 case OPUS_GET_COMPLEXITY_REQUEST:
1206 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1207 case OPUS_GET_DTX_REQUEST:
1208 case OPUS_GET_VOICE_RATIO_REQUEST:
1209 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1210 case OPUS_GET_SIGNAL_REQUEST:
1211 case OPUS_GET_LOOKAHEAD_REQUEST:
1212 case OPUS_GET_SAMPLE_RATE_REQUEST:
1213 case OPUS_GET_INBAND_FEC_REQUEST:
1214 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001215 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001216 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001217 {
1218 OpusEncoder *enc;
1219 /* For int32* GET params, just query the first stream */
1220 opus_int32 *value = va_arg(ap, opus_int32*);
1221 enc = (OpusEncoder*)ptr;
1222 ret = opus_encoder_ctl(enc, request, value);
1223 }
1224 break;
1225 case OPUS_GET_FINAL_RANGE_REQUEST:
1226 {
1227 int s;
1228 opus_uint32 *value = va_arg(ap, opus_uint32*);
1229 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001230 if (!value)
1231 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001232 goto bad_arg;
1233 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001234 *value=0;
1235 for (s=0;s<st->layout.nb_streams;s++)
1236 {
1237 OpusEncoder *enc;
1238 enc = (OpusEncoder*)ptr;
1239 if (s < st->layout.nb_coupled_streams)
1240 ptr += align(coupled_size);
1241 else
1242 ptr += align(mono_size);
1243 ret = opus_encoder_ctl(enc, request, &tmp);
1244 if (ret != OPUS_OK) break;
1245 *value ^= tmp;
1246 }
1247 }
1248 break;
1249 case OPUS_SET_LSB_DEPTH_REQUEST:
1250 case OPUS_SET_COMPLEXITY_REQUEST:
1251 case OPUS_SET_VBR_REQUEST:
1252 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001253 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001254 case OPUS_SET_BANDWIDTH_REQUEST:
1255 case OPUS_SET_SIGNAL_REQUEST:
1256 case OPUS_SET_APPLICATION_REQUEST:
1257 case OPUS_SET_INBAND_FEC_REQUEST:
1258 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1259 case OPUS_SET_DTX_REQUEST:
1260 case OPUS_SET_FORCE_MODE_REQUEST:
1261 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001262 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001263 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001264 {
1265 int s;
1266 /* This works for int32 params */
1267 opus_int32 value = va_arg(ap, opus_int32);
1268 for (s=0;s<st->layout.nb_streams;s++)
1269 {
1270 OpusEncoder *enc;
1271
1272 enc = (OpusEncoder*)ptr;
1273 if (s < st->layout.nb_coupled_streams)
1274 ptr += align(coupled_size);
1275 else
1276 ptr += align(mono_size);
1277 ret = opus_encoder_ctl(enc, request, value);
1278 if (ret != OPUS_OK)
1279 break;
1280 }
1281 }
1282 break;
1283 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1284 {
1285 int s;
1286 opus_int32 stream_id;
1287 OpusEncoder **value;
1288 stream_id = va_arg(ap, opus_int32);
1289 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1290 ret = OPUS_BAD_ARG;
1291 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001292 if (!value)
1293 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001294 goto bad_arg;
1295 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001296 for (s=0;s<stream_id;s++)
1297 {
1298 if (s < st->layout.nb_coupled_streams)
1299 ptr += align(coupled_size);
1300 else
1301 ptr += align(mono_size);
1302 }
1303 *value = (OpusEncoder*)ptr;
1304 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001305 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001306 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001307 {
1308 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001309 st->variable_duration = value;
1310 }
1311 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001312 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001313 {
1314 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001315 if (!value)
1316 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001317 goto bad_arg;
1318 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001319 *value = st->variable_duration;
1320 }
1321 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001322 case OPUS_RESET_STATE:
1323 {
1324 int s;
Michael Graczyk39256682016-05-02 21:42:18 -07001325 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001326 {
1327 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1328 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1329 }
1330 for (s=0;s<st->layout.nb_streams;s++)
1331 {
1332 OpusEncoder *enc;
1333 enc = (OpusEncoder*)ptr;
1334 if (s < st->layout.nb_coupled_streams)
1335 ptr += align(coupled_size);
1336 else
1337 ptr += align(mono_size);
1338 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1339 if (ret != OPUS_OK)
1340 break;
1341 }
1342 }
1343 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001344 default:
1345 ret = OPUS_UNIMPLEMENTED;
1346 break;
1347 }
1348
1349 va_end(ap);
1350 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001351bad_arg:
1352 va_end(ap);
1353 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001354}
1355
1356void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1357{
1358 opus_free(st);
1359}