blob: 2c4dca24f21bf6e5dc7d0e06ac5c2742ca6889c9 [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
Mark Harrisd73c5a92016-11-05 22:01:52 -0700867 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
868 if (frame_size <= 0)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500869 {
870 RESTORE_STACK;
871 return OPUS_BAD_ARG;
872 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400873
874 /* Smallest packet the encoder can produce. */
875 smallest_packet = st->layout.nb_streams*2-1;
Felicia Limbcfe0f62016-10-28 11:11:18 -0700876 /* 100 ms needs an extra byte per stream for the ToC. */
877 if (Fs/frame_size == 10)
878 smallest_packet += st->layout.nb_streams;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400879 if (max_data_bytes < smallest_packet)
880 {
881 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400882 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400883 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500884 ALLOC(buf, 2*frame_size, opus_val16);
885 coupled_size = opus_encoder_get_size(2);
886 mono_size = opus_encoder_get_size(1);
887
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400888 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700889 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400890 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500891 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 -0400892 }
893
Jean-Marc Valin74483662012-12-17 16:23:42 -0500894 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700895 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400896
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400897 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400898 {
899 if (st->bitrate_bps == OPUS_AUTO)
900 {
901 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
902 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
903 {
904 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
905 3*st->bitrate_bps/(3*8*Fs/frame_size)));
906 }
907 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500908 ptr = (char*)st + align(sizeof(OpusMSEncoder));
909 for (s=0;s<st->layout.nb_streams;s++)
910 {
911 OpusEncoder *enc;
912 enc = (OpusEncoder*)ptr;
913 if (s < st->layout.nb_coupled_streams)
914 ptr += align(coupled_size);
915 else
916 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400917 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700918 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400919 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400920 opus_int32 equiv_rate;
921 equiv_rate = st->bitrate_bps;
922 if (frame_size*50 < Fs)
923 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500924 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400925 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500926 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400927 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500928 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400929 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
930 else
931 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400932 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400933 {
934 /* To preserve the spatial image, force stereo CELT on coupled streams */
935 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400936 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400937 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400938 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700939#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
940 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
941 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
942 }
943#endif
Jean-Marc Valin74483662012-12-17 16:23:42 -0500944 }
945
946 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500947 /* Counting ToC */
948 tot_size = 0;
949 for (s=0;s<st->layout.nb_streams;s++)
950 {
951 OpusEncoder *enc;
952 int len;
953 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400954 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -0400955 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500956
957 opus_repacketizer_init(&rp);
958 enc = (OpusEncoder*)ptr;
959 if (s < st->layout.nb_coupled_streams)
960 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400961 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500962 int left, right;
963 left = get_left_channel(&st->layout, s, -1);
964 right = get_right_channel(&st->layout, s, -1);
965 (*copy_channel_in)(buf, 2,
966 pcm, st->layout.nb_channels, left, frame_size);
967 (*copy_channel_in)(buf+1, 2,
968 pcm, st->layout.nb_channels, right, frame_size);
969 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -0700970 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400971 {
972 for (i=0;i<21;i++)
973 {
974 bandLogE[i] = bandSMR[21*left+i];
975 bandLogE[21+i] = bandSMR[21*right+i];
976 }
977 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400978 c1 = left;
979 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500980 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400981 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500982 int chan = get_mono_channel(&st->layout, s, -1);
983 (*copy_channel_in)(buf, 1,
984 pcm, st->layout.nb_channels, chan, frame_size);
985 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -0700986 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400987 {
988 for (i=0;i<21;i++)
989 bandLogE[i] = bandSMR[21*chan+i];
990 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400991 c1 = chan;
992 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500993 }
Michael Graczyk39256682016-05-02 21:42:18 -0700994 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400995 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500996 /* number of bytes left (+Toc) */
997 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -0400998 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400999 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Felicia Lim8fec4162016-10-31 11:58:26 -07001000 /* For 100 ms, reserve an extra byte per stream for the ToC */
Felicia Limbcfe0f62016-10-28 11:11:18 -07001001 if (Fs/frame_size == 10)
Felicia Lim8fec4162016-10-31 11:58:26 -07001002 curr_max -= st->layout.nb_streams-s-1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001003 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001004 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -04001005 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -04001006 if (!vbr && s == st->layout.nb_streams-1)
1007 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04001008 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001009 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001010 if (len<0)
1011 {
1012 RESTORE_STACK;
1013 return len;
1014 }
1015 /* We need to use the repacketizer to add the self-delimiting lengths
1016 while taking into account the fact that the encoder can now return
1017 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001018 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1019 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1020 with the encoder. */
1021 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001022 {
1023 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001024 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001025 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001026 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1027 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 -05001028 data += len;
1029 tot_size += len;
1030 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001031 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001032 RESTORE_STACK;
1033 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001034}
1035
Pedro Becerra1af7f952013-07-11 00:00:47 -04001036#if !defined(DISABLE_FLOAT_API)
1037static void opus_copy_channel_in_float(
1038 opus_val16 *dst,
1039 int dst_stride,
1040 const void *src,
1041 int src_stride,
1042 int src_channel,
1043 int frame_size
1044)
1045{
1046 const float *float_src;
1047 opus_int32 i;
1048 float_src = (const float *)src;
1049 for (i=0;i<frame_size;i++)
1050#if defined(FIXED_POINT)
1051 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1052#else
1053 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1054#endif
1055}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001056#endif
1057
1058static void opus_copy_channel_in_short(
1059 opus_val16 *dst,
1060 int dst_stride,
1061 const void *src,
1062 int src_stride,
1063 int src_channel,
1064 int frame_size
1065)
1066{
1067 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001068 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001069 short_src = (const opus_int16 *)src;
1070 for (i=0;i<frame_size;i++)
1071#if defined(FIXED_POINT)
1072 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1073#else
1074 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1075#endif
1076}
1077
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001078
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001079#ifdef FIXED_POINT
1080int opus_multistream_encode(
1081 OpusMSEncoder *st,
1082 const opus_val16 *pcm,
1083 int frame_size,
1084 unsigned char *data,
1085 opus_int32 max_data_bytes
1086)
1087{
1088 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001089 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001090}
1091
1092#ifndef DISABLE_FLOAT_API
1093int opus_multistream_encode_float(
1094 OpusMSEncoder *st,
1095 const float *pcm,
1096 int frame_size,
1097 unsigned char *data,
1098 opus_int32 max_data_bytes
1099)
1100{
1101 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001102 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001103}
1104#endif
1105
1106#else
1107
1108int opus_multistream_encode_float
1109(
1110 OpusMSEncoder *st,
1111 const opus_val16 *pcm,
1112 int frame_size,
1113 unsigned char *data,
1114 opus_int32 max_data_bytes
1115)
1116{
1117 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001118 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001119}
1120
1121int opus_multistream_encode(
1122 OpusMSEncoder *st,
1123 const opus_int16 *pcm,
1124 int frame_size,
1125 unsigned char *data,
1126 opus_int32 max_data_bytes
1127)
1128{
1129 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001130 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001131}
1132#endif
1133
1134int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1135{
1136 va_list ap;
1137 int coupled_size, mono_size;
1138 char *ptr;
1139 int ret = OPUS_OK;
1140
1141 va_start(ap, request);
1142
1143 coupled_size = opus_encoder_get_size(2);
1144 mono_size = opus_encoder_get_size(1);
1145 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1146 switch (request)
1147 {
1148 case OPUS_SET_BITRATE_REQUEST:
1149 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001150 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001151 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001152 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001153 if (value <= 0)
1154 goto bad_arg;
1155 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001156 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001157 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001158 }
1159 break;
1160 case OPUS_GET_BITRATE_REQUEST:
1161 {
1162 int s;
1163 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001164 if (!value)
1165 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001166 goto bad_arg;
1167 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001168 *value = 0;
1169 for (s=0;s<st->layout.nb_streams;s++)
1170 {
1171 opus_int32 rate;
1172 OpusEncoder *enc;
1173 enc = (OpusEncoder*)ptr;
1174 if (s < st->layout.nb_coupled_streams)
1175 ptr += align(coupled_size);
1176 else
1177 ptr += align(mono_size);
1178 opus_encoder_ctl(enc, request, &rate);
1179 *value += rate;
1180 }
1181 }
1182 break;
1183 case OPUS_GET_LSB_DEPTH_REQUEST:
1184 case OPUS_GET_VBR_REQUEST:
1185 case OPUS_GET_APPLICATION_REQUEST:
1186 case OPUS_GET_BANDWIDTH_REQUEST:
1187 case OPUS_GET_COMPLEXITY_REQUEST:
1188 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1189 case OPUS_GET_DTX_REQUEST:
1190 case OPUS_GET_VOICE_RATIO_REQUEST:
1191 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1192 case OPUS_GET_SIGNAL_REQUEST:
1193 case OPUS_GET_LOOKAHEAD_REQUEST:
1194 case OPUS_GET_SAMPLE_RATE_REQUEST:
1195 case OPUS_GET_INBAND_FEC_REQUEST:
1196 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001197 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001198 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001199 {
1200 OpusEncoder *enc;
1201 /* For int32* GET params, just query the first stream */
1202 opus_int32 *value = va_arg(ap, opus_int32*);
1203 enc = (OpusEncoder*)ptr;
1204 ret = opus_encoder_ctl(enc, request, value);
1205 }
1206 break;
1207 case OPUS_GET_FINAL_RANGE_REQUEST:
1208 {
1209 int s;
1210 opus_uint32 *value = va_arg(ap, opus_uint32*);
1211 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001212 if (!value)
1213 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001214 goto bad_arg;
1215 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001216 *value=0;
1217 for (s=0;s<st->layout.nb_streams;s++)
1218 {
1219 OpusEncoder *enc;
1220 enc = (OpusEncoder*)ptr;
1221 if (s < st->layout.nb_coupled_streams)
1222 ptr += align(coupled_size);
1223 else
1224 ptr += align(mono_size);
1225 ret = opus_encoder_ctl(enc, request, &tmp);
1226 if (ret != OPUS_OK) break;
1227 *value ^= tmp;
1228 }
1229 }
1230 break;
1231 case OPUS_SET_LSB_DEPTH_REQUEST:
1232 case OPUS_SET_COMPLEXITY_REQUEST:
1233 case OPUS_SET_VBR_REQUEST:
1234 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001235 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001236 case OPUS_SET_BANDWIDTH_REQUEST:
1237 case OPUS_SET_SIGNAL_REQUEST:
1238 case OPUS_SET_APPLICATION_REQUEST:
1239 case OPUS_SET_INBAND_FEC_REQUEST:
1240 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1241 case OPUS_SET_DTX_REQUEST:
1242 case OPUS_SET_FORCE_MODE_REQUEST:
1243 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001244 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001245 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001246 {
1247 int s;
1248 /* This works for int32 params */
1249 opus_int32 value = va_arg(ap, opus_int32);
1250 for (s=0;s<st->layout.nb_streams;s++)
1251 {
1252 OpusEncoder *enc;
1253
1254 enc = (OpusEncoder*)ptr;
1255 if (s < st->layout.nb_coupled_streams)
1256 ptr += align(coupled_size);
1257 else
1258 ptr += align(mono_size);
1259 ret = opus_encoder_ctl(enc, request, value);
1260 if (ret != OPUS_OK)
1261 break;
1262 }
1263 }
1264 break;
1265 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1266 {
1267 int s;
1268 opus_int32 stream_id;
1269 OpusEncoder **value;
1270 stream_id = va_arg(ap, opus_int32);
1271 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1272 ret = OPUS_BAD_ARG;
1273 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001274 if (!value)
1275 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001276 goto bad_arg;
1277 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001278 for (s=0;s<stream_id;s++)
1279 {
1280 if (s < st->layout.nb_coupled_streams)
1281 ptr += align(coupled_size);
1282 else
1283 ptr += align(mono_size);
1284 }
1285 *value = (OpusEncoder*)ptr;
1286 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001287 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001288 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001289 {
1290 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001291 st->variable_duration = value;
1292 }
1293 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001294 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001295 {
1296 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001297 if (!value)
1298 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001299 goto bad_arg;
1300 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001301 *value = st->variable_duration;
1302 }
1303 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001304 case OPUS_RESET_STATE:
1305 {
1306 int s;
Michael Graczyk39256682016-05-02 21:42:18 -07001307 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001308 {
1309 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1310 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1311 }
1312 for (s=0;s<st->layout.nb_streams;s++)
1313 {
1314 OpusEncoder *enc;
1315 enc = (OpusEncoder*)ptr;
1316 if (s < st->layout.nb_coupled_streams)
1317 ptr += align(coupled_size);
1318 else
1319 ptr += align(mono_size);
1320 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1321 if (ret != OPUS_OK)
1322 break;
1323 }
1324 }
1325 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001326 default:
1327 ret = OPUS_UNIMPLEMENTED;
1328 break;
1329 }
1330
1331 va_end(ap);
1332 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001333bad_arg:
1334 va_end(ap);
1335 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001336}
1337
1338void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1339{
1340 opus_free(st);
1341}