Loading system/embdrv/lc3/include/lc3.h +60 −19 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ * Bluetooth Specification v1.0 * * * The LC3 is an efficient, low latency, audio codec. * The LC3 is an efficient low latency audio codec. * * - Unlike most other codecs, the LC3 codec is focused on audio streaming * in constrained (on packet sizes and interval) tranport layer. Loading @@ -35,8 +35,8 @@ * the user (or transport layer). * * However, the bitrate (bytes budget for encoding a frame) can be * freely changed at any time. BUT it does never rely on signal * complexity, it can follow a temporary bandwidth increase or reduction. * freely changed at any time. But will not rely on signal complexity, * it can follow a temporary bandwidth increase or reduction. * * - Unlike classic codecs, the LC3 codecs does not run on fixed amount * of samples as input. It operate only on fixed frame duration, for Loading @@ -54,8 +54,8 @@ * 1. The frame size will not be 7.5 ms or 10 ms, but is scaled * by 'supported samplerate' / 'input samplerate' * * 2. The bandwith will be hard limited (to 20 KHz) if you select 48 KHz. * The encoded bandwith will also be affected by the above inverse * 2. The bandwidth will be hard limited (to 20 KHz) if you select 48 KHz. * The encoded bandwidth will also be affected by the above inverse * factor of 20 KHz. * * Applied to 44.1 KHz, we get : Loading @@ -63,23 +63,23 @@ * 1. About 8.16 ms frame duration, instead of 7.5 ms * About 10.88 ms frame duration, instead of 10 ms * * 2. The bandwith becomes limited to 18.375 KHz * 2. The bandwidth becomes limited to 18.375 KHz * * * --- How to encode --- * --- How to encode / decode --- * * An encoder context need to be setup. This context keep states on * the current stream to encode, and samples that overlapped accross * An encoder / decoder context need to be setup. This context keep states * on the current stream to proceed, and samples that overlapped across * frames. * * You have two ways to setup the encoder : * You have two ways to setup the encoder / decoder : * * - Using static memory allocation (this module does not rely on * any dynamic memory allocation). The types `lc3_encoder_mem_16k_t`, * and `lc3_encoder_mem_48k_t` have size of the memory needed for * any dynamic memory allocation). The types `lc3_xxcoder_mem_16k_t`, * and `lc3_xxcoder_mem_48k_t` have size of the memory needed for * encoding up to 16 KHz or 48 KHz. * * - Using dynamic memory allocation. The `lc3_encoder_size()` procedure * - Using dynamic memory allocation. The `lc3_xxcoder_size()` procedure * returns the needed memory size, for a given configuration. The memory * space must be aligned to a pointer size. As an example, you can setup * encoder like this : Loading Loading @@ -149,6 +149,7 @@ extern "C" { */ typedef struct lc3_encoder *lc3_encoder_t; typedef struct lc3_decoder *lc3_decoder_t; /** Loading @@ -156,18 +157,22 @@ typedef struct lc3_encoder *lc3_encoder_t; * * Propose types suitable for static memory allocation, supporting * any frame duration, and maximum samplerates 16k and 48k respectively * You can customize your type using the `LC3_ENCODER_MEM_T` macro. * You can customize your type using the `LC3_ENCODER_MEM_T` or * `LC3_DECODER_MEM_T` macro. */ typedef LC3_ENCODER_MEM_T(10000, 16000) lc3_encoder_mem_16k_t; typedef LC3_ENCODER_MEM_T(10000, 48000) lc3_encoder_mem_48k_t; typedef LC3_DECODER_MEM_T(10000, 16000) lc3_decoder_mem_16k_t; typedef LC3_DECODER_MEM_T(10000, 48000) lc3_decoder_mem_48k_t; /** * Return the number of PCM samples in a frame * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 * return Number of PCM samples, 0 on bad parameter * return Number of PCM samples, -1 on bad parameters */ int lc3_frame_samples(int dt_us, int sr_hz); Loading @@ -175,7 +180,7 @@ int lc3_frame_samples(int dt_us, int sr_hz); * Return the size of frames, from bitrate * dt_us Frame duration in us, 7500 or 10000 * bitrate Target bitrate in bit per seconds * return The floor size in bytes of the frames * return The floor size in bytes of the frames, -1 on bad parameters */ int lc3_frame_bytes(int dt_us, int bitrate); Loading @@ -183,10 +188,18 @@ int lc3_frame_bytes(int dt_us, int bitrate); * Resolve the bitrate, from the size of frames * dt_us Frame duration in us, 7500 or 10000 * nbytes Size in bytes of the frames * return The according bitrate in bps * return The according bitrate in bps, -1 on bad parameters */ int lc3_resolve_bitrate(int dt_us, int nbytes); /** * Return algorithmic delay, as a number of samples * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 * return Number of algorithmic delay samples, -1 on bad parameters */ int lc3_delay_samples(int dt_us, int sr_hz); /** * Return size needed for an encoder * dt_us Frame duration in us, 7500 or 10000 Loading @@ -208,11 +221,39 @@ lc3_encoder_t lc3_setup_encoder(int dt_us, int sr_hz, void *mem); * Encode a frame * encoder Handle of the encoder * pcm, pitch Input PCM samples, and count between two consecutives * out, nbytes Output buffer, and size in bytes (20 to 400) * nbytes Target size, in bytes, of the frame (20 to 400) * out Output buffer of `nbytes` size * return 0: On success -1: Wrong parameters */ int lc3_encode(lc3_encoder_t encoder, const int16_t *pcm, int pitch, void *out, int nbytes); const int16_t *pcm, int pitch, int nbytes, void *out); /** * Return size needed for an decoder * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 * return Size of then decoder in bytes, 0 on bad parameters */ unsigned lc3_decoder_size(int dt_us, int sr_hz); /** * Setup decoder * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 * mem Decoder memory space, aligned to pointer type * return Decoder as an handle, NULL on bad parameters */ lc3_decoder_t lc3_setup_decoder(int dt_us, int sr_hz, void *mem); /** * Decode a frame * decoder Handle of the decoder * in, nbytes Input bitstream, and size in bytes, NULL performs PLC * pcm, pitch Output PCM samples, and count between two consecutives * return 0: On success 1: PLC operated -1: Wrong parameters */ int lc3_decode(lc3_decoder_t decoder, const void *in, int nbytes, int16_t *pcm, int pitch); #ifdef __cplusplus Loading system/embdrv/lc3/include/lc3_private.h +52 −15 Original line number Diff line number Diff line Loading @@ -19,12 +19,14 @@ #ifndef __LC3_PRIVATE_H #define __LC3_PRIVATE_H #include <stdint.h> #include <stdbool.h> /** * Return number of samples, delayed samples and * encoded spectrum coefficients within a frame * For decoding, add number of samples of 18 ms history */ #define __LC3_NS(dt_us, sr_hz) \ Loading @@ -34,6 +36,9 @@ ( (dt_us) == 7500 ? 23 * __LC3_NS(dt_us, sr_hz) / 30 \ : 5 * __LC3_NS(dt_us, sr_hz) / 8 ) #define __LC3_NH(sr_hz) \ ( (18 * sr_hz) / 1000 ) /** * Frame duration 7.5ms or 10ms Loading Loading @@ -62,19 +67,19 @@ enum lc3_srate { /** * Encoder state * Encoder state and memory */ typedef struct lc3_attdet_state { typedef struct lc3_attdet_analysis { float en1, an1; int p_att; } lc3_attdet_state_t; } lc3_attdet_analysis_t; struct lc3_ltpf_hp50_state { float s1, s2; }; typedef struct lc3_ltpf_state { typedef struct lc3_ltpf_analysis { bool active; int pitch; float nc[2]; Loading @@ -83,29 +88,24 @@ typedef struct lc3_ltpf_state { float x_12k8[384]; float x_6k4[178]; int tc; } lc3_ltpf_state_t; } lc3_ltpf_analysis_t; typedef struct lc3_quant_state { typedef struct lc3_spec_analysis { float nbits_off; int nbits_spare; } lc3_quant_state_t; } lc3_spec_analysis_t; struct lc3_encoder { enum lc3_dt dt; enum lc3_srate sr; lc3_attdet_state_t attdet; lc3_ltpf_state_t ltpf; lc3_quant_state_t quant; lc3_attdet_analysis_t attdet; lc3_ltpf_analysis_t ltpf; lc3_spec_analysis_t spec; float *xs, *xf, s[0]; }; /** * Encoder memory */ #define LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz) \ ( 2*__LC3_NS(dt_us, sr_hz) + __LC3_ND(dt_us, sr_hz) ) Loading @@ -116,4 +116,41 @@ struct lc3_encoder { } /** * Decoder state and memory */ typedef struct lc3_ltpf_synthesis { bool active; int pitch; float c[12][2], x[12]; } lc3_ltpf_synthesis_t; typedef struct lc3_plc_state { uint16_t seed; int count; float alpha; } lc3_plc_state_t; struct lc3_decoder { enum lc3_dt dt; enum lc3_srate sr; lc3_ltpf_synthesis_t ltpf; lc3_plc_state_t plc; float *xs, *xd, *xg, s[0]; }; #define LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz) \ ( __LC3_NH(sr_hz) + __LC3_NS(dt_us, sr_hz) + \ __LC3_ND(dt_us, sr_hz) + __LC3_NS(dt_us, sr_hz) ) #define LC3_DECODER_MEM_T(dt_us, sr_hz) \ struct { \ struct lc3_decoder __d; \ float __s[LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz)]; \ } #endif /* __LC3_PRIVATE_H */ system/embdrv/lc3/src/attdet.c +6 −6 Original line number Diff line number Diff line Loading @@ -23,11 +23,11 @@ * Time domain attack detector */ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr, unsigned nbytes, struct lc3_attdet_state *state, const float *x) int nbytes, struct lc3_attdet_analysis *attdet, const float *x) { /* --- Check enabling --- */ const unsigned nbytes_ranges[LC3_NUM_DT][LC3_NUM_SRATE - LC3_SRATE_32K][2] = { const int nbytes_ranges[LC3_NUM_DT][LC3_NUM_SRATE - LC3_SRATE_32K][2] = { [LC3_DT_7M5] = { { 61, 149 }, { 75, 149 } }, [LC3_DT_10M] = { { 81, INT_MAX }, { 100, INT_MAX } }, }; Loading Loading @@ -78,15 +78,15 @@ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr, float a[4]; for (int i = 0; i < nblk; i++) { a[i] = fmaxf(0.25 * state->an1, state->en1); state->en1 = e[i], state->an1 = a[i]; a[i] = fmaxf(0.25 * attdet->an1, attdet->en1); attdet->en1 = e[i], attdet->an1 = a[i]; if (e[i] > 8.5 * a[i]) p_att = i + 1; } int att = state->p_att >= 1 + (nblk >> 1) || p_att > 0; state->p_att = p_att; int att = attdet->p_att >= 1 + (nblk >> 1) || p_att > 0; attdet->p_att = p_att; return att; } system/embdrv/lc3/src/attdet.h +2 −2 Original line number Diff line number Diff line Loading @@ -33,12 +33,12 @@ * Time domain attack detector * dt, sr Duration and samplerate of the frame * nbytes Size in bytes of the frame * state State of the Attack Detector * attdet Context of the Attack Detector * x [-6..-1] Previous, [0..ns-1] Current samples * return 1: Attack detected 0: Otherwise */ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr, unsigned nbytes, lc3_attdet_state_t *state, const float *x); int nbytes, lc3_attdet_analysis_t *attdet, const float *x); #endif /* __LC3_ATTDET_H */ system/embdrv/lc3/src/bits.c +208 −81 Original line number Diff line number Diff line Loading @@ -20,18 +20,127 @@ #include "common.h" /* ---------------------------------------------------------------------------- * Common * -------------------------------------------------------------------------- */ static inline int ac_get(struct lc3_bits_buffer *); static inline void accu_load(struct lc3_bits_accu *, struct lc3_bits_buffer *); /** * Arithmetic coder return range bits * ac Arithmetic coder * return 1 + log2(ac->range) */ static int ac_get_range_bits(const struct lc3_bits_ac *ac) { int nbits = 0; for (unsigned r = ac->range; r; r >>= 1, nbits++); return nbits; } /** * Arithmetic coder return pending bits * ac Arithmetic coder * return Pending bits */ static int ac_get_pending_bits(const struct lc3_bits_ac *ac) { return 26 - ac_get_range_bits(ac) + ((ac->cache >= 0) + ac->carry_count) * 8; } /** * Return number of bits left in the bitstream * bits Bitstream context * return >= 0: Number of bits left < 0: Overflow */ static int get_bits_left(const struct lc3_bits *bits) { const struct lc3_bits_buffer *buffer = &bits->buffer; const struct lc3_bits_accu *accu = &bits->accu; const struct lc3_bits_ac *ac = &bits->ac; uintptr_t end = (uintptr_t)buffer->p_bw + (bits->mode == LC3_BITS_MODE_READ ? LC3_ACCU_BITS/8 : 0); uintptr_t start = (uintptr_t)buffer->p_fw - (bits->mode == LC3_BITS_MODE_READ ? LC3_AC_BITS/8 : 0); return 8 * (end - start) - (accu->n + accu->nover + ac_get_pending_bits(ac)); } /** * Setup bitstream writing */ void lc3_setup_bits(struct lc3_bits *bits, enum lc3_bits_mode mode, void *buffer, int len) { *bits = (struct lc3_bits){ .mode = mode, .accu = { .n = mode == LC3_BITS_MODE_READ ? LC3_ACCU_BITS : 0, }, .ac = { .range = 0xffffff, .cache = -1 }, .buffer = { .start = (uint8_t *)buffer, .end = (uint8_t *)buffer + len, .p_fw = (uint8_t *)buffer, .p_bw = (uint8_t *)buffer + len, } }; if (mode == LC3_BITS_MODE_READ) { struct lc3_bits_ac *ac = &bits->ac; struct lc3_bits_accu *accu = &bits->accu; struct lc3_bits_buffer *buffer = &bits->buffer; ac->low = ac_get(buffer) << 16; ac->low |= ac_get(buffer) << 8; ac->low |= ac_get(buffer); accu_load(accu, buffer); } } /** * Return number of bits left in the bitstream */ int lc3_get_bits_left(const struct lc3_bits *bits) { return LC3_MAX(get_bits_left(bits), 0); } /** * Return number of bits left in the bitstream */ int lc3_check_bits(const struct lc3_bits *bits) { const struct lc3_bits_ac *ac = &bits->ac; return -(get_bits_left(bits) < 0 || ac->error); } /* ---------------------------------------------------------------------------- * Writing * -------------------------------------------------------------------------- */ /** * Flush the bits accumulator * accu Bitstream accumulator * buffer Bitstream buffer */ static void accu_flush(struct lc3_bits_accu *accu, struct lc3_bits_buffer *buffer) static inline void accu_flush( struct lc3_bits_accu *accu, struct lc3_bits_buffer *buffer) { unsigned nbytes = LC3_MIN(accu->n >> 3, buffer->nleft); int nbytes = LC3_MIN(accu->n >> 3, buffer->p_bw - buffer->p_fw); accu->n -= 8 * nbytes; buffer->nleft -= nbytes; for ( ; nbytes; accu->v >>= 8, nbytes--) *(--buffer->p_bw) = accu->v & 0xff; Loading @@ -45,15 +154,10 @@ static void accu_flush(struct lc3_bits_accu *accu, * buffer Bitstream buffer * byte Byte to output */ static void ac_put(struct lc3_bits_buffer *buffer, unsigned byte) static inline void ac_put(struct lc3_bits_buffer *buffer, int byte) { buffer->overflow |= (buffer->nleft_fw <= 0); if (buffer->overflow) return; if (buffer->p_fw < buffer->end) *(buffer->p_fw++) = byte; buffer->nleft_fw--; buffer->nleft--; } /** Loading @@ -61,8 +165,8 @@ static void ac_put(struct lc3_bits_buffer *buffer, unsigned byte) * ac Arithmetic coder * buffer Bitstream buffer */ static void ac_shift(struct lc3_bits_ac *ac, struct lc3_bits_buffer *buffer) static inline void ac_shift( struct lc3_bits_ac *ac, struct lc3_bits_buffer *buffer) { if (ac->low < 0xff0000 || ac->carry) { Loading @@ -76,38 +180,11 @@ static void ac_shift(struct lc3_bits_ac *ac, ac->carry = 0; } else { ac->carry_count++; } ac->low = (ac->low << 8) & 0xffffff; } /** * Arithmetic coder return range bits * ac Arithmetic coder * return 1 + log2(ac->range) */ static int ac_get_range_bits(const struct lc3_bits_ac *ac) { int nbits = 0; for (unsigned r = ac->range; r; r >>= 1, nbits++); return nbits; } /** * Arithmetic coder return pending bits * ac Arithmetic coder * return Pending bits */ static int ac_get_pending_bits(const struct lc3_bits_ac *ac) { return 26 - ac_get_range_bits(ac) + ((ac->cache >= 0) + ac->carry_count) * 8; } /** * Arithmetic coder termination * ac Arithmetic coder Loading Loading @@ -155,44 +232,12 @@ static void ac_terminate(struct lc3_bits_ac *ac, end_val = nbits < 8 ? 0 : 0xff; } if (buffer->nleft_fw > 0) { if (buffer->p_fw < buffer->end) { *buffer->p_fw &= 0xff >> nbits; *buffer->p_fw |= end_val << (8 - nbits); } } /** * Setup bitstream writing */ void lc3_setup_bits(struct lc3_bits *bits, void *buffer, unsigned len) { *bits = (struct lc3_bits){ .ac = { .range = 0xffffff, .cache = -1 }, .buffer = { .p_fw = (uint8_t *)buffer, .p_bw = (uint8_t *)buffer + len, .nleft_fw = len, .nleft = len } }; } /** * Return number of bits left in the bitstream */ int lc3_get_bits_left(const struct lc3_bits *bits) { int nbits_left = 8 * bits->buffer.nleft; nbits_left -= LC3_MIN(bits->accu.n, nbits_left); nbits_left -= LC3_MIN(ac_get_pending_bits(&bits->ac), nbits_left); return nbits_left; } /** * Flush and terminate bitstream */ Loading @@ -202,7 +247,8 @@ void lc3_flush_bits(struct lc3_bits *bits) struct lc3_bits_accu *accu = &bits->accu; struct lc3_bits_buffer *buffer = &bits->buffer; for (int n = 8 * buffer->nleft - accu->n; n > 0; n -= 32) int nleft = buffer->p_bw - buffer->p_fw; for (int n = 8 * nleft - accu->n; n > 0; n -= 32) lc3_put_bits(bits, 0, LC3_MIN(n, 32)); accu_flush(accu, buffer); Loading @@ -211,19 +257,19 @@ void lc3_flush_bits(struct lc3_bits *bits) } /** * Write from 0 to 32 bits, * Write from 1 to 32 bits, * exceeding the capacity of the accumulator */ void __lc3_put_bits_over(struct lc3_bits *bits, unsigned v, int n) void lc3_put_bits_generic(struct lc3_bits *bits, unsigned v, int n) { struct lc3_bits_accu *accu = &bits->accu; /* --- Fullfill accumulator and flush -- */ /* --- Fulfill accumulator and flush -- */ int n1 = LC3_MIN(ACCU_BITS - accu->n, n); int n1 = LC3_MIN(LC3_ACCU_BITS - accu->n, n); if (n1) { accu->v |= v << accu->n; accu->n = ACCU_BITS; accu->n = LC3_ACCU_BITS; } accu_flush(accu, &bits->buffer); Loading @@ -237,10 +283,91 @@ void __lc3_put_bits_over(struct lc3_bits *bits, unsigned v, int n) /** * Arithmetic coder renormalization */ void __lc3_renorm_ac(struct lc3_bits *bits) void lc3_ac_write_renorm(struct lc3_bits *bits) { struct lc3_bits_ac *ac = &bits->ac; for ( ; ac->range < 0x10000; ac->range <<= 8) ac_shift(ac, &bits->buffer); } /* ---------------------------------------------------------------------------- * Reading * -------------------------------------------------------------------------- */ /** * Arithmetic coder get byte * buffer Bitstream buffer * return Byte read, 0 on overflow */ static inline int ac_get(struct lc3_bits_buffer *buffer) { return buffer->p_fw < buffer->end ? *(buffer->p_fw++) : 0; } /** * Load the accumulator * accu Bitstream accumulator * buffer Bitstream buffer */ static inline void accu_load(struct lc3_bits_accu *accu, struct lc3_bits_buffer *buffer) { int nbytes = LC3_MIN(accu->n >> 3, buffer->p_bw - buffer->start); accu->n -= 8 * nbytes; for ( ; nbytes; nbytes--) { accu->v >>= 8; accu->v |= *(--buffer->p_bw) << (LC3_ACCU_BITS - 8); } if (accu->n >= 8) { accu->nover = LC3_MIN(accu->nover + accu->n, LC3_ACCU_BITS); accu->v >>= accu->n; accu->n = 0; } } /** * Read from 1 to 32 bits, * exceeding the capacity of the accumulator */ unsigned lc3_get_bits_generic(struct lc3_bits *bits, int n) { struct lc3_bits_accu *accu = &bits->accu; struct lc3_bits_buffer *buffer = &bits->buffer; /* --- Fulfill accumulator and read -- */ accu_load(accu, buffer); int n1 = LC3_MIN(LC3_ACCU_BITS - accu->n, n); unsigned v = (accu->v >> accu->n) & ((1u << n1) - 1); accu->n += n1; /* --- Second round --- */ int n2 = n - n1; if (n2) { accu_load(accu, buffer); v |= ((accu->v >> accu->n) & ((1u << n2) - 1)) << n1; accu->n += n2; } return v; } /** * Arithmetic coder renormalization */ void lc3_ac_read_renorm(struct lc3_bits *bits) { struct lc3_bits_ac *ac = &bits->ac; for ( ; ac->range < 0x10000; ac->range <<= 8) ac->low = ((ac->low << 8) | ac_get(&bits->buffer)) & 0xffffff; } Loading
system/embdrv/lc3/include/lc3.h +60 −19 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ * Bluetooth Specification v1.0 * * * The LC3 is an efficient, low latency, audio codec. * The LC3 is an efficient low latency audio codec. * * - Unlike most other codecs, the LC3 codec is focused on audio streaming * in constrained (on packet sizes and interval) tranport layer. Loading @@ -35,8 +35,8 @@ * the user (or transport layer). * * However, the bitrate (bytes budget for encoding a frame) can be * freely changed at any time. BUT it does never rely on signal * complexity, it can follow a temporary bandwidth increase or reduction. * freely changed at any time. But will not rely on signal complexity, * it can follow a temporary bandwidth increase or reduction. * * - Unlike classic codecs, the LC3 codecs does not run on fixed amount * of samples as input. It operate only on fixed frame duration, for Loading @@ -54,8 +54,8 @@ * 1. The frame size will not be 7.5 ms or 10 ms, but is scaled * by 'supported samplerate' / 'input samplerate' * * 2. The bandwith will be hard limited (to 20 KHz) if you select 48 KHz. * The encoded bandwith will also be affected by the above inverse * 2. The bandwidth will be hard limited (to 20 KHz) if you select 48 KHz. * The encoded bandwidth will also be affected by the above inverse * factor of 20 KHz. * * Applied to 44.1 KHz, we get : Loading @@ -63,23 +63,23 @@ * 1. About 8.16 ms frame duration, instead of 7.5 ms * About 10.88 ms frame duration, instead of 10 ms * * 2. The bandwith becomes limited to 18.375 KHz * 2. The bandwidth becomes limited to 18.375 KHz * * * --- How to encode --- * --- How to encode / decode --- * * An encoder context need to be setup. This context keep states on * the current stream to encode, and samples that overlapped accross * An encoder / decoder context need to be setup. This context keep states * on the current stream to proceed, and samples that overlapped across * frames. * * You have two ways to setup the encoder : * You have two ways to setup the encoder / decoder : * * - Using static memory allocation (this module does not rely on * any dynamic memory allocation). The types `lc3_encoder_mem_16k_t`, * and `lc3_encoder_mem_48k_t` have size of the memory needed for * any dynamic memory allocation). The types `lc3_xxcoder_mem_16k_t`, * and `lc3_xxcoder_mem_48k_t` have size of the memory needed for * encoding up to 16 KHz or 48 KHz. * * - Using dynamic memory allocation. The `lc3_encoder_size()` procedure * - Using dynamic memory allocation. The `lc3_xxcoder_size()` procedure * returns the needed memory size, for a given configuration. The memory * space must be aligned to a pointer size. As an example, you can setup * encoder like this : Loading Loading @@ -149,6 +149,7 @@ extern "C" { */ typedef struct lc3_encoder *lc3_encoder_t; typedef struct lc3_decoder *lc3_decoder_t; /** Loading @@ -156,18 +157,22 @@ typedef struct lc3_encoder *lc3_encoder_t; * * Propose types suitable for static memory allocation, supporting * any frame duration, and maximum samplerates 16k and 48k respectively * You can customize your type using the `LC3_ENCODER_MEM_T` macro. * You can customize your type using the `LC3_ENCODER_MEM_T` or * `LC3_DECODER_MEM_T` macro. */ typedef LC3_ENCODER_MEM_T(10000, 16000) lc3_encoder_mem_16k_t; typedef LC3_ENCODER_MEM_T(10000, 48000) lc3_encoder_mem_48k_t; typedef LC3_DECODER_MEM_T(10000, 16000) lc3_decoder_mem_16k_t; typedef LC3_DECODER_MEM_T(10000, 48000) lc3_decoder_mem_48k_t; /** * Return the number of PCM samples in a frame * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 * return Number of PCM samples, 0 on bad parameter * return Number of PCM samples, -1 on bad parameters */ int lc3_frame_samples(int dt_us, int sr_hz); Loading @@ -175,7 +180,7 @@ int lc3_frame_samples(int dt_us, int sr_hz); * Return the size of frames, from bitrate * dt_us Frame duration in us, 7500 or 10000 * bitrate Target bitrate in bit per seconds * return The floor size in bytes of the frames * return The floor size in bytes of the frames, -1 on bad parameters */ int lc3_frame_bytes(int dt_us, int bitrate); Loading @@ -183,10 +188,18 @@ int lc3_frame_bytes(int dt_us, int bitrate); * Resolve the bitrate, from the size of frames * dt_us Frame duration in us, 7500 or 10000 * nbytes Size in bytes of the frames * return The according bitrate in bps * return The according bitrate in bps, -1 on bad parameters */ int lc3_resolve_bitrate(int dt_us, int nbytes); /** * Return algorithmic delay, as a number of samples * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 * return Number of algorithmic delay samples, -1 on bad parameters */ int lc3_delay_samples(int dt_us, int sr_hz); /** * Return size needed for an encoder * dt_us Frame duration in us, 7500 or 10000 Loading @@ -208,11 +221,39 @@ lc3_encoder_t lc3_setup_encoder(int dt_us, int sr_hz, void *mem); * Encode a frame * encoder Handle of the encoder * pcm, pitch Input PCM samples, and count between two consecutives * out, nbytes Output buffer, and size in bytes (20 to 400) * nbytes Target size, in bytes, of the frame (20 to 400) * out Output buffer of `nbytes` size * return 0: On success -1: Wrong parameters */ int lc3_encode(lc3_encoder_t encoder, const int16_t *pcm, int pitch, void *out, int nbytes); const int16_t *pcm, int pitch, int nbytes, void *out); /** * Return size needed for an decoder * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 * return Size of then decoder in bytes, 0 on bad parameters */ unsigned lc3_decoder_size(int dt_us, int sr_hz); /** * Setup decoder * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 * mem Decoder memory space, aligned to pointer type * return Decoder as an handle, NULL on bad parameters */ lc3_decoder_t lc3_setup_decoder(int dt_us, int sr_hz, void *mem); /** * Decode a frame * decoder Handle of the decoder * in, nbytes Input bitstream, and size in bytes, NULL performs PLC * pcm, pitch Output PCM samples, and count between two consecutives * return 0: On success 1: PLC operated -1: Wrong parameters */ int lc3_decode(lc3_decoder_t decoder, const void *in, int nbytes, int16_t *pcm, int pitch); #ifdef __cplusplus Loading
system/embdrv/lc3/include/lc3_private.h +52 −15 Original line number Diff line number Diff line Loading @@ -19,12 +19,14 @@ #ifndef __LC3_PRIVATE_H #define __LC3_PRIVATE_H #include <stdint.h> #include <stdbool.h> /** * Return number of samples, delayed samples and * encoded spectrum coefficients within a frame * For decoding, add number of samples of 18 ms history */ #define __LC3_NS(dt_us, sr_hz) \ Loading @@ -34,6 +36,9 @@ ( (dt_us) == 7500 ? 23 * __LC3_NS(dt_us, sr_hz) / 30 \ : 5 * __LC3_NS(dt_us, sr_hz) / 8 ) #define __LC3_NH(sr_hz) \ ( (18 * sr_hz) / 1000 ) /** * Frame duration 7.5ms or 10ms Loading Loading @@ -62,19 +67,19 @@ enum lc3_srate { /** * Encoder state * Encoder state and memory */ typedef struct lc3_attdet_state { typedef struct lc3_attdet_analysis { float en1, an1; int p_att; } lc3_attdet_state_t; } lc3_attdet_analysis_t; struct lc3_ltpf_hp50_state { float s1, s2; }; typedef struct lc3_ltpf_state { typedef struct lc3_ltpf_analysis { bool active; int pitch; float nc[2]; Loading @@ -83,29 +88,24 @@ typedef struct lc3_ltpf_state { float x_12k8[384]; float x_6k4[178]; int tc; } lc3_ltpf_state_t; } lc3_ltpf_analysis_t; typedef struct lc3_quant_state { typedef struct lc3_spec_analysis { float nbits_off; int nbits_spare; } lc3_quant_state_t; } lc3_spec_analysis_t; struct lc3_encoder { enum lc3_dt dt; enum lc3_srate sr; lc3_attdet_state_t attdet; lc3_ltpf_state_t ltpf; lc3_quant_state_t quant; lc3_attdet_analysis_t attdet; lc3_ltpf_analysis_t ltpf; lc3_spec_analysis_t spec; float *xs, *xf, s[0]; }; /** * Encoder memory */ #define LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz) \ ( 2*__LC3_NS(dt_us, sr_hz) + __LC3_ND(dt_us, sr_hz) ) Loading @@ -116,4 +116,41 @@ struct lc3_encoder { } /** * Decoder state and memory */ typedef struct lc3_ltpf_synthesis { bool active; int pitch; float c[12][2], x[12]; } lc3_ltpf_synthesis_t; typedef struct lc3_plc_state { uint16_t seed; int count; float alpha; } lc3_plc_state_t; struct lc3_decoder { enum lc3_dt dt; enum lc3_srate sr; lc3_ltpf_synthesis_t ltpf; lc3_plc_state_t plc; float *xs, *xd, *xg, s[0]; }; #define LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz) \ ( __LC3_NH(sr_hz) + __LC3_NS(dt_us, sr_hz) + \ __LC3_ND(dt_us, sr_hz) + __LC3_NS(dt_us, sr_hz) ) #define LC3_DECODER_MEM_T(dt_us, sr_hz) \ struct { \ struct lc3_decoder __d; \ float __s[LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz)]; \ } #endif /* __LC3_PRIVATE_H */
system/embdrv/lc3/src/attdet.c +6 −6 Original line number Diff line number Diff line Loading @@ -23,11 +23,11 @@ * Time domain attack detector */ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr, unsigned nbytes, struct lc3_attdet_state *state, const float *x) int nbytes, struct lc3_attdet_analysis *attdet, const float *x) { /* --- Check enabling --- */ const unsigned nbytes_ranges[LC3_NUM_DT][LC3_NUM_SRATE - LC3_SRATE_32K][2] = { const int nbytes_ranges[LC3_NUM_DT][LC3_NUM_SRATE - LC3_SRATE_32K][2] = { [LC3_DT_7M5] = { { 61, 149 }, { 75, 149 } }, [LC3_DT_10M] = { { 81, INT_MAX }, { 100, INT_MAX } }, }; Loading Loading @@ -78,15 +78,15 @@ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr, float a[4]; for (int i = 0; i < nblk; i++) { a[i] = fmaxf(0.25 * state->an1, state->en1); state->en1 = e[i], state->an1 = a[i]; a[i] = fmaxf(0.25 * attdet->an1, attdet->en1); attdet->en1 = e[i], attdet->an1 = a[i]; if (e[i] > 8.5 * a[i]) p_att = i + 1; } int att = state->p_att >= 1 + (nblk >> 1) || p_att > 0; state->p_att = p_att; int att = attdet->p_att >= 1 + (nblk >> 1) || p_att > 0; attdet->p_att = p_att; return att; }
system/embdrv/lc3/src/attdet.h +2 −2 Original line number Diff line number Diff line Loading @@ -33,12 +33,12 @@ * Time domain attack detector * dt, sr Duration and samplerate of the frame * nbytes Size in bytes of the frame * state State of the Attack Detector * attdet Context of the Attack Detector * x [-6..-1] Previous, [0..ns-1] Current samples * return 1: Attack detected 0: Otherwise */ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr, unsigned nbytes, lc3_attdet_state_t *state, const float *x); int nbytes, lc3_attdet_analysis_t *attdet, const float *x); #endif /* __LC3_ATTDET_H */
system/embdrv/lc3/src/bits.c +208 −81 Original line number Diff line number Diff line Loading @@ -20,18 +20,127 @@ #include "common.h" /* ---------------------------------------------------------------------------- * Common * -------------------------------------------------------------------------- */ static inline int ac_get(struct lc3_bits_buffer *); static inline void accu_load(struct lc3_bits_accu *, struct lc3_bits_buffer *); /** * Arithmetic coder return range bits * ac Arithmetic coder * return 1 + log2(ac->range) */ static int ac_get_range_bits(const struct lc3_bits_ac *ac) { int nbits = 0; for (unsigned r = ac->range; r; r >>= 1, nbits++); return nbits; } /** * Arithmetic coder return pending bits * ac Arithmetic coder * return Pending bits */ static int ac_get_pending_bits(const struct lc3_bits_ac *ac) { return 26 - ac_get_range_bits(ac) + ((ac->cache >= 0) + ac->carry_count) * 8; } /** * Return number of bits left in the bitstream * bits Bitstream context * return >= 0: Number of bits left < 0: Overflow */ static int get_bits_left(const struct lc3_bits *bits) { const struct lc3_bits_buffer *buffer = &bits->buffer; const struct lc3_bits_accu *accu = &bits->accu; const struct lc3_bits_ac *ac = &bits->ac; uintptr_t end = (uintptr_t)buffer->p_bw + (bits->mode == LC3_BITS_MODE_READ ? LC3_ACCU_BITS/8 : 0); uintptr_t start = (uintptr_t)buffer->p_fw - (bits->mode == LC3_BITS_MODE_READ ? LC3_AC_BITS/8 : 0); return 8 * (end - start) - (accu->n + accu->nover + ac_get_pending_bits(ac)); } /** * Setup bitstream writing */ void lc3_setup_bits(struct lc3_bits *bits, enum lc3_bits_mode mode, void *buffer, int len) { *bits = (struct lc3_bits){ .mode = mode, .accu = { .n = mode == LC3_BITS_MODE_READ ? LC3_ACCU_BITS : 0, }, .ac = { .range = 0xffffff, .cache = -1 }, .buffer = { .start = (uint8_t *)buffer, .end = (uint8_t *)buffer + len, .p_fw = (uint8_t *)buffer, .p_bw = (uint8_t *)buffer + len, } }; if (mode == LC3_BITS_MODE_READ) { struct lc3_bits_ac *ac = &bits->ac; struct lc3_bits_accu *accu = &bits->accu; struct lc3_bits_buffer *buffer = &bits->buffer; ac->low = ac_get(buffer) << 16; ac->low |= ac_get(buffer) << 8; ac->low |= ac_get(buffer); accu_load(accu, buffer); } } /** * Return number of bits left in the bitstream */ int lc3_get_bits_left(const struct lc3_bits *bits) { return LC3_MAX(get_bits_left(bits), 0); } /** * Return number of bits left in the bitstream */ int lc3_check_bits(const struct lc3_bits *bits) { const struct lc3_bits_ac *ac = &bits->ac; return -(get_bits_left(bits) < 0 || ac->error); } /* ---------------------------------------------------------------------------- * Writing * -------------------------------------------------------------------------- */ /** * Flush the bits accumulator * accu Bitstream accumulator * buffer Bitstream buffer */ static void accu_flush(struct lc3_bits_accu *accu, struct lc3_bits_buffer *buffer) static inline void accu_flush( struct lc3_bits_accu *accu, struct lc3_bits_buffer *buffer) { unsigned nbytes = LC3_MIN(accu->n >> 3, buffer->nleft); int nbytes = LC3_MIN(accu->n >> 3, buffer->p_bw - buffer->p_fw); accu->n -= 8 * nbytes; buffer->nleft -= nbytes; for ( ; nbytes; accu->v >>= 8, nbytes--) *(--buffer->p_bw) = accu->v & 0xff; Loading @@ -45,15 +154,10 @@ static void accu_flush(struct lc3_bits_accu *accu, * buffer Bitstream buffer * byte Byte to output */ static void ac_put(struct lc3_bits_buffer *buffer, unsigned byte) static inline void ac_put(struct lc3_bits_buffer *buffer, int byte) { buffer->overflow |= (buffer->nleft_fw <= 0); if (buffer->overflow) return; if (buffer->p_fw < buffer->end) *(buffer->p_fw++) = byte; buffer->nleft_fw--; buffer->nleft--; } /** Loading @@ -61,8 +165,8 @@ static void ac_put(struct lc3_bits_buffer *buffer, unsigned byte) * ac Arithmetic coder * buffer Bitstream buffer */ static void ac_shift(struct lc3_bits_ac *ac, struct lc3_bits_buffer *buffer) static inline void ac_shift( struct lc3_bits_ac *ac, struct lc3_bits_buffer *buffer) { if (ac->low < 0xff0000 || ac->carry) { Loading @@ -76,38 +180,11 @@ static void ac_shift(struct lc3_bits_ac *ac, ac->carry = 0; } else { ac->carry_count++; } ac->low = (ac->low << 8) & 0xffffff; } /** * Arithmetic coder return range bits * ac Arithmetic coder * return 1 + log2(ac->range) */ static int ac_get_range_bits(const struct lc3_bits_ac *ac) { int nbits = 0; for (unsigned r = ac->range; r; r >>= 1, nbits++); return nbits; } /** * Arithmetic coder return pending bits * ac Arithmetic coder * return Pending bits */ static int ac_get_pending_bits(const struct lc3_bits_ac *ac) { return 26 - ac_get_range_bits(ac) + ((ac->cache >= 0) + ac->carry_count) * 8; } /** * Arithmetic coder termination * ac Arithmetic coder Loading Loading @@ -155,44 +232,12 @@ static void ac_terminate(struct lc3_bits_ac *ac, end_val = nbits < 8 ? 0 : 0xff; } if (buffer->nleft_fw > 0) { if (buffer->p_fw < buffer->end) { *buffer->p_fw &= 0xff >> nbits; *buffer->p_fw |= end_val << (8 - nbits); } } /** * Setup bitstream writing */ void lc3_setup_bits(struct lc3_bits *bits, void *buffer, unsigned len) { *bits = (struct lc3_bits){ .ac = { .range = 0xffffff, .cache = -1 }, .buffer = { .p_fw = (uint8_t *)buffer, .p_bw = (uint8_t *)buffer + len, .nleft_fw = len, .nleft = len } }; } /** * Return number of bits left in the bitstream */ int lc3_get_bits_left(const struct lc3_bits *bits) { int nbits_left = 8 * bits->buffer.nleft; nbits_left -= LC3_MIN(bits->accu.n, nbits_left); nbits_left -= LC3_MIN(ac_get_pending_bits(&bits->ac), nbits_left); return nbits_left; } /** * Flush and terminate bitstream */ Loading @@ -202,7 +247,8 @@ void lc3_flush_bits(struct lc3_bits *bits) struct lc3_bits_accu *accu = &bits->accu; struct lc3_bits_buffer *buffer = &bits->buffer; for (int n = 8 * buffer->nleft - accu->n; n > 0; n -= 32) int nleft = buffer->p_bw - buffer->p_fw; for (int n = 8 * nleft - accu->n; n > 0; n -= 32) lc3_put_bits(bits, 0, LC3_MIN(n, 32)); accu_flush(accu, buffer); Loading @@ -211,19 +257,19 @@ void lc3_flush_bits(struct lc3_bits *bits) } /** * Write from 0 to 32 bits, * Write from 1 to 32 bits, * exceeding the capacity of the accumulator */ void __lc3_put_bits_over(struct lc3_bits *bits, unsigned v, int n) void lc3_put_bits_generic(struct lc3_bits *bits, unsigned v, int n) { struct lc3_bits_accu *accu = &bits->accu; /* --- Fullfill accumulator and flush -- */ /* --- Fulfill accumulator and flush -- */ int n1 = LC3_MIN(ACCU_BITS - accu->n, n); int n1 = LC3_MIN(LC3_ACCU_BITS - accu->n, n); if (n1) { accu->v |= v << accu->n; accu->n = ACCU_BITS; accu->n = LC3_ACCU_BITS; } accu_flush(accu, &bits->buffer); Loading @@ -237,10 +283,91 @@ void __lc3_put_bits_over(struct lc3_bits *bits, unsigned v, int n) /** * Arithmetic coder renormalization */ void __lc3_renorm_ac(struct lc3_bits *bits) void lc3_ac_write_renorm(struct lc3_bits *bits) { struct lc3_bits_ac *ac = &bits->ac; for ( ; ac->range < 0x10000; ac->range <<= 8) ac_shift(ac, &bits->buffer); } /* ---------------------------------------------------------------------------- * Reading * -------------------------------------------------------------------------- */ /** * Arithmetic coder get byte * buffer Bitstream buffer * return Byte read, 0 on overflow */ static inline int ac_get(struct lc3_bits_buffer *buffer) { return buffer->p_fw < buffer->end ? *(buffer->p_fw++) : 0; } /** * Load the accumulator * accu Bitstream accumulator * buffer Bitstream buffer */ static inline void accu_load(struct lc3_bits_accu *accu, struct lc3_bits_buffer *buffer) { int nbytes = LC3_MIN(accu->n >> 3, buffer->p_bw - buffer->start); accu->n -= 8 * nbytes; for ( ; nbytes; nbytes--) { accu->v >>= 8; accu->v |= *(--buffer->p_bw) << (LC3_ACCU_BITS - 8); } if (accu->n >= 8) { accu->nover = LC3_MIN(accu->nover + accu->n, LC3_ACCU_BITS); accu->v >>= accu->n; accu->n = 0; } } /** * Read from 1 to 32 bits, * exceeding the capacity of the accumulator */ unsigned lc3_get_bits_generic(struct lc3_bits *bits, int n) { struct lc3_bits_accu *accu = &bits->accu; struct lc3_bits_buffer *buffer = &bits->buffer; /* --- Fulfill accumulator and read -- */ accu_load(accu, buffer); int n1 = LC3_MIN(LC3_ACCU_BITS - accu->n, n); unsigned v = (accu->v >> accu->n) & ((1u << n1) - 1); accu->n += n1; /* --- Second round --- */ int n2 = n - n1; if (n2) { accu_load(accu, buffer); v |= ((accu->v >> accu->n) & ((1u << n2) - 1)) << n1; accu->n += n2; } return v; } /** * Arithmetic coder renormalization */ void lc3_ac_read_renorm(struct lc3_bits *bits) { struct lc3_bits_ac *ac = &bits->ac; for ( ; ac->range < 0x10000; ac->range <<= 8) ac->low = ((ac->low << 8) | ac_get(&bits->buffer)) & 0xffffff; }