1e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/* Copyright (c) 2011 Xiph.Org Foundation
2e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   Written by Jean-Marc Valin */
3e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/*
4e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   Redistribution and use in source and binary forms, with or without
5e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   modification, are permitted provided that the following conditions
6e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   are met:
7e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
8e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   - Redistributions of source code must retain the above copyright
9e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   notice, this list of conditions and the following disclaimer.
10e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
11e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   - Redistributions in binary form must reproduce the above copyright
12e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   notice, this list of conditions and the following disclaimer in the
13e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   documentation and/or other materials provided with the distribution.
14e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
15e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org*/
27e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
28e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#ifdef HAVE_CONFIG_H
29e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "config.h"
30e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
31e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
32e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "opus_multistream.h"
33e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "opus.h"
34e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "opus_private.h"
35e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "stack_alloc.h"
36e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include <stdarg.h>
37e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "float_cast.h"
38e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "os_support.h"
39e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "mathops.h"
40e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "mdct.h"
41e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "modes.h"
42e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "bands.h"
43e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "quant_bands.h"
44e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
45e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgtypedef struct {
46e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int nb_streams;
47e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int nb_coupled_streams;
48e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   unsigned char mapping[8];
49e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org} VorbisLayout;
50e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
51e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/* Index is nb_channel-1*/
52e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic const VorbisLayout vorbis_mappings[8] = {
53e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {1, 0, {0}},                      /* 1: mono */
54e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {1, 1, {0, 1}},                   /* 2: stereo */
55e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {2, 1, {0, 2, 1}},                /* 3: 1-d surround */
56e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {2, 2, {0, 1, 2, 3}},             /* 4: quadraphonic surround */
57e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {3, 2, {0, 4, 1, 2, 3}},          /* 5: 5-channel surround */
58e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {4, 2, {0, 4, 1, 2, 3, 5}},       /* 6: 5.1 surround */
59e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {4, 3, {0, 4, 1, 2, 3, 5, 6}},    /* 7: 6.1 surround */
60e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
61e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org};
62e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
63e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgtypedef void (*opus_copy_channel_in_func)(
64e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  opus_val16 *dst,
65e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int dst_stride,
66e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  const void *src,
67e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int src_stride,
68e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int src_channel,
69e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int frame_size
70e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org);
71e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
72e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstruct OpusMSEncoder {
73e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ChannelLayout layout;
74e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int lfe_stream;
75e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int application;
76e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int variable_duration;
77e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int surround;
78e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_int32 bitrate_bps;
793c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   float subframe_mem[3];
80e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* Encoder states go here */
81e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* then opus_val32 window_mem[channels*120]; */
82e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* then opus_val32 preemph_mem[channels]; */
83e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org};
84e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
85e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
86e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
87e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int s;
88e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   char *ptr;
89e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int coupled_size, mono_size;
90e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
91e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   coupled_size = opus_encoder_get_size(2);
92e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   mono_size = opus_encoder_get_size(1);
93e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ptr = (char*)st + align(sizeof(OpusMSEncoder));
94e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (s=0;s<st->layout.nb_streams;s++)
95e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
96e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (s < st->layout.nb_coupled_streams)
97e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ptr += align(coupled_size);
98e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      else
99e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ptr += align(mono_size);
100e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
101e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return (opus_val32*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
102e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
103e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
104e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
105e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
106e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int s;
107e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   char *ptr;
108e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int coupled_size, mono_size;
109e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
110e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   coupled_size = opus_encoder_get_size(2);
111e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   mono_size = opus_encoder_get_size(1);
112e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ptr = (char*)st + align(sizeof(OpusMSEncoder));
113e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (s=0;s<st->layout.nb_streams;s++)
114e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
115e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (s < st->layout.nb_coupled_streams)
116e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ptr += align(coupled_size);
117e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      else
118e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ptr += align(mono_size);
119e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
120e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return (opus_val32*)ptr;
121e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
122e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
123e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic int validate_encoder_layout(const ChannelLayout *layout)
124e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
125e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int s;
126e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (s=0;s<layout->nb_streams;s++)
127e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
128e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (s < layout->nb_coupled_streams)
129e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
130e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (get_left_channel(layout, s, -1)==-1)
131e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            return 0;
132e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (get_right_channel(layout, s, -1)==-1)
133e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            return 0;
134e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      } else {
135e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (get_mono_channel(layout, s, -1)==-1)
136e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            return 0;
137e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
138e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
139e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return 1;
140e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
141e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
142e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic void channel_pos(int channels, int pos[8])
143e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
144e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
145e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (channels==4)
146e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
147e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[0]=1;
148e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[1]=3;
149e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[2]=1;
150e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[3]=3;
151e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else if (channels==3||channels==5||channels==6)
152e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
153e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[0]=1;
154e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[1]=2;
155e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[2]=3;
156e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[3]=1;
157e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[4]=3;
158e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[5]=0;
159e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else if (channels==7)
160e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
161e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[0]=1;
162e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[1]=2;
163e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[2]=3;
164e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[3]=1;
165e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[4]=3;
166e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[5]=2;
167e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[6]=0;
168e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else if (channels==8)
169e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
170e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[0]=1;
171e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[1]=2;
172e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[2]=3;
173e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[3]=1;
174e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[4]=3;
175e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[5]=1;
176e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[6]=3;
177e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pos[7]=0;
178e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
179e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
180e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
181e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#if 1
182e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/* Computes a rough approximation of log2(2^a + 2^b) */
183e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic opus_val16 logSum(opus_val16 a, opus_val16 b)
184e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
185e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_val16 max;
186e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_val32 diff;
187e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_val16 frac;
188e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   static const opus_val16 diff_table[17] = {
189e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
190e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
191e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         QCONST16(0.0028123f, DB_SHIFT)
192e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   };
193e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int low;
194e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (a>b)
195e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
196e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      max = a;
197e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      diff = SUB32(EXTEND32(a),EXTEND32(b));
198e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else {
199e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      max = b;
200e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      diff = SUB32(EXTEND32(b),EXTEND32(a));
201e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
202e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (diff >= QCONST16(8.f, DB_SHIFT))
203e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return max;
204e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#ifdef FIXED_POINT
205e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   low = SHR32(diff, DB_SHIFT-1);
206e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
207e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#else
2083c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   low = (int)floor(2*diff);
209e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   frac = 2*diff - low;
210e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
211e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
212e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
213e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#else
214e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgopus_val16 logSum(opus_val16 a, opus_val16 b)
215e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
216e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return log2(pow(4, a)+ pow(4, b))/2;
217e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
218e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
219e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
220e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgvoid surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
221e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in
222e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
223e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
224e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int c;
225e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int i;
226e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int LM;
227e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int pos[8] = {0};
228e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int upsample;
229e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int frame_size;
230e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_val16 channel_offset;
231e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_val32 bandE[21];
232e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_val16 maskLogE[3][21];
233e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   VARDECL(opus_val32, in);
234e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   VARDECL(opus_val16, x);
235e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   VARDECL(opus_val32, freq);
236e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   SAVE_STACK;
237e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
238e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   upsample = resampling_factor(rate);
239e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   frame_size = len*upsample;
240e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
2413c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   for (LM=0;LM<celt_mode->maxLM;LM++)
242e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (celt_mode->shortMdctSize<<LM==frame_size)
243e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         break;
244e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
245e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ALLOC(in, frame_size+overlap, opus_val32);
246e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ALLOC(x, len, opus_val16);
247e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ALLOC(freq, frame_size, opus_val32);
248e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
249e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   channel_pos(channels, pos);
250e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
251e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (c=0;c<3;c++)
252e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (i=0;i<21;i++)
253e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
254e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
255e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (c=0;c<channels;c++)
256e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
257e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OPUS_COPY(in, mem+c*overlap, overlap);
258e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      (*copy_channel_in)(x, 1, pcm, channels, c, len);
2593c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
260e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1);
261e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (upsample != 1)
262e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
263e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         int bound = len;
264e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         for (i=0;i<bound;i++)
265e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            freq[i] *= upsample;
266e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         for (;i<frame_size;i++)
267e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            freq[i] = 0;
268e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
269e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
270e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      compute_band_energies(celt_mode, freq, bandE, 21, 1, 1<<LM);
271e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
272e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
273e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (i=1;i<21;i++)
274e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
275e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (i=19;i>=0;i--)
276e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT));
277e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (pos[c]==1)
278e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
279e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         for (i=0;i<21;i++)
280e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
281e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      } else if (pos[c]==3)
282e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
283e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         for (i=0;i<21;i++)
284e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
285e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      } else if (pos[c]==2)
286e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
287e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         for (i=0;i<21;i++)
288e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         {
289e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
290e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
291e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         }
292e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
293e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#if 0
294e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (i=0;i<21;i++)
295e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         printf("%f ", bandLogE[21*c+i]);
296e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      float sum=0;
297e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (i=0;i<21;i++)
298e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         sum += bandLogE[21*c+i];
299e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      printf("%f ", sum/21);
300e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
301e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
302e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
303e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (i=0;i<21;i++)
304e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
305e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
306e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (c=0;c<3;c++)
307e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (i=0;i<21;i++)
308e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         maskLogE[c][i] += channel_offset;
309e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#if 0
310e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (c=0;c<3;c++)
311e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
312e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (i=0;i<21;i++)
313e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         printf("%f ", maskLogE[c][i]);
314e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
315e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
316e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (c=0;c<channels;c++)
317e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
318e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_val16 *mask;
319e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (pos[c]!=0)
320e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
321e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         mask = &maskLogE[pos[c]-1][0];
322e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         for (i=0;i<21;i++)
323e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
324e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      } else {
325e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         for (i=0;i<21;i++)
326e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            bandLogE[21*c+i] = 0;
327e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
328e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#if 0
329e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (i=0;i<21;i++)
330e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         printf("%f ", bandLogE[21*c+i]);
331e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      printf("\n");
332e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
333e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#if 0
334e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      float sum=0;
335e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (i=0;i<21;i++)
336e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         sum += bandLogE[21*c+i];
337e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
338e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      printf("\n");
339e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
340e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
341e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   RESTORE_STACK;
342e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
343e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
344e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgopus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
345e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
346e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int coupled_size;
347e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int mono_size;
348e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
349e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
350e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   coupled_size = opus_encoder_get_size(2);
351e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   mono_size = opus_encoder_get_size(1);
352e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return align(sizeof(OpusMSEncoder))
353e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org        + nb_coupled_streams * align(coupled_size)
354e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org        + (nb_streams-nb_coupled_streams) * align(mono_size);
355e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
356e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
357e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgopus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
358e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
359e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int nb_streams;
360e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int nb_coupled_streams;
361e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_int32 size;
362e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
363e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (mapping_family==0)
364e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
365e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (channels==1)
366e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
367e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         nb_streams=1;
368e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         nb_coupled_streams=0;
369e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      } else if (channels==2)
370e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
371e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         nb_streams=1;
372e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         nb_coupled_streams=1;
373e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      } else
374e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         return 0;
375e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else if (mapping_family==1 && channels<=8 && channels>=1)
376e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
377e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      nb_streams=vorbis_mappings[channels-1].nb_streams;
378e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
379e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else if (mapping_family==255)
380e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
381e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      nb_streams=channels;
382e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      nb_coupled_streams=0;
383e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else
384e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return 0;
385e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
386e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (channels>2)
387e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
388e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
389e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
390e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return size;
391e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
392e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
393e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
394e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic int opus_multistream_encoder_init_impl(
395e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OpusMSEncoder *st,
396e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 Fs,
397e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int channels,
398e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int streams,
399e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int coupled_streams,
400e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      const unsigned char *mapping,
401e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int application,
402e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int surround
403e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
404e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
405e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int coupled_size;
406e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int mono_size;
407e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int i, ret;
408e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   char *ptr;
409e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
410e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
411e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org       (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
412e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return OPUS_BAD_ARG;
413e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
414e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st->layout.nb_channels = channels;
415e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st->layout.nb_streams = streams;
416e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st->layout.nb_coupled_streams = coupled_streams;
417e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
418e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (!surround)
419e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      st->lfe_stream = -1;
420e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st->bitrate_bps = OPUS_AUTO;
421e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st->application = application;
422e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st->variable_duration = OPUS_FRAMESIZE_ARG;
423e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (i=0;i<st->layout.nb_channels;i++)
424e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      st->layout.mapping[i] = mapping[i];
425e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
426e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return OPUS_BAD_ARG;
427e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ptr = (char*)st + align(sizeof(OpusMSEncoder));
428e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   coupled_size = opus_encoder_get_size(2);
429e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   mono_size = opus_encoder_get_size(1);
430e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
431e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (i=0;i<st->layout.nb_coupled_streams;i++)
432e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
433e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
434e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if(ret!=OPUS_OK)return ret;
435e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (i==st->lfe_stream)
436e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
437e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      ptr += align(coupled_size);
438e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
439e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (;i<st->layout.nb_streams;i++)
440e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
441e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
442e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (i==st->lfe_stream)
443e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
444e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if(ret!=OPUS_OK)return ret;
445e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      ptr += align(mono_size);
446e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
447e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (surround)
448e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
449e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OPUS_CLEAR(ms_get_preemph_mem(st), channels);
450e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OPUS_CLEAR(ms_get_window_mem(st), channels*120);
451e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
452e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st->surround = surround;
453e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return OPUS_OK;
454e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
455e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
456e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgint opus_multistream_encoder_init(
457e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OpusMSEncoder *st,
458e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 Fs,
459e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int channels,
460e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int streams,
461e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int coupled_streams,
462e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      const unsigned char *mapping,
463e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int application
464e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
465e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
466e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
467e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
468e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
469e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgint opus_multistream_surround_encoder_init(
470e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OpusMSEncoder *st,
471e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 Fs,
472e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int channels,
473e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int mapping_family,
474e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int *streams,
475e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int *coupled_streams,
476e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      unsigned char *mapping,
477e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int application
478e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
479e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
480e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if ((channels>255) || (channels<1))
481e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return OPUS_BAD_ARG;
482e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st->lfe_stream = -1;
483e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (mapping_family==0)
484e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
485e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (channels==1)
486e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
487e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         *streams=1;
488e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         *coupled_streams=0;
489e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         mapping[0]=0;
490e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      } else if (channels==2)
491e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
492e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         *streams=1;
493e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         *coupled_streams=1;
494e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         mapping[0]=0;
495e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         mapping[1]=1;
496e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      } else
497e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         return OPUS_UNIMPLEMENTED;
498e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else if (mapping_family==1 && channels<=8 && channels>=1)
499e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
500e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int i;
501e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      *streams=vorbis_mappings[channels-1].nb_streams;
502e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
503e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (i=0;i<channels;i++)
504e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         mapping[i] = vorbis_mappings[channels-1].mapping[i];
505e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (channels>=6)
506e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         st->lfe_stream = *streams-1;
507e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else if (mapping_family==255)
508e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
509e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int i;
510e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      *streams=channels;
511e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      *coupled_streams=0;
512e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for(i=0;i<channels;i++)
513e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         mapping[i] = i;
514e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else
515e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return OPUS_UNIMPLEMENTED;
516e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
517e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         mapping, application, channels>2&&mapping_family==1);
518e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
519e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
520e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgOpusMSEncoder *opus_multistream_encoder_create(
521e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 Fs,
522e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int channels,
523e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int streams,
524e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int coupled_streams,
525e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      const unsigned char *mapping,
526e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int application,
527e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int *error
528e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
529e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
530e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int ret;
531e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   OpusMSEncoder *st;
532e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
533e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org       (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
534e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
535e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (error)
536e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         *error = OPUS_BAD_ARG;
537e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return NULL;
538e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
539e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
540e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (st==NULL)
541e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
542e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (error)
543e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         *error = OPUS_ALLOC_FAIL;
544e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return NULL;
545e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
546e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
547e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (ret != OPUS_OK)
548e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
549e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_free(st);
550e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      st = NULL;
551e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
552e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (error)
553e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      *error = ret;
554e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return st;
555e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
556e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
557e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgOpusMSEncoder *opus_multistream_surround_encoder_create(
558e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 Fs,
559e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int channels,
560e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int mapping_family,
561e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int *streams,
562e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int *coupled_streams,
563e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      unsigned char *mapping,
564e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int application,
565e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int *error
566e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
567e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
568e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int ret;
569e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   OpusMSEncoder *st;
570e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if ((channels>255) || (channels<1))
571e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
572e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (error)
573e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         *error = OPUS_BAD_ARG;
574e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return NULL;
575e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
576e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
577e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (st==NULL)
578e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
579e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (error)
580e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         *error = OPUS_ALLOC_FAIL;
581e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return NULL;
582e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
583e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
584e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (ret != OPUS_OK)
585e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
586e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_free(st);
587e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      st = NULL;
588e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
589e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (error)
590e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      *error = ret;
591e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return st;
592e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
593e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
594e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic void surround_rate_allocation(
595e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OpusMSEncoder *st,
596e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 *rate,
597e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int frame_size
598e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      )
599e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
600e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int i;
601e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_int32 channel_rate;
602e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_int32 Fs;
603e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   char *ptr;
604e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int stream_offset;
605e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int lfe_offset;
606e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int coupled_ratio; /* Q8 */
607e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int lfe_ratio;     /* Q8 */
608e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
609e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ptr = (char*)st + align(sizeof(OpusMSEncoder));
610e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
611e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
612e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (st->bitrate_bps > st->layout.nb_channels*40000)
613e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      stream_offset = 20000;
614e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   else
615e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
6163c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   stream_offset += 60*(Fs/frame_size-50);
617e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* We start by giving each stream (coupled or uncoupled) the same bitrate.
618e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      This models the main saving of coupled channels over uncoupled. */
619e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* The LFE stream is an exception to the above and gets fewer bits. */
6203c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   lfe_offset = 3500 + 60*(Fs/frame_size-50);
621e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* Coupled streams get twice the mono rate after the first 20 kb/s. */
622e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   coupled_ratio = 512;
623e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
624e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   lfe_ratio = 32;
625e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
626e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* Compute bitrate allocation between streams */
627e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (st->bitrate_bps==OPUS_AUTO)
628e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
629e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      channel_rate = Fs+60*Fs/frame_size;
630e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
631e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
632e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      channel_rate = 300000;
633e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   } else {
634e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int nb_lfe;
635e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int nb_uncoupled;
636e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int nb_coupled;
637e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int total;
638e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      nb_lfe = (st->lfe_stream!=-1);
639e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      nb_coupled = st->layout.nb_coupled_streams;
640e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
641e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      total = (nb_uncoupled<<8)         /* mono */
642e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            + coupled_ratio*nb_coupled /* stereo */
643e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            + nb_lfe*lfe_ratio;
644e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
645e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
646e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#ifndef FIXED_POINT
647e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
648e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
649e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 bonus;
650e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      bonus = 60*(Fs/frame_size-50);
651e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      channel_rate += bonus;
652e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
653e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
654e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
655e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (i=0;i<st->layout.nb_streams;i++)
656e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
657e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (i<st->layout.nb_coupled_streams)
658e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
659e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      else if (i!=st->lfe_stream)
660e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         rate[i] = stream_offset+channel_rate;
661e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      else
662e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
663e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
664e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
665e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
666e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/* Max size in case the encoder decides to return three frames */
667e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#define MS_FRAME_TMP (3*1275+7)
668e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic int opus_multistream_encode_native
669e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org(
670e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    OpusMSEncoder *st,
671e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    opus_copy_channel_in_func copy_channel_in,
672e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    const void *pcm,
673e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    int analysis_frame_size,
674e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    unsigned char *data,
675e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    opus_int32 max_data_bytes,
676e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    int lsb_depth,
677e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    downmix_func downmix
678e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
679e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
680e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_int32 Fs;
681e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int coupled_size;
682e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int mono_size;
683e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int s;
684e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   char *ptr;
685e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int tot_size;
686e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   VARDECL(opus_val16, buf);
687e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   VARDECL(opus_val16, bandSMR);
688e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   unsigned char tmp_data[MS_FRAME_TMP];
689e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   OpusRepacketizer rp;
6903c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   opus_int32 vbr;
691e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   const CELTMode *celt_mode;
692e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_int32 bitrates[256];
693e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_val16 bandLogE[42];
694e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_val32 *mem = NULL;
695e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_val32 *preemph_mem=NULL;
696e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int frame_size;
697e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ALLOC_STACK;
698e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
699e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (st->surround)
700e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
701e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      preemph_mem = ms_get_preemph_mem(st);
702e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      mem = ms_get_window_mem(st);
703e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
704e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
705e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ptr = (char*)st + align(sizeof(OpusMSEncoder));
706e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
7073c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
708e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
709e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
710e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
711e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 delay_compensation;
712e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int channels;
713e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
714e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
715e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
716e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      delay_compensation -= Fs/400;
717e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      frame_size = compute_frame_size(pcm, analysis_frame_size,
718e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            st->variable_duration, channels, Fs, st->bitrate_bps,
7193c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com            delay_compensation, downmix
7203c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com#ifndef DISABLE_FLOAT_API
7213c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com            , st->subframe_mem
7223c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com#endif
7233c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com            );
724e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
725e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
726e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (400*frame_size < Fs)
727e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
728e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      RESTORE_STACK;
729e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return OPUS_BAD_ARG;
730e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
731e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* Validate frame_size before using it to allocate stack space.
732e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      This mirrors the checks in opus_encode[_float](). */
733e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (400*frame_size != Fs && 200*frame_size != Fs &&
734e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org       100*frame_size != Fs &&  50*frame_size != Fs &&
735e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org        25*frame_size != Fs &&  50*frame_size != 3*Fs)
736e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
737e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      RESTORE_STACK;
738e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return OPUS_BAD_ARG;
739e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
740e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ALLOC(buf, 2*frame_size, opus_val16);
741e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   coupled_size = opus_encoder_get_size(2);
742e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   mono_size = opus_encoder_get_size(1);
743e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
744e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
745e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (st->surround)
746e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
747e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in);
748e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
749e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
750e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   if (max_data_bytes < 4*st->layout.nb_streams-1)
751e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
752e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      RESTORE_STACK;
753e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      return OPUS_BUFFER_TOO_SMALL;
754e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
755e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
756e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* Compute bitrate allocation between streams (this could be a lot better) */
757e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   surround_rate_allocation(st, bitrates, frame_size);
758e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
7593c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   if (!vbr)
7603c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      max_data_bytes = IMIN(max_data_bytes, 3*st->bitrate_bps/(3*8*Fs/frame_size));
7613c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com
762e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ptr = (char*)st + align(sizeof(OpusMSEncoder));
763e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (s=0;s<st->layout.nb_streams;s++)
764e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
765e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OpusEncoder *enc;
766e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      enc = (OpusEncoder*)ptr;
767e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (s < st->layout.nb_coupled_streams)
768e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ptr += align(coupled_size);
769e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      else
770e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ptr += align(mono_size);
771e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
772e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (st->surround)
773e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
774e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         opus_int32 equiv_rate;
775e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         equiv_rate = st->bitrate_bps;
776e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (frame_size*50 < Fs)
777e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
7783c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         if (equiv_rate > 10000*st->layout.nb_channels)
779e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
7803c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         else if (equiv_rate > 7000*st->layout.nb_channels)
781e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
7823c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         else if (equiv_rate > 5000*st->layout.nb_channels)
783e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
784e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         else
785e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
786e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (s < st->layout.nb_coupled_streams)
787e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         {
788e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            /* To preserve the spatial image, force stereo CELT on coupled streams */
789e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
790e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
791e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         }
792e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
793e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
794e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
795e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ptr = (char*)st + align(sizeof(OpusMSEncoder));
796e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /* Counting ToC */
797e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   tot_size = 0;
798e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (s=0;s<st->layout.nb_streams;s++)
799e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
800e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OpusEncoder *enc;
801e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int len;
802e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int curr_max;
803e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int c1, c2;
804e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
805e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_repacketizer_init(&rp);
806e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      enc = (OpusEncoder*)ptr;
807e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (s < st->layout.nb_coupled_streams)
808e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
809e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         int i;
810e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         int left, right;
811e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         left = get_left_channel(&st->layout, s, -1);
812e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         right = get_right_channel(&st->layout, s, -1);
813e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         (*copy_channel_in)(buf, 2,
814e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            pcm, st->layout.nb_channels, left, frame_size);
815e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         (*copy_channel_in)(buf+1, 2,
816e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            pcm, st->layout.nb_channels, right, frame_size);
817e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ptr += align(coupled_size);
818e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (st->surround)
819e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         {
820e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            for (i=0;i<21;i++)
821e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            {
822e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org               bandLogE[i] = bandSMR[21*left+i];
823e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org               bandLogE[21+i] = bandSMR[21*right+i];
824e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            }
825e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         }
826e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         c1 = left;
827e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         c2 = right;
828e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      } else {
829e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         int i;
830e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         int chan = get_mono_channel(&st->layout, s, -1);
831e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         (*copy_channel_in)(buf, 1,
832e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            pcm, st->layout.nb_channels, chan, frame_size);
833e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ptr += align(mono_size);
834e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (st->surround)
835e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         {
836e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            for (i=0;i<21;i++)
837e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org               bandLogE[i] = bandSMR[21*chan+i];
838e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         }
839e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         c1 = chan;
840e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         c2 = -1;
841e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
842e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (st->surround)
843e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
844e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      /* number of bytes left (+Toc) */
845e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      curr_max = max_data_bytes - tot_size;
846e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      /* Reserve three bytes for the last stream and four for the others */
847e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
848e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      curr_max = IMIN(curr_max,MS_FRAME_TMP);
8493c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      if (!vbr && s == st->layout.nb_streams-1)
8503c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
851e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
852e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix);
853e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (len<0)
854e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
855e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         RESTORE_STACK;
856e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         return len;
857e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
858e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      /* We need to use the repacketizer to add the self-delimiting lengths
859e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         while taking into account the fact that the encoder can now return
860e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         more than one frame at a time (e.g. 60 ms CELT-only) */
861e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_repacketizer_cat(&rp, tmp_data, len);
8623c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
8633c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com            data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1);
864e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      data += len;
865e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      tot_size += len;
866e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
867e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   /*printf("\n");*/
868e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   RESTORE_STACK;
869e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return tot_size;
870e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
871e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
872e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#if !defined(DISABLE_FLOAT_API)
873e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic void opus_copy_channel_in_float(
874e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  opus_val16 *dst,
875e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int dst_stride,
876e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  const void *src,
877e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int src_stride,
878e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int src_channel,
879e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int frame_size
880e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
881e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
882e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   const float *float_src;
883e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_int32 i;
884e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   float_src = (const float *)src;
885e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (i=0;i<frame_size;i++)
886e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#if defined(FIXED_POINT)
887e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
888e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#else
889e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      dst[i*dst_stride] = float_src[i*src_stride+src_channel];
890e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
891e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
892e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
893e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
894e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic void opus_copy_channel_in_short(
895e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  opus_val16 *dst,
896e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int dst_stride,
897e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  const void *src,
898e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int src_stride,
899e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int src_channel,
900e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org  int frame_size
901e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
902e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
903e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   const opus_int16 *short_src;
904e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   opus_int32 i;
905e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   short_src = (const opus_int16 *)src;
906e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   for (i=0;i<frame_size;i++)
907e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#if defined(FIXED_POINT)
908e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      dst[i*dst_stride] = short_src[i*src_stride+src_channel];
909e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#else
910e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
911e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
912e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
913e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
914e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
915e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#ifdef FIXED_POINT
916e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgint opus_multistream_encode(
917e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    OpusMSEncoder *st,
918e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    const opus_val16 *pcm,
919e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    int frame_size,
920e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    unsigned char *data,
921e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    opus_int32 max_data_bytes
922e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
923e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
924e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return opus_multistream_encode_native(st, opus_copy_channel_in_short,
925e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pcm, frame_size, data, max_data_bytes, 16, downmix_int);
926e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
927e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
928e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#ifndef DISABLE_FLOAT_API
929e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgint opus_multistream_encode_float(
930e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    OpusMSEncoder *st,
931e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    const float *pcm,
932e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    int frame_size,
933e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    unsigned char *data,
934e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    opus_int32 max_data_bytes
935e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
936e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
937e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return opus_multistream_encode_native(st, opus_copy_channel_in_float,
938e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pcm, frame_size, data, max_data_bytes, 16, downmix_float);
939e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
940e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
941e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
942e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#else
943e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
944e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgint opus_multistream_encode_float
945e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org(
946e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    OpusMSEncoder *st,
947e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    const opus_val16 *pcm,
948e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    int frame_size,
949e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    unsigned char *data,
950e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    opus_int32 max_data_bytes
951e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
952e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
953e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return opus_multistream_encode_native(st, opus_copy_channel_in_float,
954e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pcm, frame_size, data, max_data_bytes, 24, downmix_float);
955e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
956e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
957e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgint opus_multistream_encode(
958e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    OpusMSEncoder *st,
959e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    const opus_int16 *pcm,
960e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    int frame_size,
961e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    unsigned char *data,
962e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    opus_int32 max_data_bytes
963e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org)
964e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
965e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return opus_multistream_encode_native(st, opus_copy_channel_in_short,
966e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      pcm, frame_size, data, max_data_bytes, 16, downmix_int);
967e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
968e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif
969e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
970e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgint opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
971e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
972e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   va_list ap;
973e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int coupled_size, mono_size;
974e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   char *ptr;
975e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   int ret = OPUS_OK;
976e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
977e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   va_start(ap, request);
978e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
979e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   coupled_size = opus_encoder_get_size(2);
980e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   mono_size = opus_encoder_get_size(1);
981e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   ptr = (char*)st + align(sizeof(OpusMSEncoder));
982e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   switch (request)
983e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
984e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_BITRATE_REQUEST:
985e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
986e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 value = va_arg(ap, opus_int32);
987e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
988e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
989e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         goto bad_arg;
990e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
991e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      st->bitrate_bps = value;
992e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
993e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   break;
994e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_BITRATE_REQUEST:
995e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
996e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int s;
997e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 *value = va_arg(ap, opus_int32*);
998e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (!value)
999e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
1000e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         goto bad_arg;
1001e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
1002e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      *value = 0;
1003e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (s=0;s<st->layout.nb_streams;s++)
1004e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
1005e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         opus_int32 rate;
1006e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         OpusEncoder *enc;
1007e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         enc = (OpusEncoder*)ptr;
1008e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (s < st->layout.nb_coupled_streams)
1009e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            ptr += align(coupled_size);
1010e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         else
1011e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            ptr += align(mono_size);
1012e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         opus_encoder_ctl(enc, request, &rate);
1013e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         *value += rate;
1014e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
1015e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
1016e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   break;
1017e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_LSB_DEPTH_REQUEST:
1018e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_VBR_REQUEST:
1019e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_APPLICATION_REQUEST:
1020e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_BANDWIDTH_REQUEST:
1021e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_COMPLEXITY_REQUEST:
1022e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1023e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_DTX_REQUEST:
1024e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_VOICE_RATIO_REQUEST:
1025e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1026e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_SIGNAL_REQUEST:
1027e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_LOOKAHEAD_REQUEST:
1028e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_SAMPLE_RATE_REQUEST:
1029e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_INBAND_FEC_REQUEST:
1030e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_FORCE_CHANNELS_REQUEST:
10313c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   case OPUS_GET_PREDICTION_DISABLED_REQUEST:
1032e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
1033e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OpusEncoder *enc;
1034e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      /* For int32* GET params, just query the first stream */
1035e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 *value = va_arg(ap, opus_int32*);
1036e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      enc = (OpusEncoder*)ptr;
1037e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      ret = opus_encoder_ctl(enc, request, value);
1038e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
1039e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   break;
1040e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_FINAL_RANGE_REQUEST:
1041e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
1042e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int s;
1043e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_uint32 *value = va_arg(ap, opus_uint32*);
1044e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_uint32 tmp;
1045e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (!value)
1046e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
1047e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         goto bad_arg;
1048e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
1049e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      *value=0;
1050e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (s=0;s<st->layout.nb_streams;s++)
1051e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
1052e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         OpusEncoder *enc;
1053e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         enc = (OpusEncoder*)ptr;
1054e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (s < st->layout.nb_coupled_streams)
1055e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            ptr += align(coupled_size);
1056e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         else
1057e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            ptr += align(mono_size);
1058e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ret = opus_encoder_ctl(enc, request, &tmp);
1059e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (ret != OPUS_OK) break;
1060e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         *value ^= tmp;
1061e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
1062e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
1063e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   break;
1064e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_LSB_DEPTH_REQUEST:
1065e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_COMPLEXITY_REQUEST:
1066e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_VBR_REQUEST:
1067e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_VBR_CONSTRAINT_REQUEST:
1068e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_MAX_BANDWIDTH_REQUEST:
1069e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_BANDWIDTH_REQUEST:
1070e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_SIGNAL_REQUEST:
1071e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_APPLICATION_REQUEST:
1072e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_INBAND_FEC_REQUEST:
1073e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1074e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_DTX_REQUEST:
1075e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_FORCE_MODE_REQUEST:
1076e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_FORCE_CHANNELS_REQUEST:
10773c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   case OPUS_SET_PREDICTION_DISABLED_REQUEST:
1078e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
1079e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int s;
1080e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      /* This works for int32 params */
1081e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 value = va_arg(ap, opus_int32);
1082e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (s=0;s<st->layout.nb_streams;s++)
1083e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
1084e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         OpusEncoder *enc;
1085e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
1086e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         enc = (OpusEncoder*)ptr;
1087e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (s < st->layout.nb_coupled_streams)
1088e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            ptr += align(coupled_size);
1089e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         else
1090e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            ptr += align(mono_size);
1091e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ret = opus_encoder_ctl(enc, request, value);
1092e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (ret != OPUS_OK)
1093e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            break;
1094e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
1095e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
1096e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   break;
1097e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1098e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
1099e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      int s;
1100e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      opus_int32 stream_id;
1101e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      OpusEncoder **value;
1102e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      stream_id = va_arg(ap, opus_int32);
1103e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (stream_id<0 || stream_id >= st->layout.nb_streams)
1104e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         ret = OPUS_BAD_ARG;
1105e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      value = va_arg(ap, OpusEncoder**);
1106e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      if (!value)
1107e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
1108e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         goto bad_arg;
1109e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
1110e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      for (s=0;s<stream_id;s++)
1111e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      {
1112e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         if (s < st->layout.nb_coupled_streams)
1113e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            ptr += align(coupled_size);
1114e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org         else
1115e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org            ptr += align(mono_size);
1116e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      }
1117e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      *value = (OpusEncoder*)ptr;
1118e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
1119e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   break;
1120e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
1121e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
1122e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org       opus_int32 value = va_arg(ap, opus_int32);
1123e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org       st->variable_duration = value;
1124e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
1125e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   break;
1126e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
1127e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   {
1128e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org       opus_int32 *value = va_arg(ap, opus_int32*);
1129e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org       if (!value)
1130e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org       {
1131e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org          goto bad_arg;
1132e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org       }
1133e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org       *value = st->variable_duration;
1134e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
1135e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   break;
11363c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   case OPUS_RESET_STATE:
11373c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   {
11383c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      int s;
11393c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
11403c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      if (st->surround)
11413c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      {
11423c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
11433c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
11443c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      }
11453c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      for (s=0;s<st->layout.nb_streams;s++)
11463c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      {
11473c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         OpusEncoder *enc;
11483c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         enc = (OpusEncoder*)ptr;
11493c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         if (s < st->layout.nb_coupled_streams)
11503c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com            ptr += align(coupled_size);
11513c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         else
11523c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com            ptr += align(mono_size);
11533c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
11543c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com         if (ret != OPUS_OK)
11553c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com            break;
11563c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com      }
11573c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   }
11583c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com   break;
1159e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   default:
1160e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      ret = OPUS_UNIMPLEMENTED;
1161e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org      break;
1162e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   }
1163e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
1164e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   va_end(ap);
1165e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return ret;
1166e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgbad_arg:
1167e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   va_end(ap);
1168e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org   return OPUS_BAD_ARG;
1169e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
1170e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org
1171e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgvoid opus_multistream_encoder_destroy(OpusMSEncoder *st)
1172e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org{
1173e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org    opus_free(st);
1174e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org}
1175