blob: c07132f107cc3c5d0d1a7b324ea387ee189a0ff4 [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 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;
253
Michael Graczyk39256682016-05-02 21:42:18 -0700254 /* LM = log2(frame_size / 120) */
Jean-Marc Valin2e653a72013-10-14 17:47:18 -0400255 for (LM=0;LM<celt_mode->maxLM;LM++)
Jean-Marc Valin54bddf02013-09-11 23:34:51 -0400256 if (celt_mode->shortMdctSize<<LM==frame_size)
257 break;
258
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400259 ALLOC(in, frame_size+overlap, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400260 ALLOC(x, len, opus_val16);
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400261 ALLOC(freq, frame_size, opus_val32);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400262
263 channel_pos(channels, pos);
264
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400265 for (c=0;c<3;c++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400266 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400267 maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400268
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400269 for (c=0;c<channels;c++)
270 {
271 OPUS_COPY(in, mem+c*overlap, overlap);
272 (*copy_channel_in)(x, 1, pcm, channels, c, len);
Jean-Marc Valin2dc27df2013-11-13 19:35:43 -0500273 celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -0400274#ifndef FIXED_POINT
275 {
276 opus_val32 sum;
277 sum = celt_inner_prod(in, in, frame_size+overlap, 0);
278 /* This should filter out both NaNs and ridiculous signals that could
279 cause NaNs further down. */
280 if (!(sum < 1e9f) || celt_isnan(sum))
281 {
282 OPUS_CLEAR(in, frame_size+overlap);
283 preemph_mem[c] = 0;
284 }
285 }
286#endif
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500287 clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window,
288 overlap, celt_mode->maxLM-LM, 1, arch);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400289 if (upsample != 1)
290 {
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400291 int bound = len;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400292 for (i=0;i<bound;i++)
293 freq[i] *= upsample;
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400294 for (;i<frame_size;i++)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400295 freq[i] = 0;
296 }
297
Mark Harris58107d82014-01-25 16:32:18 -0800298 compute_band_energies(celt_mode, freq, bandE, 21, 1, LM);
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400299 amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
Jean-Marc Valin0f686962013-09-05 12:49:55 -0400300 /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
301 for (i=1;i<21;i++)
302 bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
303 for (i=19;i>=0;i--)
304 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 -0400305 if (pos[c]==1)
306 {
307 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400308 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400309 } else if (pos[c]==3)
310 {
311 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400312 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400313 } else if (pos[c]==2)
314 {
315 for (i=0;i<21;i++)
316 {
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400317 maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
318 maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400319 }
320 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400321#if 0
322 for (i=0;i<21;i++)
323 printf("%f ", bandLogE[21*c+i]);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400324 float sum=0;
325 for (i=0;i<21;i++)
326 sum += bandLogE[21*c+i];
327 printf("%f ", sum/21);
328#endif
Jean-Marc Valin978e4cb2013-09-11 00:51:22 -0400329 OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400330 }
331 for (i=0;i<21;i++)
Jean-Marc Valina714ae92013-08-31 02:05:32 -0400332 maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400333 channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400334 for (c=0;c<3;c++)
335 for (i=0;i<21;i++)
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400336 maskLogE[c][i] += channel_offset;
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400337#if 0
338 for (c=0;c<3;c++)
339 {
340 for (i=0;i<21;i++)
341 printf("%f ", maskLogE[c][i]);
342 }
343#endif
344 for (c=0;c<channels;c++)
345 {
346 opus_val16 *mask;
347 if (pos[c]!=0)
348 {
349 mask = &maskLogE[pos[c]-1][0];
350 for (i=0;i<21;i++)
351 bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
352 } else {
353 for (i=0;i<21;i++)
354 bandLogE[21*c+i] = 0;
355 }
356#if 0
357 for (i=0;i<21;i++)
358 printf("%f ", bandLogE[21*c+i]);
359 printf("\n");
360#endif
361#if 0
362 float sum=0;
363 for (i=0;i<21;i++)
364 sum += bandLogE[21*c+i];
Jean-Marc Valin942fc812013-10-01 19:27:30 -0400365 printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400366 printf("\n");
367#endif
368 }
369 RESTORE_STACK;
370}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500371
372opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
373{
374 int coupled_size;
375 int mono_size;
376
377 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
378 coupled_size = opus_encoder_get_size(2);
379 mono_size = opus_encoder_get_size(1);
380 return align(sizeof(OpusMSEncoder))
381 + nb_coupled_streams * align(coupled_size)
382 + (nb_streams-nb_coupled_streams) * align(mono_size);
383}
384
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400385opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
386{
387 int nb_streams;
388 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400389 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400390
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400391 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400392 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400393 if (channels==1)
394 {
395 nb_streams=1;
396 nb_coupled_streams=0;
397 } else if (channels==2)
398 {
399 nb_streams=1;
400 nb_coupled_streams=1;
401 } else
402 return 0;
403 } else if (mapping_family==1 && channels<=8 && channels>=1)
404 {
405 nb_streams=vorbis_mappings[channels-1].nb_streams;
406 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
407 } else if (mapping_family==255)
408 {
409 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400410 nb_coupled_streams=0;
Michael Graczyk39256682016-05-02 21:42:18 -0700411#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
412 } else if (mapping_family==254)
413 {
414 nb_streams=channels;
415 nb_coupled_streams=0;
416#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400417 } else
418 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400419 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
420 if (channels>2)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400421 {
422 size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
423 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400424 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400425}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500426
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400427static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500428 OpusMSEncoder *st,
429 opus_int32 Fs,
430 int channels,
431 int streams,
432 int coupled_streams,
433 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400434 int application,
Michael Graczyk39256682016-05-02 21:42:18 -0700435 MappingType mapping_type
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500436)
437{
438 int coupled_size;
439 int mono_size;
440 int i, ret;
441 char *ptr;
442
443 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800444 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500445 return OPUS_BAD_ARG;
446
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500447 st->arch = opus_select_arch();
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500448 st->layout.nb_channels = channels;
449 st->layout.nb_streams = streams;
450 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400451 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
Michael Graczyk39256682016-05-02 21:42:18 -0700452 if (mapping_type != MAPPING_TYPE_SURROUND)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400453 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500454 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400455 st->application = application;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500456 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500457 for (i=0;i<st->layout.nb_channels;i++)
458 st->layout.mapping[i] = mapping[i];
459 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
460 return OPUS_BAD_ARG;
461 ptr = (char*)st + align(sizeof(OpusMSEncoder));
462 coupled_size = opus_encoder_get_size(2);
463 mono_size = opus_encoder_get_size(1);
464
465 for (i=0;i<st->layout.nb_coupled_streams;i++)
466 {
467 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400468 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400469 if (i==st->lfe_stream)
470 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500471 ptr += align(coupled_size);
472 }
473 for (;i<st->layout.nb_streams;i++)
474 {
475 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400476 if (i==st->lfe_stream)
477 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500478 if(ret!=OPUS_OK)return ret;
479 ptr += align(mono_size);
480 }
Michael Graczyk39256682016-05-02 21:42:18 -0700481 if (mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400482 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400483 OPUS_CLEAR(ms_get_preemph_mem(st), channels);
484 OPUS_CLEAR(ms_get_window_mem(st), channels*120);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400485 }
Michael Graczyk39256682016-05-02 21:42:18 -0700486 st->mapping_type = mapping_type;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500487 return OPUS_OK;
488}
489
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400490int opus_multistream_encoder_init(
491 OpusMSEncoder *st,
492 opus_int32 Fs,
493 int channels,
494 int streams,
495 int coupled_streams,
496 const unsigned char *mapping,
497 int application
498)
499{
Michael Graczyk39256682016-05-02 21:42:18 -0700500 return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
501 coupled_streams, mapping,
502 application, MAPPING_TYPE_NONE);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400503}
504
505int opus_multistream_surround_encoder_init(
506 OpusMSEncoder *st,
507 opus_int32 Fs,
508 int channels,
509 int mapping_family,
510 int *streams,
511 int *coupled_streams,
512 unsigned char *mapping,
513 int application
514)
515{
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700516 MappingType mapping_type;
517
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400518 if ((channels>255) || (channels<1))
519 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400520 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400521 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400522 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400523 if (channels==1)
524 {
525 *streams=1;
526 *coupled_streams=0;
527 mapping[0]=0;
528 } else if (channels==2)
529 {
530 *streams=1;
531 *coupled_streams=1;
532 mapping[0]=0;
533 mapping[1]=1;
534 } else
535 return OPUS_UNIMPLEMENTED;
536 } else if (mapping_family==1 && channels<=8 && channels>=1)
537 {
538 int i;
539 *streams=vorbis_mappings[channels-1].nb_streams;
540 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
541 for (i=0;i<channels;i++)
542 mapping[i] = vorbis_mappings[channels-1].mapping[i];
543 if (channels>=6)
544 st->lfe_stream = *streams-1;
545 } else if (mapping_family==255)
546 {
547 int i;
548 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400549 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400550 for(i=0;i<channels;i++)
551 mapping[i] = i;
Michael Graczyk39256682016-05-02 21:42:18 -0700552#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
553 } else if (mapping_family==254)
554 {
555 int i;
556 *streams=channels;
557 *coupled_streams=0;
558 for(i=0;i<channels;i++)
559 mapping[i] = i;
560#endif
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400561 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400562 return OPUS_UNIMPLEMENTED;
Michael Graczyk39256682016-05-02 21:42:18 -0700563
564 if (channels>2 && mapping_family==1) {
565 mapping_type = MAPPING_TYPE_SURROUND;
566#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
567 } else if (mapping_family==254)
568 {
569 mapping_type = MAPPING_TYPE_AMBISONICS;
570#endif
571 } else
572 {
573 mapping_type = MAPPING_TYPE_NONE;
574 }
575 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
576 *coupled_streams, mapping,
577 application, mapping_type);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400578}
579
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500580OpusMSEncoder *opus_multistream_encoder_create(
581 opus_int32 Fs,
582 int channels,
583 int streams,
584 int coupled_streams,
585 const unsigned char *mapping,
586 int application,
587 int *error
588)
589{
590 int ret;
591 OpusMSEncoder *st;
592 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
Mark Harris25b27a92014-11-27 08:48:09 -0800593 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500594 {
595 if (error)
596 *error = OPUS_BAD_ARG;
597 return NULL;
598 }
599 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
600 if (st==NULL)
601 {
602 if (error)
603 *error = OPUS_ALLOC_FAIL;
604 return NULL;
605 }
606 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
607 if (ret != OPUS_OK)
608 {
609 opus_free(st);
610 st = NULL;
611 }
612 if (error)
613 *error = ret;
614 return st;
615}
616
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400617OpusMSEncoder *opus_multistream_surround_encoder_create(
618 opus_int32 Fs,
619 int channels,
620 int mapping_family,
621 int *streams,
622 int *coupled_streams,
623 unsigned char *mapping,
624 int application,
625 int *error
626)
627{
628 int ret;
Mark Harris25b27a92014-11-27 08:48:09 -0800629 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400630 OpusMSEncoder *st;
631 if ((channels>255) || (channels<1))
632 {
633 if (error)
634 *error = OPUS_BAD_ARG;
635 return NULL;
636 }
Mark Harris25b27a92014-11-27 08:48:09 -0800637 size = opus_multistream_surround_encoder_get_size(channels, mapping_family);
638 if (!size)
639 {
640 if (error)
641 *error = OPUS_UNIMPLEMENTED;
642 return NULL;
643 }
644 st = (OpusMSEncoder *)opus_alloc(size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400645 if (st==NULL)
646 {
647 if (error)
648 *error = OPUS_ALLOC_FAIL;
649 return NULL;
650 }
651 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
652 if (ret != OPUS_OK)
653 {
654 opus_free(st);
655 st = NULL;
656 }
657 if (error)
658 *error = ret;
659 return st;
660}
661
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700662static void surround_rate_allocation(
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400663 OpusMSEncoder *st,
664 opus_int32 *rate,
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700665 int frame_size,
666 opus_int32 Fs
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400667 )
668{
669 int i;
670 opus_int32 channel_rate;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400671 int stream_offset;
672 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400673 int coupled_ratio; /* Q8 */
674 int lfe_ratio; /* Q8 */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400675
Jean-Marc Valin49587512013-07-07 02:50:18 -0400676 if (st->bitrate_bps > st->layout.nb_channels*40000)
677 stream_offset = 20000;
678 else
679 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
Jean-Marc Valin87ca6c02013-11-13 22:58:10 -0500680 stream_offset += 60*(Fs/frame_size-50);
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400681 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
682 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400683 /* The LFE stream is an exception to the above and gets fewer bits. */
Jean-Marc Valin87ca6c02013-11-13 22:58:10 -0500684 lfe_offset = 3500 + 60*(Fs/frame_size-50);
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400685 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
686 coupled_ratio = 512;
687 /* 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 -0400688 lfe_ratio = 32;
689
690 /* Compute bitrate allocation between streams */
691 if (st->bitrate_bps==OPUS_AUTO)
692 {
693 channel_rate = Fs+60*Fs/frame_size;
694 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
695 {
696 channel_rate = 300000;
697 } else {
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400698 int nb_lfe;
699 int nb_uncoupled;
700 int nb_coupled;
701 int total;
702 nb_lfe = (st->lfe_stream!=-1);
703 nb_coupled = st->layout.nb_coupled_streams;
704 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
705 total = (nb_uncoupled<<8) /* mono */
706 + coupled_ratio*nb_coupled /* stereo */
707 + nb_lfe*lfe_ratio;
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -0400708 channel_rate = 256*(opus_int64)(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400709 }
710#ifndef FIXED_POINT
711 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
712 {
713 opus_int32 bonus;
714 bonus = 60*(Fs/frame_size-50);
715 channel_rate += bonus;
716 }
717#endif
718
719 for (i=0;i<st->layout.nb_streams;i++)
720 {
721 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400722 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400723 else if (i!=st->lfe_stream)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400724 rate[i] = stream_offset+channel_rate;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400725 else
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400726 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700727 }
728}
729
730#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
731static void ambisonics_rate_allocation(
732 OpusMSEncoder *st,
733 opus_int32 *rate,
734 int frame_size,
735 opus_int32 Fs
736 )
737{
738 int i;
739 int non_mono_rate;
740 int total_rate;
741
742 /* The mono channel gets (rate_ratio_num / rate_ratio_den) times as many bits
743 * as all other channels */
744 const int rate_ratio_num = 4;
745 const int rate_ratio_den = 3;
746 const int num_channels = st->layout.nb_streams;
747
748 if (st->bitrate_bps==OPUS_AUTO)
749 {
Michael Graczykfa2578b2016-09-07 15:26:51 -0700750 total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
751 (Fs+60*Fs/frame_size) + st->layout.nb_streams * 15000;
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700752 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
753 {
754 total_rate = num_channels * 320000;
755 } else {
756 total_rate = st->bitrate_bps;
757 }
758
759 /* Let y be the non-mono rate and let p, q be integers such that the mono
760 * channel rate is (p/q) * y.
761 * Also let T be the total bitrate to allocate. Then
762 * (n - 1) y + (p/q) y = T
763 * y = (T q) / (qn - q + p)
764 */
765 non_mono_rate =
766 total_rate * rate_ratio_den
767 / (rate_ratio_den*num_channels + rate_ratio_num - rate_ratio_den);
768
769#ifndef FIXED_POINT
770 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
771 {
772 opus_int32 bonus = 60*(Fs/frame_size-50);
773 non_mono_rate += bonus;
774 }
775#endif
776
777 rate[0] = total_rate - (num_channels - 1) * non_mono_rate;
778 for (i=1;i<st->layout.nb_streams;i++)
779 {
780 rate[i] = non_mono_rate;
781 }
782}
783#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
784
785static opus_int32 rate_allocation(
786 OpusMSEncoder *st,
787 opus_int32 *rate,
788 int frame_size
789 )
790{
791 int i;
792 opus_int32 rate_sum=0;
793 opus_int32 Fs;
794 char *ptr;
795
796 ptr = (char*)st + align(sizeof(OpusMSEncoder));
797 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
798
799#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
800 if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
801 ambisonics_rate_allocation(st, rate, frame_size, Fs);
802 } else
803#endif
804 {
805 surround_rate_allocation(st, rate, frame_size, Fs);
806 }
807
808 for (i=0;i<st->layout.nb_streams;i++)
809 {
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400810 rate[i] = IMAX(rate[i], 500);
811 rate_sum += rate[i];
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400812 }
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400813 return rate_sum;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400814}
815
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500816/* Max size in case the encoder decides to return three frames */
817#define MS_FRAME_TMP (3*1275+7)
818static int opus_multistream_encode_native
819(
820 OpusMSEncoder *st,
821 opus_copy_channel_in_func copy_channel_in,
822 const void *pcm,
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400823 int analysis_frame_size,
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500824 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500825 opus_int32 max_data_bytes,
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400826 int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -0500827 downmix_func downmix,
828 int float_api
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500829)
830{
831 opus_int32 Fs;
832 int coupled_size;
833 int mono_size;
834 int s;
835 char *ptr;
836 int tot_size;
837 VARDECL(opus_val16, buf);
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400838 VARDECL(opus_val16, bandSMR);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500839 unsigned char tmp_data[MS_FRAME_TMP];
840 OpusRepacketizer rp;
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400841 opus_int32 vbr;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500842 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400843 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400844 opus_val16 bandLogE[42];
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400845 opus_val32 *mem = NULL;
846 opus_val32 *preemph_mem=NULL;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400847 int frame_size;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400848 opus_int32 rate_sum;
849 opus_int32 smallest_packet;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500850 ALLOC_STACK;
851
Michael Graczyk39256682016-05-02 21:42:18 -0700852 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400853 {
854 preemph_mem = ms_get_preemph_mem(st);
855 mem = ms_get_window_mem(st);
856 }
857
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500858 ptr = (char*)st + align(sizeof(OpusMSEncoder));
859 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400860 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500861 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500862
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400863 {
864 opus_int32 delay_compensation;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400865
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400866 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
867 delay_compensation -= Fs/400;
868 frame_size = compute_frame_size(pcm, analysis_frame_size,
Mark Harris7d0e33f2016-08-27 07:10:15 -0700869 st->variable_duration, st->layout.nb_channels, Fs, st->bitrate_bps,
Jean-Marc Valinc2b34412013-10-28 21:48:50 -0400870 delay_compensation, downmix
871#ifndef DISABLE_FLOAT_API
872 , st->subframe_mem
873#endif
874 );
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -0400875 }
876
Jean-Marc Valin74483662012-12-17 16:23:42 -0500877 if (400*frame_size < Fs)
878 {
879 RESTORE_STACK;
880 return OPUS_BAD_ARG;
881 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500882 /* Validate frame_size before using it to allocate stack space.
883 This mirrors the checks in opus_encode[_float](). */
884 if (400*frame_size != Fs && 200*frame_size != Fs &&
885 100*frame_size != Fs && 50*frame_size != Fs &&
886 25*frame_size != Fs && 50*frame_size != 3*Fs)
887 {
888 RESTORE_STACK;
889 return OPUS_BAD_ARG;
890 }
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400891
892 /* Smallest packet the encoder can produce. */
893 smallest_packet = st->layout.nb_streams*2-1;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400894 if (max_data_bytes < smallest_packet)
895 {
896 RESTORE_STACK;
Jean-Marc Valine1326fe2014-09-04 01:48:46 -0400897 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400898 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500899 ALLOC(buf, 2*frame_size, opus_val16);
900 coupled_size = opus_encoder_get_size(2);
901 mono_size = opus_encoder_get_size(1);
902
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400903 ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
Michael Graczyk39256682016-05-02 21:42:18 -0700904 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400905 {
Viswanath Puttaguntaf48abe82015-05-15 12:42:19 -0500906 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 -0400907 }
908
Jean-Marc Valin74483662012-12-17 16:23:42 -0500909 /* Compute bitrate allocation between streams (this could be a lot better) */
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700910 rate_sum = rate_allocation(st, bitrates, frame_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400911
Jean-Marc Valineab134c2013-10-14 15:01:36 -0400912 if (!vbr)
Jean-Marc Valin8dc91de2014-06-21 01:16:46 -0400913 {
914 if (st->bitrate_bps == OPUS_AUTO)
915 {
916 max_data_bytes = IMIN(max_data_bytes, 3*rate_sum/(3*8*Fs/frame_size));
917 } else if (st->bitrate_bps != OPUS_BITRATE_MAX)
918 {
919 max_data_bytes = IMIN(max_data_bytes, IMAX(smallest_packet,
920 3*st->bitrate_bps/(3*8*Fs/frame_size)));
921 }
922 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500923 ptr = (char*)st + align(sizeof(OpusMSEncoder));
924 for (s=0;s<st->layout.nb_streams;s++)
925 {
926 OpusEncoder *enc;
927 enc = (OpusEncoder*)ptr;
928 if (s < st->layout.nb_coupled_streams)
929 ptr += align(coupled_size);
930 else
931 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400932 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Michael Graczyk39256682016-05-02 21:42:18 -0700933 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400934 {
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400935 opus_int32 equiv_rate;
936 equiv_rate = st->bitrate_bps;
937 if (frame_size*50 < Fs)
938 equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500939 if (equiv_rate > 10000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400940 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500941 else if (equiv_rate > 7000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400942 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
Jean-Marc Valinccf7d9b2013-11-24 01:57:52 -0500943 else if (equiv_rate > 5000*st->layout.nb_channels)
Jean-Marc Valin6fbfed62013-09-13 17:16:38 -0400944 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
945 else
946 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400947 if (s < st->layout.nb_coupled_streams)
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400948 {
949 /* To preserve the spatial image, force stereo CELT on coupled streams */
950 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400951 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400952 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400953 }
Michael Graczyk1ac3a562016-04-04 19:31:04 -0700954#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
955 else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
956 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
957 }
958#endif
Jean-Marc Valin74483662012-12-17 16:23:42 -0500959 }
960
961 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500962 /* Counting ToC */
963 tot_size = 0;
964 for (s=0;s<st->layout.nb_streams;s++)
965 {
966 OpusEncoder *enc;
967 int len;
968 int curr_max;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400969 int c1, c2;
Jean-Marc Valin328953e2016-07-04 01:29:23 -0400970 int ret;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500971
972 opus_repacketizer_init(&rp);
973 enc = (OpusEncoder*)ptr;
974 if (s < st->layout.nb_coupled_streams)
975 {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400976 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500977 int left, right;
978 left = get_left_channel(&st->layout, s, -1);
979 right = get_right_channel(&st->layout, s, -1);
980 (*copy_channel_in)(buf, 2,
981 pcm, st->layout.nb_channels, left, frame_size);
982 (*copy_channel_in)(buf+1, 2,
983 pcm, st->layout.nb_channels, right, frame_size);
984 ptr += align(coupled_size);
Michael Graczyk39256682016-05-02 21:42:18 -0700985 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400986 {
987 for (i=0;i<21;i++)
988 {
989 bandLogE[i] = bandSMR[21*left+i];
990 bandLogE[21+i] = bandSMR[21*right+i];
991 }
992 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400993 c1 = left;
994 c2 = right;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500995 } else {
Jean-Marc Valinfdceae82013-08-30 21:58:02 -0400996 int i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500997 int chan = get_mono_channel(&st->layout, s, -1);
998 (*copy_channel_in)(buf, 1,
999 pcm, st->layout.nb_channels, chan, frame_size);
1000 ptr += align(mono_size);
Michael Graczyk39256682016-05-02 21:42:18 -07001001 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001002 {
1003 for (i=0;i<21;i++)
1004 bandLogE[i] = bandSMR[21*chan+i];
1005 }
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001006 c1 = chan;
1007 c2 = -1;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001008 }
Michael Graczyk39256682016-05-02 21:42:18 -07001009 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001010 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001011 /* number of bytes left (+Toc) */
1012 curr_max = max_data_bytes - tot_size;
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001013 /* Reserve one byte for the last stream and two for the others */
Jean-Marc Valine1326fe2014-09-04 01:48:46 -04001014 curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001015 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinda97db12014-09-04 02:48:21 -04001016 /* Repacketizer will add one or two bytes for self-delimited frames */
Jean-Marc Valin648eb9a2014-09-04 02:44:09 -04001017 if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
Jean-Marc Valin2e653a72013-10-14 17:47:18 -04001018 if (!vbr && s == st->layout.nb_streams-1)
1019 opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04001020 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001021 pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001022 if (len<0)
1023 {
1024 RESTORE_STACK;
1025 return len;
1026 }
1027 /* We need to use the repacketizer to add the self-delimiting lengths
1028 while taking into account the fact that the encoder can now return
1029 more than one frame at a time (e.g. 60 ms CELT-only) */
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001030 ret = opus_repacketizer_cat(&rp, tmp_data, len);
1031 /* If the opus_repacketizer_cat() fails, then something's seriously wrong
1032 with the encoder. */
1033 if (ret != OPUS_OK)
Jean-Marc Valin92035652016-07-04 10:45:15 -04001034 {
1035 RESTORE_STACK;
Jean-Marc Valin328953e2016-07-04 01:29:23 -04001036 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin92035652016-07-04 10:45:15 -04001037 }
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05001038 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
1039 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 -05001040 data += len;
1041 tot_size += len;
1042 }
Jean-Marc Valinfdceae82013-08-30 21:58:02 -04001043 /*printf("\n");*/
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001044 RESTORE_STACK;
1045 return tot_size;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001046}
1047
Pedro Becerra1af7f952013-07-11 00:00:47 -04001048#if !defined(DISABLE_FLOAT_API)
1049static void opus_copy_channel_in_float(
1050 opus_val16 *dst,
1051 int dst_stride,
1052 const void *src,
1053 int src_stride,
1054 int src_channel,
1055 int frame_size
1056)
1057{
1058 const float *float_src;
1059 opus_int32 i;
1060 float_src = (const float *)src;
1061 for (i=0;i<frame_size;i++)
1062#if defined(FIXED_POINT)
1063 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
1064#else
1065 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
1066#endif
1067}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001068#endif
1069
1070static void opus_copy_channel_in_short(
1071 opus_val16 *dst,
1072 int dst_stride,
1073 const void *src,
1074 int src_stride,
1075 int src_channel,
1076 int frame_size
1077)
1078{
1079 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -07001080 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001081 short_src = (const opus_int16 *)src;
1082 for (i=0;i<frame_size;i++)
1083#if defined(FIXED_POINT)
1084 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
1085#else
1086 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
1087#endif
1088}
1089
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001090
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001091#ifdef FIXED_POINT
1092int opus_multistream_encode(
1093 OpusMSEncoder *st,
1094 const opus_val16 *pcm,
1095 int frame_size,
1096 unsigned char *data,
1097 opus_int32 max_data_bytes
1098)
1099{
1100 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001101 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001102}
1103
1104#ifndef DISABLE_FLOAT_API
1105int opus_multistream_encode_float(
1106 OpusMSEncoder *st,
1107 const float *pcm,
1108 int frame_size,
1109 unsigned char *data,
1110 opus_int32 max_data_bytes
1111)
1112{
1113 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001114 pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001115}
1116#endif
1117
1118#else
1119
1120int opus_multistream_encode_float
1121(
1122 OpusMSEncoder *st,
1123 const opus_val16 *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_float,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001130 pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001131}
1132
1133int opus_multistream_encode(
1134 OpusMSEncoder *st,
1135 const opus_int16 *pcm,
1136 int frame_size,
1137 unsigned char *data,
1138 opus_int32 max_data_bytes
1139)
1140{
1141 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001142 pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001143}
1144#endif
1145
1146int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
1147{
1148 va_list ap;
1149 int coupled_size, mono_size;
1150 char *ptr;
1151 int ret = OPUS_OK;
1152
1153 va_start(ap, request);
1154
1155 coupled_size = opus_encoder_get_size(2);
1156 mono_size = opus_encoder_get_size(1);
1157 ptr = (char*)st + align(sizeof(OpusMSEncoder));
1158 switch (request)
1159 {
1160 case OPUS_SET_BITRATE_REQUEST:
1161 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001162 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001163 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001164 {
Jean-Marc Valinf4f5a6a2016-09-06 22:32:22 -04001165 if (value <= 0)
1166 goto bad_arg;
1167 value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001168 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001169 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001170 }
1171 break;
1172 case OPUS_GET_BITRATE_REQUEST:
1173 {
1174 int s;
1175 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001176 if (!value)
1177 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001178 goto bad_arg;
1179 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001180 *value = 0;
1181 for (s=0;s<st->layout.nb_streams;s++)
1182 {
1183 opus_int32 rate;
1184 OpusEncoder *enc;
1185 enc = (OpusEncoder*)ptr;
1186 if (s < st->layout.nb_coupled_streams)
1187 ptr += align(coupled_size);
1188 else
1189 ptr += align(mono_size);
1190 opus_encoder_ctl(enc, request, &rate);
1191 *value += rate;
1192 }
1193 }
1194 break;
1195 case OPUS_GET_LSB_DEPTH_REQUEST:
1196 case OPUS_GET_VBR_REQUEST:
1197 case OPUS_GET_APPLICATION_REQUEST:
1198 case OPUS_GET_BANDWIDTH_REQUEST:
1199 case OPUS_GET_COMPLEXITY_REQUEST:
1200 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1201 case OPUS_GET_DTX_REQUEST:
1202 case OPUS_GET_VOICE_RATIO_REQUEST:
1203 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1204 case OPUS_GET_SIGNAL_REQUEST:
1205 case OPUS_GET_LOOKAHEAD_REQUEST:
1206 case OPUS_GET_SAMPLE_RATE_REQUEST:
1207 case OPUS_GET_INBAND_FEC_REQUEST:
1208 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001209 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001210 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001211 {
1212 OpusEncoder *enc;
1213 /* For int32* GET params, just query the first stream */
1214 opus_int32 *value = va_arg(ap, opus_int32*);
1215 enc = (OpusEncoder*)ptr;
1216 ret = opus_encoder_ctl(enc, request, value);
1217 }
1218 break;
1219 case OPUS_GET_FINAL_RANGE_REQUEST:
1220 {
1221 int s;
1222 opus_uint32 *value = va_arg(ap, opus_uint32*);
1223 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001224 if (!value)
1225 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001226 goto bad_arg;
1227 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001228 *value=0;
1229 for (s=0;s<st->layout.nb_streams;s++)
1230 {
1231 OpusEncoder *enc;
1232 enc = (OpusEncoder*)ptr;
1233 if (s < st->layout.nb_coupled_streams)
1234 ptr += align(coupled_size);
1235 else
1236 ptr += align(mono_size);
1237 ret = opus_encoder_ctl(enc, request, &tmp);
1238 if (ret != OPUS_OK) break;
1239 *value ^= tmp;
1240 }
1241 }
1242 break;
1243 case OPUS_SET_LSB_DEPTH_REQUEST:
1244 case OPUS_SET_COMPLEXITY_REQUEST:
1245 case OPUS_SET_VBR_REQUEST:
1246 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Daniel Jensenc0c0ef62013-07-22 16:31:31 -06001247 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001248 case OPUS_SET_BANDWIDTH_REQUEST:
1249 case OPUS_SET_SIGNAL_REQUEST:
1250 case OPUS_SET_APPLICATION_REQUEST:
1251 case OPUS_SET_INBAND_FEC_REQUEST:
1252 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1253 case OPUS_SET_DTX_REQUEST:
1254 case OPUS_SET_FORCE_MODE_REQUEST:
1255 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001256 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
Mark Harris691d4932016-09-03 10:42:19 -07001257 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001258 {
1259 int s;
1260 /* This works for int32 params */
1261 opus_int32 value = va_arg(ap, opus_int32);
1262 for (s=0;s<st->layout.nb_streams;s++)
1263 {
1264 OpusEncoder *enc;
1265
1266 enc = (OpusEncoder*)ptr;
1267 if (s < st->layout.nb_coupled_streams)
1268 ptr += align(coupled_size);
1269 else
1270 ptr += align(mono_size);
1271 ret = opus_encoder_ctl(enc, request, value);
1272 if (ret != OPUS_OK)
1273 break;
1274 }
1275 }
1276 break;
1277 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1278 {
1279 int s;
1280 opus_int32 stream_id;
1281 OpusEncoder **value;
1282 stream_id = va_arg(ap, opus_int32);
1283 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1284 ret = OPUS_BAD_ARG;
1285 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001286 if (!value)
1287 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001288 goto bad_arg;
1289 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001290 for (s=0;s<stream_id;s++)
1291 {
1292 if (s < st->layout.nb_coupled_streams)
1293 ptr += align(coupled_size);
1294 else
1295 ptr += align(mono_size);
1296 }
1297 *value = (OpusEncoder*)ptr;
1298 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001299 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001300 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001301 {
1302 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001303 st->variable_duration = value;
1304 }
1305 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001306 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001307 {
1308 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001309 if (!value)
1310 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001311 goto bad_arg;
1312 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001313 *value = st->variable_duration;
1314 }
1315 break;
Jean-Marc Valin811db622013-10-28 16:11:53 -04001316 case OPUS_RESET_STATE:
1317 {
1318 int s;
1319 st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
Michael Graczyk39256682016-05-02 21:42:18 -07001320 if (st->mapping_type == MAPPING_TYPE_SURROUND)
Jean-Marc Valin811db622013-10-28 16:11:53 -04001321 {
1322 OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
1323 OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
1324 }
1325 for (s=0;s<st->layout.nb_streams;s++)
1326 {
1327 OpusEncoder *enc;
1328 enc = (OpusEncoder*)ptr;
1329 if (s < st->layout.nb_coupled_streams)
1330 ptr += align(coupled_size);
1331 else
1332 ptr += align(mono_size);
1333 ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
1334 if (ret != OPUS_OK)
1335 break;
1336 }
1337 }
1338 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001339 default:
1340 ret = OPUS_UNIMPLEMENTED;
1341 break;
1342 }
1343
1344 va_end(ap);
1345 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001346bad_arg:
1347 va_end(ap);
1348 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001349}
1350
1351void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1352{
1353 opus_free(st);
1354}