tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

opus_projection_decoder.c (8481B)


      1 /* Copyright (c) 2017 Google Inc.
      2   Written by Andrew Allen */
      3 /*
      4   Redistribution and use in source and binary forms, with or without
      5   modification, are permitted provided that the following conditions
      6   are met:
      7 
      8   - Redistributions of source code must retain the above copyright
      9   notice, this list of conditions and the following disclaimer.
     10 
     11   - Redistributions in binary form must reproduce the above copyright
     12   notice, this list of conditions and the following disclaimer in the
     13   documentation and/or other materials provided with the distribution.
     14 
     15   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     18   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     19   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     23   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     24   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     25   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 */
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include "config.h"
     30 #endif
     31 
     32 #include "mathops.h"
     33 #include "os_support.h"
     34 #include "opus_private.h"
     35 #include "opus_defines.h"
     36 #include "opus_projection.h"
     37 #include "opus_multistream.h"
     38 #include "mapping_matrix.h"
     39 #include "stack_alloc.h"
     40 
     41 struct OpusProjectionDecoder
     42 {
     43  opus_int32 demixing_matrix_size_in_bytes;
     44  /* Encoder states go here */
     45 };
     46 
     47 #if !defined(DISABLE_FLOAT_API)
     48 static void opus_projection_copy_channel_out_float(
     49  void *dst,
     50  int dst_stride,
     51  int dst_channel,
     52  const opus_res *src,
     53  int src_stride,
     54  int frame_size,
     55  void *user_data)
     56 {
     57  float *float_dst;
     58  const MappingMatrix *matrix;
     59  float_dst = (float *)dst;
     60  matrix = (const MappingMatrix *)user_data;
     61 
     62  if (dst_channel == 0)
     63    OPUS_CLEAR(float_dst, frame_size * dst_stride);
     64 
     65  if (src != NULL)
     66    mapping_matrix_multiply_channel_out_float(matrix, src, dst_channel,
     67      src_stride, float_dst, dst_stride, frame_size);
     68 }
     69 #endif
     70 
     71 static void opus_projection_copy_channel_out_short(
     72  void *dst,
     73  int dst_stride,
     74  int dst_channel,
     75  const opus_res *src,
     76  int src_stride,
     77  int frame_size,
     78  void *user_data)
     79 {
     80  opus_int16 *short_dst;
     81  const MappingMatrix *matrix;
     82  short_dst = (opus_int16 *)dst;
     83  matrix = (const MappingMatrix *)user_data;
     84  if (dst_channel == 0)
     85    OPUS_CLEAR(short_dst, frame_size * dst_stride);
     86 
     87  if (src != NULL)
     88    mapping_matrix_multiply_channel_out_short(matrix, src, dst_channel,
     89      src_stride, short_dst, dst_stride, frame_size);
     90 }
     91 
     92 static void opus_projection_copy_channel_out_int24(
     93  void *dst,
     94  int dst_stride,
     95  int dst_channel,
     96  const opus_res *src,
     97  int src_stride,
     98  int frame_size,
     99  void *user_data)
    100 {
    101  opus_int32 *short_dst;
    102  const MappingMatrix *matrix;
    103  short_dst = (opus_int32 *)dst;
    104  matrix = (const MappingMatrix *)user_data;
    105  if (dst_channel == 0)
    106    OPUS_CLEAR(short_dst, frame_size * dst_stride);
    107 
    108  if (src != NULL)
    109    mapping_matrix_multiply_channel_out_int24(matrix, src, dst_channel,
    110      src_stride, short_dst, dst_stride, frame_size);
    111 }
    112 
    113 static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st)
    114 {
    115  /* void* cast avoids clang -Wcast-align warning */
    116  return (MappingMatrix*)(void*)((char*)st +
    117    align(sizeof(OpusProjectionDecoder)));
    118 }
    119 
    120 static OpusMSDecoder *get_multistream_decoder(OpusProjectionDecoder *st)
    121 {
    122  /* void* cast avoids clang -Wcast-align warning */
    123  return (OpusMSDecoder*)(void*)((char*)st +
    124    align(sizeof(OpusProjectionDecoder) +
    125    st->demixing_matrix_size_in_bytes));
    126 }
    127 
    128 opus_int32 opus_projection_decoder_get_size(int channels, int streams,
    129                                            int coupled_streams)
    130 {
    131  opus_int32 matrix_size;
    132  opus_int32 decoder_size;
    133 
    134  matrix_size =
    135    mapping_matrix_get_size(streams + coupled_streams, channels);
    136  if (!matrix_size)
    137    return 0;
    138 
    139  decoder_size = opus_multistream_decoder_get_size(streams, coupled_streams);
    140  if (!decoder_size)
    141    return 0;
    142 
    143  return align(sizeof(OpusProjectionDecoder)) + matrix_size + decoder_size;
    144 }
    145 
    146 int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
    147  int channels, int streams, int coupled_streams,
    148  unsigned char *demixing_matrix, opus_int32 demixing_matrix_size)
    149 {
    150  int nb_input_streams;
    151  opus_int32 expected_matrix_size;
    152  int i, ret;
    153  unsigned char mapping[255];
    154  VARDECL(opus_int16, buf);
    155  ALLOC_STACK;
    156 
    157  /* Verify supplied matrix size. */
    158  nb_input_streams = streams + coupled_streams;
    159  expected_matrix_size = nb_input_streams * channels * sizeof(opus_int16);
    160  if (expected_matrix_size != demixing_matrix_size)
    161  {
    162    RESTORE_STACK;
    163    return OPUS_BAD_ARG;
    164  }
    165 
    166  /* Convert demixing matrix input into internal format. */
    167  ALLOC(buf, nb_input_streams * channels, opus_int16);
    168  for (i = 0; i < nb_input_streams * channels; i++)
    169  {
    170    int s = demixing_matrix[2*i + 1] << 8 | demixing_matrix[2*i];
    171    s = ((s & 0xFFFF) ^ 0x8000) - 0x8000;
    172    buf[i] = (opus_int16)s;
    173  }
    174 
    175  /* Assign demixing matrix. */
    176  st->demixing_matrix_size_in_bytes =
    177    mapping_matrix_get_size(channels, nb_input_streams);
    178  if (!st->demixing_matrix_size_in_bytes)
    179  {
    180    RESTORE_STACK;
    181    return OPUS_BAD_ARG;
    182  }
    183 
    184  mapping_matrix_init(get_dec_demixing_matrix(st), channels, nb_input_streams, 0,
    185    buf, demixing_matrix_size);
    186 
    187  /* Set trivial mapping so each input channel pairs with a matrix column. */
    188  for (i = 0; i < channels; i++)
    189    mapping[i] = i;
    190 
    191  ret = opus_multistream_decoder_init(
    192    get_multistream_decoder(st), Fs, channels, streams, coupled_streams, mapping);
    193  RESTORE_STACK;
    194  return ret;
    195 }
    196 
    197 OpusProjectionDecoder *opus_projection_decoder_create(
    198  opus_int32 Fs, int channels, int streams, int coupled_streams,
    199  unsigned char *demixing_matrix, opus_int32 demixing_matrix_size, int *error)
    200 {
    201  int size;
    202  int ret;
    203  OpusProjectionDecoder *st;
    204 
    205  /* Allocate space for the projection decoder. */
    206  size = opus_projection_decoder_get_size(channels, streams, coupled_streams);
    207  if (!size) {
    208    if (error)
    209      *error = OPUS_ALLOC_FAIL;
    210    return NULL;
    211  }
    212  st = (OpusProjectionDecoder *)opus_alloc(size);
    213  if (!st)
    214  {
    215    if (error)
    216      *error = OPUS_ALLOC_FAIL;
    217    return NULL;
    218  }
    219 
    220  /* Initialize projection decoder with provided settings. */
    221  ret = opus_projection_decoder_init(st, Fs, channels, streams, coupled_streams,
    222                                     demixing_matrix, demixing_matrix_size);
    223  if (ret != OPUS_OK)
    224  {
    225    opus_free(st);
    226    st = NULL;
    227  }
    228  if (error)
    229    *error = ret;
    230  return st;
    231 }
    232 
    233 #ifdef FIXED_POINT
    234 #define OPTIONAL_CLIP 0
    235 #else
    236 #define OPTIONAL_CLIP 1
    237 #endif
    238 
    239 int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
    240                           opus_int32 len, opus_int16 *pcm, int frame_size,
    241                           int decode_fec)
    242 {
    243  return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
    244    pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, OPTIONAL_CLIP,
    245    get_dec_demixing_matrix(st));
    246 }
    247 
    248 int opus_projection_decode24(OpusProjectionDecoder *st, const unsigned char *data,
    249                           opus_int32 len, opus_int32 *pcm, int frame_size,
    250                           int decode_fec)
    251 {
    252  return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
    253    pcm, opus_projection_copy_channel_out_int24, frame_size, decode_fec, 0,
    254    get_dec_demixing_matrix(st));
    255 }
    256 
    257 #ifndef DISABLE_FLOAT_API
    258 int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data,
    259                                 opus_int32 len, float *pcm, int frame_size, int decode_fec)
    260 {
    261  return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
    262    pcm, opus_projection_copy_channel_out_float, frame_size, decode_fec, 0,
    263    get_dec_demixing_matrix(st));
    264 }
    265 #endif
    266 
    267 int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...)
    268 {
    269  va_list ap;
    270  int ret = OPUS_OK;
    271 
    272  va_start(ap, request);
    273  ret = opus_multistream_decoder_ctl_va_list(get_multistream_decoder(st),
    274    request, ap);
    275  va_end(ap);
    276  return ret;
    277 }
    278 
    279 void opus_projection_decoder_destroy(OpusProjectionDecoder *st)
    280 {
    281  opus_free(st);
    282 }