Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion opus_sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ src/opus_multistream_decoder.c \
src/repacketizer.c \
src/opus_projection_encoder.c \
src/opus_projection_decoder.c \
src/mapping_matrix.c
src/mapping_matrix.c \
src/mapping_matrix_hoa.c

OPUS_SOURCES_FLOAT = \
src/analysis.c \
Expand Down
77 changes: 73 additions & 4 deletions src/mapping_matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,13 @@ opus_int32 mapping_matrix_get_size(int rows, int cols)
opus_int32 size;

/* Mapping Matrix must only support up to 255 channels in or out.
* Additionally, the total cell count must be <= 65004 octets in order
* for the matrix to be stored in an OGG header.
* Note that a matrix larger than MAPPING_MATRIX_MAX_OGG_HEADER_OCTETS cannot
* be stored in an Ogg OpusHead; that is a container limit, checked by the
* muxer, and it excludes only 13th- and 14th-order ambisonics.
*/
if (rows > 255 || cols > 255)
return 0;
size = rows * (opus_int32)cols * sizeof(opus_int16);
if (size > 65004)
return 0;

return align(sizeof(MappingMatrix)) + align(size);
}
Expand Down Expand Up @@ -995,3 +994,73 @@ const opus_int16 mapping_matrix_fifthoa_demixing_data[1444] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 32767
};

/* Built-in projection matrices by ambisonic order, so that callers do not need a
* branch per order. Index 0 is unused: order 0 (mono) has no projection matrix.
*/
typedef struct {
const MappingMatrix *matrix;
const opus_int16 *data;
opus_int32 data_size;
} AmbisonicMatrix;

#define MAPPING_MATRIX_ENTRY(stem, kind) \
{ &mapping_matrix_ ## stem ## _ ## kind, mapping_matrix_ ## stem ## _ ## kind ## _data, \
sizeof(mapping_matrix_ ## stem ## _ ## kind ## _data) }

static const AmbisonicMatrix ambisonic_mixing_matrices[
MAPPING_MATRIX_MAX_AMBISONIC_ORDER + 1] = {
{ NULL, NULL, 0 },
MAPPING_MATRIX_ENTRY(foa, mixing),
MAPPING_MATRIX_ENTRY(soa, mixing),
MAPPING_MATRIX_ENTRY(toa, mixing),
MAPPING_MATRIX_ENTRY(fourthoa, mixing),
MAPPING_MATRIX_ENTRY(fifthoa, mixing),
MAPPING_MATRIX_ENTRY(sixthoa, mixing),
MAPPING_MATRIX_ENTRY(seventhoa, mixing),
MAPPING_MATRIX_ENTRY(eighthoa, mixing),
MAPPING_MATRIX_ENTRY(ninthoa, mixing),
MAPPING_MATRIX_ENTRY(tenthoa, mixing),
MAPPING_MATRIX_ENTRY(eleventhoa, mixing),
MAPPING_MATRIX_ENTRY(twelfthoa, mixing),
MAPPING_MATRIX_ENTRY(thirteenthoa, mixing),
MAPPING_MATRIX_ENTRY(fourteenthoa, mixing)
};

static const AmbisonicMatrix ambisonic_demixing_matrices[
MAPPING_MATRIX_MAX_AMBISONIC_ORDER + 1] = {
{ NULL, NULL, 0 },
MAPPING_MATRIX_ENTRY(foa, demixing),
MAPPING_MATRIX_ENTRY(soa, demixing),
MAPPING_MATRIX_ENTRY(toa, demixing),
MAPPING_MATRIX_ENTRY(fourthoa, demixing),
MAPPING_MATRIX_ENTRY(fifthoa, demixing),
MAPPING_MATRIX_ENTRY(sixthoa, demixing),
MAPPING_MATRIX_ENTRY(seventhoa, demixing),
MAPPING_MATRIX_ENTRY(eighthoa, demixing),
MAPPING_MATRIX_ENTRY(ninthoa, demixing),
MAPPING_MATRIX_ENTRY(tenthoa, demixing),
MAPPING_MATRIX_ENTRY(eleventhoa, demixing),
MAPPING_MATRIX_ENTRY(twelfthoa, demixing),
MAPPING_MATRIX_ENTRY(thirteenthoa, demixing),
MAPPING_MATRIX_ENTRY(fourteenthoa, demixing)
};

int mapping_matrix_get_ambisonic(int order, int demixing,
const MappingMatrix **matrix, const opus_int16 **data, opus_int32 *data_size)
{
const AmbisonicMatrix *entry;

if (order < 1 || order > MAPPING_MATRIX_MAX_AMBISONIC_ORDER)
return OPUS_BAD_ARG;

entry = demixing ? &ambisonic_demixing_matrices[order]
: &ambisonic_mixing_matrices[order];
if (matrix)
*matrix = entry->matrix;
if (data)
*data = entry->data;
if (data_size)
*data_size = entry->data_size;
return OPUS_OK;
}
82 changes: 81 additions & 1 deletion src/mapping_matrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,33 @@ void mapping_matrix_multiply_channel_out_int24(
int output_rows,
int frame_size
);
/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics.
/* Highest ambisonic order with a built-in projection matrix pair. */
#define MAPPING_MATRIX_MAX_AMBISONIC_ORDER 14

/* A mapping matrix can only be stored in an Ogg OpusHead (RFC 8486 section 3.2)
* if its cell data fits in one Ogg page: 65025 octets of payload less the
* 21-octet OpusHead prefix. Ambisonic orders up to 12 satisfy this (order 12 is
* 171x171 cells = 58482 octets); orders 13 and 14 do not, and can only be
* carried by a container without that limit.
*/
#define MAPPING_MATRIX_MAX_OGG_HEADER_OCTETS 65004

/* Look up the built-in projection matrix pair for ambisonic order `order`
* (1 to MAPPING_MATRIX_MAX_AMBISONIC_ORDER), returning the demixing matrix when
* `demixing` is set and the mixing matrix otherwise. Returns OPUS_BAD_ARG if no
* table exists for that order, in which case the outputs are untouched.
*/
int mapping_matrix_get_ambisonic(
int order,
int demixing,
const MappingMatrix **matrix,
const opus_int16 **data,
opus_int32 *data_size
);

/* Pre-computed mixing and demixing matrices for 1st to 14th-order ambisonics.
* 1st to 5th order live in mapping_matrix.c, 6th to 14th in
* mapping_matrix_hoa.c.
* foa: first-order ambisonics
* soa: second-order ambisonics
* toa: third-order ambisonics
Expand All @@ -139,6 +165,33 @@ extern const opus_int16 mapping_matrix_fourthoa_mixing_data[729];
extern const MappingMatrix mapping_matrix_fifthoa_mixing;
extern const opus_int16 mapping_matrix_fifthoa_mixing_data[1444];

extern const MappingMatrix mapping_matrix_sixthoa_mixing;
extern const opus_int16 mapping_matrix_sixthoa_mixing_data[2601];

extern const MappingMatrix mapping_matrix_seventhoa_mixing;
extern const opus_int16 mapping_matrix_seventhoa_mixing_data[4356];

extern const MappingMatrix mapping_matrix_eighthoa_mixing;
extern const opus_int16 mapping_matrix_eighthoa_mixing_data[6889];

extern const MappingMatrix mapping_matrix_ninthoa_mixing;
extern const opus_int16 mapping_matrix_ninthoa_mixing_data[10404];

extern const MappingMatrix mapping_matrix_tenthoa_mixing;
extern const opus_int16 mapping_matrix_tenthoa_mixing_data[15129];

extern const MappingMatrix mapping_matrix_eleventhoa_mixing;
extern const opus_int16 mapping_matrix_eleventhoa_mixing_data[21316];

extern const MappingMatrix mapping_matrix_twelfthoa_mixing;
extern const opus_int16 mapping_matrix_twelfthoa_mixing_data[29241];

extern const MappingMatrix mapping_matrix_thirteenthoa_mixing;
extern const opus_int16 mapping_matrix_thirteenthoa_mixing_data[39204];

extern const MappingMatrix mapping_matrix_fourteenthoa_mixing;
extern const opus_int16 mapping_matrix_fourteenthoa_mixing_data[51529];

extern const MappingMatrix mapping_matrix_foa_demixing;
extern const opus_int16 mapping_matrix_foa_demixing_data[36];

Expand All @@ -154,4 +207,31 @@ extern const opus_int16 mapping_matrix_fourthoa_demixing_data[729];
extern const MappingMatrix mapping_matrix_fifthoa_demixing;
extern const opus_int16 mapping_matrix_fifthoa_demixing_data[1444];

extern const MappingMatrix mapping_matrix_sixthoa_demixing;
extern const opus_int16 mapping_matrix_sixthoa_demixing_data[2601];

extern const MappingMatrix mapping_matrix_seventhoa_demixing;
extern const opus_int16 mapping_matrix_seventhoa_demixing_data[4356];

extern const MappingMatrix mapping_matrix_eighthoa_demixing;
extern const opus_int16 mapping_matrix_eighthoa_demixing_data[6889];

extern const MappingMatrix mapping_matrix_ninthoa_demixing;
extern const opus_int16 mapping_matrix_ninthoa_demixing_data[10404];

extern const MappingMatrix mapping_matrix_tenthoa_demixing;
extern const opus_int16 mapping_matrix_tenthoa_demixing_data[15129];

extern const MappingMatrix mapping_matrix_eleventhoa_demixing;
extern const opus_int16 mapping_matrix_eleventhoa_demixing_data[21316];

extern const MappingMatrix mapping_matrix_twelfthoa_demixing;
extern const opus_int16 mapping_matrix_twelfthoa_demixing_data[29241];

extern const MappingMatrix mapping_matrix_thirteenthoa_demixing;
extern const opus_int16 mapping_matrix_thirteenthoa_demixing_data[39204];

extern const MappingMatrix mapping_matrix_fourteenthoa_demixing;
extern const opus_int16 mapping_matrix_fourteenthoa_demixing_data[51529];

#endif /* MAPPING_MATRIX_H */
Loading