diff options
author | Andrew Allen <bitllama@google.com> | 2017-12-04 15:32:18 -0800 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2017-12-07 13:04:19 -0500 |
commit | 65f11d326db773b2353d5066fd6b9191e9b3df81 (patch) | |
tree | d88b0ff49cf750d169c234e345d65a8dc5eb6496 /src | |
parent | eee689824288c905eadffe9aef04bfc0c4753485 (diff) | |
download | opus-65f11d326db773b2353d5066fd6b9191e9b3df81.tar.gz |
Fix memory issues in Projection API.
Modified by Jean-Marc Valin
Signed-off-by: Jean-Marc Valin <jmvalin@jmvalin.ca>
Diffstat (limited to 'src')
-rw-r--r-- | src/mapping_matrix.c | 155 | ||||
-rw-r--r-- | src/mapping_matrix.h | 30 | ||||
-rw-r--r-- | src/opus_multistream_decoder.c | 40 | ||||
-rw-r--r-- | src/opus_multistream_encoder.c | 38 | ||||
-rw-r--r-- | src/opus_private.h | 46 | ||||
-rw-r--r-- | src/opus_projection_decoder.c | 127 | ||||
-rw-r--r-- | src/opus_projection_encoder.c | 99 |
7 files changed, 345 insertions, 190 deletions
diff --git a/src/mapping_matrix.c b/src/mapping_matrix.c index 5268bc6d..d3d59d61 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 @@ 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; } } } diff --git a/src/mapping_matrix.h b/src/mapping_matrix.h index 8fe82eab..381c8e1a 100644 --- a/src/mapping_matrix.h +++ b/src/mapping_matrix.h @@ -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 diff --git a/src/opus_multistream_decoder.c b/src/opus_multistream_decoder.c index 6ab5d4c7..d5dbf4fe 100644 --- a/src/opus_multistream_decoder.c +++ b/src/opus_multistream_decoder.c @@ -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 diff --git a/src/opus_multistream_encoder.c b/src/opus_multistream_encoder.c index 07de6cce..1df9e7db 100644 --- a/src/opus_multistream_encoder.c +++ b/src/opus_multistream_encoder.c @@ -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 diff --git a/src/opus_private.h b/src/opus_private.h index acbb0ae8..193ff938 100644 --- a/src/opus_private.h +++ b/src/opus_private.h @@ -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 */ diff --git a/src/opus_projection_decoder.c b/src/opus_projection_decoder.c index 0d1ee41f..6cdadbe9 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 @@ 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 diff --git a/src/opus_projection_encoder.c b/src/opus_projection_encoder.c index a2c2f353..3cf516ab 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 @@ 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) |