Fix memory issues in Projection API.
Modified by Jean-Marc Valin
Signed-off-by: Jean-Marc Valin <jmvalin@jmvalin.ca>
diff --git a/src/mapping_matrix.c b/src/mapping_matrix.c
index 5268bc6..d3d59d6 100644
--- a/src/mapping_matrix.c
+++ b/src/mapping_matrix.c
@@ -41,12 +41,12 @@
int mapping_matrix_get_size(int rows, int cols)
{
- return align(sizeof(MappingMatrix)) + rows * cols * sizeof(opus_int16);
+ return align(sizeof(MappingMatrix)) + align(rows * cols * sizeof(opus_int16));
}
opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
{
- return (opus_int16*)(void *)(matrix + align(sizeof(MappingMatrix)));
+ return (opus_int16*)((char*)matrix + align(sizeof(MappingMatrix)));
}
void mapping_matrix_init(MappingMatrix * const matrix,
@@ -58,7 +58,7 @@
#if !defined(ENABLE_ASSERTIONS)
(void)data_size;
#endif
- celt_assert((opus_uint32)data_size == rows * cols * sizeof(opus_int16));
+ celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16)));
matrix->rows = rows;
matrix->cols = cols;
@@ -71,18 +71,18 @@
}
#ifndef DISABLE_FLOAT_API
-void mapping_matrix_multiply_float(const MappingMatrix *matrix,
- const float *input, int input_rows,
- float *output, int output_rows,
- int frame_size)
+void mapping_matrix_multiply_channel_in_float(
+ const MappingMatrix *matrix,
+ const float *input,
+ int input_rows,
+ opus_val16 *output,
+ int output_row,
+ int output_rows,
+ int frame_size)
{
- /* Matrix data is ordered col-wise.
- * Input (x) is [n x k], output (y) is [m x k], matrix (M) is [m x n]:
- * y = M x
- */
+ /* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
- int i, row, col;
- float matrix_cell, input_sample;
+ int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
@@ -90,31 +90,70 @@
for (i = 0; i < frame_size; i++)
{
+ float tmp = 0;
+ for (col = 0; col < input_rows; col++)
+ {
+ tmp +=
+ matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+ input[MATRIX_INDEX(input_rows, col, i)];
+ }
+#if defined(FIXED_POINT)
+ output[output_rows * i] = FLOAT2INT16((1/32768.f)*tmp);
+#else
+ output[output_rows * i] = (1/32768.f)*tmp;
+#endif
+ }
+}
+
+void mapping_matrix_multiply_channel_out_float(
+ const MappingMatrix *matrix,
+ const opus_val16 *input,
+ int input_row,
+ int input_rows,
+ float *output,
+ int output_rows,
+ int frame_size
+)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, row;
+ float input_sample;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+#if defined(FIXED_POINT)
+ input_sample = (1/32768.f)*input[input_rows * i];
+#else
+ input_sample = input[input_rows * i];
+#endif
for (row = 0; row < output_rows; row++)
{
- output[MATRIX_INDEX(output_rows, row, i)] = 0;
- for (col = 0; col < input_rows; col++)
- {
- matrix_cell = (0.000030518f)*(float)matrix_data[MATRIX_INDEX(matrix->rows, row, col)];
- input_sample = input[MATRIX_INDEX(input_rows, col, i)];
- output[MATRIX_INDEX(output_rows, row, i)] += matrix_cell * input_sample;
- }
+ float tmp =
+ (1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+ input_sample;
+ output[MATRIX_INDEX(output_rows, row, i)] += tmp;
}
}
}
#endif /* DISABLE_FLOAT_API */
-void mapping_matrix_multiply_short(const MappingMatrix *matrix,
- const opus_int16 *input, int input_rows,
- opus_int16 *output, int output_rows,
- int frame_size)
+void mapping_matrix_multiply_channel_in_short(
+ const MappingMatrix *matrix,
+ const opus_int16 *input,
+ int input_rows,
+ opus_val16 *output,
+ int output_row,
+ int output_rows,
+ int frame_size)
{
- /* Matrix data is ordered col-wise.
- * Input (x) is [n x k], output (y) is [m x k], matrix (M) is [m x n]:
- * y = M x
- */
+ /* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
- int i, row, col;
+ int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
@@ -122,16 +161,58 @@
for (i = 0; i < frame_size; i++)
{
+ opus_val32 tmp = 0;
+ for (col = 0; col < input_rows; col++)
+ {
+#if defined(FIXED_POINT)
+ tmp +=
+ ((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+ (opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
+#else
+ tmp +=
+ matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+ input[MATRIX_INDEX(input_rows, col, i)];
+#endif
+ }
+#if defined(FIXED_POINT)
+ output[output_rows * i] = (opus_int16)((tmp + 64) >> 7);
+#else
+ output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
+#endif
+ }
+}
+
+void mapping_matrix_multiply_channel_out_short(
+ const MappingMatrix *matrix,
+ const opus_val16 *input,
+ int input_row,
+ int input_rows,
+ opus_int16 *output,
+ int output_rows,
+ int frame_size)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, row;
+ opus_int32 input_sample;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+#if defined(FIXED_POINT)
+ input_sample = (opus_int32)input[input_rows * i];
+#else
+ input_sample = (opus_int32)FLOAT2INT16(input[input_rows * i]);
+#endif
for (row = 0; row < output_rows; row++)
{
- opus_int32 tmp = 0;
- for (col = 0; col < input_rows; col++)
- {
- tmp +=
- (matrix_data[MATRIX_INDEX(matrix->rows, row, col)] *
- input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
- }
- output[MATRIX_INDEX(output_rows, row, i)] = (tmp + 64)>>7;
+ opus_int32 tmp =
+ (opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+ input_sample;
+ output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
}
}
}
diff --git a/src/mapping_matrix.h b/src/mapping_matrix.h
index 8fe82ea..381c8e1 100644
--- a/src/mapping_matrix.h
+++ b/src/mapping_matrix.h
@@ -44,8 +44,8 @@
typedef struct MappingMatrix
{
- int rows;
- int cols;
+ int rows; /* number of channels outputted from matrix. */
+ int cols; /* number of channels inputted to matrix. */
int gain; /* in dB. S7.8-format. */
/* Matrix cell data goes here using col-wise ordering. */
} MappingMatrix;
@@ -64,20 +64,42 @@
);
#ifndef DISABLE_FLOAT_API
-void mapping_matrix_multiply_float(
+void mapping_matrix_multiply_channel_in_float(
const MappingMatrix *matrix,
const float *input,
int input_rows,
+ opus_val16 *output,
+ int output_row,
+ int output_rows,
+ int frame_size
+);
+
+void mapping_matrix_multiply_channel_out_float(
+ const MappingMatrix *matrix,
+ const opus_val16 *input,
+ int input_row,
+ int input_rows,
float *output,
int output_rows,
int frame_size
);
#endif /* DISABLE_FLOAT_API */
-void mapping_matrix_multiply_short(
+void mapping_matrix_multiply_channel_in_short(
const MappingMatrix *matrix,
const opus_int16 *input,
int input_rows,
+ opus_val16 *output,
+ int output_row,
+ int output_rows,
+ int frame_size
+);
+
+void mapping_matrix_multiply_channel_out_short(
+ const MappingMatrix *matrix,
+ const opus_val16 *input,
+ int input_row,
+ int input_rows,
opus_int16 *output,
int output_rows,
int frame_size
diff --git a/src/opus_multistream_decoder.c b/src/opus_multistream_decoder.c
index 6ab5d4c..d5dbf4f 100644
--- a/src/opus_multistream_decoder.c
+++ b/src/opus_multistream_decoder.c
@@ -135,15 +135,6 @@
return st;
}
-typedef void (*opus_copy_channel_out_func)(
- void *dst,
- int dst_stride,
- int dst_channel,
- const opus_val16 *src,
- int src_stride,
- int frame_size
-);
-
static int opus_multistream_packet_validate(const unsigned char *data,
opus_int32 len, int nb_streams, opus_int32 Fs)
{
@@ -173,7 +164,7 @@
return samples;
}
-static int opus_multistream_decode_native(
+int opus_multistream_decode_native(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
@@ -181,7 +172,8 @@
opus_copy_channel_out_func copy_channel_out,
int frame_size,
int decode_fec,
- int soft_clip
+ int soft_clip,
+ void *user_data
)
{
opus_int32 Fs;
@@ -258,7 +250,7 @@
while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
- buf, 2, frame_size);
+ buf, 2, frame_size, user_data);
prev = chan;
}
prev = -1;
@@ -266,7 +258,7 @@
while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
- buf+1, 2, frame_size);
+ buf+1, 2, frame_size, user_data);
prev = chan;
}
} else {
@@ -276,7 +268,7 @@
while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
- buf, 1, frame_size);
+ buf, 1, frame_size, user_data);
prev = chan;
}
}
@@ -287,7 +279,7 @@
if (st->layout.mapping[c] == 255)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, c,
- NULL, 0, frame_size);
+ NULL, 0, frame_size, user_data);
}
}
RESTORE_STACK;
@@ -301,11 +293,13 @@
int dst_channel,
const opus_val16 *src,
int src_stride,
- int frame_size
+ int frame_size,
+ void *user_data
)
{
float *float_dst;
opus_int32 i;
+ (void)user_data;
float_dst = (float*)dst;
if (src != NULL)
{
@@ -330,11 +324,13 @@
int dst_channel,
const opus_val16 *src,
int src_stride,
- int frame_size
+ int frame_size,
+ void *user_data
)
{
opus_int16 *short_dst;
opus_int32 i;
+ (void)user_data;
short_dst = (opus_int16*)dst;
if (src != NULL)
{
@@ -365,7 +361,7 @@
)
{
return opus_multistream_decode_native(st, data, len,
- pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0);
+ pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0, NULL);
}
#ifndef DISABLE_FLOAT_API
@@ -373,7 +369,7 @@
opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
return opus_multistream_decode_native(st, data, len,
- pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
+ pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
}
#endif
@@ -383,20 +379,20 @@
opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
{
return opus_multistream_decode_native(st, data, len,
- pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1);
+ pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1, NULL);
}
int opus_multistream_decode_float(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
- float *pcm,
+ opus_val16 *pcm,
int frame_size,
int decode_fec
)
{
return opus_multistream_decode_native(st, data, len,
- pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
+ pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
}
#endif
diff --git a/src/opus_multistream_encoder.c b/src/opus_multistream_encoder.c
index 07de6cc..1df9e7d 100644
--- a/src/opus_multistream_encoder.c
+++ b/src/opus_multistream_encoder.c
@@ -61,15 +61,6 @@
{5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
};
-typedef void (*opus_copy_channel_in_func)(
- opus_val16 *dst,
- int dst_stride,
- const void *src,
- int src_stride,
- int src_channel,
- int frame_size
-);
-
static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
{
int s;
@@ -274,7 +265,7 @@
int nb_frames = frame_size/freq_size;
celt_assert(nb_frames*freq_size == frame_size);
OPUS_COPY(in, mem+c*overlap, overlap);
- (*copy_channel_in)(x, 1, pcm, channels, c, len);
+ (*copy_channel_in)(x, 1, pcm, channels, c, len, NULL);
celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
#ifndef FIXED_POINT
{
@@ -862,7 +853,7 @@
/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
#define MS_FRAME_TMP (6*1275+12)
-static int opus_multistream_encode_native
+int opus_multistream_encode_native
(
OpusMSEncoder *st,
opus_copy_channel_in_func copy_channel_in,
@@ -872,7 +863,8 @@
opus_int32 max_data_bytes,
int lsb_depth,
downmix_func downmix,
- int float_api
+ int float_api,
+ void *user_data
)
{
opus_int32 Fs;
@@ -1006,9 +998,9 @@
left = get_left_channel(&st->layout, s, -1);
right = get_right_channel(&st->layout, s, -1);
(*copy_channel_in)(buf, 2,
- pcm, st->layout.nb_channels, left, frame_size);
+ pcm, st->layout.nb_channels, left, frame_size, user_data);
(*copy_channel_in)(buf+1, 2,
- pcm, st->layout.nb_channels, right, frame_size);
+ pcm, st->layout.nb_channels, right, frame_size, user_data);
ptr += align(coupled_size);
if (st->mapping_type == MAPPING_TYPE_SURROUND)
{
@@ -1024,7 +1016,7 @@
int i;
int chan = get_mono_channel(&st->layout, s, -1);
(*copy_channel_in)(buf, 1,
- pcm, st->layout.nb_channels, chan, frame_size);
+ pcm, st->layout.nb_channels, chan, frame_size, user_data);
ptr += align(mono_size);
if (st->mapping_type == MAPPING_TYPE_SURROUND)
{
@@ -1083,11 +1075,13 @@
const void *src,
int src_stride,
int src_channel,
- int frame_size
+ int frame_size,
+ void *user_data
)
{
const float *float_src;
opus_int32 i;
+ (void)user_data;
float_src = (const float *)src;
for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT)
@@ -1104,11 +1098,13 @@
const void *src,
int src_stride,
int src_channel,
- int frame_size
+ int frame_size,
+ void *user_data
)
{
const opus_int16 *short_src;
opus_int32 i;
+ (void)user_data;
short_src = (const opus_int16 *)src;
for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT)
@@ -1129,7 +1125,7 @@
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_short,
- pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
+ pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
}
#ifndef DISABLE_FLOAT_API
@@ -1142,7 +1138,7 @@
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
- pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
+ pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL);
}
#endif
@@ -1158,7 +1154,7 @@
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
- pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
+ pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL);
}
int opus_multistream_encode(
@@ -1170,7 +1166,7 @@
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_short,
- pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
+ pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
}
#endif
diff --git a/src/opus_private.h b/src/opus_private.h
index acbb0ae..193ff93 100644
--- a/src/opus_private.h
+++ b/src/opus_private.h
@@ -88,7 +88,25 @@
int get_right_channel(const ChannelLayout *layout, int stream_id, int prev);
int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev);
+typedef void (*opus_copy_channel_in_func)(
+ opus_val16 *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size,
+ void *user_data
+);
+typedef void (*opus_copy_channel_out_func)(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_val16 *src,
+ int src_stride,
+ int frame_size,
+ void *user_data
+);
#define MODE_SILK_ONLY 1000
#define MODE_HYBRID 1001
@@ -156,4 +174,30 @@
int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len);
+int opus_multistream_encode_native
+(
+ struct OpusMSEncoder *st,
+ opus_copy_channel_in_func copy_channel_in,
+ const void *pcm,
+ int analysis_frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes,
+ int lsb_depth,
+ downmix_func downmix,
+ int float_api,
+ void *user_data
+);
+
+int opus_multistream_decode_native(
+ struct OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ void *pcm,
+ opus_copy_channel_out_func copy_channel_out,
+ int frame_size,
+ int decode_fec,
+ int soft_clip,
+ void *user_data
+);
+
#endif /* OPUS_PRIVATE_H */
diff --git a/src/opus_projection_decoder.c b/src/opus_projection_decoder.c
index 0d1ee41..6cdadbe 100644
--- a/src/opus_projection_decoder.c
+++ b/src/opus_projection_decoder.c
@@ -42,18 +42,63 @@
struct OpusProjectionDecoder
{
- int demixing_matrix_size_in_bytes;
+ opus_int32 demixing_matrix_size_in_bytes;
/* Encoder states go here */
};
+#if !defined(DISABLE_FLOAT_API)
+static void opus_projection_copy_channel_out_float(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_val16 *src,
+ int src_stride,
+ int frame_size,
+ void *user_data)
+{
+ float *float_dst;
+ const MappingMatrix *matrix;
+ float_dst = (float *)dst;
+ matrix = (const MappingMatrix *)user_data;
+
+ if (dst_channel == 0)
+ OPUS_CLEAR(float_dst, frame_size * dst_stride);
+
+ if (src != NULL)
+ mapping_matrix_multiply_channel_out_float(matrix, src, dst_channel,
+ src_stride, float_dst, dst_stride, frame_size);
+}
+#endif
+
+static void opus_projection_copy_channel_out_short(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_val16 *src,
+ int src_stride,
+ int frame_size,
+ void *user_data)
+{
+ opus_int16 *short_dst;
+ const MappingMatrix *matrix;
+ short_dst = (opus_int16 *)dst;
+ matrix = (const MappingMatrix *)user_data;
+ if (dst_channel == 0)
+ OPUS_CLEAR(short_dst, frame_size * dst_stride);
+
+ if (src != NULL)
+ mapping_matrix_multiply_channel_out_short(matrix, src, dst_channel,
+ src_stride, short_dst, dst_stride, frame_size);
+}
+
static MappingMatrix *get_demixing_matrix(OpusProjectionDecoder *st)
{
- return (MappingMatrix *)((char*)st + align(sizeof(OpusProjectionDecoder)));
+ return (MappingMatrix*)((char*)st + align(sizeof(OpusProjectionDecoder)));
}
static OpusMSDecoder *get_multistream_decoder(OpusProjectionDecoder *st)
{
- return (OpusMSDecoder *)((char*)st + align(sizeof(OpusProjectionDecoder) +
+ return (OpusMSDecoder*)((char*)st + align(sizeof(OpusProjectionDecoder) +
st->demixing_matrix_size_in_bytes));
}
@@ -69,7 +114,7 @@
if (!decoder_size)
return 0;
- return align(sizeof(OpusProjectionDecoder) + matrix_size + decoder_size);
+ return align(sizeof(OpusProjectionDecoder)) + matrix_size + decoder_size;
}
int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
@@ -86,14 +131,14 @@
/* Verify supplied matrix size. */
nb_input_streams = streams + coupled_streams;
expected_matrix_size = nb_input_streams * channels * sizeof(opus_int16);
- if (expected_matrix_size != demixing_matrix_size)
+ if (align(expected_matrix_size) != align(demixing_matrix_size))
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
/* Convert demixing matrix input into internal format. */
- ALLOC(buf, demixing_matrix_size, opus_int16);
+ ALLOC(buf, nb_input_streams * channels, opus_int16);
for (i = 0; i < nb_input_streams * channels; i++)
{
int s = demixing_matrix[2*i + 1] << 8 | demixing_matrix[2*i];
@@ -102,15 +147,13 @@
}
/* Assign demixing matrix. */
- st->demixing_matrix_size_in_bytes = expected_matrix_size;
+ st->demixing_matrix_size_in_bytes = mapping_matrix_get_size(channels, nb_input_streams);
mapping_matrix_init(get_demixing_matrix(st), channels, nb_input_streams, 0,
buf, demixing_matrix_size);
/* Set trivial mapping so each input channel pairs with a matrix column. */
for (i = 0; i < channels; i++)
- {
mapping[i] = i;
- }
ret = opus_multistream_decoder_init(
get_multistream_decoder(st), Fs, channels, streams, coupled_streams, mapping);
@@ -154,63 +197,33 @@
return st;
}
+#ifdef FIXED_POINT
int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size,
int decode_fec)
{
-#ifdef NONTHREADSAFE_PSEUDOSTACK
- celt_fatal("Unable to use opus_projection_decode() when NONTHREADSAFE_PSEUDOSTACK is defined.");
-#endif
- MappingMatrix *matrix;
- OpusMSDecoder *ms_decoder;
- int ret;
- VARDECL(opus_int16, buf);
- ALLOC_STACK;
-
- ms_decoder = get_multistream_decoder(st);
- ALLOC(buf, (ms_decoder->layout.nb_streams + ms_decoder->layout.nb_coupled_streams) *
- frame_size, opus_int16);
- ret = opus_multistream_decode(ms_decoder, data, len, buf, frame_size,
- decode_fec);
- if (ret <= 0)
- return ret;
- frame_size = ret;
- matrix = get_demixing_matrix(st);
- mapping_matrix_multiply_short(matrix, buf,
- ms_decoder->layout.nb_streams + ms_decoder->layout.nb_coupled_streams,
- pcm, ms_decoder->layout.nb_channels, frame_size);
- RESTORE_STACK;
- return frame_size;
+ return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+ pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, 0,
+ get_demixing_matrix(st));
}
+#else
+int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_int16 *pcm, int frame_size,
+ int decode_fec)
+{
+ return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+ pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, 1,
+ get_demixing_matrix(st));
+}
+#endif
#ifndef DISABLE_FLOAT_API
int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data,
- opus_int32 len, float *pcm,
- int frame_size, int decode_fec)
+ opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
-#ifdef NONTHREADSAFE_PSEUDOSTACK
- celt_fatal("Unable to use opus_projection_decode_float() when NONTHREADSAFE_PSEUDOSTACK is defined.");
-#endif
- MappingMatrix *matrix;
- OpusMSDecoder *ms_decoder;
- int ret;
- VARDECL(float, buf);
- ALLOC_STACK;
-
- ms_decoder = get_multistream_decoder(st);
- ALLOC(buf, (ms_decoder->layout.nb_streams + ms_decoder->layout.nb_coupled_streams) *
- frame_size, float);
- ret = opus_multistream_decode_float(ms_decoder, data, len, buf,
- frame_size, decode_fec);
- if (ret <= 0)
- return ret;
- frame_size = ret;
- matrix = get_demixing_matrix(st);
- mapping_matrix_multiply_float(matrix, buf,
- ms_decoder->layout.nb_streams + ms_decoder->layout.nb_coupled_streams,
- pcm, ms_decoder->layout.nb_channels, frame_size);
- RESTORE_STACK;
- return frame_size;
+ return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+ pcm, opus_projection_copy_channel_out_float, frame_size, decode_fec, 0,
+ get_demixing_matrix(st));
}
#endif
diff --git a/src/opus_projection_encoder.c b/src/opus_projection_encoder.c
index a2c2f35..3cf516a 100644
--- a/src/opus_projection_encoder.c
+++ b/src/opus_projection_encoder.c
@@ -42,11 +42,41 @@
struct OpusProjectionEncoder
{
- int mixing_matrix_size_in_bytes;
- int demixing_matrix_size_in_bytes;
+ opus_int32 mixing_matrix_size_in_bytes;
+ opus_int32 demixing_matrix_size_in_bytes;
/* Encoder states go here */
};
+#if !defined(DISABLE_FLOAT_API)
+static void opus_projection_copy_channel_in_float(
+ opus_val16 *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size,
+ void *user_data
+)
+{
+ mapping_matrix_multiply_channel_in_float((const MappingMatrix*)user_data,
+ (const float*)src, src_stride, dst, src_channel, dst_stride, frame_size);
+}
+#endif
+
+static void opus_projection_copy_channel_in_short(
+ opus_val16 *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size,
+ void *user_data
+)
+{
+ mapping_matrix_multiply_channel_in_short((const MappingMatrix*)user_data,
+ (const opus_int16*)src, src_stride, dst, src_channel, dst_stride, frame_size);
+}
+
static int get_order_plus_one_from_channels(int channels, int *order_plus_one)
{
int order_plus_one_;
@@ -115,10 +145,8 @@
ret = get_streams_from_channels(channels, mapping_family, &nb_streams,
&nb_coupled_streams, &order_plus_one);
- if (ret != OPUS_OK)
- {
+ if (ret != OPUS_OK || order_plus_one < 2 || order_plus_one > 4)
return 0;
- }
matrix_rows = order_plus_one * order_plus_one + 2;
matrix_size = mapping_matrix_get_size(matrix_rows, matrix_rows);
@@ -126,7 +154,7 @@
opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
if (!encoder_size)
return 0;
- return align(sizeof(OpusProjectionEncoder) + matrix_size + matrix_size + encoder_size);
+ return align(sizeof(OpusProjectionEncoder)) + matrix_size + matrix_size + encoder_size;
}
int opus_projection_ambisonics_encoder_init(OpusProjectionEncoder *st, opus_int32 Fs,
@@ -218,9 +246,7 @@
/* Set trivial mapping so each input channel pairs with a matrix column. */
for (i = 0; i < channels; i++)
- {
mapping[i] = i;
- }
/* Initialize multistream encoder with provided settings. */
ms_encoder = get_multistream_encoder(st);
@@ -269,54 +295,31 @@
int frame_size, unsigned char *data,
opus_int32 max_data_bytes)
{
-#ifdef NONTHREADSAFE_PSEUDOSTACK
- celt_fatal("Unable to use opus_projection_encode() when NONTHREADSAFE_PSEUDOSTACK is defined.");
-#endif
- MappingMatrix *matrix;
- OpusMSEncoder *ms_encoder;
- int ret;
- VARDECL(opus_int16, buf);
- ALLOC_STACK;
-
- matrix = get_mixing_matrix(st);
- ms_encoder = get_multistream_encoder(st);
- ALLOC(buf, (ms_encoder->layout.nb_streams + ms_encoder->layout.nb_coupled_streams) *
- frame_size, opus_int16);
- mapping_matrix_multiply_short(matrix, pcm,
- ms_encoder->layout.nb_channels, buf,
- ms_encoder->layout.nb_streams + ms_encoder->layout.nb_coupled_streams,
- frame_size);
- ret = opus_multistream_encode(ms_encoder, buf, frame_size, data, max_data_bytes);
- RESTORE_STACK;
- return ret;
+ return opus_multistream_encode_native(get_multistream_encoder(st),
+ opus_projection_copy_channel_in_short, pcm, frame_size, data,
+ max_data_bytes, 16, downmix_int, 0, get_mixing_matrix(st));
}
#ifndef DISABLE_FLOAT_API
+#ifdef FIXED_POINT
int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
int frame_size, unsigned char *data,
opus_int32 max_data_bytes)
{
-#ifdef NONTHREADSAFE_PSEUDOSTACK
- celt_fatal("Unable to use opus_projection_encode_float() when NONTHREADSAFE_PSEUDOSTACK is defined.");
-#endif
- MappingMatrix *matrix;
- OpusMSEncoder *ms_encoder;
- int ret;
- VARDECL(float, buf);
- ALLOC_STACK;
-
- matrix = get_mixing_matrix(st);
- ms_encoder = get_multistream_encoder(st);
- ALLOC(buf, (ms_encoder->layout.nb_streams + ms_encoder->layout.nb_coupled_streams) *
- frame_size, float);
- mapping_matrix_multiply_float(matrix, pcm,
- ms_encoder->layout.nb_channels, buf,
- ms_encoder->layout.nb_streams + ms_encoder->layout.nb_coupled_streams,
- frame_size);
- ret = opus_multistream_encode_float(ms_encoder, buf, frame_size, data, max_data_bytes);
- RESTORE_STACK;
- return ret;
+ return opus_multistream_encode_native(get_multistream_encoder(st),
+ opus_projection_copy_channel_in_float, pcm, frame_size, data,
+ max_data_bytes, 16, downmix_float, 1, get_mixing_matrix(st));
}
+#else
+int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
+ int frame_size, unsigned char *data,
+ opus_int32 max_data_bytes)
+{
+ return opus_multistream_encode_native(get_multistream_encoder(st),
+ opus_projection_copy_channel_in_float, pcm, frame_size, data,
+ max_data_bytes, 24, downmix_float, 1, get_mixing_matrix(st));
+}
+#endif
#endif
void opus_projection_encoder_destroy(OpusProjectionEncoder *st)