Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1930d630 authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Gerrit Code Review
Browse files

Merge changes I5a9b1168,I5f2f7627

* changes:
  Fix abort of the sanitizer
  New LC3 Encoder
parents 52e4d674 dbdda238
Loading
Loading
Loading
Loading
+222 −0
Original line number Original line Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2021 Google, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

/**
 * Low Complexity Communication Codec (LC3)
 *
 * This implementation conforms to :
 *   Low Complexity Communication Codec (LC3)
 *   Bluetooth Specification v1.0
 *
 *
 * 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.
 *   In this way, the LC3 does not handle :
 *   VBR (Variable Bitrate), based on input signal complexity
 *   ABR (Adaptative Bitrate). It does not rely on any bit reservoir,
 *       a frame will be strictly encoded in the bytes budget given by
 *       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.
 *
 * - Unlike classic codecs, the LC3 codecs does not run on fixed amount
 *   of samples as input. It operate only on fixed frame duration, for
 *   any supported samplerates (8 to 48 KHz). Two frame duration are
 *   available 7.5ms and 10ms.
 *
 *
 * --- About 44.1 KHz samplerate ---
 *
 * The Bluetooth specification oddly add the 44.1 KHz samplerate. Although
 * there is NO SUPPORT in the core algorithm of the codec of 44.1 KHz.
 * We can summarize the 44.1 KHz support by "you can put any samplerate
 * around the base defined samplerates". But be concerned by :
 *
 *   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
 *      factor of 20 KHz.
 *
 * Applied to 44.1 KHz, we get :
 *
 *   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
 *
 *
 * --- How to encode ---
 *
 * An encoder context need to be setup. This context keep states on
 * the current stream to encode, and samples that overlapped accross
 * frames.
 *
 * You have two ways to setup the encoder :
 *
 * - 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
 *   encoding up to 16 KHz or 48 KHz.
 *
 * - Using dynamic memory allocation. The `lc3_encoder_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 :
 *
 *   | enc = lc3_setup_encoder(frame_us, samplerate,
 *   |      malloc(lc3_encoder_size(frame_us, samplerate)));
 *   | ...
 *   | free(enc);
 *
 *   Note :
 *   - A NULL memory adress as input, will return a NULL encoder context.
 *   - The returned encoder handle is set at the address of the allocated
 *     memory space, you can directly free the handle.
 *
 * Next, call the `lc3_encode()` encoding procedure, for each frames.
 * To handle multichannel streams (Stereo or more), you can proceed with
 * inerleaved channels PCM stream like this :
 *
 *   | for(int ich = 0; ich < nch: ich++)
 *   |     lc3_encode(encoder[ich], pcm + ich, nch, ...);
 *
 *   with `nch` as the number of channels in the PCM stream
 */

#ifndef __LC3_H
#define __LC3_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdbool.h>

#include "lc3_private.h"


/**
 * Limitations
 * - On the bitrate, in bps, of a stream
 * - On the size of the frames in bytes
 */

#define LC3_MIN_BITRATE    16000
#define LC3_MAX_BITRATE   320000

#define LC3_MIN_FRAME_BYTES   20
#define LC3_MAX_FRAME_BYTES  400


/**
 * Parameters check
 *   LC3_CHECK_DT_US(us)  True when frame duration in us is suitable
 *   LC3_CHECK_SR_HZ(sr)  True when samplerate in Hz is suitable
 */

#define LC3_CHECK_DT_US(us) \
    ( ((us) == 7500) || ((us) == 10000) )

#define LC3_CHECK_SR_HZ(sr) \
    ( ((sr) ==  8000) || ((sr) == 16000) || ((sr) == 24000) || \
      ((sr) == 32000) || ((sr) == 48000)                       )


/**
 * Handle
 */

typedef struct lc3_encoder *lc3_encoder_t;


/**
 * Static memory of encoder context
 *
 * 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.
 */

typedef LC3_ENCODER_MEM_T(10000, 16000) lc3_encoder_mem_16k_t;
typedef LC3_ENCODER_MEM_T(10000, 48000) lc3_encoder_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
 */
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
 */
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
 */
int lc3_resolve_bitrate(int dt_us, int nbytes);

/**
 * Return size needed for an encoder
 * dt_us           Frame duration in us, 7500 or 10000
 * sr_hz           Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000
 * return          Size of then encoder in bytes, 0 on bad parameters
 */
unsigned lc3_encoder_size(int dt_us, int sr_hz);

/**
 * Setup encoder
 * dt_us           Frame duration in us, 7500 or 10000
 * sr_hz           Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000
 * mem             Encoder memory space, aligned to pointer type
 * return          Encoder as an handle, NULL on bad parameters
 */
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)
 * return          0: On success  -1: Wrong parameters
 */
int lc3_encode(lc3_encoder_t encoder,
    const int16_t *pcm, int pitch, void *out, int nbytes);


#ifdef __cplusplus
}
#endif

#endif /* __LC3_H */
+119 −0
Original line number Original line Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2015 Google, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#ifndef __LC3_PRIVATE_H
#define __LC3_PRIVATE_H

#include <stdbool.h>


/**
 * Return number of samples, delayed samples and
 * encoded spectrum coefficients within a frame
 */

#define __LC3_NS(dt_us, sr_hz) \
    ((dt_us * sr_hz) / 1000 / 1000)

#define __LC3_ND(dt_us, sr_hz) \
    ( (dt_us) == 7500 ? 23 * __LC3_NS(dt_us, sr_hz) / 30 \
                      :  5 * __LC3_NS(dt_us, sr_hz) /  8 )


/**
 * Frame duration 7.5ms or 10ms
 */

enum lc3_dt {
    LC3_DT_7M5,
    LC3_DT_10M,

    LC3_NUM_DT
};

/**
 * Sampling frequency
 */

enum lc3_srate {
    LC3_SRATE_8K,
    LC3_SRATE_16K,
    LC3_SRATE_24K,
    LC3_SRATE_32K,
    LC3_SRATE_48K,

    LC3_NUM_SRATE,
};


/**
 * Encoder state
 */

typedef struct lc3_attdet_state {
    float en1, an1;
    int p_att;
} lc3_attdet_state_t;

struct lc3_ltpf_hp50_state {
    float s1, s2;
};

typedef struct lc3_ltpf_state {
    bool active;
    int pitch;
    float nc[2];

    struct lc3_ltpf_hp50_state hp50;
    float x_12k8[384];
    float x_6k4[178];
    int tc;
} lc3_ltpf_state_t;

typedef struct lc3_quant_state {
    float nbits_off;
    int nbits_spare;
} lc3_quant_state_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;

    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) )

#define LC3_ENCODER_MEM_T(dt_us, sr_hz) \
    struct { \
        struct lc3_encoder __e; \
        float __s[LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz)]; \
    }


#endif /* __LC3_PRIVATE_H */
+92 −0
Original line number Original line Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2021 Google, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#include "attdet.h"


/**
 * 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)
{
    /* --- Check enabling --- */

    const unsigned *nbytes_range =
        (const unsigned [LC3_NUM_DT][LC3_NUM_SRATE-LC3_SRATE_32K][2]){
            [LC3_DT_7M5] = { { 61,      149 }, {  75,      149 } },
            [LC3_DT_10M] = { { 81, UINT_MAX }, { 100, UINT_MAX } },
        }[dt][sr - LC3_SRATE_32K];

    if (sr < LC3_SRATE_32K || nbytes < nbytes_range[0]
                           || nbytes > nbytes_range[1])
        return 0;

    /* --- Filtering & Energy calculation --- */

    int nblk = 4 - (dt == LC3_DT_7M5);
    float e[4];

    for (int i = 0; i < nblk; i++) {
        e[i] = 0;

        if (sr == LC3_SRATE_32K) {
            float xn2 = x[-4] + x[-3];
            float xn1 = x[-2] + x[-1];
            float xn, xf;

            for (int j = 0; j < 40; j++, x += 2, xn2 = xn1, xn1 = xn) {
                xn = x[0] + x[1];
                xf = 0.375 * xn - 0.5 * xn1 + 0.125 * xn2;
                e[i] += xf * xf;
            }
        }

        else {
            float xn2 = x[-6] + x[-5] + x[-4];
            float xn1 = x[-3] + x[-2] + x[-1];
            float xn, xf;

            for (int j = 0; j < 40; j++, x += 3, xn2 = xn1, xn1 = xn) {
                xn = x[0] + x[1] + x[2];
                xf = 0.375 * xn - 0.5 * xn1 + 0.125 * xn2;
                e[i] += xf * xf;
            }
        }
    }

    /* --- Attack detection ---
     * The attack block `p_att` is defined as the normative value + 1,
     * in such way, it will be initialized to 0 */

    int p_att = 0;
    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];

        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;

    return att;
}
+44 −0
Original line number Original line Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2021 Google, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

/**
 * LC3 - Time domain attack detector
 *
 * Reference : Low Complexity Communication Codec (LC3)
 *             Bluetooth Specification v1.0
 */

#ifndef __LC3_ATTDET_H
#define __LC3_ATTDET_H

#include "common.h"


/**
 * 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
 * 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);


#endif /* __LC3_ATTDET_H */
+246 −0
Original line number Original line Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2021 Google, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#include "bits.h"
#include "common.h"


/**
 * Flush the bits accumulator
 * accu            Bitstream accumulator
 * buffer          Bitstream buffer
 */
static void accu_flush(struct lc3_bits_accu *accu,
    struct lc3_bits_buffer *buffer)
{
    unsigned nbytes = LC3_MIN(accu->n >> 3, buffer->nleft);

    accu->n -= 8 * nbytes;
    buffer->nleft -= nbytes;

    for ( ; nbytes; accu->v >>= 8, nbytes--)
        *(--buffer->p_bw) = accu->v & 0xff;

    if (accu->n >= 8)
        accu->n = 0;
}

/**
 * Arithmetic coder put byte
 * buffer          Bitstream buffer
 * byte            Byte to output
 */
static void ac_put(struct lc3_bits_buffer *buffer, unsigned byte)
{
    buffer->overflow |= (buffer->nleft_fw <= 0);
    if (buffer->overflow)
        return;

    *(buffer->p_fw++) = byte;
    buffer->nleft_fw--;
    buffer->nleft--;
}

/**
 * Arithmetic coder range shift
 * ac              Arithmetic coder
 * buffer          Bitstream buffer
 */
static void ac_shift(struct lc3_bits_ac *ac,
    struct lc3_bits_buffer *buffer)
{
    if (ac->low < 0xff0000 || ac->carry)
    {
        if (ac->cache >= 0)
            ac_put(buffer, ac->cache + ac->carry);

        for ( ; ac->carry_count > 0; ac->carry_count--)
            ac_put(buffer, ac->carry ? 0x00 : 0xff);

         ac->cache = ac->low >> 16;
         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
 * buffer          Bitstream buffer
 * end_val/nbits   End value and count of bits to terminate (1 to 8)
 */
static void ac_terminate(struct lc3_bits_ac *ac,
    struct lc3_bits_buffer *buffer)
{
    int nbits = 25 - ac_get_range_bits(ac);
    unsigned mask = 0xffffff >> nbits;
    unsigned val  = ac->low + mask;
    unsigned high = ac->low + ac->range;

    bool over_val  = val  >> 24;
    bool over_high = high >> 24;

    val  = (val  & 0xffffff) & ~mask;
    high = (high & 0xffffff);

    if (over_val == over_high) {

        if (val + mask >= high) {
            nbits++;
            mask >>= 1;
            val = ((ac->low + mask) & 0xffffff) & ~mask;
        }

        ac->carry |= val < ac->low;
    }

    ac->low = val;

    for (; nbits > 8; nbits -= 8)
        ac_shift(ac, buffer);
    ac_shift(ac, buffer);

    int end_val = ac->cache >> (8 - nbits);

    if (ac->carry_count) {
        ac_put(buffer, ac->cache);
        for ( ; ac->carry_count > 1; ac->carry_count--)
            ac_put(buffer, 0xff);

        end_val = nbits < 8 ? 0 : 0xff;
    }

    if (buffer->nleft_fw > 0) {
        *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
 */
void lc3_flush_bits(struct lc3_bits *bits)
{
    struct lc3_bits_ac *ac = &bits->ac;
    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)
        lc3_put_bits(bits, 0, LC3_MIN(n, 32));

    accu_flush(accu, buffer);

    ac_terminate(ac, buffer);
}

/**
 * Write from 0 to 32 bits,
 * exceeding the capacity of the accumulator
 */
void __lc3_put_bits_over(struct lc3_bits *bits, unsigned v, int n)
{
    struct lc3_bits_accu *accu = &bits->accu;

    /* --- Fullfill accumulator and flush -- */

    int n1 = LC3_MIN(ACCU_BITS - accu->n, n);
    if (n1) {
        accu->v |= v << accu->n;
        accu->n = ACCU_BITS;
    }

    accu_flush(accu, &bits->buffer);

    /* --- Accumulate remaining bits -- */

    accu->v = v >> n1;
    accu->n = n - n1;
}

/**
 * Arithmetic coder renormalization
 */
void __lc3_renorm_ac(struct lc3_bits *bits)
{
    struct lc3_bits_ac *ac = &bits->ac;

    for ( ; ac->range < 0x10000; ac->range <<= 8)
        ac_shift(ac, &bits->buffer);
}
Loading