blob: 6ec0fc5ab1caeb114a32df2bef4948d1354dd753 [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 Valinab86a9c2013-11-13 23:06:25 -050090 float subframe_mem[3];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050091 /* Encoder states go here */
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040092 /* then opus_val32 window_mem[channels*120]; */
93 /* then opus_val32 preemph_mem[channels]; */
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050094};
95
Jean-Marc Valinfdceae82013-08-30 21:58:02 -040096static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
97{
98 int s;
99 char *ptr;
100 int coupled_size, mono_size;
101
102 coupled_size = opus_encoder_get_size(2);
103 mono_size = opus_encoder_get_size(1);
104 ptr = (char*)st + align(sizeof(OpusMSEncoder));
105 for (s=0;s<st->layout.nb_streams;s++)
106 {
107 if (s < st->layout.nb_coupled_streams)
108 ptr += align(coupled_size);
109 else
110 ptr += align(mono_size);
111 }
Mark Harris4feb0df2015-08-07 01:24:48 -0700112 /* void* cast avoids clang -Wcast-align warning */
113 return (opus_val32*)(void*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400114}
115
116static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
117{
118 int s;
119 char *ptr;
120 int coupled_size, mono_size;
121
122 coupled_size = opus_encoder_get_size(2);
123 mono_size = opus_encoder_get_size(1);
124 ptr = (char*)st + align(sizeof(OpusMSEncoder));
125 for (s=0;s<st->layout.nb_streams;s++)
126 {
127 if (s < st->layout.nb_coupled_streams)
128 ptr += align(coupled_size);
129 else
130 ptr += align(mono_size);
131 }
Mark Harris4feb0df2015-08-07 01:24:48 -0700132 /* void* cast avoids clang -Wcast-align warning */
133 return (opus_val32*)(void*)ptr;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400134}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500135
136static int validate_encoder_layout(const ChannelLayout *layout)
137{
138 int s;
139 for (s=0;s<layout->nb_streams;s++)
140 {
141 if (s < layout->nb_coupled_streams)
142 {
143 if (get_left_channel(layout, s, -1)==-1)
144 return 0;
145 if (get_right_channel(layout, s, -1)==-1)
146 return 0;
147 } else {
148 if (get_mono_channel(layout, s, -1)==-1)
149 return 0;
150 }
151 }
152 return 1;
153}
154
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400155static void channel_pos(int channels, int pos[8])
156{
157 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
158 if (channels==4)
159 {
160 pos[0]=1;
161 pos[1]=3;
162 pos[2]=1;
163 pos[3]=3;
164 } else if (channels==3||channels==5||channels==6)
165 {
166 pos[0]=1;
167 pos[1]=2;
168 pos[2]=3;
169 pos[3]=1;
170 pos[4]=3;
171 pos[5]=0;
172 } else if (channels==7)
173 {
174 pos[0]=1;
175 pos[1]=2;
176 pos[2]=3;
177 pos[3]=1;
178 pos[4]=3;
179 pos[5]=2;
180 pos[6]=0;
181 } else if (channels==8)
182 {
183 pos[0]=1;
184 pos[1]=2;
185 pos[2]=3;
186 pos[3]=1;
187 pos[4]=3;
188 pos[5]=1;
189 pos[6]=3;
190 pos[7]=0;
191 }
192}
193
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400194#if 1
195/* Computes a rough approximation of log2(2^a + 2^b) */
196static opus_val16 logSum(opus_val16 a, opus_val16 b)
197{
198 opus_val16 max;
199 opus_val32 diff;
200 opus_val16 frac;
201 static const opus_val16 diff_table[17] = {
202 QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
203 QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
204 QCONST16(0.0028123f, DB_SHIFT)
205 };
206 int low;
207 if (a>b)
208 {
209 max = a;
210 diff = SUB32(EXTEND32(a),EXTEND32(b));
211 } else {
212 max = b;
213 diff = SUB32(EXTEND32(b),EXTEND32(a));
214 }
Mark Harrisa6595e62015-10-07 09:21:23 -0400215 if (!(diff < QCONST16(8.f, DB_SHIFT))) /* inverted to catch NaNs */
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400216 return max;
217#ifdef FIXED_POINT
218 low = SHR32(diff, DB_SHIFT-1);
219 frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
220#else
Jean-Marc Valina71c9ad2013-11-13 12:07:01 -0500221 low = (int)floor(2*diff);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400222 frac = 2*diff - low;
223#endif
224 return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
225}
226#else
227opus_val16 logSum(opus_val16 a, opus_val16 b)
228{
229 return log2(pow(4, a)+ pow(4, b))/2;
230}
231#endif
232
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400233void 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 -0500234 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 -0400235)
236{
237 int c;
238 int i;
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400239 int LM;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400240 int pos[8] = {0};
241 int upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400242 int frame_size;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400243 int freq_size;
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400244 opus_val16 channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400245 opus_val32 bandE[21];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400246 opus_val16 maskLogE[3][21];
247 VARDECL(opus_val32, in);
248 VARDECL(opus_val16, x);
Jean-Marc Valine8e5ecb2013-10-01 17:16:33 -0400249 VARDECL(opus_val32, freq);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400250 SAVE_STACK;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400251
252 upsample = resampling_factor(rate);
253 frame_size = len*upsample;
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400254 freq_size = IMIN(960, frame_size);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400255
Michael Graczyk39256682016-05-02 21:42:18 -0700256 /* LM = log2(frame_size / 120) */
Jean-Marc Valin2e653a72013-10-14 17:47:18 -0400257 for (LM=0;LM<celt_mode->maxLM;LM++)
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400258 if (celt_mode->shortMdctSize<<LM==frame_size)
259 break;
260
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400261 ALLOC(in, frame_size+overlap, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400262 ALLOC(x, len, opus_val16);
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400263 ALLOC(freq, freq_size, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400264
265 channel_pos(channels, pos);
266
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400267 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400268 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400269 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400270
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400271 for (c=0;c<channels;c++)
272 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400273 int frame;
274 int nb_frames = frame_size/freq_size;
275 celt_assert(nb_frames*freq_size == frame_size);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400276 OPUS_COPY(in, mem+c*overlap, overlap);
277 (*copy_channel_in)(x, 1, pcm, channels, c, len);
Jean-Marc Valin2dc27df2013-11-13 19:35:43 -0500278 celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400279#ifndef FIXED_POINT
280 {
281 opus_val32 sum;
282 sum = celt_inner_prod(in, in, frame_size+overlap, 0);
283 /* This should filter out both NaNs and ridiculous signals that could
284 cause NaNs further down. */
285 if (!(sum < 1e9f) || celt_isnan(sum))
286 {
287 OPUS_CLEAR(in, frame_size+overlap);
288 preemph_mem[c] = 0;
289 }
290 }
291#endif
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400292 OPUS_CLEAR(bandE, 21);
293 for (frame=0;frame<nb_frames;frame++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400294 {
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400295 opus_val32 tmpE[21];
296 clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window,
297 overlap, celt_mode->maxLM-LM, 1, arch);
298 if (upsample != 1)
299 {
300 int bound = freq_size/upsample;
301 for (i=0;i<bound;i++)
302 freq[i] *= upsample;
303 for (;i<freq_size;i++)
304 freq[i] = 0;
305 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400306
Jean-Marc Valina3fadcb2016-09-09 16:13:43 -0400307 compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM);
308 /* If we have multiple frames, take the max energy. */
309 for (i=0;i<21;i++)
310 bandE[i] = MAX32(bandE[i], tmpE[i]);
311 }
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400312 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400313 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
314 for (i=1;i<21;i++)
315 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
316 for (i=19;i>=0;i--)
317 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 -0400318 if (pos[c]==1)
319 {
320 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400321 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400322 } else if (pos[c]==3)
323 {
324 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400325 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400326 } else if (pos[c]==2)
327 {
328 for (i=0;i<21;i++)
329 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400330 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
331 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400332 }
333 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400334#if 0
335 for (i=0;i<21;i++)
336 printf("%f ", bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400337 float sum=0;
338 for (i=0;i<21;i++)
339 sum += bandLogE[21*c+i];
340 printf("%f ", sum/21);
341#endif
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400342 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400343 }
344 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400345 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400346 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400347 for (c=0;c<3;c++)
348 for (i=0;i<21;i++)
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400349 maskLogE[c][i] += channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400350#if 0
351 for (c=0;c<3;c++)
352 {
353 for (i=0;i<21;i++)
354 printf("%f ", maskLogE[c][i]);
355 }
356#endif
357 for (c=0;c<channels;c++)
358 {
359 opus_val16 *mask;
360 if (pos[c]!=0)
361 {
362 mask = &maskLogE[pos[c]-1][0];
363 for (i=0;i<21;i++)
364 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
365 } else {
366 for (i=0;i<21;i++)
367 bandLogE[21*c+i] = 0;
368 }
369#if 0
370 for (i=0;i<21;i++)
371 printf("%f ", bandLogE[21*c+i]);
372 printf("\n");
373#endif
374#if 0
375 float sum=0;
376 for (i=0;i<21;i++)
377 sum += bandLogE[21*c+i];
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400378 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400379 printf("\n");
380#endif
381 }
382 RESTORE_STACK;
383}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500384
385opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
386{
387 int coupled_size;
388 int mono_size;
389
390 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
391 coupled_size = opus_encoder_get_size(2);
392 mono_size = opus_encoder_get_size(1);
393 return align(sizeof(OpusMSEncoder))
394 + nb_coupled_streams * align(coupled_size)
395 + (nb_streams-nb_coupled_streams) * align(mono_size);
396}
397
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400398opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
399{
400 int nb_streams;
401 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400402 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400403
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400404 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400405 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400406 if (channels==1)
407 {
408 nb_streams=1;
409 nb_coupled_streams=0;
410 } else if (channels==2)
411 {
412 nb_streams=1;
413 nb_coupled_streams=1;
414 } else
415 return 0;
416 } else if (mapping_family==1 && channels<=8 && channels>=1)
417 {
418 nb_streams=vorbis_mappings[channels-1].nb_streams;
419 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
420 } else if (mapping_family==255)
421 {
422 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400423 nb_coupled_streams=0;
Michael Graczyk39256682016-05-02 21:42:18 -0700424#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
425 } else if (mapping_family==254)
426 {
427 nb_streams=channels;
428 nb_coupled_streams=0;
429#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400430 } else
431 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400432 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
433 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400434 {
435 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
436 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400437 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400438}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500439
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400440static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500441 OpusMSEncoder *st,
442 opus_int32 Fs,
443 int channels,
444 int streams,
445 int coupled_streams,
446 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400447 int application,
Michael Graczyk39256682016-05-02 21:42:18 -0700448 MappingType mapping_type
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500449)
450{
451 int coupled_size;
452 int mono_size;
453 int i, ret;
454 char *ptr;
455
456 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800457 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500458 return OPUS_BAD_ARG;
459
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500460 st->arch = opus_select_arch();
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500461 st->layout.nb_channels = channels;
462 st->layout.nb_streams = streams;
463 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400464 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
Michael Graczyk39256682016-05-02 21:42:18 -0700465 if (mapping_type != MAPPING_TYPE_SURROUND)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400466 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500467 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400468 st->application = application;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500469 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500470 for (i=0;i<st->layout.nb_channels;i++)
471 st->layout.mapping[i] = mapping[i];
472 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
473 return OPUS_BAD_ARG;
474 ptr = (char*)st + align(sizeof(OpusMSEncoder));
475 coupled_size = opus_encoder_get_size(2);
476 mono_size = opus_encoder_get_size(1);
477
478 for (i=0;i<st->layout.nb_coupled_streams;i++)
479 {
480 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400481 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400482 if (i==st->lfe_stream)
483 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500484 ptr += align(coupled_size);
485 }
486 for (;i<st->layout.nb_streams;i++)
487 {
488 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400489 if (i==st->lfe_stream)
490 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500491 if(ret!=OPUS_OK)return ret;
492 ptr += align(mono_size);
493 }
Michael Graczyk39256682016-05-02 21:42:18 -0700494 if (mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400495 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400496 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
497 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400498 }
Michael Graczyk39256682016-05-02 21:42:18 -0700499 st->mapping_type = mapping_type;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500500 return OPUS_OK;
501}
502
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400503int opus_multistream_encoder_init(
504 OpusMSEncoder *st,
505 opus_int32 Fs,
506 int channels,
507 int streams,
508 int coupled_streams,
509 const unsigned char *mapping,
510 int application
511)
512{
Michael Graczyk39256682016-05-02 21:42:18 -0700513 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
514 coupled_streams, mapping,
515 application, MAPPING_TYPE_NONE);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400516}
517
518int opus_multistream_surround_encoder_init(
519 OpusMSEncoder *st,
520 opus_int32 Fs,
521 int channels,
522 int mapping_family,
523 int *streams,
524 int *coupled_streams,
525 unsigned char *mapping,
526 int application
527)
528{
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700529 MappingType mapping_type;
530
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400531 if ((channels>255) || (channels<1))
532 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400533 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400534 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400535 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400536 if (channels==1)
537 {
538 *streams=1;
539 *coupled_streams=0;
540 mapping[0]=0;
541 } else if (channels==2)
542 {
543 *streams=1;
544 *coupled_streams=1;
545 mapping[0]=0;
546 mapping[1]=1;
547 } else
548 return OPUS_UNIMPLEMENTED;
549 } else if (mapping_family==1 && channels<=8 && channels>=1)
550 {
551 int i;
552 *streams=vorbis_mappings[channels-1].nb_streams;
553 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
554 for (i=0;i<channels;i++)
555 mapping[i] = vorbis_mappings[channels-1].mapping[i];
556 if (channels>=6)
557 st->lfe_stream = *streams-1;
558 } else if (mapping_family==255)
559 {
560 int i;
561 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400562 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400563 for(i=0;i<channels;i++)
564 mapping[i] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700565#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
566 } else if (mapping_family==254)
567 {
568 int i;
569 *streams=channels;
570 *coupled_streams=0;
571 for(i=0;i<channels;i++)
572 mapping[i] = i;
573#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400574 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400575 return OPUS_UNIMPLEMENTED;
Michael Graczyk39256682016-05-02 21:42:18 -0700576
577 if (channels>2 && mapping_family==1) {
578 mapping_type = MAPPING_TYPE_SURROUND;
579#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
580 } else if (mapping_family==254)
581 {
582 mapping_type = MAPPING_TYPE_AMBISONICS;
583#endif
584 } else
585 {
586 mapping_type = MAPPING_TYPE_NONE;
587 }
588 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
589 *coupled_streams, mapping,
590 application, mapping_type);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400591}
592
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500593OpusMSEncoder *opus_multistream_encoder_create(
594 opus_int32 Fs,
595 int channels,
596 int streams,
597 int coupled_streams,
598 const unsigned char *mapping,
599 int application,
600 int *error
601)
602{
603 int ret;
604 OpusMSEncoder *st;
605 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800606 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500607 {
608 if (error)
609 *error = OPUS_BAD_ARG;
610 return NULL;
611 }
612 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
613 if (st==NULL)
614 {
615 if (error)
616 *error = OPUS_ALLOC_FAIL;
617 return NULL;
618 }
619 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
620 if (ret != OPUS_OK)
621 {
622 opus_free(st);
623 st = NULL;
624 }
625 if (error)
626 *error = ret;
627 return st;
628}
629
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400630OpusMSEncoder *opus_multistream_surround_encoder_create(
631 opus_int32 Fs,
632 int channels,
633 int mapping_family,
634 int *streams,
635 int *coupled_streams,
636 unsigned char *mapping,
637 int application,
638 int *error
639)
640{
641 int ret;
Mark Harris25b27a92014-11-27 08:48:09 -0800642 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400643 OpusMSEncoder *st;
644 if ((channels>255) || (channels<1))
645 {
646 if (error)
647 *error = OPUS_BAD_ARG;
648 return NULL;
649 }
Mark Harris25b27a92014-11-27 08:48:09 -0800650 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
651 if (!size)
652 {
653 if (error)
654 *error = OPUS_UNIMPLEMENTED;
655 return NULL;
656 }
657 st = (OpusMSEncoder *)opus_alloc(size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400658 if (st==NULL)
659 {
660 if (error)
661 *error = OPUS_ALLOC_FAIL;
662 return NULL;
663 }
664 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
665 if (ret != OPUS_OK)
666 {
667 opus_free(st);
668 st = NULL;
669 }
670 if (error)
671 *error = ret;
672 return st;
673}
674
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700675static void surround_rate_allocation(
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400676 OpusMSEncoder *st,
677 opus_int32 *rate,
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700678 int frame_size,
679 opus_int32 Fs
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400680 )
681{
682 int i;
683 opus_int32 channel_rate;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400684 int stream_offset;
685 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400686 int coupled_ratio; /* Q8 */
687 int lfe_ratio; /* Q8 */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400688 int nb_lfe;
689 int nb_uncoupled;
690 int nb_coupled;
691 int nb_normal;
692 opus_int32 channel_offset;
693 opus_int32 bitrate;
694 int total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400695
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400696 nb_lfe = (st->lfe_stream!=-1);
697 nb_coupled = st->layout.nb_coupled_streams;
698 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
699 nb_normal = 2*nb_coupled + nb_uncoupled;
700
701 /* Give each non-LFE channel enough bits per channel for coding band energy. */
702 channel_offset = 40*IMAX(50, Fs/frame_size);
703
704 if (st->bitrate_bps==OPUS_AUTO)
705 {
706 bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
707 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
708 {
709 bitrate = nb_normal*300000 + nb_lfe*128000;
710 } else {
711 bitrate = st->bitrate_bps;
712 }
713
714 /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
715 total rate for the non-energy part to avoid problems at really low rate. */
716 lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
717
718 /* We give each stream (coupled or uncoupled) a starting bitrate.
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400719 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400720 stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
721 stream_offset = IMAX(0, IMIN(20000, stream_offset));
722
723 /* Coupled streams get twice the mono rate after the offset is allocated. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400724 coupled_ratio = 512;
725 /* 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 -0400726 lfe_ratio = 32;
727
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400728 total = (nb_uncoupled<<8) /* mono */
729 + coupled_ratio*nb_coupled /* stereo */
730 + nb_lfe*lfe_ratio;
731 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 -0400732#ifndef FIXED_POINT
733 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
734 {
735 opus_int32 bonus;
736 bonus = 60*(Fs/frame_size-50);
737 channel_rate += bonus;
738 }
739#endif
740
741 for (i=0;i<st->layout.nb_streams;i++)
742 {
743 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400744 rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400745 else if (i!=st->lfe_stream)
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400746 rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400747 else
Jean-Marc Valin8ac5d892016-09-19 17:18:58 -0400748 rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700749 }
750}
751
752#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
753static void ambisonics_rate_allocation(
754 OpusMSEncoder *st,
755 opus_int32 *rate,
756 int frame_size,
757 opus_int32 Fs
758 )
759{
760 int i;
761 int non_mono_rate;
762 int total_rate;
763
764 /* The mono channel gets (rate_ratio_num / rate_ratio_den) times as many bits
765 * as all other channels */
766 const int rate_ratio_num = 4;
767 const int rate_ratio_den = 3;
768 const int num_channels = st->layout.nb_streams;
769
770 if (st->bitrate_bps==OPUS_AUTO)
771 {
Michael Graczykfa2578b2016-09-07 15:26:51 -0700772 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
773 (Fs+60*Fs/frame_size) + st->layout.nb_streams * 15000;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700774 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
775 {
776 total_rate = num_channels * 320000;
777 } else {
778 total_rate = st->bitrate_bps;
779 }
780
781 /* Let y be the non-mono rate and let p, q be integers such that the mono
782 * channel rate is (p/q) * y.
783 * Also let T be the total bitrate to allocate. Then
784 * (n - 1) y + (p/q) y = T
785 * y = (T q) / (qn - q + p)
786 */
787 non_mono_rate =
788 total_rate * rate_ratio_den
789 / (rate_ratio_den*num_channels + rate_ratio_num - rate_ratio_den);
790
791#ifndef FIXED_POINT
792 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
793 {
794 opus_int32 bonus = 60*(Fs/frame_size-50);
795 non_mono_rate += bonus;
796 }
797#endif
798
799 rate[0] = total_rate - (num_channels - 1) * non_mono_rate;
800 for (i=1;i<st->layout.nb_streams;i++)
801 {
802 rate[i] = non_mono_rate;
803 }
804}
805#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
806
807static opus_int32 rate_allocation(
808 OpusMSEncoder *st,
809 opus_int32 *rate,
810 int frame_size
811 )
812{
813 int i;
814 opus_int32 rate_sum=0;
815 opus_int32 Fs;
816 char *ptr;
817
818 ptr = (char*)st + align(sizeof(OpusMSEncoder));
819 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
820
821#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
822 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
823 ambisonics_rate_allocation(st, rate, frame_size, Fs);
824 } else
825#endif
826 {
827 surround_rate_allocation(st, rate, frame_size, Fs);
828 }
829
830 for (i=0;i<st->layout.nb_streams;i++)
831 {
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400832 rate[i] = IMAX(rate[i], 500);
833 rate_sum += rate[i];
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400834 }
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400835 return rate_sum;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400836}
837
Felicia Lim0962cbe2016-10-27 17:03:36 -0700838/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
839#define MS_FRAME_TMP (6*1275+12)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500840static int opus_multistream_encode_native
841(
842 OpusMSEncoder *st,
843 opus_copy_channel_in_func copy_channel_in,
844 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400845 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500846 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500847 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400848 int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500849 downmix_func downmix,
850 int float_api
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500851)
852{
853 opus_int32 Fs;
854 int coupled_size;
855 int mono_size;
856 int s;
857 char *ptr;
858 int tot_size;
859 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400860 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500861 unsigned char tmp_data[MS_FRAME_TMP];
862 OpusRepacketizer rp;
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400863 opus_int32 vbr;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500864 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400865 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400866 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400867 opus_val32 *mem = NULL;
868 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400869 int frame_size;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400870 opus_int32 rate_sum;
871 opus_int32 smallest_packet;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500872 ALLOC_STACK;
873
Michael Graczyk39256682016-05-02 21:42:18 -0700874 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400875 {
876 preemph_mem = ms_get_preemph_mem(st);
877 mem = ms_get_window_mem(st);
878 }
879
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500880 ptr = (char*)st + align(sizeof(OpusMSEncoder));
881 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400882 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500883 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500884
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400885 {
886 opus_int32 delay_compensation;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400887
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400888 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
889 delay_compensation -= Fs/400;
890 frame_size = compute_frame_size(pcm, analysis_frame_size,
Mark Harris7d0e33f2016-08-27 07:10:15 -0700891 st->variable_duration, st->layout.nb_channels, Fs, st->bitrate_bps,
Jean-Marc Valinc2b34412013-10-28 21:48:50 -0400892 delay_compensation, downmix
893#ifndef DISABLE_FLOAT_API
894 , st->subframe_mem
895#endif
896 );
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400897 }
898
Jean-Marc Valin74483662012-12-17 16:23:42 -0500899 if (400*frame_size < Fs)
900 {
901 RESTORE_STACK;
902 return OPUS_BAD_ARG;
903 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500904 /* Validate frame_size before using it to allocate stack space.
905 This mirrors the checks in opus_encode[_float](). */
Felicia Lim0962cbe2016-10-27 17:03:36 -0700906 if (400*frame_size != Fs && 200*frame_size != Fs &&
907 100*frame_size != Fs && 50*frame_size != Fs &&
908 25*frame_size != Fs && 50*frame_size != 3*Fs &&
909 50*frame_size != 4*Fs && 50*frame_size != 5*Fs &&
910 50*frame_size != 6*Fs)
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500911 {
912 RESTORE_STACK;
913 return OPUS_BAD_ARG;
914 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400915
916 /* Smallest packet the encoder can produce. */
917 smallest_packet = st->layout.nb_streams*2-1;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400918 if (max_data_bytes < smallest_packet)
919 {
920 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400921 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400922 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500923 ALLOC(buf, 2*frame_size, opus_val16);
924 coupled_size = opus_encoder_get_size(2);
925 mono_size = opus_encoder_get_size(1);
926
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400927 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700928 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400929 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500930 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 -0400931 }
932
Jean-Marc Valin74483662012-12-17 16:23:42 -0500933 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700934 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400935
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400936 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400937 {
938 if (st->bitrate_bps == OPUS_AUTO)
939 {
940 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
941 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
942 {
943 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
944 3*st->bitrate_bps/(3*8*Fs/frame_size)));
945 }
946 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500947 ptr = (char*)st + align(sizeof(OpusMSEncoder));
948 for (s=0;s<st->layout.nb_streams;s++)
949 {
950 OpusEncoder *enc;
951 enc = (OpusEncoder*)ptr;
952 if (s < st->layout.nb_coupled_streams)
953 ptr += align(coupled_size);
954 else
955 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400956 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700957 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400958 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400959 opus_int32 equiv_rate;
960 equiv_rate = st->bitrate_bps;
961 if (frame_size*50 < Fs)
962 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500963 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400964 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500965 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400966 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500967 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400968 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
969 else
970 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400971 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400972 {
973 /* To preserve the spatial image, force stereo CELT on coupled streams */
974 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400975 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400976 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400977 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700978#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
979 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
980 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
981 }
982#endif
Jean-Marc Valin74483662012-12-17 16:23:42 -0500983 }
984
985 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500986 /* Counting ToC */
987 tot_size = 0;
988 for (s=0;s<st->layout.nb_streams;s++)
989 {
990 OpusEncoder *enc;
991 int len;
992 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400993 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -0400994 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500995
996 opus_repacketizer_init(&rp);
997 enc = (OpusEncoder*)ptr;
998 if (s < st->layout.nb_coupled_streams)
999 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001000 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001001 int left, right;
1002 left = get_left_channel(&st->layout, s, -1);
1003 right = get_right_channel(&st->layout, s, -1);
1004 (*copy_channel_in)(buf, 2,
1005 pcm, st->layout.nb_channels, left, frame_size);
1006 (*copy_channel_in)(buf+1, 2,
1007 pcm, st->layout.nb_channels, right, frame_size);
1008 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001009 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001010 {
1011 for (i=0;i<21;i++)
1012 {
1013 bandLogE[i] = bandSMR[21*left+i];
1014 bandLogE[21+i] = bandSMR[21*right+i];
1015 }
1016 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001017 c1 = left;
1018 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001019 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001020 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001021 int chan = get_mono_channel(&st->layout, s, -1);
1022 (*copy_channel_in)(buf, 1,
1023 pcm, st->layout.nb_channels, chan, frame_size);
1024 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001025 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001026 {
1027 for (i=0;i<21;i++)
1028 bandLogE[i] = bandSMR[21*chan+i];
1029 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001030 c1 = chan;
1031 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001032 }
Michael Graczyk39256682016-05-02 21:42:18 -07001033 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001034 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001035 /* number of bytes left (+Toc) */
1036 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001037 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -04001038 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001039 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001040 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -04001041 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -04001042 if (!vbr && s == st->layout.nb_streams-1)
1043 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04001044 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001045 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001046 if (len<0)
1047 {
1048 RESTORE_STACK;
1049 return len;
1050 }
1051 /* We need to use the repacketizer to add the self-delimiting lengths
1052 while taking into account the fact that the encoder can now return
1053 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001054 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1055 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1056 with the encoder. */
1057 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001058 {
1059 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001060 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001061 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001062 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1063 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 -05001064 data += len;
1065 tot_size += len;
1066 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001067 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001068 RESTORE_STACK;
1069 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001070}
1071
Pedro Becerra1af7f952013-07-11 00:00:47 -04001072#if !defined(DISABLE_FLOAT_API)
1073static void opus_copy_channel_in_float(
1074 opus_val16 *dst,
1075 int dst_stride,
1076 const void *src,
1077 int src_stride,
1078 int src_channel,
1079 int frame_size
1080)
1081{
1082 const float *float_src;
1083 opus_int32 i;
1084 float_src = (const float *)src;
1085 for (i=0;i<frame_size;i++)
1086#if defined(FIXED_POINT)
1087 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1088#else
1089 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1090#endif
1091}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001092#endif
1093
1094static void opus_copy_channel_in_short(
1095 opus_val16 *dst,
1096 int dst_stride,
1097 const void *src,
1098 int src_stride,
1099 int src_channel,
1100 int frame_size
1101)
1102{
1103 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001104 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001105 short_src = (const opus_int16 *)src;
1106 for (i=0;i<frame_size;i++)
1107#if defined(FIXED_POINT)
1108 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1109#else
1110 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1111#endif
1112}
1113
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001114
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001115#ifdef FIXED_POINT
1116int opus_multistream_encode(
1117 OpusMSEncoder *st,
1118 const opus_val16 *pcm,
1119 int frame_size,
1120 unsigned char *data,
1121 opus_int32 max_data_bytes
1122)
1123{
1124 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001125 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001126}
1127
1128#ifndef DISABLE_FLOAT_API
1129int opus_multistream_encode_float(
1130 OpusMSEncoder *st,
1131 const float *pcm,
1132 int frame_size,
1133 unsigned char *data,
1134 opus_int32 max_data_bytes
1135)
1136{
1137 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001138 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001139}
1140#endif
1141
1142#else
1143
1144int opus_multistream_encode_float
1145(
1146 OpusMSEncoder *st,
1147 const opus_val16 *pcm,
1148 int frame_size,
1149 unsigned char *data,
1150 opus_int32 max_data_bytes
1151)
1152{
1153 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001154 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001155}
1156
1157int opus_multistream_encode(
1158 OpusMSEncoder *st,
1159 const opus_int16 *pcm,
1160 int frame_size,
1161 unsigned char *data,
1162 opus_int32 max_data_bytes
1163)
1164{
1165 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001166 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001167}
1168#endif
1169
1170int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1171{
1172 va_list ap;
1173 int coupled_size, mono_size;
1174 char *ptr;
1175 int ret = OPUS_OK;
1176
1177 va_start(ap, request);
1178
1179 coupled_size = opus_encoder_get_size(2);
1180 mono_size = opus_encoder_get_size(1);
1181 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1182 switch (request)
1183 {
1184 case OPUS_SET_BITRATE_REQUEST:
1185 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001186 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001187 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001188 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001189 if (value <= 0)
1190 goto bad_arg;
1191 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001192 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001193 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001194 }
1195 break;
1196 case OPUS_GET_BITRATE_REQUEST:
1197 {
1198 int s;
1199 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001200 if (!value)
1201 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001202 goto bad_arg;
1203 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001204 *value = 0;
1205 for (s=0;s<st->layout.nb_streams;s++)
1206 {
1207 opus_int32 rate;
1208 OpusEncoder *enc;
1209 enc = (OpusEncoder*)ptr;
1210 if (s < st->layout.nb_coupled_streams)
1211 ptr += align(coupled_size);
1212 else
1213 ptr += align(mono_size);
1214 opus_encoder_ctl(enc, request, &rate);
1215 *value += rate;
1216 }
1217 }
1218 break;
1219 case OPUS_GET_LSB_DEPTH_REQUEST:
1220 case OPUS_GET_VBR_REQUEST:
1221 case OPUS_GET_APPLICATION_REQUEST:
1222 case OPUS_GET_BANDWIDTH_REQUEST:
1223 case OPUS_GET_COMPLEXITY_REQUEST:
1224 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1225 case OPUS_GET_DTX_REQUEST:
1226 case OPUS_GET_VOICE_RATIO_REQUEST:
1227 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1228 case OPUS_GET_SIGNAL_REQUEST:
1229 case OPUS_GET_LOOKAHEAD_REQUEST:
1230 case OPUS_GET_SAMPLE_RATE_REQUEST:
1231 case OPUS_GET_INBAND_FEC_REQUEST:
1232 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001233 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001234 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001235 {
1236 OpusEncoder *enc;
1237 /* For int32* GET params, just query the first stream */
1238 opus_int32 *value = va_arg(ap, opus_int32*);
1239 enc = (OpusEncoder*)ptr;
1240 ret = opus_encoder_ctl(enc, request, value);
1241 }
1242 break;
1243 case OPUS_GET_FINAL_RANGE_REQUEST:
1244 {
1245 int s;
1246 opus_uint32 *value = va_arg(ap, opus_uint32*);
1247 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001248 if (!value)
1249 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001250 goto bad_arg;
1251 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001252 *value=0;
1253 for (s=0;s<st->layout.nb_streams;s++)
1254 {
1255 OpusEncoder *enc;
1256 enc = (OpusEncoder*)ptr;
1257 if (s < st->layout.nb_coupled_streams)
1258 ptr += align(coupled_size);
1259 else
1260 ptr += align(mono_size);
1261 ret = opus_encoder_ctl(enc, request, &tmp);
1262 if (ret != OPUS_OK) break;
1263 *value ^= tmp;
1264 }
1265 }
1266 break;
1267 case OPUS_SET_LSB_DEPTH_REQUEST:
1268 case OPUS_SET_COMPLEXITY_REQUEST:
1269 case OPUS_SET_VBR_REQUEST:
1270 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001271 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001272 case OPUS_SET_BANDWIDTH_REQUEST:
1273 case OPUS_SET_SIGNAL_REQUEST:
1274 case OPUS_SET_APPLICATION_REQUEST:
1275 case OPUS_SET_INBAND_FEC_REQUEST:
1276 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1277 case OPUS_SET_DTX_REQUEST:
1278 case OPUS_SET_FORCE_MODE_REQUEST:
1279 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001280 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001281 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001282 {
1283 int s;
1284 /* This works for int32 params */
1285 opus_int32 value = va_arg(ap, opus_int32);
1286 for (s=0;s<st->layout.nb_streams;s++)
1287 {
1288 OpusEncoder *enc;
1289
1290 enc = (OpusEncoder*)ptr;
1291 if (s < st->layout.nb_coupled_streams)
1292 ptr += align(coupled_size);
1293 else
1294 ptr += align(mono_size);
1295 ret = opus_encoder_ctl(enc, request, value);
1296 if (ret != OPUS_OK)
1297 break;
1298 }
1299 }
1300 break;
1301 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1302 {
1303 int s;
1304 opus_int32 stream_id;
1305 OpusEncoder **value;
1306 stream_id = va_arg(ap, opus_int32);
1307 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1308 ret = OPUS_BAD_ARG;
1309 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001310 if (!value)
1311 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001312 goto bad_arg;
1313 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001314 for (s=0;s<stream_id;s++)
1315 {
1316 if (s < st->layout.nb_coupled_streams)
1317 ptr += align(coupled_size);
1318 else
1319 ptr += align(mono_size);
1320 }
1321 *value = (OpusEncoder*)ptr;
1322 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001323 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001324 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001325 {
1326 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001327 st->variable_duration = value;
1328 }
1329 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001330 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001331 {
1332 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001333 if (!value)
1334 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001335 goto bad_arg;
1336 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001337 *value = st->variable_duration;
1338 }
1339 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001340 case OPUS_RESET_STATE:
1341 {
1342 int s;
1343 st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
Michael Graczyk39256682016-05-02 21:42:18 -07001344 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001345 {
1346 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1347 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1348 }
1349 for (s=0;s<st->layout.nb_streams;s++)
1350 {
1351 OpusEncoder *enc;
1352 enc = (OpusEncoder*)ptr;
1353 if (s < st->layout.nb_coupled_streams)
1354 ptr += align(coupled_size);
1355 else
1356 ptr += align(mono_size);
1357 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1358 if (ret != OPUS_OK)
1359 break;
1360 }
1361 }
1362 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001363 default:
1364 ret = OPUS_UNIMPLEMENTED;
1365 break;
1366 }
1367
1368 va_end(ap);
1369 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001370bad_arg:
1371 va_end(ap);
1372 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001373}
1374
1375void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1376{
1377 opus_free(st);
1378}