Fix memory issues in Projection API.
Modified by Jean-Marc Valin Signed-off-by: Jean-Marc Valin <jmvalin@jmvalin.ca>
This commit is contained in:
parent
eee6898242
commit
65f11d326d
8 changed files with 456 additions and 330 deletions
|
@ -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 @@ void mapping_matrix_init(MappingMatrix * const matrix,
|
|||
#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 @@ void mapping_matrix_init(MappingMatrix * const matrix,
|
|||
}
|
||||
|
||||
#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 @@ void mapping_matrix_multiply_float(const MappingMatrix *matrix,
|
|||
|
||||
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 @@ void mapping_matrix_multiply_short(const MappingMatrix *matrix,
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,8 +44,8 @@ extern "C" {
|
|||
|
||||
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 @@ void mapping_matrix_init(
|
|||
);
|
||||
|
||||
#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
|
||||
|
|
|
@ -135,15 +135,6 @@ OpusMSDecoder *opus_multistream_decoder_create(
|
|||
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 @@ static int opus_multistream_packet_validate(const unsigned char *data,
|
|||
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 @@ static int opus_multistream_decode_native(
|
|||
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 @@ static int opus_multistream_decode_native(
|
|||
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 @@ static int opus_multistream_decode_native(
|
|||
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 @@ static int opus_multistream_decode_native(
|
|||
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 @@ static int opus_multistream_decode_native(
|
|||
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 @@ static void opus_copy_channel_out_float(
|
|||
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 @@ static void opus_copy_channel_out_short(
|
|||
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 @@ int opus_multistream_decode(
|
|||
)
|
||||
{
|
||||
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 @@ int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
|
|||
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 @@ int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
|
|||
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
|
||||
|
||||
|
|
|
@ -61,15 +61,6 @@ static const VorbisLayout vorbis_mappings[8] = {
|
|||
{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 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
|
|||
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 @@ static opus_int32 rate_allocation(
|
|||
|
||||
/* 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 @@ static int opus_multistream_encode_native
|
|||
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 @@ static int opus_multistream_encode_native
|
|||
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 @@ static int opus_multistream_encode_native
|
|||
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 @@ static void opus_copy_channel_in_float(
|
|||
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 @@ static void opus_copy_channel_in_short(
|
|||
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 @@ int opus_multistream_encode(
|
|||
)
|
||||
{
|
||||
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 @@ int opus_multistream_encode_float(
|
|||
)
|
||||
{
|
||||
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 @@ int opus_multistream_encode_float
|
|||
)
|
||||
{
|
||||
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 @@ int opus_multistream_encode(
|
|||
)
|
||||
{
|
||||
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
|
||||
|
||||
|
|
|
@ -88,7 +88,25 @@ int get_left_channel(const ChannelLayout *layout, int stream_id, int prev);
|
|||
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 @@ opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int
|
|||
|
||||
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 */
|
||||
|
|
|
@ -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 @@ opus_int32 opus_projection_decoder_get_size(int channels, int streams,
|
|||
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 @@ int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
|
|||
/* 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 @@ int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
|
|||
}
|
||||
|
||||
/* 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 @@ OpusProjectionDecoder *opus_projection_decoder_create(
|
|||
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
|
||||
|
||||
|
|
|
@ -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 @@ opus_int32 opus_projection_ambisonics_encoder_get_size(int channels,
|
|||
|
||||
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_int32 opus_projection_ambisonics_encoder_get_size(int channels,
|
|||
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 @@ int opus_projection_ambisonics_encoder_init(OpusProjectionEncoder *st, opus_int3
|
|||
|
||||
/* 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 opus_projection_encode(OpusProjectionEncoder *st, const opus_int16 *pcm,
|
|||
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)
|
||||
|
|
|
@ -47,170 +47,141 @@
|
|||
#define BUFFER_SIZE 960
|
||||
#define MAX_DATA_BYTES 32768
|
||||
#define MAX_FRAME_SAMPLES 5760
|
||||
#define ERROR_TOLERANCE 1
|
||||
|
||||
#define INT16_TO_FLOAT(x) ((1/32768.f)*(float)x)
|
||||
#define SIMPLE_MATRIX_SIZE 12
|
||||
#define SIMPLE_MATRIX_FRAME_SIZE 10
|
||||
#define SIMPLE_MATRIX_INPUT_SIZE 30
|
||||
#define SIMPLE_MATRIX_OUTPUT_SIZE 40
|
||||
|
||||
void print_matrix_short(const opus_int16 *data, int rows, int cols)
|
||||
int assert_is_equal(
|
||||
const opus_val16 *a, const opus_int16 *b, int size, opus_int16 tolerance)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < rows; i++)
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
for (j = 0; j < cols; j++)
|
||||
{
|
||||
fprintf(stderr, "%8.5f ", (float)INT16_TO_FLOAT(data[j * rows + i]));
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
#ifdef FIXED_POINT
|
||||
opus_int16 val = a[i];
|
||||
#else
|
||||
opus_int16 val = FLOAT2INT16(a[i]);
|
||||
#endif
|
||||
if (abs(val - b[i]) > tolerance)
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_matrix_float(const float *data, int rows, int cols)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < rows; i++)
|
||||
{
|
||||
for (j = 0; j < cols; j++)
|
||||
{
|
||||
fprintf(stderr, "%8.5f ", data[j * rows + i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void print_matrix(MappingMatrix *matrix)
|
||||
{
|
||||
opus_int16 *data;
|
||||
|
||||
fprintf(stderr, "%d x %d, gain: %d\n", matrix->rows, matrix->cols,
|
||||
matrix->gain);
|
||||
|
||||
data = mapping_matrix_get_data(matrix);
|
||||
print_matrix_short(data, matrix->rows, matrix->cols);
|
||||
}
|
||||
|
||||
int assert_transform_short(
|
||||
int assert_is_equal_short(
|
||||
const opus_int16 *a, const opus_int16 *b, int size, opus_int16 tolerance)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (abs(a[i] - b[i]) > tolerance)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int assert_transform_float(
|
||||
const float *a, const float *b, int size, float tolerance)
|
||||
void test_simple_matrix(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (fabsf(a[i] - b[i]) > tolerance)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void test_matrix_transform(void)
|
||||
{
|
||||
/* Create testing mixing matrix (4 x 3), gain 0dB:
|
||||
* [ 0 1 0 ]
|
||||
* [ 1 0 0 ]
|
||||
* [ 0 0 0 ]
|
||||
* [ 0 0 1 ]
|
||||
*/
|
||||
opus_int32 matrix_size;
|
||||
MappingMatrix *testing_matrix;
|
||||
const opus_int16 testing_matrix_data[12] = {
|
||||
0, 32767, 0, 0, 32767, 0, 0, 0, 0, 0, 0, 32767 };
|
||||
|
||||
const int frame_size = 10;
|
||||
const opus_int16 input[30] = {
|
||||
const MappingMatrix simple_matrix_params = {4, 3, 0};
|
||||
const opus_int16 simple_matrix_data[SIMPLE_MATRIX_SIZE] = {0, 32767, 0, 0, 32767, 0, 0, 0, 0, 0, 0, 32767};
|
||||
const opus_int16 input_int16[SIMPLE_MATRIX_INPUT_SIZE] = {
|
||||
32767, 0, -32768, 29491, -3277, -29491, 26214, -6554, -26214, 22938, -9830,
|
||||
-22938, 19661, -13107, -19661, 16384, -16384, -16384, 13107, -19661, -13107,
|
||||
9830, -22938, -9830, 6554, -26214, -6554, 3277, -29491, -3277};
|
||||
const opus_int16 expected_output[40] = {
|
||||
const opus_int16 expected_output_int16[SIMPLE_MATRIX_OUTPUT_SIZE] = {
|
||||
0, 32767, 0, -32768, -3277, 29491, 0, -29491, -6554, 26214, 0, -26214,
|
||||
-9830, 22938, 0, -22938, -13107, 19661, 0, -19661, -16384, 16384, 0, -16384,
|
||||
-19661, 13107, 0, -13107, -22938, 9830, 0, -9830, -26214, 6554, 0, -6554,
|
||||
-29491, 3277, 0, -3277};
|
||||
opus_int16 output[40] = {0};
|
||||
|
||||
#ifndef DISABLE_FLOAT_API
|
||||
int i;
|
||||
/* Sample-accurate to -93.9794 dB */
|
||||
float flt_tolerance = 2e-5f;
|
||||
float input32[30] = {0};
|
||||
float output32[40] = {0};
|
||||
float expected_output32[40] = {0};
|
||||
int i, ret;
|
||||
opus_val16 *input_val16;
|
||||
opus_val16 *output_val16;
|
||||
opus_int16 *output_int16;
|
||||
MappingMatrix *simple_matrix;
|
||||
|
||||
/* Convert short to float representations. */
|
||||
for (i = 0; i < 30; i++)
|
||||
/* Allocate input/output buffers. */
|
||||
input_val16 = (opus_val16 *)opus_alloc(align(sizeof(opus_val16) * SIMPLE_MATRIX_INPUT_SIZE));
|
||||
output_int16 = (opus_int16 *)opus_alloc(align(sizeof(opus_int16) * SIMPLE_MATRIX_OUTPUT_SIZE));
|
||||
output_val16 = (opus_val16 *)opus_alloc(align(sizeof(opus_val16) * SIMPLE_MATRIX_OUTPUT_SIZE));
|
||||
|
||||
/* Initialize matrix */
|
||||
simple_matrix = (MappingMatrix *)opus_alloc(
|
||||
mapping_matrix_get_size(simple_matrix_params.rows,
|
||||
simple_matrix_params.cols));
|
||||
mapping_matrix_init(simple_matrix, simple_matrix_params.rows,
|
||||
simple_matrix_params.cols, simple_matrix_params.gain, simple_matrix_data,
|
||||
sizeof(simple_matrix_data));
|
||||
|
||||
/* Copy inputs. */
|
||||
for (i = 0; i < SIMPLE_MATRIX_INPUT_SIZE; i++)
|
||||
{
|
||||
input32[i] = INT16_TO_FLOAT(input[i]);
|
||||
}
|
||||
for (i = 0; i < 40; i++)
|
||||
{
|
||||
expected_output32[i] = INT16_TO_FLOAT(expected_output[i]);
|
||||
}
|
||||
#endif /* DISABLE_FLOAT_API */
|
||||
|
||||
/* Create the matrix. */
|
||||
matrix_size = mapping_matrix_get_size(4, 3);
|
||||
testing_matrix = (MappingMatrix *)opus_alloc(matrix_size);
|
||||
mapping_matrix_init(testing_matrix, 4, 3, 0, testing_matrix_data,
|
||||
12 * sizeof(opus_int16));
|
||||
|
||||
mapping_matrix_multiply_short(testing_matrix, input, testing_matrix->cols,
|
||||
output, testing_matrix->rows, frame_size);
|
||||
if (!assert_transform_short(output, expected_output, 40, 1))
|
||||
{
|
||||
fprintf(stderr, "Matrix:\n");
|
||||
print_matrix(testing_matrix);
|
||||
|
||||
fprintf(stderr, "Input (short):\n");
|
||||
print_matrix_short(input, testing_matrix->cols, frame_size);
|
||||
|
||||
fprintf(stderr, "Expected Output (short):\n");
|
||||
print_matrix_short(expected_output, testing_matrix->rows, frame_size);
|
||||
|
||||
fprintf(stderr, "Output (short):\n");
|
||||
print_matrix_short(output, testing_matrix->rows, frame_size);
|
||||
|
||||
goto bad_cleanup;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_FLOAT_API
|
||||
mapping_matrix_multiply_float(testing_matrix, input32, testing_matrix->cols,
|
||||
output32, testing_matrix->rows, frame_size);
|
||||
if (!assert_transform_float(output32, expected_output32, 40, flt_tolerance))
|
||||
{
|
||||
fprintf(stderr, "Matrix:\n");
|
||||
print_matrix(testing_matrix);
|
||||
|
||||
fprintf(stderr, "Input (float):\n");
|
||||
print_matrix_float(input32, testing_matrix->cols, frame_size);
|
||||
|
||||
fprintf(stderr, "Expected Output (float):\n");
|
||||
print_matrix_float(expected_output32, testing_matrix->rows, frame_size);
|
||||
|
||||
fprintf(stderr, "Output (float):\n");
|
||||
print_matrix_float(output32, testing_matrix->rows, frame_size);
|
||||
|
||||
goto bad_cleanup;
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
input_val16[i] = input_int16[i];
|
||||
#else
|
||||
input_val16[i] = (1/32768.f)*input_int16[i];
|
||||
#endif
|
||||
opus_free(testing_matrix);
|
||||
return;
|
||||
bad_cleanup:
|
||||
opus_free(testing_matrix);
|
||||
test_failed();
|
||||
}
|
||||
|
||||
/* _in_short */
|
||||
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
|
||||
output_val16[i] = 0;
|
||||
for (i = 0; i < simple_matrix->rows; i++)
|
||||
{
|
||||
mapping_matrix_multiply_channel_in_short(simple_matrix,
|
||||
input_int16, simple_matrix->cols, &output_val16[i], i,
|
||||
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
|
||||
}
|
||||
ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
|
||||
if (ret)
|
||||
test_failed();
|
||||
|
||||
/* _out_short */
|
||||
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
|
||||
output_int16[i] = 0;
|
||||
for (i = 0; i < simple_matrix->cols; i++)
|
||||
{
|
||||
mapping_matrix_multiply_channel_out_short(simple_matrix,
|
||||
&input_val16[i], i, simple_matrix->cols, output_int16,
|
||||
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
|
||||
}
|
||||
ret = assert_is_equal_short(output_int16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
|
||||
if (ret)
|
||||
test_failed();
|
||||
|
||||
#if !defined(DISABLE_FLOAT_API) && !defined(FIXED_POINT)
|
||||
/* _in_float */
|
||||
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
|
||||
output_val16[i] = 0;
|
||||
for (i = 0; i < simple_matrix->rows; i++)
|
||||
{
|
||||
mapping_matrix_multiply_channel_in_float(simple_matrix,
|
||||
input_val16, simple_matrix->cols, &output_val16[i], i,
|
||||
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
|
||||
}
|
||||
ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
|
||||
if (ret)
|
||||
test_failed();
|
||||
|
||||
/* _out_float */
|
||||
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
|
||||
output_val16[i] = 0;
|
||||
for (i = 0; i < simple_matrix->cols; i++)
|
||||
{
|
||||
mapping_matrix_multiply_channel_out_float(simple_matrix,
|
||||
&input_val16[i], i, simple_matrix->cols, output_val16,
|
||||
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
|
||||
}
|
||||
ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
|
||||
if (ret)
|
||||
test_failed();
|
||||
#endif
|
||||
|
||||
opus_free(input_val16);
|
||||
opus_free(output_int16);
|
||||
opus_free(output_val16);
|
||||
opus_free(simple_matrix);
|
||||
}
|
||||
|
||||
void test_creation_arguments(const int channels, const int mapping_family)
|
||||
|
@ -403,15 +374,15 @@ int main(int _argc, char **_argv)
|
|||
(void)_argc;
|
||||
(void)_argv;
|
||||
|
||||
/* Test matrix creation/multiplication. */
|
||||
test_matrix_transform();
|
||||
/* Test simple matrix multiplication routines. */
|
||||
test_simple_matrix();
|
||||
|
||||
/* Test full range of channels in creation arguments. */
|
||||
for (i = 0; i < 255; i++)
|
||||
test_creation_arguments(i, 253);
|
||||
|
||||
/* Test encode/decode pipeline. */
|
||||
test_encode_decode(64 * 16, 16, 253);
|
||||
test_encode_decode(64 * 18, 18, 253);
|
||||
|
||||
fprintf(stderr, "All projection tests passed.\n");
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue