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
14 changes: 10 additions & 4 deletions celt/celt.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,17 @@
#define CELTDecoder OacCustomDecoder
#define CELTMode OacCustomMode

/** Maximum supported ambisonics order. */
#define OAC_MAX_AMBISONICS_ORDER 5
/** Maximum ambisonics order the bitstream and the decoder support.
* The extended ToC codes the order as 2*C+S on 4 bits, so 15 is the largest
* order that can be signalled at all. (15+1)^2 = 256 channels. */
#define OAC_MAX_AMBISONICS_ORDER 15
/** Maximum ambisonics order the *encoder* supports. Lower than the decoder
* limit because we only have projection matrices up to order 5. */
#define OAC_MAX_ENCODER_AMBISONICS_ORDER 5
#define OAC_MAX_AMBISONICS_CHANNELS ((OAC_MAX_AMBISONICS_ORDER+1)*(OAC_MAX_AMBISONICS_ORDER+1))
#define OAC_MAX_CHANNELS 255
/* Check that OAC_MAX_CHANNELS is large enough */
#define OAC_MAX_CHANNELS 256
/* Check that OAC_MAX_CHANNELS is large enough. This is now tight: raising
OAC_MAX_AMBISONICS_ORDER without raising OAC_MAX_CHANNELS will trip it. */
typedef char oac_assert_max_channels_sufficient[(OAC_MAX_CHANNELS >= OAC_MAX_AMBISONICS_CHANNELS) ? 1 : -1];
#define LEAK_BANDS 19

Expand Down
6 changes: 3 additions & 3 deletions celt/celt_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ static void oaci_celt_decode_lost(CELTDecoder * OAC_RESTRICT st, int N, int LM
out_syn[c] = decode_mem[c] + decode_buffer_size - N;
} while (++c < C);
{
int max_channels = (st->format == OAC_FORMAT_AMBISONICS) ? C : 2;
int max_channels = IMAX(2, C);
oldBandE = (celt_glog*)(st->_decode_mem + (decode_buffer_size + overlap)*C);
oldLogE = oldBandE + max_channels*nbEBands;
oldLogE2 = oldLogE + max_channels*nbEBands;
Expand Down Expand Up @@ -1125,7 +1125,7 @@ int oaci_celt_decode_with_ec_dred(CELTDecoder * OAC_RESTRICT st, const unsigned

/* For band energy arrays, standard format always uses stride 2 (even for mono),
ambisonics uses the actual channel count. */
max_channels = (st->format == OAC_FORMAT_AMBISONICS) ? C : 2;
max_channels = IMAX(2, CC);
oldBandE = (celt_glog*)(st->_decode_mem + (decode_buffer_size + overlap)*CC);
oldLogE = oldBandE + max_channels*nbEBands;
oldLogE2 = oldLogE + max_channels*nbEBands;
Expand Down Expand Up @@ -1645,7 +1645,7 @@ int oac_custom_decoder_ctl(CELTDecoder * OAC_RESTRICT st, int request, ...) {
int i;
celt_glog *oldBandE, *oldLogE, *oldLogE2;
int decode_buffer_size;
int max_channels = (st->format == OAC_FORMAT_AMBISONICS) ? st->channels : 2;
int max_channels = IMAX(2, st->channels);
#ifdef ENABLE_QEXT
int qext_scale = st->qext_scale;
#endif
Expand Down
80 changes: 57 additions & 23 deletions include/oac.h
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,6 @@ OAC_EXPORT int oac_decoder_dred_decode_float(OacDecoder *st, const OacDRED *dred
* @param [out] frames <tt>char*[OAC_MAX_FRAMES_PER_PACKET]</tt> encapsulated frames
* @param [out] size <tt>oac_int32[OAC_MAX_FRAMES_PER_PACKET]</tt> sizes of the encapsulated frames
* @param [out] payload_offset <tt>int*</tt>: returns the position of the payload within the packet (in bytes)
* @param [in] format <tt>int</tt>: Audio format (OAC_FORMAT_STANDARD or OAC_FORMAT_AMBISONICS)
* @returns number of frames
*/
OAC_EXPORT int oac_packet_parse(
Expand All @@ -764,38 +763,57 @@ OAC_EXPORT int oac_packet_parse(
unsigned char *out_toc,
const unsigned char *frames[OAC_MAX_FRAMES_PER_PACKET],
oac_int32 size[OAC_MAX_FRAMES_PER_PACKET],
int *payload_offset,
int format) OAC_ARG_NONNULL(1) OAC_ARG_NONNULL(5);
int *payload_offset) OAC_ARG_NONNULL(1) OAC_ARG_NONNULL(5);

/** Gets the bandwidth of an Oac packet.
* @param [in] data <tt>char*</tt>: Oac packet
* @param [in] len <tt>oac_int32</tt>: Length of packet
* @retval OAC_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass)
* @retval OAC_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass)
* @retval OAC_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass)
* @retval OAC_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass)
* @retval OAC_BANDWIDTH_FULLBAND Fullband (20kHz bandpass)
* @retval OAC_BAD_ARG Insufficient data was passed to the function
* @retval OAC_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
*/
OAC_EXPORT OAC_WARN_UNUSED_RESULT int oac_packet_get_bandwidth(const unsigned char *data) OAC_ARG_NONNULL(1);
OAC_EXPORT OAC_WARN_UNUSED_RESULT int oac_packet_get_bandwidth(const unsigned char *data,
oac_int32 len) OAC_ARG_NONNULL(1);

/** Gets the number of samples per frame from an Oac packet.
* @param [in] data <tt>char*</tt>: Oac packet.
* This must contain at least one byte of
* data.
* @param [in] len <tt>oac_int32</tt>: Length of packet
* @param [in] Fs <tt>oac_int32</tt>: Sampling rate in Hz.
* This must be a multiple of 400, or
* inaccurate results will be returned.
* @returns Number of samples per frame.
* @retval OAC_BAD_ARG Insufficient data was passed to the function
* @retval OAC_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
*/
OAC_EXPORT OAC_WARN_UNUSED_RESULT int oac_packet_get_samples_per_frame(const unsigned char *data,
oac_int32 Fs) OAC_ARG_NONNULL(1);
oac_int32 len, oac_int32 Fs) OAC_ARG_NONNULL(1);

/** Gets the number of channels from an Oac packet.
* @param [in] data <tt>char*</tt>: Oac packet
* @returns Number of channels
/** Gets the number of channels described by an Oac packet.
* Note that this is what the packet <em>contains</em>; a decoder may still
* up/downmix it to the channel count it was created with.
* @param [in] packet <tt>char*</tt>: Oac packet
* @param [in] len <tt>oac_int32</tt>: Length of packet
* @returns Number of channels, from 1 to 256
* @retval OAC_BAD_ARG Insufficient data was passed to the function
* @retval OAC_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
*/
OAC_EXPORT OAC_WARN_UNUSED_RESULT int oac_packet_get_nb_channels(const unsigned char packet[],
oac_int32 len) OAC_ARG_NONNULL(1);

/** Gets the format of an Oac packet.
* @param [in] packet <tt>char*</tt>: Oac packet
* @param [in] len <tt>oac_int32</tt>: Length of packet
* @retval OAC_FORMAT_STANDARD Mono, stereo or surround
* @retval OAC_FORMAT_AMBISONICS Ambisonics
* @retval OAC_BAD_ARG Insufficient data was passed to the function
* @retval OAC_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
*/
OAC_EXPORT OAC_WARN_UNUSED_RESULT int oac_packet_get_nb_channels(const unsigned char *data) OAC_ARG_NONNULL(1);
OAC_EXPORT OAC_WARN_UNUSED_RESULT int oac_packet_get_format(const unsigned char packet[],
oac_int32 len) OAC_ARG_NONNULL(1);

/** Gets the number of frames in an Oac packet.
* @param [in] packet <tt>char*</tt>: Oac packet
Expand Down Expand Up @@ -891,7 +909,7 @@ OAC_EXPORT void oac_pcm_soft_clip(float *pcm, int frame_size, int channels, floa
* int len;
* while (get_next_packet(&data, &len))
* {
* unsigned char out[OAC_SIZE_MAX + 1];
* unsigned char out[OAC_SIZE_MAX + 3];
* oac_int32 out_len;
* int nb_frames;
* int err;
Expand Down Expand Up @@ -928,11 +946,13 @@ OAC_EXPORT void oac_pcm_soft_clip(float *pcm, int frame_size, int channels, floa
* oac_int32 len[(TARGET_DURATION_MS*2/5)+1];
* int nb_packets;
* // Worst case output size: every frame may need a three-byte length field,
* // plus the TOC and frame count bytes. MAX_FRAME_BYTES is the largest frame
* // the producer emits; frames may be up to OAC_SIZE_MAX bytes long.
* unsigned char out[(MAX_FRAME_BYTES+3)*(TARGET_DURATION_MS*2/5)+2];
* // plus up to three ToC bytes for the packet. MAX_FRAME_BYTES is the largest
* // frame the producer emits; frames may be up to OAC_SIZE_MAX bytes long.
* unsigned char out[(MAX_FRAME_BYTES+3)*(TARGET_DURATION_MS*2/5)+3];
* oac_int32 out_len;
* int prev_toc;
* int prev_channels;
* int prev_format;
* nb_packets = 0;
* while (get_next_packet(data+nb_packets, len+nb_packets))
* {
Expand All @@ -955,9 +975,15 @@ OAC_EXPORT void oac_pcm_soft_clip(float *pcm, int frame_size, int channels, floa
* // been set to a valid value. Additionally, len[nb_packets] > 0 is
* // guaranteed by the call to oac_packet_get_nb_frames() above, so the
* // reference to data[nb_packets][0] should be valid.
* // N.B., Comparing the top 5 bits covers the coding mode, audio bandwidth
* // and frame size. The channel count is not compared here because the
* // same count can be signalled in more than one way, so it has to be
* // resolved with oac_packet_get_nb_channels()/oac_packet_get_format().
* if (nb_packets > 0 && (
* ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) ||
* oac_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames >
* ((prev_toc & 0xF8) != (data[nb_packets][0] & 0xF8)) ||
* oac_packet_get_nb_channels(data[nb_packets], len[nb_packets]) != prev_channels ||
* oac_packet_get_format(data[nb_packets], len[nb_packets]) != prev_format ||
* oac_packet_get_samples_per_frame(data[nb_packets], len[nb_packets], 48000)*nb_frames >
* TARGET_DURATION_MS*48))
* {
* out_len = oac_repacketizer_out(rp, out, sizeof(out));
Expand All @@ -980,6 +1006,8 @@ OAC_EXPORT void oac_pcm_soft_clip(float *pcm, int frame_size, int channels, floa
* return err;
* }
* prev_toc = data[nb_packets][0];
* prev_channels = oac_packet_get_nb_channels(data[nb_packets], len[nb_packets]);
* prev_format = oac_packet_get_format(data[nb_packets], len[nb_packets]);
* nb_packets++;
* }
* // Output the final, partial packet.
Expand Down Expand Up @@ -1022,16 +1050,14 @@ OAC_EXPORT OAC_WARN_UNUSED_RESULT int oac_repacketizer_get_size(void);
* @see oac_repacketizer_cat
* @param rp <tt>OacRepacketizer*</tt>: The repacketizer state to
* (re)initialize.
* @param format <tt>int</tt>: Audio format (OAC_FORMAT_STANDARD or OAC_FORMAT_AMBISONICS).
* @returns A pointer to the same repacketizer state that was passed in.
*/
OAC_EXPORT OacRepacketizer *oac_repacketizer_init(OacRepacketizer *rp, int format) OAC_ARG_NONNULL(1);
OAC_EXPORT OacRepacketizer *oac_repacketizer_init(OacRepacketizer *rp) OAC_ARG_NONNULL(1);

/** Allocates memory and initializes the new repacketizer with
* oac_repacketizer_init().
* @param format <tt>int</tt>: Audio format (OAC_FORMAT_STANDARD or OAC_FORMAT_AMBISONICS).
*/
OAC_EXPORT OAC_WARN_UNUSED_RESULT OacRepacketizer *oac_repacketizer_create(int format);
OAC_EXPORT OAC_WARN_UNUSED_RESULT OacRepacketizer *oac_repacketizer_create(void);

/** Frees an <code>OacRepacketizer</code> allocated by
* oac_repacketizer_create().
Expand Down Expand Up @@ -1104,7 +1130,7 @@ OAC_EXPORT int oac_repacketizer_cat(OacRepacketizer *rp, const unsigned char *da
* @param maxlen <tt>oac_int32</tt>: The maximum number of bytes to store in
* the output buffer. In order to guarantee
* success, this should be at least
* <code>OAC_SIZE_MAX+1</code> for a single
* <code>OAC_SIZE_MAX+3</code> for a single
* frame, or for multiple frames,
* <code>(OAC_SIZE_MAX+4)*(end-begin)</code>.
* However, <code>3*(end-begin)</code> plus
Expand All @@ -1113,11 +1139,19 @@ OAC_EXPORT int oac_repacketizer_cat(OacRepacketizer *rp, const unsigned char *da
* oac_repacketizer_init() or
* oac_repacketizer_create() is also
* sufficient, and possibly much smaller.
* The number of frames requested must be one the ToC can signal for the frame
* size in the repacketizer state. The packet duration is the frame duration
* stepped forward along the list 2.5, 5, 10, 20, 40, 60, 80, 120 ms, so the
* legal counts are 1,2,4,8,16,24,32,48 for 2.5 ms frames; 1,2,4,8,12,16,24 for
* 5 ms; 1,2,4,6,8,12 for 10 ms; 1,2,3,4,6 for 20 ms; 1,2,3 for 40 ms; and 1,2
* for 60 ms. Any other count returns #OAC_BAD_ARG.
* @returns The total size of the output packet on success, or an error code
* on failure.
* @retval #OAC_BAD_ARG <code>[begin,end)</code> was an invalid range of
* frames (begin < 0, begin >= end, or end >
* oac_repacketizer_get_nb_frames()).
* oac_repacketizer_get_nb_frames()), or
* <code>end-begin</code> is not a frame count the ToC
* can signal for this frame size.
* @retval #OAC_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
* complete output packet.
*/
Expand Down
33 changes: 29 additions & 4 deletions include/oac_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,30 @@ extern "C" {
* @hideinitializer */
#define OAC_SIZE_MAX 2105535

/** @cond OAC_INTERNAL_DOC
* Table of Contents (ToC) layout, bits numbered MSB-first as in RFC 6716.
*
* Main ToC byte, always present:
* bits 0-5 (mask 0xFC) M/S mode / bandwidth / frame duration, plus the
* stereo-or-channel-LSB flag S (mask 0x04)
* bit 6 (mask 0x02) X an extended ToC byte follows
* bit 7 (mask 0x01) P padding is present
*
* Extended ToC byte, present iff X=1:
* bit 0 (mask 0x80) V 0 = all frames the same size, 1 = explicit sizes
* bits 1-3 (mask 0x70) F increment along 2.5/5/10/20/40/60/80/120 ms
* bit 4 (mask 0x08) A 0 = regular/surround, 1 = ambisonics
* bits 5-7 (mask 0x07) C channel count / ambisonics order field
*
* With X=0 the packet holds exactly one frame of 1 or 2 (=S+1) channels.
* With X=1, A=1 the ambisonics order is 2*C+S, giving (order+1)^2 channels.
* With X=1, A=0 the channel count is 2*C+S+1, except that C=7,S=1 escapes to
* one more byte holding (channels-1).
*
* Byte order: main ToC, extended ToC, channel escape byte, padding length
* bytes, frame length fields, frame data, padding.
* @endcond */

#define OAC_SIGNAL_VOICE 3001 /**< Signal being encoded is voice */
#define OAC_SIGNAL_MUSIC 3002 /**< Signal being encoded is music */
#define OAC_BANDWIDTH_NARROWBAND 1101 /**< 4 kHz bandpass @hideinitializer*/
Expand All @@ -288,6 +312,10 @@ extern "C" {
#define OAC_BANDWIDTH_SUPERWIDEBAND 1104 /**<12 kHz bandpass @hideinitializer*/
#define OAC_BANDWIDTH_FULLBAND 1105 /**<20 kHz bandpass @hideinitializer*/

/* NOTE: OAC_FRAMESIZE_2_5_MS .. OAC_FRAMESIZE_120_MS must stay contiguous and in
increasing order: oaci_frame_size_select() indexes oaci_frame_dur[] with
(value - OAC_FRAMESIZE_2_5_MS). There is deliberately no 100 ms: the packet
duration list is 2.5/5/10/20/40/60/80/120 ms and 100 ms is not representable. */
#define OAC_FRAMESIZE_ARG 5000 /**< Select frame size from the argument (default) */
#define OAC_FRAMESIZE_2_5_MS 5001 /**< Use 2.5 ms frames */
#define OAC_FRAMESIZE_5_MS 5002 /**< Use 5 ms frames */
Expand All @@ -296,8 +324,7 @@ extern "C" {
#define OAC_FRAMESIZE_40_MS 5005 /**< Use 40 ms frames */
#define OAC_FRAMESIZE_60_MS 5006 /**< Use 60 ms frames */
#define OAC_FRAMESIZE_80_MS 5007 /**< Use 80 ms frames */
#define OAC_FRAMESIZE_100_MS 5008 /**< Use 100 ms frames */
#define OAC_FRAMESIZE_120_MS 5009 /**< Use 120 ms frames */
#define OAC_FRAMESIZE_120_MS 5008 /**< Use 120 ms frames */

/**@}*/

Expand Down Expand Up @@ -659,7 +686,6 @@ extern "C" {
* <dt>OAC_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
* <dt>OAC_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
* <dt>OAC_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
* <dt>OAC_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
* <dt>OAC_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
* </dl>
* @hideinitializer */
Expand All @@ -676,7 +702,6 @@ extern "C" {
* <dt>OAC_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
* <dt>OAC_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
* <dt>OAC_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
* <dt>OAC_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
* <dt>OAC_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
* </dl>
* @hideinitializer */
Expand Down
2 changes: 1 addition & 1 deletion include/oac_multistream.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ extern "C" {
* nb_frames = oac_packet_get_nb_frames(data, len);
* if (nb_frames < 1)
* return nb_frames;
* nb_samples = oac_packet_get_samples_per_frame(data, 48000) * nb_frames;
* nb_samples = oac_packet_get_samples_per_frame(data, len, 48000) * nb_frames;
* @endcode
*
* The general encoding and decoding process proceeds exactly the same as in
Expand Down
Loading
Loading