12bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/* Copyright (c) 2011 Xiph.Org Foundation
22bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   Written by Jean-Marc Valin */
32bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/*
42bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   Redistribution and use in source and binary forms, with or without
52bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   modification, are permitted provided that the following conditions
62bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   are met:
72bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
82bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   - Redistributions of source code must retain the above copyright
92bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   notice, this list of conditions and the following disclaimer.
102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   - Redistributions in binary form must reproduce the above copyright
122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   notice, this list of conditions and the following disclaimer in the
132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   documentation and/or other materials provided with the distribution.
142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian*/
272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef HAVE_CONFIG_H
292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "config.h"
302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "opus_multistream.h"
332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "opus.h"
342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "opus_private.h"
352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "stack_alloc.h"
362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include <stdarg.h>
372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "float_cast.h"
382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "os_support.h"
392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "mathops.h"
402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "mdct.h"
412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "modes.h"
422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "bands.h"
432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "quant_bands.h"
442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramaniantypedef struct {
462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int nb_streams;
472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int nb_coupled_streams;
482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   unsigned char mapping[8];
492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian} VorbisLayout;
502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/* Index is nb_channel-1*/
522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic const VorbisLayout vorbis_mappings[8] = {
532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {1, 0, {0}},                      /* 1: mono */
542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {1, 1, {0, 1}},                   /* 2: stereo */
552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {2, 1, {0, 2, 1}},                /* 3: 1-d surround */
562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {2, 2, {0, 1, 2, 3}},             /* 4: quadraphonic surround */
572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {3, 2, {0, 4, 1, 2, 3}},          /* 5: 5-channel surround */
582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {4, 2, {0, 4, 1, 2, 3, 5}},       /* 6: 5.1 surround */
592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {4, 3, {0, 4, 1, 2, 3, 5, 6}},    /* 7: 6.1 surround */
602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian};
622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramaniantypedef void (*opus_copy_channel_in_func)(
642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  opus_val16 *dst,
652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int dst_stride,
662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  const void *src,
672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int src_stride,
682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int src_channel,
692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int frame_size
702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian);
712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstruct OpusMSEncoder {
732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ChannelLayout layout;
742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int lfe_stream;
752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int application;
762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int variable_duration;
772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int surround;
782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 bitrate_bps;
792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   float subframe_mem[3];
802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Encoder states go here */
812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* then opus_val32 window_mem[channels*120]; */
822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* then opus_val32 preemph_mem[channels]; */
832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian};
842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int s;
882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   char *ptr;
892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int coupled_size, mono_size;
902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   coupled_size = opus_encoder_get_size(2);
922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   mono_size = opus_encoder_get_size(1);
932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ptr = (char*)st + align(sizeof(OpusMSEncoder));
942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (s=0;s<st->layout.nb_streams;s++)
952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (s < st->layout.nb_coupled_streams)
972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ptr += align(coupled_size);
982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else
992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ptr += align(mono_size);
1002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
1012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return (opus_val32*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32));
1022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
1052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int s;
1072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   char *ptr;
1082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int coupled_size, mono_size;
1092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   coupled_size = opus_encoder_get_size(2);
1112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   mono_size = opus_encoder_get_size(1);
1122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ptr = (char*)st + align(sizeof(OpusMSEncoder));
1132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (s=0;s<st->layout.nb_streams;s++)
1142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (s < st->layout.nb_coupled_streams)
1162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ptr += align(coupled_size);
1172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else
1182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ptr += align(mono_size);
1192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
1202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return (opus_val32*)ptr;
1212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic int validate_encoder_layout(const ChannelLayout *layout)
1242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int s;
1262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (s=0;s<layout->nb_streams;s++)
1272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (s < layout->nb_coupled_streams)
1292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
1302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (get_left_channel(layout, s, -1)==-1)
1312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            return 0;
1322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (get_right_channel(layout, s, -1)==-1)
1332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            return 0;
1342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else {
1352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (get_mono_channel(layout, s, -1)==-1)
1362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            return 0;
1372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
1382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
1392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return 1;
1402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic void channel_pos(int channels, int pos[8])
1432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
1452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (channels==4)
1462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[0]=1;
1482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[1]=3;
1492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[2]=1;
1502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[3]=3;
1512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if (channels==3||channels==5||channels==6)
1522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[0]=1;
1542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[1]=2;
1552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[2]=3;
1562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[3]=1;
1572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[4]=3;
1582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[5]=0;
1592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if (channels==7)
1602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[0]=1;
1622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[1]=2;
1632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[2]=3;
1642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[3]=1;
1652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[4]=3;
1662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[5]=2;
1672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[6]=0;
1682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if (channels==8)
1692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[0]=1;
1712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[1]=2;
1722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[2]=3;
1732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[3]=1;
1742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[4]=3;
1752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[5]=1;
1762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[6]=3;
1772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pos[7]=0;
1782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
1792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#if 1
1822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/* Computes a rough approximation of log2(2^a + 2^b) */
1832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic opus_val16 logSum(opus_val16 a, opus_val16 b)
1842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 max;
1862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val32 diff;
1872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 frac;
1882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   static const opus_val16 diff_table[17] = {
1892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT),
1902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT),
1912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         QCONST16(0.0028123f, DB_SHIFT)
1922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   };
1932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int low;
1942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (a>b)
1952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      max = a;
1972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      diff = SUB32(EXTEND32(a),EXTEND32(b));
1982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
1992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      max = b;
2002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      diff = SUB32(EXTEND32(b),EXTEND32(a));
2012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
2022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (diff >= QCONST16(8.f, DB_SHIFT))
2032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return max;
2042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef FIXED_POINT
2052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   low = SHR32(diff, DB_SHIFT-1);
2062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT);
2072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
2082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   low = (int)floor(2*diff);
2092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   frac = 2*diff - low;
2102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
2112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low]));
2122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
2132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
2142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianopus_val16 logSum(opus_val16 a, opus_val16 b)
2152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
2162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return log2(pow(4, a)+ pow(4, b))/2;
2172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
2182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
2192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianvoid surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem,
2212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in
2222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
2232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
2242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int c;
2252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int i;
2262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int LM;
2272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int pos[8] = {0};
2282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int upsample;
2292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int frame_size;
2302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 channel_offset;
2312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val32 bandE[21];
2322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 maskLogE[3][21];
2332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_val32, in);
2342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_val16, x);
2352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_val32, freq);
2362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   SAVE_STACK;
2372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   upsample = resampling_factor(rate);
2392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   frame_size = len*upsample;
2402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (LM=0;LM<celt_mode->maxLM;LM++)
2422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (celt_mode->shortMdctSize<<LM==frame_size)
2432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         break;
2442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(in, frame_size+overlap, opus_val32);
2462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(x, len, opus_val16);
2472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(freq, frame_size, opus_val32);
2482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   channel_pos(channels, pos);
2502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (c=0;c<3;c++)
2522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<21;i++)
2532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
2542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (c=0;c<channels;c++)
2562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
2572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OPUS_COPY(in, mem+c*overlap, overlap);
2582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      (*copy_channel_in)(x, 1, pcm, channels, c, len);
2592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
2602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1);
2612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (upsample != 1)
2622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
2632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int bound = len;
2642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<bound;i++)
2652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            freq[i] *= upsample;
2662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (;i<frame_size;i++)
2672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            freq[i] = 0;
2682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
2692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      compute_band_energies(celt_mode, freq, bandE, 21, 1, 1<<LM);
2712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
2722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
2732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=1;i<21;i++)
2742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
2752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=19;i>=0;i--)
2762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT));
2772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (pos[c]==1)
2782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
2792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<21;i++)
2802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]);
2812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else if (pos[c]==3)
2822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
2832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<21;i++)
2842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]);
2852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else if (pos[c]==2)
2862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
2872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<21;i++)
2882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
2892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
2902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT));
2912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
2922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
2932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#if 0
2942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<21;i++)
2952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         printf("%f ", bandLogE[21*c+i]);
2962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      float sum=0;
2972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<21;i++)
2982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         sum += bandLogE[21*c+i];
2992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      printf("%f ", sum/21);
3002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
3012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OPUS_COPY(mem+c*overlap, in+frame_size, overlap);
3022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
3032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (i=0;i<21;i++)
3042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]);
3052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1)));
3062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (c=0;c<3;c++)
3072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<21;i++)
3082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         maskLogE[c][i] += channel_offset;
3092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#if 0
3102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (c=0;c<3;c++)
3112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<21;i++)
3132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         printf("%f ", maskLogE[c][i]);
3142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
3152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
3162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (c=0;c<channels;c++)
3172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_val16 *mask;
3192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (pos[c]!=0)
3202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
3212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         mask = &maskLogE[pos[c]-1][0];
3222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<21;i++)
3232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i];
3242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else {
3252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<21;i++)
3262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            bandLogE[21*c+i] = 0;
3272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
3282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#if 0
3292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<21;i++)
3302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         printf("%f ", bandLogE[21*c+i]);
3312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      printf("\n");
3322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
3332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#if 0
3342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      float sum=0;
3352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<21;i++)
3362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         sum += bandLogE[21*c+i];
3372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT));
3382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      printf("\n");
3392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
3402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
3412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   RESTORE_STACK;
3422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
3432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianopus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
3452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
3462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int coupled_size;
3472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int mono_size;
3482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
3502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   coupled_size = opus_encoder_get_size(2);
3512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   mono_size = opus_encoder_get_size(1);
3522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return align(sizeof(OpusMSEncoder))
3532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        + nb_coupled_streams * align(coupled_size)
3542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        + (nb_streams-nb_coupled_streams) * align(mono_size);
3552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
3562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianopus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
3582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
3592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int nb_streams;
3602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int nb_coupled_streams;
3612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 size;
3622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (mapping_family==0)
3642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (channels==1)
3662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
3672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         nb_streams=1;
3682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         nb_coupled_streams=0;
3692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else if (channels==2)
3702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
3712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         nb_streams=1;
3722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         nb_coupled_streams=1;
3732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else
3742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return 0;
3752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if (mapping_family==1 && channels<=8 && channels>=1)
3762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      nb_streams=vorbis_mappings[channels-1].nb_streams;
3782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
3792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if (mapping_family==255)
3802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      nb_streams=channels;
3822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      nb_coupled_streams=0;
3832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else
3842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return 0;
3852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
3862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (channels>2)
3872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
3892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
3902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return size;
3912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
3922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic int opus_multistream_encoder_init_impl(
3952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OpusMSEncoder *st,
3962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 Fs,
3972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int channels,
3982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int streams,
3992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int coupled_streams,
4002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      const unsigned char *mapping,
4012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int application,
4022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int surround
4032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
4042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
4052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int coupled_size;
4062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int mono_size;
4072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int i, ret;
4082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   char *ptr;
4092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
4112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
4122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
4132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->layout.nb_channels = channels;
4152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->layout.nb_streams = streams;
4162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->layout.nb_coupled_streams = coupled_streams;
4172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
4182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (!surround)
4192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->lfe_stream = -1;
4202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->bitrate_bps = OPUS_AUTO;
4212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->application = application;
4222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->variable_duration = OPUS_FRAMESIZE_ARG;
4232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (i=0;i<st->layout.nb_channels;i++)
4242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->layout.mapping[i] = mapping[i];
4252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
4262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
4272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ptr = (char*)st + align(sizeof(OpusMSEncoder));
4282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   coupled_size = opus_encoder_get_size(2);
4292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   mono_size = opus_encoder_get_size(1);
4302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (i=0;i<st->layout.nb_coupled_streams;i++)
4322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
4342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if(ret!=OPUS_OK)return ret;
4352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (i==st->lfe_stream)
4362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
4372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ptr += align(coupled_size);
4382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (;i<st->layout.nb_streams;i++)
4402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
4422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (i==st->lfe_stream)
4432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
4442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if(ret!=OPUS_OK)return ret;
4452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ptr += align(mono_size);
4462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (surround)
4482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OPUS_CLEAR(ms_get_preemph_mem(st), channels);
4502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OPUS_CLEAR(ms_get_window_mem(st), channels*120);
4512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->surround = surround;
4532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return OPUS_OK;
4542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
4552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_multistream_encoder_init(
4572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OpusMSEncoder *st,
4582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 Fs,
4592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int channels,
4602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int streams,
4612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int coupled_streams,
4622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      const unsigned char *mapping,
4632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int application
4642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
4652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
4662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
4672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
4682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_multistream_surround_encoder_init(
4702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OpusMSEncoder *st,
4712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 Fs,
4722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int channels,
4732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int mapping_family,
4742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int *streams,
4752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int *coupled_streams,
4762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      unsigned char *mapping,
4772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int application
4782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
4792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
4802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if ((channels>255) || (channels<1))
4812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
4822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->lfe_stream = -1;
4832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (mapping_family==0)
4842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (channels==1)
4862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
4872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *streams=1;
4882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *coupled_streams=0;
4892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         mapping[0]=0;
4902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else if (channels==2)
4912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
4922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *streams=1;
4932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *coupled_streams=1;
4942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         mapping[0]=0;
4952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         mapping[1]=1;
4962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else
4972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return OPUS_UNIMPLEMENTED;
4982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if (mapping_family==1 && channels<=8 && channels>=1)
4992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int i;
5012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *streams=vorbis_mappings[channels-1].nb_streams;
5022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
5032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<channels;i++)
5042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         mapping[i] = vorbis_mappings[channels-1].mapping[i];
5052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (channels>=6)
5062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         st->lfe_stream = *streams-1;
5072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if (mapping_family==255)
5082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int i;
5102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *streams=channels;
5112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *coupled_streams=0;
5122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for(i=0;i<channels;i++)
5132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         mapping[i] = i;
5142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else
5152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_UNIMPLEMENTED;
5162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
5172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         mapping, application, channels>2&&mapping_family==1);
5182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
5192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh VenkatasubramanianOpusMSEncoder *opus_multistream_encoder_create(
5212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 Fs,
5222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int channels,
5232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int streams,
5242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int coupled_streams,
5252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      const unsigned char *mapping,
5262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int application,
5272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int *error
5282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
5292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
5302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret;
5312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   OpusMSEncoder *st;
5322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
5332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
5342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (error)
5362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *error = OPUS_BAD_ARG;
5372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return NULL;
5382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
5402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st==NULL)
5412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (error)
5432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *error = OPUS_ALLOC_FAIL;
5442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return NULL;
5452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
5472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ret != OPUS_OK)
5482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_free(st);
5502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st = NULL;
5512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (error)
5532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *error = ret;
5542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return st;
5552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
5562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh VenkatasubramanianOpusMSEncoder *opus_multistream_surround_encoder_create(
5582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 Fs,
5592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int channels,
5602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int mapping_family,
5612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int *streams,
5622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int *coupled_streams,
5632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      unsigned char *mapping,
5642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int application,
5652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int *error
5662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
5672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
5682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret;
5692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   OpusMSEncoder *st;
5702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if ((channels>255) || (channels<1))
5712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (error)
5732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *error = OPUS_BAD_ARG;
5742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return NULL;
5752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
5772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st==NULL)
5782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (error)
5802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *error = OPUS_ALLOC_FAIL;
5812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return NULL;
5822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
5842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ret != OPUS_OK)
5852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_free(st);
5872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st = NULL;
5882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (error)
5902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *error = ret;
5912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return st;
5922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
5932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic void surround_rate_allocation(
5952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OpusMSEncoder *st,
5962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 *rate,
5972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int frame_size
5982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      )
5992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
6002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int i;
6012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 channel_rate;
6022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 Fs;
6032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   char *ptr;
6042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int stream_offset;
6052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int lfe_offset;
6062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int coupled_ratio; /* Q8 */
6072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int lfe_ratio;     /* Q8 */
6082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ptr = (char*)st + align(sizeof(OpusMSEncoder));
6102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
6112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st->bitrate_bps > st->layout.nb_channels*40000)
6132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      stream_offset = 20000;
6142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else
6152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
6162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   stream_offset += 60*(Fs/frame_size-50);
6172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* We start by giving each stream (coupled or uncoupled) the same bitrate.
6182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      This models the main saving of coupled channels over uncoupled. */
6192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* The LFE stream is an exception to the above and gets fewer bits. */
6202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   lfe_offset = 3500 + 60*(Fs/frame_size-50);
6212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Coupled streams get twice the mono rate after the first 20 kb/s. */
6222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   coupled_ratio = 512;
6232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
6242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   lfe_ratio = 32;
6252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Compute bitrate allocation between streams */
6272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st->bitrate_bps==OPUS_AUTO)
6282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
6292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      channel_rate = Fs+60*Fs/frame_size;
6302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
6312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
6322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      channel_rate = 300000;
6332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
6342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int nb_lfe;
6352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int nb_uncoupled;
6362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int nb_coupled;
6372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int total;
6382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      nb_lfe = (st->lfe_stream!=-1);
6392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      nb_coupled = st->layout.nb_coupled_streams;
6402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
6412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      total = (nb_uncoupled<<8)         /* mono */
6422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            + coupled_ratio*nb_coupled /* stereo */
6432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            + nb_lfe*lfe_ratio;
6442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
6452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
6462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef FIXED_POINT
6472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
6482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
6492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 bonus;
6502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      bonus = 60*(Fs/frame_size-50);
6512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      channel_rate += bonus;
6522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
6532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
6542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (i=0;i<st->layout.nb_streams;i++)
6562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
6572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (i<st->layout.nb_coupled_streams)
6582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
6592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else if (i!=st->lfe_stream)
6602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         rate[i] = stream_offset+channel_rate;
6612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else
6622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
6632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
6642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
6652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/* Max size in case the encoder decides to return three frames */
6672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#define MS_FRAME_TMP (3*1275+7)
6682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic int opus_multistream_encode_native
6692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian(
6702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    OpusMSEncoder *st,
6712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    opus_copy_channel_in_func copy_channel_in,
6722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    const void *pcm,
6732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    int analysis_frame_size,
6742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    unsigned char *data,
6752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    opus_int32 max_data_bytes,
6762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    int lsb_depth,
6772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    downmix_func downmix
6782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
6792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
6802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 Fs;
6812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int coupled_size;
6822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int mono_size;
6832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int s;
6842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   char *ptr;
6852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int tot_size;
6862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_val16, buf);
6872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_val16, bandSMR);
6882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   unsigned char tmp_data[MS_FRAME_TMP];
6892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   OpusRepacketizer rp;
6902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 vbr;
6912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const CELTMode *celt_mode;
6922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 bitrates[256];
6932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 bandLogE[42];
6942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val32 *mem = NULL;
6952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val32 *preemph_mem=NULL;
6962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int frame_size;
6972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC_STACK;
6982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st->surround)
7002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      preemph_mem = ms_get_preemph_mem(st);
7022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      mem = ms_get_window_mem(st);
7032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ptr = (char*)st + align(sizeof(OpusMSEncoder));
7062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
7072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
7082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
7092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 delay_compensation;
7122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int channels;
7132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
7152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
7162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      delay_compensation -= Fs/400;
7172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      frame_size = compute_frame_size(pcm, analysis_frame_size,
7182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            st->variable_duration, channels, Fs, st->bitrate_bps,
7192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            delay_compensation, downmix
7202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef DISABLE_FLOAT_API
7212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            , st->subframe_mem
7222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
7232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            );
7242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (400*frame_size < Fs)
7272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      RESTORE_STACK;
7292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
7302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Validate frame_size before using it to allocate stack space.
7322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      This mirrors the checks in opus_encode[_float](). */
7332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (400*frame_size != Fs && 200*frame_size != Fs &&
7342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       100*frame_size != Fs &&  50*frame_size != Fs &&
7352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        25*frame_size != Fs &&  50*frame_size != 3*Fs)
7362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      RESTORE_STACK;
7382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
7392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(buf, 2*frame_size, opus_val16);
7412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   coupled_size = opus_encoder_get_size(2);
7422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   mono_size = opus_encoder_get_size(1);
7432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
7452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st->surround)
7462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in);
7482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (max_data_bytes < 4*st->layout.nb_streams-1)
7512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      RESTORE_STACK;
7532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BUFFER_TOO_SMALL;
7542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Compute bitrate allocation between streams (this could be a lot better) */
7572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   surround_rate_allocation(st, bitrates, frame_size);
7582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (!vbr)
7602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      max_data_bytes = IMIN(max_data_bytes, 3*st->bitrate_bps/(3*8*Fs/frame_size));
7612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ptr = (char*)st + align(sizeof(OpusMSEncoder));
7632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (s=0;s<st->layout.nb_streams;s++)
7642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OpusEncoder *enc;
7662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      enc = (OpusEncoder*)ptr;
7672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (s < st->layout.nb_coupled_streams)
7682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ptr += align(coupled_size);
7692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else
7702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ptr += align(mono_size);
7712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
7722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (st->surround)
7732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
7742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_int32 equiv_rate;
7752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         equiv_rate = st->bitrate_bps;
7762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (frame_size*50 < Fs)
7772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels;
7782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (equiv_rate > 10000*st->layout.nb_channels)
7792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
7802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         else if (equiv_rate > 7000*st->layout.nb_channels)
7812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
7822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         else if (equiv_rate > 5000*st->layout.nb_channels)
7832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
7842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         else
7852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
7862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (s < st->layout.nb_coupled_streams)
7872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
7882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            /* To preserve the spatial image, force stereo CELT on coupled streams */
7892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
7902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
7912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
7922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
7932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ptr = (char*)st + align(sizeof(OpusMSEncoder));
7962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Counting ToC */
7972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   tot_size = 0;
7982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (s=0;s<st->layout.nb_streams;s++)
7992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OpusEncoder *enc;
8012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int len;
8022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int curr_max;
8032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int c1, c2;
8042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_repacketizer_init(&rp);
8062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      enc = (OpusEncoder*)ptr;
8072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (s < st->layout.nb_coupled_streams)
8082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
8092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int i;
8102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int left, right;
8112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         left = get_left_channel(&st->layout, s, -1);
8122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         right = get_right_channel(&st->layout, s, -1);
8132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         (*copy_channel_in)(buf, 2,
8142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            pcm, st->layout.nb_channels, left, frame_size);
8152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         (*copy_channel_in)(buf+1, 2,
8162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            pcm, st->layout.nb_channels, right, frame_size);
8172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ptr += align(coupled_size);
8182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (st->surround)
8192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
8202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            for (i=0;i<21;i++)
8212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            {
8222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               bandLogE[i] = bandSMR[21*left+i];
8232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               bandLogE[21+i] = bandSMR[21*right+i];
8242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            }
8252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
8262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         c1 = left;
8272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         c2 = right;
8282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else {
8292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int i;
8302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int chan = get_mono_channel(&st->layout, s, -1);
8312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         (*copy_channel_in)(buf, 1,
8322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            pcm, st->layout.nb_channels, chan, frame_size);
8332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ptr += align(mono_size);
8342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (st->surround)
8352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
8362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            for (i=0;i<21;i++)
8372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               bandLogE[i] = bandSMR[21*chan+i];
8382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
8392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         c1 = chan;
8402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         c2 = -1;
8412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
8422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (st->surround)
8432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
8442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* number of bytes left (+Toc) */
8452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      curr_max = max_data_bytes - tot_size;
8462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Reserve three bytes for the last stream and four for the others */
8472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
8482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      curr_max = IMIN(curr_max,MS_FRAME_TMP);
8492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (!vbr && s == st->layout.nb_streams-1)
8502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
8512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
8522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix);
8532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (len<0)
8542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
8552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         RESTORE_STACK;
8562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return len;
8572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
8582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* We need to use the repacketizer to add the self-delimiting lengths
8592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         while taking into account the fact that the encoder can now return
8602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         more than one frame at a time (e.g. 60 ms CELT-only) */
8612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_repacketizer_cat(&rp, tmp_data, len);
8622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
8632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1);
8642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      data += len;
8652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      tot_size += len;
8662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
8672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /*printf("\n");*/
8682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   RESTORE_STACK;
8692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return tot_size;
8702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
8712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#if !defined(DISABLE_FLOAT_API)
8732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic void opus_copy_channel_in_float(
8742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  opus_val16 *dst,
8752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int dst_stride,
8762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  const void *src,
8772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int src_stride,
8782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int src_channel,
8792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int frame_size
8802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
8812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
8822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const float *float_src;
8832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 i;
8842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   float_src = (const float *)src;
8852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (i=0;i<frame_size;i++)
8862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#if defined(FIXED_POINT)
8872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
8882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
8892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      dst[i*dst_stride] = float_src[i*src_stride+src_channel];
8902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
8912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
8922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
8932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic void opus_copy_channel_in_short(
8952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  opus_val16 *dst,
8962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int dst_stride,
8972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  const void *src,
8982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int src_stride,
8992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int src_channel,
9002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  int frame_size
9012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
9022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const opus_int16 *short_src;
9042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 i;
9052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   short_src = (const opus_int16 *)src;
9062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (i=0;i<frame_size;i++)
9072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#if defined(FIXED_POINT)
9082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      dst[i*dst_stride] = short_src[i*src_stride+src_channel];
9092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
9102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
9112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
9122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
9132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef FIXED_POINT
9162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_multistream_encode(
9172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    OpusMSEncoder *st,
9182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    const opus_val16 *pcm,
9192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    int frame_size,
9202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    unsigned char *data,
9212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    opus_int32 max_data_bytes
9222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
9232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return opus_multistream_encode_native(st, opus_copy_channel_in_short,
9252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pcm, frame_size, data, max_data_bytes, 16, downmix_int);
9262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
9272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef DISABLE_FLOAT_API
9292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_multistream_encode_float(
9302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    OpusMSEncoder *st,
9312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    const float *pcm,
9322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    int frame_size,
9332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    unsigned char *data,
9342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    opus_int32 max_data_bytes
9352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
9362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return opus_multistream_encode_native(st, opus_copy_channel_in_float,
9382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pcm, frame_size, data, max_data_bytes, 16, downmix_float);
9392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
9402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
9412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
9432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_multistream_encode_float
9452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian(
9462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    OpusMSEncoder *st,
9472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    const opus_val16 *pcm,
9482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    int frame_size,
9492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    unsigned char *data,
9502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    opus_int32 max_data_bytes
9512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
9522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return opus_multistream_encode_native(st, opus_copy_channel_in_float,
9542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pcm, frame_size, data, max_data_bytes, 24, downmix_float);
9552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
9562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_multistream_encode(
9582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    OpusMSEncoder *st,
9592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    const opus_int16 *pcm,
9602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    int frame_size,
9612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    unsigned char *data,
9622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    opus_int32 max_data_bytes
9632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian)
9642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return opus_multistream_encode_native(st, opus_copy_channel_in_short,
9662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pcm, frame_size, data, max_data_bytes, 16, downmix_int);
9672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
9682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
9692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
9712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_list ap;
9732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int coupled_size, mono_size;
9742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   char *ptr;
9752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret = OPUS_OK;
9762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_start(ap, request);
9782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   coupled_size = opus_encoder_get_size(2);
9802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   mono_size = opus_encoder_get_size(1);
9812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ptr = (char*)st + align(sizeof(OpusMSEncoder));
9822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   switch (request)
9832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_BITRATE_REQUEST:
9852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 value = va_arg(ap, opus_int32);
9872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
9882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
9892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_arg;
9902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
9912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->bitrate_bps = value;
9922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
9932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
9942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_BITRATE_REQUEST:
9952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int s;
9972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 *value = va_arg(ap, opus_int32*);
9982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (!value)
9992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
10002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_arg;
10012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
10022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *value = 0;
10032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (s=0;s<st->layout.nb_streams;s++)
10042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
10052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_int32 rate;
10062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OpusEncoder *enc;
10072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         enc = (OpusEncoder*)ptr;
10082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (s < st->layout.nb_coupled_streams)
10092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ptr += align(coupled_size);
10102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         else
10112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ptr += align(mono_size);
10122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_encoder_ctl(enc, request, &rate);
10132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *value += rate;
10142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
10152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
10162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
10172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_LSB_DEPTH_REQUEST:
10182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_VBR_REQUEST:
10192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_APPLICATION_REQUEST:
10202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_BANDWIDTH_REQUEST:
10212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_COMPLEXITY_REQUEST:
10222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
10232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_DTX_REQUEST:
10242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_VOICE_RATIO_REQUEST:
10252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_VBR_CONSTRAINT_REQUEST:
10262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_SIGNAL_REQUEST:
10272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_LOOKAHEAD_REQUEST:
10282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_SAMPLE_RATE_REQUEST:
10292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_INBAND_FEC_REQUEST:
10302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_FORCE_CHANNELS_REQUEST:
10312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_PREDICTION_DISABLED_REQUEST:
10322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
10332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OpusEncoder *enc;
10342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* For int32* GET params, just query the first stream */
10352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 *value = va_arg(ap, opus_int32*);
10362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      enc = (OpusEncoder*)ptr;
10372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ret = opus_encoder_ctl(enc, request, value);
10382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
10392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
10402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_FINAL_RANGE_REQUEST:
10412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
10422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int s;
10432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_uint32 *value = va_arg(ap, opus_uint32*);
10442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_uint32 tmp;
10452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (!value)
10462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
10472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_arg;
10482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
10492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *value=0;
10502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (s=0;s<st->layout.nb_streams;s++)
10512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
10522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OpusEncoder *enc;
10532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         enc = (OpusEncoder*)ptr;
10542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (s < st->layout.nb_coupled_streams)
10552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ptr += align(coupled_size);
10562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         else
10572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ptr += align(mono_size);
10582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ret = opus_encoder_ctl(enc, request, &tmp);
10592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (ret != OPUS_OK) break;
10602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *value ^= tmp;
10612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
10622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
10632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
10642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_LSB_DEPTH_REQUEST:
10652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_COMPLEXITY_REQUEST:
10662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_VBR_REQUEST:
10672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_VBR_CONSTRAINT_REQUEST:
10682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_MAX_BANDWIDTH_REQUEST:
10692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_BANDWIDTH_REQUEST:
10702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_SIGNAL_REQUEST:
10712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_APPLICATION_REQUEST:
10722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_INBAND_FEC_REQUEST:
10732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
10742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_DTX_REQUEST:
10752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_FORCE_MODE_REQUEST:
10762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_FORCE_CHANNELS_REQUEST:
10772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_PREDICTION_DISABLED_REQUEST:
10782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
10792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int s;
10802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* This works for int32 params */
10812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 value = va_arg(ap, opus_int32);
10822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (s=0;s<st->layout.nb_streams;s++)
10832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
10842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OpusEncoder *enc;
10852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
10862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         enc = (OpusEncoder*)ptr;
10872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (s < st->layout.nb_coupled_streams)
10882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ptr += align(coupled_size);
10892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         else
10902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ptr += align(mono_size);
10912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ret = opus_encoder_ctl(enc, request, value);
10922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (ret != OPUS_OK)
10932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            break;
10942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
10952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
10962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
10972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
10982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
10992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int s;
11002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 stream_id;
11012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OpusEncoder **value;
11022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      stream_id = va_arg(ap, opus_int32);
11032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (stream_id<0 || stream_id >= st->layout.nb_streams)
11042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ret = OPUS_BAD_ARG;
11052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      value = va_arg(ap, OpusEncoder**);
11062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (!value)
11072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
11082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_arg;
11092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
11102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (s=0;s<stream_id;s++)
11112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
11122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (s < st->layout.nb_coupled_streams)
11132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ptr += align(coupled_size);
11142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         else
11152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ptr += align(mono_size);
11162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
11172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *value = (OpusEncoder*)ptr;
11182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
11192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
11202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
11212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
11222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       opus_int32 value = va_arg(ap, opus_int32);
11232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       st->variable_duration = value;
11242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
11252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
11262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
11272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
11282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       opus_int32 *value = va_arg(ap, opus_int32*);
11292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       if (!value)
11302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       {
11312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian          goto bad_arg;
11322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       }
11332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       *value = st->variable_duration;
11342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
11352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
11362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_RESET_STATE:
11372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
11382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int s;
11392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
11402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (st->surround)
11412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
11422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
11432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
11442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
11452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (s=0;s<st->layout.nb_streams;s++)
11462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
11472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OpusEncoder *enc;
11482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         enc = (OpusEncoder*)ptr;
11492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (s < st->layout.nb_coupled_streams)
11502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ptr += align(coupled_size);
11512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         else
11522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ptr += align(mono_size);
11532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ret = opus_encoder_ctl(enc, OPUS_RESET_STATE);
11542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (ret != OPUS_OK)
11552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            break;
11562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
11572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
11582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
11592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   default:
11602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ret = OPUS_UNIMPLEMENTED;
11612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
11622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
11632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_end(ap);
11652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return ret;
11662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianbad_arg:
11672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_end(ap);
11682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return OPUS_BAD_ARG;
11692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
11702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianvoid opus_multistream_encoder_destroy(OpusMSEncoder *st)
11722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
11732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    opus_free(st);
11742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1175