Adds 24-bit API for projection encoder/decoder
Some checks failed
Autotools / AutoMake/Linux/GCC (push) Has been cancelled
Autotools / AutoMake/Linux/GCC/EnableDNN (push) Has been cancelled
Autotools / AutoMake/Linux/GCC/EnableCustomModes (push) Has been cancelled
Autotools / AutoMake/Linux/GCC/EnableAssertions (push) Has been cancelled
CMake / Test build with CMake 3.16.0 (push) Has been cancelled
CMake / CMake MINGW (push) Has been cancelled
CMake / CMake/Linux/Lib/X64/Release (push) Has been cancelled
CMake / CMake/MacOSX/Lib/X64/Release (push) Has been cancelled
CMake / CMake/MacOSX/Framework/X64/Release (push) Has been cancelled
CMake / CMake/Linux/So/X64/Release (push) Has been cancelled
CMake / CMake/MacOSX/So/X64/Release (push) Has been cancelled
CMake / CMake/Android/So/ARMv8/Release (push) Has been cancelled
CMake / CMake/Android/Lib/ARMv8/Release (push) Has been cancelled
CMake / CMake/Android/So/X86/Release (push) Has been cancelled
CMake / CMake/Android/Lib/X86/Release (push) Has been cancelled
CMake / CMake/Android/So/X64/Release (push) Has been cancelled
CMake / CMake/Android/Lib/X64/Release (push) Has been cancelled
CMake / CMake/AssertionsFuzz/Linux/Lib/X64/Release (push) Has been cancelled
CMake / CMake/AssertionsFuzz/MacOSX/Lib/X64/Release (push) Has been cancelled
CMake / CMake/CustomModes/Linux/Lib/X64/Release (push) Has been cancelled
CMake / CMake/iOS/Framework/arm64/Release (push) Has been cancelled
CMake / CMake/iOS/Dll/arm64/Release (push) Has been cancelled
CMake / CMake/iOS/Lib/arm64/Release (push) Has been cancelled
CMake / CMake/Windows/Dll/ARMv8/Release (push) Has been cancelled
CMake / CMake/Windows/Lib/armv8/Release (push) Has been cancelled
CMake / CMake/Windows/Dll/X64/Release (push) Has been cancelled
CMake / CMake/Windows/Dll/X86/Release (push) Has been cancelled
CMake / CMake/AssertionsFuzz/Windows/Lib/X64/Release (push) Has been cancelled
CMake / CMake/Windows/Lib/X64/Release (push) Has been cancelled
CMake / CMake/Windows/Lib/X86/Release (push) Has been cancelled
DRED / CMake/Android/Lib/ARMv8/Release (push) Has been cancelled
DRED / CMake/Android/Lib/X64/Release (push) Has been cancelled
DRED / CMake/MacOSX/Lib/X64/Release (push) Has been cancelled
DRED / CMake/Linux/Lib/X64/Release (push) Has been cancelled
DRED / CMake/iOS/Lib/arm64/Release (push) Has been cancelled
DRED / CMake/Windows/Lib/armv8/Release (push) Has been cancelled
DRED / CMake/Windows/Lib/X64/Release (push) Has been cancelled
DRED / AutoTools/Linux/Clang (push) Has been cancelled
DRED / AutoTools/Linux/GCC (push) Has been cancelled
Repository / Check trailing white spaces (push) Has been cancelled

This commit is contained in:
Jean-Marc Valin 2024-06-13 10:55:12 -04:00
parent 568ebfc123
commit d0235b29e7
No known key found for this signature in database
GPG key ID: 8D2952BBB52C646D
5 changed files with 214 additions and 0 deletions

View file

@ -260,6 +260,44 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode(
opus_int32 max_data_bytes opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a projection Opus frame.
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
* @param[in] pcm <tt>const opus_int32*</tt>: The input signal as interleaved
* samples representing (or slightly exceeding) 24-bit values.
* This must contain
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
* signal.
* This must be an Opus frame size for the
* encoder's sampling rate.
* For example, at 48 kHz the permitted values
* are 120, 240, 480, 960, 1920, and 2880.
* Passing in a duration of less than 10 ms
* (480 samples at 48 kHz) will prevent the
* encoder from using the LPC or hybrid modes.
* @param[out] data <tt>unsigned char*</tt>: Output payload.
* This must contain storage for at
* least \a max_data_bytes.
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
* memory for the output
* payload. This may be
* used to impose an upper limit on
* the instant bitrate, but should
* not be used as the only bitrate
* control. Use #OPUS_SET_BITRATE to
* control the bitrate.
* @returns The length of the encoded packet (in bytes) on success or a
* negative error code (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode24(
OpusProjectionEncoder *st,
const opus_int32 *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a projection Opus frame from floating point input. /** Encodes a projection Opus frame from floating point input.
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state. * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
@ -493,6 +531,43 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode(
int decode_fec int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode a projection Opus packet.
* @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
* Use a <code>NULL</code>
* pointer to indicate packet
* loss.
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
* @param[out] pcm <tt>opus_int32*</tt>: Output signal, with interleaved
* samples representing (or slightly exceeding) 24-bit values.
* This must contain room for
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: The number of samples per channel of
* available space in \a pcm.
* If this is less than the maximum packet duration
* (120 ms; 5760 for 48kHz), this function will not be capable
* of decoding some packets. In the case of PLC (data==NULL)
* or FEC (decode_fec=1), then frame_size needs to be exactly
* the duration of audio that is missing, otherwise the
* decoder will not be in the optimal state to decode the
* next incoming packet. For the PLC and FEC cases, frame_size
* <b>must</b> be a multiple of 2.5 ms.
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
* forward error correction data be decoded.
* If no such data is available, the frame is
* decoded as if it were lost.
* @returns Number of samples decoded on success or a negative error code
* (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode24(
OpusProjectionDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int32 *pcm,
int frame_size,
int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode a projection Opus packet with floating point output. /** Decode a projection Opus packet with floating point output.
* @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state. * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.

View file

@ -216,6 +216,72 @@ void mapping_matrix_multiply_channel_out_short(
} }
} }
void mapping_matrix_multiply_channel_in_int24(
const MappingMatrix *matrix,
const opus_int32 *input,
int input_rows,
opus_res *output,
int output_row,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
opus_val64 tmp = 0;
for (col = 0; col < input_rows; col++)
{
tmp +=
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
(opus_val64)input[MATRIX_INDEX(input_rows, col, i)];
}
#if defined(FIXED_POINT)
output[output_rows * i] = INT24TORES((tmp + 16384) >> 15);
#else
output[output_rows * i] = INT24TORES((1/(32768.f))*tmp);
#endif
}
}
void mapping_matrix_multiply_channel_out_int24(
const MappingMatrix *matrix,
const opus_res *input,
int input_row,
int input_rows,
opus_int32 *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++)
{
input_sample = RES2INT24(input[input_rows * i]);
for (row = 0; row < output_rows; row++)
{
opus_int64 tmp =
(opus_int64)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
input_sample;
output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
}
}
}
const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 }; const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
const opus_int16 mapping_matrix_foa_mixing_data[36] = { const opus_int16 mapping_matrix_foa_mixing_data[36] = {
16384, 0, -16384, 23170, 0, 0, 16384, 23170, 16384, 0, -16384, 23170, 0, 0, 16384, 23170,

View file

@ -103,6 +103,26 @@ void mapping_matrix_multiply_channel_out_short(
int frame_size int frame_size
); );
void mapping_matrix_multiply_channel_in_int24(
const MappingMatrix *matrix,
const opus_int32 *input,
int input_rows,
opus_res *output,
int output_row,
int output_rows,
int frame_size
);
void mapping_matrix_multiply_channel_out_int24(
const MappingMatrix *matrix,
const opus_res *input,
int input_row,
int input_rows,
opus_int32 *output,
int output_rows,
int frame_size
);
/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics. /* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics.
* foa: first-order ambisonics * foa: first-order ambisonics
* soa: second-order ambisonics * soa: second-order ambisonics

View file

@ -89,6 +89,27 @@ static void opus_projection_copy_channel_out_short(
src_stride, short_dst, dst_stride, frame_size); src_stride, short_dst, dst_stride, frame_size);
} }
static void opus_projection_copy_channel_out_int24(
void *dst,
int dst_stride,
int dst_channel,
const opus_res *src,
int src_stride,
int frame_size,
void *user_data)
{
opus_int32 *short_dst;
const MappingMatrix *matrix;
short_dst = (opus_int32 *)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_int24(matrix, src, dst_channel,
src_stride, short_dst, dst_stride, frame_size);
}
static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st) static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st)
{ {
/* void* cast avoids clang -Wcast-align warning */ /* void* cast avoids clang -Wcast-align warning */
@ -224,6 +245,15 @@ int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
get_dec_demixing_matrix(st)); get_dec_demixing_matrix(st));
} }
int opus_projection_decode24(OpusProjectionDecoder *st, const unsigned char *data,
opus_int32 len, opus_int32 *pcm, int frame_size,
int decode_fec)
{
return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
pcm, opus_projection_copy_channel_out_int24, frame_size, decode_fec, 0,
get_dec_demixing_matrix(st));
}
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data, 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)

View file

@ -75,6 +75,20 @@ static void opus_projection_copy_channel_in_short(
(const opus_int16*)src, src_stride, dst, src_channel, dst_stride, frame_size); (const opus_int16*)src, src_stride, dst, src_channel, dst_stride, frame_size);
} }
static void opus_projection_copy_channel_in_int24(
opus_res *dst,
int dst_stride,
const void *src,
int src_stride,
int src_channel,
int frame_size,
void *user_data
)
{
mapping_matrix_multiply_channel_in_int24((const MappingMatrix*)user_data,
(const opus_int32*)src, src_stride, dst, src_channel, dst_stride, frame_size);
}
static int get_order_plus_one_from_channels(int channels, int *order_plus_one) static int get_order_plus_one_from_channels(int channels, int *order_plus_one)
{ {
int order_plus_one_; int order_plus_one_;
@ -392,6 +406,15 @@ int opus_projection_encode(OpusProjectionEncoder *st, const opus_int16 *pcm,
max_data_bytes, 16, downmix_int, 0, get_mixing_matrix(st)); max_data_bytes, 16, downmix_int, 0, get_mixing_matrix(st));
} }
int opus_projection_encode24(OpusProjectionEncoder *st, const opus_int32 *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_int24, pcm, frame_size, data,
max_data_bytes, MAX_ENCODING_DEPTH, downmix_int, 0, get_mixing_matrix(st));
}
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm, int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
int frame_size, unsigned char *data, int frame_size, unsigned char *data,