1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libopus/src/opus_multistream_encoder.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1174 @@ 1.4 +/* Copyright (c) 2011 Xiph.Org Foundation 1.5 + Written by Jean-Marc Valin */ 1.6 +/* 1.7 + Redistribution and use in source and binary forms, with or without 1.8 + modification, are permitted provided that the following conditions 1.9 + are met: 1.10 + 1.11 + - Redistributions of source code must retain the above copyright 1.12 + notice, this list of conditions and the following disclaimer. 1.13 + 1.14 + - Redistributions in binary form must reproduce the above copyright 1.15 + notice, this list of conditions and the following disclaimer in the 1.16 + documentation and/or other materials provided with the distribution. 1.17 + 1.18 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.19 + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.20 + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.21 + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 1.22 + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1.23 + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 1.24 + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 1.25 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 1.26 + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 1.27 + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1.28 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.29 +*/ 1.30 + 1.31 +#ifdef HAVE_CONFIG_H 1.32 +#include "config.h" 1.33 +#endif 1.34 + 1.35 +#include "opus_multistream.h" 1.36 +#include "opus.h" 1.37 +#include "opus_private.h" 1.38 +#include "stack_alloc.h" 1.39 +#include <stdarg.h> 1.40 +#include "float_cast.h" 1.41 +#include "os_support.h" 1.42 +#include "mathops.h" 1.43 +#include "mdct.h" 1.44 +#include "modes.h" 1.45 +#include "bands.h" 1.46 +#include "quant_bands.h" 1.47 + 1.48 +typedef struct { 1.49 + int nb_streams; 1.50 + int nb_coupled_streams; 1.51 + unsigned char mapping[8]; 1.52 +} VorbisLayout; 1.53 + 1.54 +/* Index is nb_channel-1*/ 1.55 +static const VorbisLayout vorbis_mappings[8] = { 1.56 + {1, 0, {0}}, /* 1: mono */ 1.57 + {1, 1, {0, 1}}, /* 2: stereo */ 1.58 + {2, 1, {0, 2, 1}}, /* 3: 1-d surround */ 1.59 + {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */ 1.60 + {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */ 1.61 + {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */ 1.62 + {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */ 1.63 + {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */ 1.64 +}; 1.65 + 1.66 +typedef void (*opus_copy_channel_in_func)( 1.67 + opus_val16 *dst, 1.68 + int dst_stride, 1.69 + const void *src, 1.70 + int src_stride, 1.71 + int src_channel, 1.72 + int frame_size 1.73 +); 1.74 + 1.75 +struct OpusMSEncoder { 1.76 + ChannelLayout layout; 1.77 + int lfe_stream; 1.78 + int application; 1.79 + int variable_duration; 1.80 + int surround; 1.81 + opus_int32 bitrate_bps; 1.82 + float subframe_mem[3]; 1.83 + /* Encoder states go here */ 1.84 + /* then opus_val32 window_mem[channels*120]; */ 1.85 + /* then opus_val32 preemph_mem[channels]; */ 1.86 +}; 1.87 + 1.88 +static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st) 1.89 +{ 1.90 + int s; 1.91 + char *ptr; 1.92 + int coupled_size, mono_size; 1.93 + 1.94 + coupled_size = opus_encoder_get_size(2); 1.95 + mono_size = opus_encoder_get_size(1); 1.96 + ptr = (char*)st + align(sizeof(OpusMSEncoder)); 1.97 + for (s=0;s<st->layout.nb_streams;s++) 1.98 + { 1.99 + if (s < st->layout.nb_coupled_streams) 1.100 + ptr += align(coupled_size); 1.101 + else 1.102 + ptr += align(mono_size); 1.103 + } 1.104 + return (opus_val32*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32)); 1.105 +} 1.106 + 1.107 +static opus_val32 *ms_get_window_mem(OpusMSEncoder *st) 1.108 +{ 1.109 + int s; 1.110 + char *ptr; 1.111 + int coupled_size, mono_size; 1.112 + 1.113 + coupled_size = opus_encoder_get_size(2); 1.114 + mono_size = opus_encoder_get_size(1); 1.115 + ptr = (char*)st + align(sizeof(OpusMSEncoder)); 1.116 + for (s=0;s<st->layout.nb_streams;s++) 1.117 + { 1.118 + if (s < st->layout.nb_coupled_streams) 1.119 + ptr += align(coupled_size); 1.120 + else 1.121 + ptr += align(mono_size); 1.122 + } 1.123 + return (opus_val32*)ptr; 1.124 +} 1.125 + 1.126 +static int validate_encoder_layout(const ChannelLayout *layout) 1.127 +{ 1.128 + int s; 1.129 + for (s=0;s<layout->nb_streams;s++) 1.130 + { 1.131 + if (s < layout->nb_coupled_streams) 1.132 + { 1.133 + if (get_left_channel(layout, s, -1)==-1) 1.134 + return 0; 1.135 + if (get_right_channel(layout, s, -1)==-1) 1.136 + return 0; 1.137 + } else { 1.138 + if (get_mono_channel(layout, s, -1)==-1) 1.139 + return 0; 1.140 + } 1.141 + } 1.142 + return 1; 1.143 +} 1.144 + 1.145 +static void channel_pos(int channels, int pos[8]) 1.146 +{ 1.147 + /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */ 1.148 + if (channels==4) 1.149 + { 1.150 + pos[0]=1; 1.151 + pos[1]=3; 1.152 + pos[2]=1; 1.153 + pos[3]=3; 1.154 + } else if (channels==3||channels==5||channels==6) 1.155 + { 1.156 + pos[0]=1; 1.157 + pos[1]=2; 1.158 + pos[2]=3; 1.159 + pos[3]=1; 1.160 + pos[4]=3; 1.161 + pos[5]=0; 1.162 + } else if (channels==7) 1.163 + { 1.164 + pos[0]=1; 1.165 + pos[1]=2; 1.166 + pos[2]=3; 1.167 + pos[3]=1; 1.168 + pos[4]=3; 1.169 + pos[5]=2; 1.170 + pos[6]=0; 1.171 + } else if (channels==8) 1.172 + { 1.173 + pos[0]=1; 1.174 + pos[1]=2; 1.175 + pos[2]=3; 1.176 + pos[3]=1; 1.177 + pos[4]=3; 1.178 + pos[5]=1; 1.179 + pos[6]=3; 1.180 + pos[7]=0; 1.181 + } 1.182 +} 1.183 + 1.184 +#if 1 1.185 +/* Computes a rough approximation of log2(2^a + 2^b) */ 1.186 +static opus_val16 logSum(opus_val16 a, opus_val16 b) 1.187 +{ 1.188 + opus_val16 max; 1.189 + opus_val32 diff; 1.190 + opus_val16 frac; 1.191 + static const opus_val16 diff_table[17] = { 1.192 + QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT), 1.193 + QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT), 1.194 + QCONST16(0.0028123f, DB_SHIFT) 1.195 + }; 1.196 + int low; 1.197 + if (a>b) 1.198 + { 1.199 + max = a; 1.200 + diff = SUB32(EXTEND32(a),EXTEND32(b)); 1.201 + } else { 1.202 + max = b; 1.203 + diff = SUB32(EXTEND32(b),EXTEND32(a)); 1.204 + } 1.205 + if (diff >= QCONST16(8.f, DB_SHIFT)) 1.206 + return max; 1.207 +#ifdef FIXED_POINT 1.208 + low = SHR32(diff, DB_SHIFT-1); 1.209 + frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT); 1.210 +#else 1.211 + low = (int)floor(2*diff); 1.212 + frac = 2*diff - low; 1.213 +#endif 1.214 + return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low])); 1.215 +} 1.216 +#else 1.217 +opus_val16 logSum(opus_val16 a, opus_val16 b) 1.218 +{ 1.219 + return log2(pow(4, a)+ pow(4, b))/2; 1.220 +} 1.221 +#endif 1.222 + 1.223 +void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem, 1.224 + int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in 1.225 +) 1.226 +{ 1.227 + int c; 1.228 + int i; 1.229 + int LM; 1.230 + int pos[8] = {0}; 1.231 + int upsample; 1.232 + int frame_size; 1.233 + opus_val16 channel_offset; 1.234 + opus_val32 bandE[21]; 1.235 + opus_val16 maskLogE[3][21]; 1.236 + VARDECL(opus_val32, in); 1.237 + VARDECL(opus_val16, x); 1.238 + VARDECL(opus_val32, freq); 1.239 + SAVE_STACK; 1.240 + 1.241 + upsample = resampling_factor(rate); 1.242 + frame_size = len*upsample; 1.243 + 1.244 + for (LM=0;LM<celt_mode->maxLM;LM++) 1.245 + if (celt_mode->shortMdctSize<<LM==frame_size) 1.246 + break; 1.247 + 1.248 + ALLOC(in, frame_size+overlap, opus_val32); 1.249 + ALLOC(x, len, opus_val16); 1.250 + ALLOC(freq, frame_size, opus_val32); 1.251 + 1.252 + channel_pos(channels, pos); 1.253 + 1.254 + for (c=0;c<3;c++) 1.255 + for (i=0;i<21;i++) 1.256 + maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT); 1.257 + 1.258 + for (c=0;c<channels;c++) 1.259 + { 1.260 + OPUS_COPY(in, mem+c*overlap, overlap); 1.261 + (*copy_channel_in)(x, 1, pcm, channels, c, len); 1.262 + celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0); 1.263 + clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1); 1.264 + if (upsample != 1) 1.265 + { 1.266 + int bound = len; 1.267 + for (i=0;i<bound;i++) 1.268 + freq[i] *= upsample; 1.269 + for (;i<frame_size;i++) 1.270 + freq[i] = 0; 1.271 + } 1.272 + 1.273 + compute_band_energies(celt_mode, freq, bandE, 21, 1, 1<<LM); 1.274 + amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1); 1.275 + /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */ 1.276 + for (i=1;i<21;i++) 1.277 + bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT)); 1.278 + for (i=19;i>=0;i--) 1.279 + bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT)); 1.280 + if (pos[c]==1) 1.281 + { 1.282 + for (i=0;i<21;i++) 1.283 + maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]); 1.284 + } else if (pos[c]==3) 1.285 + { 1.286 + for (i=0;i<21;i++) 1.287 + maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]); 1.288 + } else if (pos[c]==2) 1.289 + { 1.290 + for (i=0;i<21;i++) 1.291 + { 1.292 + maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); 1.293 + maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); 1.294 + } 1.295 + } 1.296 +#if 0 1.297 + for (i=0;i<21;i++) 1.298 + printf("%f ", bandLogE[21*c+i]); 1.299 + float sum=0; 1.300 + for (i=0;i<21;i++) 1.301 + sum += bandLogE[21*c+i]; 1.302 + printf("%f ", sum/21); 1.303 +#endif 1.304 + OPUS_COPY(mem+c*overlap, in+frame_size, overlap); 1.305 + } 1.306 + for (i=0;i<21;i++) 1.307 + maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]); 1.308 + channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1))); 1.309 + for (c=0;c<3;c++) 1.310 + for (i=0;i<21;i++) 1.311 + maskLogE[c][i] += channel_offset; 1.312 +#if 0 1.313 + for (c=0;c<3;c++) 1.314 + { 1.315 + for (i=0;i<21;i++) 1.316 + printf("%f ", maskLogE[c][i]); 1.317 + } 1.318 +#endif 1.319 + for (c=0;c<channels;c++) 1.320 + { 1.321 + opus_val16 *mask; 1.322 + if (pos[c]!=0) 1.323 + { 1.324 + mask = &maskLogE[pos[c]-1][0]; 1.325 + for (i=0;i<21;i++) 1.326 + bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i]; 1.327 + } else { 1.328 + for (i=0;i<21;i++) 1.329 + bandLogE[21*c+i] = 0; 1.330 + } 1.331 +#if 0 1.332 + for (i=0;i<21;i++) 1.333 + printf("%f ", bandLogE[21*c+i]); 1.334 + printf("\n"); 1.335 +#endif 1.336 +#if 0 1.337 + float sum=0; 1.338 + for (i=0;i<21;i++) 1.339 + sum += bandLogE[21*c+i]; 1.340 + printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT)); 1.341 + printf("\n"); 1.342 +#endif 1.343 + } 1.344 + RESTORE_STACK; 1.345 +} 1.346 + 1.347 +opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams) 1.348 +{ 1.349 + int coupled_size; 1.350 + int mono_size; 1.351 + 1.352 + if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0; 1.353 + coupled_size = opus_encoder_get_size(2); 1.354 + mono_size = opus_encoder_get_size(1); 1.355 + return align(sizeof(OpusMSEncoder)) 1.356 + + nb_coupled_streams * align(coupled_size) 1.357 + + (nb_streams-nb_coupled_streams) * align(mono_size); 1.358 +} 1.359 + 1.360 +opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family) 1.361 +{ 1.362 + int nb_streams; 1.363 + int nb_coupled_streams; 1.364 + opus_int32 size; 1.365 + 1.366 + if (mapping_family==0) 1.367 + { 1.368 + if (channels==1) 1.369 + { 1.370 + nb_streams=1; 1.371 + nb_coupled_streams=0; 1.372 + } else if (channels==2) 1.373 + { 1.374 + nb_streams=1; 1.375 + nb_coupled_streams=1; 1.376 + } else 1.377 + return 0; 1.378 + } else if (mapping_family==1 && channels<=8 && channels>=1) 1.379 + { 1.380 + nb_streams=vorbis_mappings[channels-1].nb_streams; 1.381 + nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams; 1.382 + } else if (mapping_family==255) 1.383 + { 1.384 + nb_streams=channels; 1.385 + nb_coupled_streams=0; 1.386 + } else 1.387 + return 0; 1.388 + size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams); 1.389 + if (channels>2) 1.390 + { 1.391 + size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32)); 1.392 + } 1.393 + return size; 1.394 +} 1.395 + 1.396 + 1.397 +static int opus_multistream_encoder_init_impl( 1.398 + OpusMSEncoder *st, 1.399 + opus_int32 Fs, 1.400 + int channels, 1.401 + int streams, 1.402 + int coupled_streams, 1.403 + const unsigned char *mapping, 1.404 + int application, 1.405 + int surround 1.406 +) 1.407 +{ 1.408 + int coupled_size; 1.409 + int mono_size; 1.410 + int i, ret; 1.411 + char *ptr; 1.412 + 1.413 + if ((channels>255) || (channels<1) || (coupled_streams>streams) || 1.414 + (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) 1.415 + return OPUS_BAD_ARG; 1.416 + 1.417 + st->layout.nb_channels = channels; 1.418 + st->layout.nb_streams = streams; 1.419 + st->layout.nb_coupled_streams = coupled_streams; 1.420 + st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0; 1.421 + if (!surround) 1.422 + st->lfe_stream = -1; 1.423 + st->bitrate_bps = OPUS_AUTO; 1.424 + st->application = application; 1.425 + st->variable_duration = OPUS_FRAMESIZE_ARG; 1.426 + for (i=0;i<st->layout.nb_channels;i++) 1.427 + st->layout.mapping[i] = mapping[i]; 1.428 + if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout)) 1.429 + return OPUS_BAD_ARG; 1.430 + ptr = (char*)st + align(sizeof(OpusMSEncoder)); 1.431 + coupled_size = opus_encoder_get_size(2); 1.432 + mono_size = opus_encoder_get_size(1); 1.433 + 1.434 + for (i=0;i<st->layout.nb_coupled_streams;i++) 1.435 + { 1.436 + ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application); 1.437 + if(ret!=OPUS_OK)return ret; 1.438 + if (i==st->lfe_stream) 1.439 + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1)); 1.440 + ptr += align(coupled_size); 1.441 + } 1.442 + for (;i<st->layout.nb_streams;i++) 1.443 + { 1.444 + ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application); 1.445 + if (i==st->lfe_stream) 1.446 + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1)); 1.447 + if(ret!=OPUS_OK)return ret; 1.448 + ptr += align(mono_size); 1.449 + } 1.450 + if (surround) 1.451 + { 1.452 + OPUS_CLEAR(ms_get_preemph_mem(st), channels); 1.453 + OPUS_CLEAR(ms_get_window_mem(st), channels*120); 1.454 + } 1.455 + st->surround = surround; 1.456 + return OPUS_OK; 1.457 +} 1.458 + 1.459 +int opus_multistream_encoder_init( 1.460 + OpusMSEncoder *st, 1.461 + opus_int32 Fs, 1.462 + int channels, 1.463 + int streams, 1.464 + int coupled_streams, 1.465 + const unsigned char *mapping, 1.466 + int application 1.467 +) 1.468 +{ 1.469 + return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0); 1.470 +} 1.471 + 1.472 +int opus_multistream_surround_encoder_init( 1.473 + OpusMSEncoder *st, 1.474 + opus_int32 Fs, 1.475 + int channels, 1.476 + int mapping_family, 1.477 + int *streams, 1.478 + int *coupled_streams, 1.479 + unsigned char *mapping, 1.480 + int application 1.481 +) 1.482 +{ 1.483 + if ((channels>255) || (channels<1)) 1.484 + return OPUS_BAD_ARG; 1.485 + st->lfe_stream = -1; 1.486 + if (mapping_family==0) 1.487 + { 1.488 + if (channels==1) 1.489 + { 1.490 + *streams=1; 1.491 + *coupled_streams=0; 1.492 + mapping[0]=0; 1.493 + } else if (channels==2) 1.494 + { 1.495 + *streams=1; 1.496 + *coupled_streams=1; 1.497 + mapping[0]=0; 1.498 + mapping[1]=1; 1.499 + } else 1.500 + return OPUS_UNIMPLEMENTED; 1.501 + } else if (mapping_family==1 && channels<=8 && channels>=1) 1.502 + { 1.503 + int i; 1.504 + *streams=vorbis_mappings[channels-1].nb_streams; 1.505 + *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams; 1.506 + for (i=0;i<channels;i++) 1.507 + mapping[i] = vorbis_mappings[channels-1].mapping[i]; 1.508 + if (channels>=6) 1.509 + st->lfe_stream = *streams-1; 1.510 + } else if (mapping_family==255) 1.511 + { 1.512 + int i; 1.513 + *streams=channels; 1.514 + *coupled_streams=0; 1.515 + for(i=0;i<channels;i++) 1.516 + mapping[i] = i; 1.517 + } else 1.518 + return OPUS_UNIMPLEMENTED; 1.519 + return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams, 1.520 + mapping, application, channels>2&&mapping_family==1); 1.521 +} 1.522 + 1.523 +OpusMSEncoder *opus_multistream_encoder_create( 1.524 + opus_int32 Fs, 1.525 + int channels, 1.526 + int streams, 1.527 + int coupled_streams, 1.528 + const unsigned char *mapping, 1.529 + int application, 1.530 + int *error 1.531 +) 1.532 +{ 1.533 + int ret; 1.534 + OpusMSEncoder *st; 1.535 + if ((channels>255) || (channels<1) || (coupled_streams>streams) || 1.536 + (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) 1.537 + { 1.538 + if (error) 1.539 + *error = OPUS_BAD_ARG; 1.540 + return NULL; 1.541 + } 1.542 + st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams)); 1.543 + if (st==NULL) 1.544 + { 1.545 + if (error) 1.546 + *error = OPUS_ALLOC_FAIL; 1.547 + return NULL; 1.548 + } 1.549 + ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application); 1.550 + if (ret != OPUS_OK) 1.551 + { 1.552 + opus_free(st); 1.553 + st = NULL; 1.554 + } 1.555 + if (error) 1.556 + *error = ret; 1.557 + return st; 1.558 +} 1.559 + 1.560 +OpusMSEncoder *opus_multistream_surround_encoder_create( 1.561 + opus_int32 Fs, 1.562 + int channels, 1.563 + int mapping_family, 1.564 + int *streams, 1.565 + int *coupled_streams, 1.566 + unsigned char *mapping, 1.567 + int application, 1.568 + int *error 1.569 +) 1.570 +{ 1.571 + int ret; 1.572 + OpusMSEncoder *st; 1.573 + if ((channels>255) || (channels<1)) 1.574 + { 1.575 + if (error) 1.576 + *error = OPUS_BAD_ARG; 1.577 + return NULL; 1.578 + } 1.579 + st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family)); 1.580 + if (st==NULL) 1.581 + { 1.582 + if (error) 1.583 + *error = OPUS_ALLOC_FAIL; 1.584 + return NULL; 1.585 + } 1.586 + ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application); 1.587 + if (ret != OPUS_OK) 1.588 + { 1.589 + opus_free(st); 1.590 + st = NULL; 1.591 + } 1.592 + if (error) 1.593 + *error = ret; 1.594 + return st; 1.595 +} 1.596 + 1.597 +static void surround_rate_allocation( 1.598 + OpusMSEncoder *st, 1.599 + opus_int32 *rate, 1.600 + int frame_size 1.601 + ) 1.602 +{ 1.603 + int i; 1.604 + opus_int32 channel_rate; 1.605 + opus_int32 Fs; 1.606 + char *ptr; 1.607 + int stream_offset; 1.608 + int lfe_offset; 1.609 + int coupled_ratio; /* Q8 */ 1.610 + int lfe_ratio; /* Q8 */ 1.611 + 1.612 + ptr = (char*)st + align(sizeof(OpusMSEncoder)); 1.613 + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs)); 1.614 + 1.615 + if (st->bitrate_bps > st->layout.nb_channels*40000) 1.616 + stream_offset = 20000; 1.617 + else 1.618 + stream_offset = st->bitrate_bps/st->layout.nb_channels/2; 1.619 + stream_offset += 60*(Fs/frame_size-50); 1.620 + /* We start by giving each stream (coupled or uncoupled) the same bitrate. 1.621 + This models the main saving of coupled channels over uncoupled. */ 1.622 + /* The LFE stream is an exception to the above and gets fewer bits. */ 1.623 + lfe_offset = 3500 + 60*(Fs/frame_size-50); 1.624 + /* Coupled streams get twice the mono rate after the first 20 kb/s. */ 1.625 + coupled_ratio = 512; 1.626 + /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */ 1.627 + lfe_ratio = 32; 1.628 + 1.629 + /* Compute bitrate allocation between streams */ 1.630 + if (st->bitrate_bps==OPUS_AUTO) 1.631 + { 1.632 + channel_rate = Fs+60*Fs/frame_size; 1.633 + } else if (st->bitrate_bps==OPUS_BITRATE_MAX) 1.634 + { 1.635 + channel_rate = 300000; 1.636 + } else { 1.637 + int nb_lfe; 1.638 + int nb_uncoupled; 1.639 + int nb_coupled; 1.640 + int total; 1.641 + nb_lfe = (st->lfe_stream!=-1); 1.642 + nb_coupled = st->layout.nb_coupled_streams; 1.643 + nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe; 1.644 + total = (nb_uncoupled<<8) /* mono */ 1.645 + + coupled_ratio*nb_coupled /* stereo */ 1.646 + + nb_lfe*lfe_ratio; 1.647 + channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total; 1.648 + } 1.649 +#ifndef FIXED_POINT 1.650 + if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50) 1.651 + { 1.652 + opus_int32 bonus; 1.653 + bonus = 60*(Fs/frame_size-50); 1.654 + channel_rate += bonus; 1.655 + } 1.656 +#endif 1.657 + 1.658 + for (i=0;i<st->layout.nb_streams;i++) 1.659 + { 1.660 + if (i<st->layout.nb_coupled_streams) 1.661 + rate[i] = stream_offset+(channel_rate*coupled_ratio>>8); 1.662 + else if (i!=st->lfe_stream) 1.663 + rate[i] = stream_offset+channel_rate; 1.664 + else 1.665 + rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8); 1.666 + } 1.667 +} 1.668 + 1.669 +/* Max size in case the encoder decides to return three frames */ 1.670 +#define MS_FRAME_TMP (3*1275+7) 1.671 +static int opus_multistream_encode_native 1.672 +( 1.673 + OpusMSEncoder *st, 1.674 + opus_copy_channel_in_func copy_channel_in, 1.675 + const void *pcm, 1.676 + int analysis_frame_size, 1.677 + unsigned char *data, 1.678 + opus_int32 max_data_bytes, 1.679 + int lsb_depth, 1.680 + downmix_func downmix 1.681 +) 1.682 +{ 1.683 + opus_int32 Fs; 1.684 + int coupled_size; 1.685 + int mono_size; 1.686 + int s; 1.687 + char *ptr; 1.688 + int tot_size; 1.689 + VARDECL(opus_val16, buf); 1.690 + VARDECL(opus_val16, bandSMR); 1.691 + unsigned char tmp_data[MS_FRAME_TMP]; 1.692 + OpusRepacketizer rp; 1.693 + opus_int32 vbr; 1.694 + const CELTMode *celt_mode; 1.695 + opus_int32 bitrates[256]; 1.696 + opus_val16 bandLogE[42]; 1.697 + opus_val32 *mem = NULL; 1.698 + opus_val32 *preemph_mem=NULL; 1.699 + int frame_size; 1.700 + ALLOC_STACK; 1.701 + 1.702 + if (st->surround) 1.703 + { 1.704 + preemph_mem = ms_get_preemph_mem(st); 1.705 + mem = ms_get_window_mem(st); 1.706 + } 1.707 + 1.708 + ptr = (char*)st + align(sizeof(OpusMSEncoder)); 1.709 + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs)); 1.710 + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr)); 1.711 + opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode)); 1.712 + 1.713 + { 1.714 + opus_int32 delay_compensation; 1.715 + int channels; 1.716 + 1.717 + channels = st->layout.nb_streams + st->layout.nb_coupled_streams; 1.718 + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation)); 1.719 + delay_compensation -= Fs/400; 1.720 + frame_size = compute_frame_size(pcm, analysis_frame_size, 1.721 + st->variable_duration, channels, Fs, st->bitrate_bps, 1.722 + delay_compensation, downmix 1.723 +#ifndef DISABLE_FLOAT_API 1.724 + , st->subframe_mem 1.725 +#endif 1.726 + ); 1.727 + } 1.728 + 1.729 + if (400*frame_size < Fs) 1.730 + { 1.731 + RESTORE_STACK; 1.732 + return OPUS_BAD_ARG; 1.733 + } 1.734 + /* Validate frame_size before using it to allocate stack space. 1.735 + This mirrors the checks in opus_encode[_float](). */ 1.736 + if (400*frame_size != Fs && 200*frame_size != Fs && 1.737 + 100*frame_size != Fs && 50*frame_size != Fs && 1.738 + 25*frame_size != Fs && 50*frame_size != 3*Fs) 1.739 + { 1.740 + RESTORE_STACK; 1.741 + return OPUS_BAD_ARG; 1.742 + } 1.743 + ALLOC(buf, 2*frame_size, opus_val16); 1.744 + coupled_size = opus_encoder_get_size(2); 1.745 + mono_size = opus_encoder_get_size(1); 1.746 + 1.747 + ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16); 1.748 + if (st->surround) 1.749 + { 1.750 + surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in); 1.751 + } 1.752 + 1.753 + if (max_data_bytes < 4*st->layout.nb_streams-1) 1.754 + { 1.755 + RESTORE_STACK; 1.756 + return OPUS_BUFFER_TOO_SMALL; 1.757 + } 1.758 + 1.759 + /* Compute bitrate allocation between streams (this could be a lot better) */ 1.760 + surround_rate_allocation(st, bitrates, frame_size); 1.761 + 1.762 + if (!vbr) 1.763 + max_data_bytes = IMIN(max_data_bytes, 3*st->bitrate_bps/(3*8*Fs/frame_size)); 1.764 + 1.765 + ptr = (char*)st + align(sizeof(OpusMSEncoder)); 1.766 + for (s=0;s<st->layout.nb_streams;s++) 1.767 + { 1.768 + OpusEncoder *enc; 1.769 + enc = (OpusEncoder*)ptr; 1.770 + if (s < st->layout.nb_coupled_streams) 1.771 + ptr += align(coupled_size); 1.772 + else 1.773 + ptr += align(mono_size); 1.774 + opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s])); 1.775 + if (st->surround) 1.776 + { 1.777 + opus_int32 equiv_rate; 1.778 + equiv_rate = st->bitrate_bps; 1.779 + if (frame_size*50 < Fs) 1.780 + equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels; 1.781 + if (equiv_rate > 10000*st->layout.nb_channels) 1.782 + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); 1.783 + else if (equiv_rate > 7000*st->layout.nb_channels) 1.784 + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND)); 1.785 + else if (equiv_rate > 5000*st->layout.nb_channels) 1.786 + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND)); 1.787 + else 1.788 + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND)); 1.789 + if (s < st->layout.nb_coupled_streams) 1.790 + { 1.791 + /* To preserve the spatial image, force stereo CELT on coupled streams */ 1.792 + opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY)); 1.793 + opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2)); 1.794 + } 1.795 + } 1.796 + } 1.797 + 1.798 + ptr = (char*)st + align(sizeof(OpusMSEncoder)); 1.799 + /* Counting ToC */ 1.800 + tot_size = 0; 1.801 + for (s=0;s<st->layout.nb_streams;s++) 1.802 + { 1.803 + OpusEncoder *enc; 1.804 + int len; 1.805 + int curr_max; 1.806 + int c1, c2; 1.807 + 1.808 + opus_repacketizer_init(&rp); 1.809 + enc = (OpusEncoder*)ptr; 1.810 + if (s < st->layout.nb_coupled_streams) 1.811 + { 1.812 + int i; 1.813 + int left, right; 1.814 + left = get_left_channel(&st->layout, s, -1); 1.815 + right = get_right_channel(&st->layout, s, -1); 1.816 + (*copy_channel_in)(buf, 2, 1.817 + pcm, st->layout.nb_channels, left, frame_size); 1.818 + (*copy_channel_in)(buf+1, 2, 1.819 + pcm, st->layout.nb_channels, right, frame_size); 1.820 + ptr += align(coupled_size); 1.821 + if (st->surround) 1.822 + { 1.823 + for (i=0;i<21;i++) 1.824 + { 1.825 + bandLogE[i] = bandSMR[21*left+i]; 1.826 + bandLogE[21+i] = bandSMR[21*right+i]; 1.827 + } 1.828 + } 1.829 + c1 = left; 1.830 + c2 = right; 1.831 + } else { 1.832 + int i; 1.833 + int chan = get_mono_channel(&st->layout, s, -1); 1.834 + (*copy_channel_in)(buf, 1, 1.835 + pcm, st->layout.nb_channels, chan, frame_size); 1.836 + ptr += align(mono_size); 1.837 + if (st->surround) 1.838 + { 1.839 + for (i=0;i<21;i++) 1.840 + bandLogE[i] = bandSMR[21*chan+i]; 1.841 + } 1.842 + c1 = chan; 1.843 + c2 = -1; 1.844 + } 1.845 + if (st->surround) 1.846 + opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE)); 1.847 + /* number of bytes left (+Toc) */ 1.848 + curr_max = max_data_bytes - tot_size; 1.849 + /* Reserve three bytes for the last stream and four for the others */ 1.850 + curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1); 1.851 + curr_max = IMIN(curr_max,MS_FRAME_TMP); 1.852 + if (!vbr && s == st->layout.nb_streams-1) 1.853 + opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size))); 1.854 + len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth, 1.855 + pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix); 1.856 + if (len<0) 1.857 + { 1.858 + RESTORE_STACK; 1.859 + return len; 1.860 + } 1.861 + /* We need to use the repacketizer to add the self-delimiting lengths 1.862 + while taking into account the fact that the encoder can now return 1.863 + more than one frame at a time (e.g. 60 ms CELT-only) */ 1.864 + opus_repacketizer_cat(&rp, tmp_data, len); 1.865 + len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), 1.866 + data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1); 1.867 + data += len; 1.868 + tot_size += len; 1.869 + } 1.870 + /*printf("\n");*/ 1.871 + RESTORE_STACK; 1.872 + return tot_size; 1.873 +} 1.874 + 1.875 +#if !defined(DISABLE_FLOAT_API) 1.876 +static void opus_copy_channel_in_float( 1.877 + opus_val16 *dst, 1.878 + int dst_stride, 1.879 + const void *src, 1.880 + int src_stride, 1.881 + int src_channel, 1.882 + int frame_size 1.883 +) 1.884 +{ 1.885 + const float *float_src; 1.886 + opus_int32 i; 1.887 + float_src = (const float *)src; 1.888 + for (i=0;i<frame_size;i++) 1.889 +#if defined(FIXED_POINT) 1.890 + dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]); 1.891 +#else 1.892 + dst[i*dst_stride] = float_src[i*src_stride+src_channel]; 1.893 +#endif 1.894 +} 1.895 +#endif 1.896 + 1.897 +static void opus_copy_channel_in_short( 1.898 + opus_val16 *dst, 1.899 + int dst_stride, 1.900 + const void *src, 1.901 + int src_stride, 1.902 + int src_channel, 1.903 + int frame_size 1.904 +) 1.905 +{ 1.906 + const opus_int16 *short_src; 1.907 + opus_int32 i; 1.908 + short_src = (const opus_int16 *)src; 1.909 + for (i=0;i<frame_size;i++) 1.910 +#if defined(FIXED_POINT) 1.911 + dst[i*dst_stride] = short_src[i*src_stride+src_channel]; 1.912 +#else 1.913 + dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel]; 1.914 +#endif 1.915 +} 1.916 + 1.917 + 1.918 +#ifdef FIXED_POINT 1.919 +int opus_multistream_encode( 1.920 + OpusMSEncoder *st, 1.921 + const opus_val16 *pcm, 1.922 + int frame_size, 1.923 + unsigned char *data, 1.924 + opus_int32 max_data_bytes 1.925 +) 1.926 +{ 1.927 + return opus_multistream_encode_native(st, opus_copy_channel_in_short, 1.928 + pcm, frame_size, data, max_data_bytes, 16, downmix_int); 1.929 +} 1.930 + 1.931 +#ifndef DISABLE_FLOAT_API 1.932 +int opus_multistream_encode_float( 1.933 + OpusMSEncoder *st, 1.934 + const float *pcm, 1.935 + int frame_size, 1.936 + unsigned char *data, 1.937 + opus_int32 max_data_bytes 1.938 +) 1.939 +{ 1.940 + return opus_multistream_encode_native(st, opus_copy_channel_in_float, 1.941 + pcm, frame_size, data, max_data_bytes, 16, downmix_float); 1.942 +} 1.943 +#endif 1.944 + 1.945 +#else 1.946 + 1.947 +int opus_multistream_encode_float 1.948 +( 1.949 + OpusMSEncoder *st, 1.950 + const opus_val16 *pcm, 1.951 + int frame_size, 1.952 + unsigned char *data, 1.953 + opus_int32 max_data_bytes 1.954 +) 1.955 +{ 1.956 + return opus_multistream_encode_native(st, opus_copy_channel_in_float, 1.957 + pcm, frame_size, data, max_data_bytes, 24, downmix_float); 1.958 +} 1.959 + 1.960 +int opus_multistream_encode( 1.961 + OpusMSEncoder *st, 1.962 + const opus_int16 *pcm, 1.963 + int frame_size, 1.964 + unsigned char *data, 1.965 + opus_int32 max_data_bytes 1.966 +) 1.967 +{ 1.968 + return opus_multistream_encode_native(st, opus_copy_channel_in_short, 1.969 + pcm, frame_size, data, max_data_bytes, 16, downmix_int); 1.970 +} 1.971 +#endif 1.972 + 1.973 +int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) 1.974 +{ 1.975 + va_list ap; 1.976 + int coupled_size, mono_size; 1.977 + char *ptr; 1.978 + int ret = OPUS_OK; 1.979 + 1.980 + va_start(ap, request); 1.981 + 1.982 + coupled_size = opus_encoder_get_size(2); 1.983 + mono_size = opus_encoder_get_size(1); 1.984 + ptr = (char*)st + align(sizeof(OpusMSEncoder)); 1.985 + switch (request) 1.986 + { 1.987 + case OPUS_SET_BITRATE_REQUEST: 1.988 + { 1.989 + opus_int32 value = va_arg(ap, opus_int32); 1.990 + if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX) 1.991 + { 1.992 + goto bad_arg; 1.993 + } 1.994 + st->bitrate_bps = value; 1.995 + } 1.996 + break; 1.997 + case OPUS_GET_BITRATE_REQUEST: 1.998 + { 1.999 + int s; 1.1000 + opus_int32 *value = va_arg(ap, opus_int32*); 1.1001 + if (!value) 1.1002 + { 1.1003 + goto bad_arg; 1.1004 + } 1.1005 + *value = 0; 1.1006 + for (s=0;s<st->layout.nb_streams;s++) 1.1007 + { 1.1008 + opus_int32 rate; 1.1009 + OpusEncoder *enc; 1.1010 + enc = (OpusEncoder*)ptr; 1.1011 + if (s < st->layout.nb_coupled_streams) 1.1012 + ptr += align(coupled_size); 1.1013 + else 1.1014 + ptr += align(mono_size); 1.1015 + opus_encoder_ctl(enc, request, &rate); 1.1016 + *value += rate; 1.1017 + } 1.1018 + } 1.1019 + break; 1.1020 + case OPUS_GET_LSB_DEPTH_REQUEST: 1.1021 + case OPUS_GET_VBR_REQUEST: 1.1022 + case OPUS_GET_APPLICATION_REQUEST: 1.1023 + case OPUS_GET_BANDWIDTH_REQUEST: 1.1024 + case OPUS_GET_COMPLEXITY_REQUEST: 1.1025 + case OPUS_GET_PACKET_LOSS_PERC_REQUEST: 1.1026 + case OPUS_GET_DTX_REQUEST: 1.1027 + case OPUS_GET_VOICE_RATIO_REQUEST: 1.1028 + case OPUS_GET_VBR_CONSTRAINT_REQUEST: 1.1029 + case OPUS_GET_SIGNAL_REQUEST: 1.1030 + case OPUS_GET_LOOKAHEAD_REQUEST: 1.1031 + case OPUS_GET_SAMPLE_RATE_REQUEST: 1.1032 + case OPUS_GET_INBAND_FEC_REQUEST: 1.1033 + case OPUS_GET_FORCE_CHANNELS_REQUEST: 1.1034 + case OPUS_GET_PREDICTION_DISABLED_REQUEST: 1.1035 + { 1.1036 + OpusEncoder *enc; 1.1037 + /* For int32* GET params, just query the first stream */ 1.1038 + opus_int32 *value = va_arg(ap, opus_int32*); 1.1039 + enc = (OpusEncoder*)ptr; 1.1040 + ret = opus_encoder_ctl(enc, request, value); 1.1041 + } 1.1042 + break; 1.1043 + case OPUS_GET_FINAL_RANGE_REQUEST: 1.1044 + { 1.1045 + int s; 1.1046 + opus_uint32 *value = va_arg(ap, opus_uint32*); 1.1047 + opus_uint32 tmp; 1.1048 + if (!value) 1.1049 + { 1.1050 + goto bad_arg; 1.1051 + } 1.1052 + *value=0; 1.1053 + for (s=0;s<st->layout.nb_streams;s++) 1.1054 + { 1.1055 + OpusEncoder *enc; 1.1056 + enc = (OpusEncoder*)ptr; 1.1057 + if (s < st->layout.nb_coupled_streams) 1.1058 + ptr += align(coupled_size); 1.1059 + else 1.1060 + ptr += align(mono_size); 1.1061 + ret = opus_encoder_ctl(enc, request, &tmp); 1.1062 + if (ret != OPUS_OK) break; 1.1063 + *value ^= tmp; 1.1064 + } 1.1065 + } 1.1066 + break; 1.1067 + case OPUS_SET_LSB_DEPTH_REQUEST: 1.1068 + case OPUS_SET_COMPLEXITY_REQUEST: 1.1069 + case OPUS_SET_VBR_REQUEST: 1.1070 + case OPUS_SET_VBR_CONSTRAINT_REQUEST: 1.1071 + case OPUS_SET_MAX_BANDWIDTH_REQUEST: 1.1072 + case OPUS_SET_BANDWIDTH_REQUEST: 1.1073 + case OPUS_SET_SIGNAL_REQUEST: 1.1074 + case OPUS_SET_APPLICATION_REQUEST: 1.1075 + case OPUS_SET_INBAND_FEC_REQUEST: 1.1076 + case OPUS_SET_PACKET_LOSS_PERC_REQUEST: 1.1077 + case OPUS_SET_DTX_REQUEST: 1.1078 + case OPUS_SET_FORCE_MODE_REQUEST: 1.1079 + case OPUS_SET_FORCE_CHANNELS_REQUEST: 1.1080 + case OPUS_SET_PREDICTION_DISABLED_REQUEST: 1.1081 + { 1.1082 + int s; 1.1083 + /* This works for int32 params */ 1.1084 + opus_int32 value = va_arg(ap, opus_int32); 1.1085 + for (s=0;s<st->layout.nb_streams;s++) 1.1086 + { 1.1087 + OpusEncoder *enc; 1.1088 + 1.1089 + enc = (OpusEncoder*)ptr; 1.1090 + if (s < st->layout.nb_coupled_streams) 1.1091 + ptr += align(coupled_size); 1.1092 + else 1.1093 + ptr += align(mono_size); 1.1094 + ret = opus_encoder_ctl(enc, request, value); 1.1095 + if (ret != OPUS_OK) 1.1096 + break; 1.1097 + } 1.1098 + } 1.1099 + break; 1.1100 + case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST: 1.1101 + { 1.1102 + int s; 1.1103 + opus_int32 stream_id; 1.1104 + OpusEncoder **value; 1.1105 + stream_id = va_arg(ap, opus_int32); 1.1106 + if (stream_id<0 || stream_id >= st->layout.nb_streams) 1.1107 + ret = OPUS_BAD_ARG; 1.1108 + value = va_arg(ap, OpusEncoder**); 1.1109 + if (!value) 1.1110 + { 1.1111 + goto bad_arg; 1.1112 + } 1.1113 + for (s=0;s<stream_id;s++) 1.1114 + { 1.1115 + if (s < st->layout.nb_coupled_streams) 1.1116 + ptr += align(coupled_size); 1.1117 + else 1.1118 + ptr += align(mono_size); 1.1119 + } 1.1120 + *value = (OpusEncoder*)ptr; 1.1121 + } 1.1122 + break; 1.1123 + case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: 1.1124 + { 1.1125 + opus_int32 value = va_arg(ap, opus_int32); 1.1126 + st->variable_duration = value; 1.1127 + } 1.1128 + break; 1.1129 + case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST: 1.1130 + { 1.1131 + opus_int32 *value = va_arg(ap, opus_int32*); 1.1132 + if (!value) 1.1133 + { 1.1134 + goto bad_arg; 1.1135 + } 1.1136 + *value = st->variable_duration; 1.1137 + } 1.1138 + break; 1.1139 + case OPUS_RESET_STATE: 1.1140 + { 1.1141 + int s; 1.1142 + st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0; 1.1143 + if (st->surround) 1.1144 + { 1.1145 + OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels); 1.1146 + OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120); 1.1147 + } 1.1148 + for (s=0;s<st->layout.nb_streams;s++) 1.1149 + { 1.1150 + OpusEncoder *enc; 1.1151 + enc = (OpusEncoder*)ptr; 1.1152 + if (s < st->layout.nb_coupled_streams) 1.1153 + ptr += align(coupled_size); 1.1154 + else 1.1155 + ptr += align(mono_size); 1.1156 + ret = opus_encoder_ctl(enc, OPUS_RESET_STATE); 1.1157 + if (ret != OPUS_OK) 1.1158 + break; 1.1159 + } 1.1160 + } 1.1161 + break; 1.1162 + default: 1.1163 + ret = OPUS_UNIMPLEMENTED; 1.1164 + break; 1.1165 + } 1.1166 + 1.1167 + va_end(ap); 1.1168 + return ret; 1.1169 +bad_arg: 1.1170 + va_end(ap); 1.1171 + return OPUS_BAD_ARG; 1.1172 +} 1.1173 + 1.1174 +void opus_multistream_encoder_destroy(OpusMSEncoder *st) 1.1175 +{ 1.1176 + opus_free(st); 1.1177 +}