Add LC3 codec from Google

This commit is contained in:
Matthias Ringwald 2022-04-21 13:20:09 +02:00
parent 9b9478570b
commit 9a19cd7860
31 changed files with 10273 additions and 0 deletions

2
3rd-party/README.md vendored
View File

@ -8,6 +8,7 @@ Library
[hxcmod-player](https://github.com/jfdelnero/HxCModPlayer) | 03d495c8 | Public Domain | A2DP Source Demo | mod music player
[kiss-fft](https://github.com/mborgerding/kissfft) | 131.1.0 | BSD 2-Clause | LE Audio | FFT library
[EHIMA LC3 Codec](https://github.com/zephyrproject-rtos/liblc3codec) | 6e8ad0bd | Apache 2.0 | LE Audio | audio codec
[Google LC3 Codec](https://android.googlesource.com/platform/packages/modules/Bluetooth) | 49b925f1 | Apache 2.0 | LE Audio | audio codec
[lwIP](http://savannah.nongnu.org/projects/lwip/) | b3a93941 | BSD 3-Clause | PAN Demo | complete network stack
[md5](http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5) | 1.0 | Public Domain | PBAP | cryptographic hash function
[micro-ecc](https://github.com/kmackay/micro-ecc) | e4d264b5 | BSD 2-Clause | LE SC, Mesh | elliptic curve library
@ -15,3 +16,4 @@ Library
[segger-rtt](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/) | v6.20d | BSD 3-Clause | HCI PacketLog | high-speed logging with SEGGER J-Link debug probes (development)
[tinydir](https://github.com/cxong/tinydir) | 677733da | BSD 2-Clause | GAP Bonding | get a directory listing on POSIX + Windwows systems
[Yxml](https://dev.yorhel.nl/yxml) | 10f968b0 | MIT | PBAP | minimal stream XML parser

61
3rd-party/lc3-google/Android.bp vendored Normal file
View File

@ -0,0 +1,61 @@
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "system_bt_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["system_bt_license"],
}
cc_library_static {
name: "liblc3",
host_supported: true,
apex_available: [
"//apex_available:platform",
"com.android.bluetooth"
],
defaults: ["fluoride_defaults"],
srcs: [
"src/*.c",
],
cflags: [
"-O3",
"-ffast-math",
"-Werror",
"-Wmissing-braces",
"-Wno-unused-parameter",
"-Wno-#warnings",
"-Wuninitialized",
"-Wno-self-assign",
"-Wno-implicit-fallthrough",
],
target: {
android: {
sanitize: {
misc_undefined:[
"unsigned-integer-overflow",
"signed-integer-overflow",
"bounds",
],
cfi: true,
},
},
},
export_include_dirs: [
"include",
],
}
cc_fuzz {
name: "liblc3_fuzzer",
srcs: [
"fuzzer/liblc3_fuzzer.cpp",
],
static_libs: [
"liblc3",
],
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* 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 <fuzzer/FuzzedDataProvider.h>
#include "include/lc3.h"
void TestEncoder(FuzzedDataProvider& fdp) {
enum lc3_pcm_format pcm_format =
fdp.PickValueInArray({LC3_PCM_FORMAT_S16, LC3_PCM_FORMAT_S24});
int dt_us = fdp.PickValueInArray({10000, 7500});
int sr_hz =
fdp.PickValueInArray({8000, 16000, 24000, 32000, /*44100,*/ 48000});
unsigned enc_size = lc3_encoder_size(dt_us, sr_hz);
uint16_t output_byte_count = fdp.ConsumeIntegralInRange(20, 400);
uint16_t num_frames = lc3_frame_samples(dt_us, sr_hz);
uint8_t bytes_per_frame = (pcm_format == LC3_PCM_FORMAT_S16 ? 2 : 4);
if (fdp.remaining_bytes() < num_frames * bytes_per_frame) {
return;
}
std::vector<uint32_t> input_frames(
num_frames / (pcm_format == LC3_PCM_FORMAT_S16 ? 2 : 1));
fdp.ConsumeData(input_frames.data(), num_frames * bytes_per_frame);
void* lc3_encoder_mem = nullptr;
lc3_encoder_mem = malloc(enc_size);
lc3_encoder_t lc3_encoder =
lc3_setup_encoder(dt_us, sr_hz, 0, lc3_encoder_mem);
std::vector<uint8_t> output(output_byte_count);
lc3_encode(lc3_encoder, pcm_format, (const int16_t*)input_frames.data(), 1,
output.size(), output.data());
free(lc3_encoder_mem);
lc3_encoder_mem = nullptr;
return;
}
void TestDecoder(FuzzedDataProvider& fdp) {
enum lc3_pcm_format pcm_format =
fdp.PickValueInArray({LC3_PCM_FORMAT_S16, LC3_PCM_FORMAT_S24});
int dt_us = fdp.PickValueInArray({10000, 7500});
int sr_hz =
fdp.PickValueInArray({8000, 16000, 24000, 32000, /*44100,*/ 48000});
unsigned dec_size = lc3_decoder_size(dt_us, sr_hz);
uint16_t input_byte_count = fdp.ConsumeIntegralInRange(20, 400);
uint16_t num_frames = lc3_frame_samples(dt_us, sr_hz);
if (fdp.remaining_bytes() < input_byte_count) {
return;
}
std::vector<uint8_t> input(input_byte_count);
fdp.ConsumeData(input.data(), input.size());
void* lc3_decoder_mem = nullptr;
lc3_decoder_mem = malloc(dec_size);
lc3_decoder_t lc3_decoder =
lc3_setup_decoder(dt_us, sr_hz, 0, lc3_decoder_mem);
std::vector<uint32_t> output(num_frames /
(pcm_format == LC3_PCM_FORMAT_S16 ? 2 : 1));
lc3_decode(lc3_decoder, input.data(), input.size(), pcm_format,
(int16_t*)output.data(), 1);
/* Empty input performs PLC (packet loss concealment) */
lc3_decode(lc3_decoder, nullptr, 0, pcm_format, (int16_t*)output.data(), 1);
free(lc3_decoder_mem);
lc3_decoder_mem = nullptr;
return;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider fdp(data, size);
TestEncoder(fdp);
TestDecoder(fdp);
return 0;
}

300
3rd-party/lc3-google/include/lc3.h vendored Normal file
View File

@ -0,0 +1,300 @@
/******************************************************************************
*
* 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 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
* 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 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 :
*
* 1. About 8.16 ms frame duration, instead of 7.5 ms
* About 10.88 ms frame duration, instead of 10 ms
*
* 2. The bandwidth becomes limited to 18.375 KHz
*
*
* --- How to encode / decode ---
*
* 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 / decoder :
*
* - Using static memory allocation (this module does not rely on
* 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_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 :
*
* | 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) )
/**
* PCM Sample Format
* S16 Signed 16 bits, in 16 bits words (int16_t)
* S24 Signed 24 bits, using low three bytes of 32 bits words (int32_t).
* The high byte sign extends the sample value (bits 31..24 set to b23).
*/
enum lc3_pcm_format {
LC3_PCM_FORMAT_S16,
LC3_PCM_FORMAT_S24,
};
/**
* Handle
*/
typedef struct lc3_encoder *lc3_encoder_t;
typedef struct lc3_decoder *lc3_decoder_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` 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, -1 on bad parameters
*/
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, -1 on bad parameters
*/
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, -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
* sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000
* return Size of then encoder in bytes, 0 on bad parameters
*
* The `sr_hz` parameter is the samplerate of the PCM input stream,
* and will match `sr_pcm_hz` of `lc3_setup_encoder()`.
*/
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
* sr_pcm_hz Input samplerate, downsampling option of input, or 0
* mem Encoder memory space, aligned to pointer type
* return Encoder as an handle, NULL on bad parameters
*
* The `sr_pcm_hz` parameter is a downsampling option of PCM input,
* the value `0` fallback to the samplerate of the encoded stream `sr_hz`.
* When used, `sr_pcm_hz` is intended to be higher or equal to the encoder
* samplerate `sr_hz`. The size of the context needed, given by
* `lc3_encoder_size()` will be set accordingly to `sr_pcm_hz`.
*/
lc3_encoder_t lc3_setup_encoder(
int dt_us, int sr_hz, int sr_pcm_hz, void *mem);
/**
* Encode a frame
* encoder Handle of the encoder
* fmt PCM input format
* pcm, stride Input PCM samples, and count between two consecutives
* 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, enum lc3_pcm_format fmt,
const void *pcm, int stride, 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
*
* The `sr_hz` parameter is the samplerate of the PCM output stream,
* and will match `sr_pcm_hz` of `lc3_setup_decoder()`.
*/
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
* sr_pcm_hz Output samplerate, upsampling option of output (or 0)
* mem Decoder memory space, aligned to pointer type
* return Decoder as an handle, NULL on bad parameters
*
* The `sr_pcm_hz` parameter is an upsampling option of PCM output,
* the value `0` fallback to the samplerate of the decoded stream `sr_hz`.
* When used, `sr_pcm_hz` is intended to be higher or equal to the decoder
* samplerate `sr_hz`. The size of the context needed, given by
* `lc3_decoder_size()` will be set accordingly to `sr_pcm_hz`.
*/
lc3_decoder_t lc3_setup_decoder(
int dt_us, int sr_hz, int sr_pcm_hz, void *mem);
/**
* Decode a frame
* decoder Handle of the decoder
* in, nbytes Input bitstream, and size in bytes, NULL performs PLC
* fmt PCM output format
* pcm, stride 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,
enum lc3_pcm_format fmt, void *pcm, int stride);
#ifdef __cplusplus
}
#endif
#endif /* __LC3_H */

View File

@ -0,0 +1,156 @@
/******************************************************************************
*
* 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 <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) \
((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 )
#define __LC3_NH(sr_hz) \
( (18 * sr_hz) / 1000 )
/**
* 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 and memory
*/
typedef struct lc3_attdet_analysis {
float en1, an1;
int p_att;
} lc3_attdet_analysis_t;
struct lc3_ltpf_hp50_state {
float s1, s2;
};
typedef struct lc3_ltpf_analysis {
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_analysis_t;
typedef struct lc3_spec_analysis {
float nbits_off;
int nbits_spare;
} lc3_spec_analysis_t;
struct lc3_encoder {
enum lc3_dt dt;
enum lc3_srate sr, sr_pcm;
lc3_attdet_analysis_t attdet;
lc3_ltpf_analysis_t ltpf;
lc3_spec_analysis_t spec;
float *xs, *xf, s[0];
};
#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)]; \
}
/**
* 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, sr_pcm;
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 */

92
3rd-party/lc3-google/src/attdet.c vendored Normal file
View File

@ -0,0 +1,92 @@
/******************************************************************************
*
* 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,
int nbytes, struct lc3_attdet_analysis *attdet, const float *x)
{
/* --- Check enabling --- */
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 } },
};
if (sr < LC3_SRATE_32K ||
nbytes < nbytes_ranges[dt][sr - LC3_SRATE_32K][0] ||
nbytes > nbytes_ranges[dt][sr - LC3_SRATE_32K][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 * 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 = attdet->p_att >= 1 + (nblk >> 1) || p_att > 0;
attdet->p_att = p_att;
return att;
}

44
3rd-party/lc3-google/src/attdet.h vendored Normal file
View File

@ -0,0 +1,44 @@
/******************************************************************************
*
* 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
* 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,
int nbytes, lc3_attdet_analysis_t *attdet, const float *x);
#endif /* __LC3_ATTDET_H */

375
3rd-party/lc3-google/src/bits.c vendored Normal file
View File

@ -0,0 +1,375 @@
/******************************************************************************
*
* 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"
/* ----------------------------------------------------------------------------
* 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);
int n = end > start ? (int)(end - start) : -(int)(start - end);
return 8 * n - (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 inline void accu_flush(
struct lc3_bits_accu *accu, struct lc3_bits_buffer *buffer)
{
int nbytes = LC3_MIN(accu->n >> 3,
LC3_MAX(buffer->p_bw - buffer->p_fw, 0));
accu->n -= 8 * 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 inline void ac_put(struct lc3_bits_buffer *buffer, int byte)
{
if (buffer->p_fw < buffer->end)
*(buffer->p_fw++) = byte;
}
/**
* Arithmetic coder range shift
* ac Arithmetic coder
* buffer Bitstream buffer
*/
static inline 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 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->p_fw < buffer->end) {
*buffer->p_fw &= 0xff >> nbits;
*buffer->p_fw |= end_val << (8 - nbits);
}
}
/**
* 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;
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);
ac_terminate(ac, buffer);
}
/**
* Write from 1 to 32 bits,
* exceeding the capacity of the accumulator
*/
void lc3_put_bits_generic(struct lc3_bits *bits, unsigned v, int n)
{
struct lc3_bits_accu *accu = &bits->accu;
/* --- Fulfill accumulator and flush -- */
int n1 = LC3_MIN(LC3_ACCU_BITS - accu->n, n);
if (n1) {
accu->v |= v << accu->n;
accu->n = LC3_ACCU_BITS;
}
accu_flush(accu, &bits->buffer);
/* --- Accumulate remaining bits -- */
accu->v = v >> n1;
accu->n = n - n1;
}
/**
* Arithmetic coder renormalization
*/
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;
}

314
3rd-party/lc3-google/src/bits.h vendored Normal file
View File

@ -0,0 +1,314 @@
/******************************************************************************
*
* 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 - Bitstream management
*
* The bitstream is written by the 2 ends of the buffer :
*
* - Arthmetic coder put bits while increasing memory addresses
* in the buffer (forward)
*
* - Plain bits are puts starting the end of the buffer, with memeory
* addresses decreasing (backward)
*
* .---------------------------------------------------.
* | > > > > > > > > > > : : < < < < < < < < < |
* '---------------------------------------------------'
* |---------------------> - - - - - - - - - - - - - ->|
* |< - - - <-------------------|
* Arithmetic coding Plain bits
* `lc3_put_symbol()` `lc3_put_bits()`
*
* - The forward writing is protected against buffer overflow, it cannot
* write after the buffer, but can overwrite plain bits previously
* written in the buffer.
*
* - The backward writing is protected against overwrite of the arithmetic
* coder bitstream. In such way, the backward bitstream is always limited
* by the aritmetic coder bitstream, and can be overwritten by him.
*
* .---------------------------------------------------.
* | > > > > > > > > > > : : < < < < < < < < < |
* '---------------------------------------------------'
* |---------------------> - - - - - - - - - - - - - ->|
* |< - - - - - - - - - - - - - - <-------------------|
* Arithmetic coding Plain bits
* `lc3_get_symbol()` `lc3_get_bits()`
*
* - Reading is limited to read of the complementary end of the buffer.
*
* - The procedure `lc3_check_bits()` returns indication that read has been
* made crossing the other bit plane.
*
*
* Reference : Low Complexity Communication Codec (LC3)
* Bluetooth Specification v1.0
*
*/
#ifndef __LC3_BITS_H
#define __LC3_BITS_H
#include "common.h"
/**
* Bitstream mode
*/
enum lc3_bits_mode {
LC3_BITS_MODE_READ,
LC3_BITS_MODE_WRITE,
};
/**
* Arithmetic coder symbol interval
* The model split the interval in 17 symbols
*/
struct lc3_ac_symbol {
uint16_t low : 16;
uint16_t range : 16;
};
struct lc3_ac_model {
struct lc3_ac_symbol s[17];
};
/**
* Bitstream context
*/
#define LC3_ACCU_BITS (int)(8 * sizeof(unsigned))
struct lc3_bits_accu {
unsigned v;
int n, nover;
};
#define LC3_AC_BITS (int)(24)
struct lc3_bits_ac {
unsigned low, range;
int cache, carry, carry_count;
bool error;
};
struct lc3_bits_buffer {
const uint8_t *start, *end;
uint8_t *p_fw, *p_bw;
};
typedef struct lc3_bits {
enum lc3_bits_mode mode;
struct lc3_bits_ac ac;
struct lc3_bits_accu accu;
struct lc3_bits_buffer buffer;
} lc3_bits_t;
/**
* Setup bitstream reading/writing
* bits Bitstream context
* mode Either READ or WRITE mode
* buffer, len Output buffer and length (in bytes)
*/
void lc3_setup_bits(lc3_bits_t *bits,
enum lc3_bits_mode mode, void *buffer, int len);
/**
* Return number of bits left in the bitstream
* bits Bitstream context
* return Number of bits left
*/
int lc3_get_bits_left(const lc3_bits_t *bits);
/**
* Check if error occured on bitstream reading/writing
* bits Bitstream context
* return 0: Ok -1: Bitstream overflow or AC reading error
*/
int lc3_check_bits(const lc3_bits_t *bits);
/**
* Put a bit
* bits Bitstream context
* v Bit value, 0 or 1
*/
static inline void lc3_put_bit(lc3_bits_t *bits, int v);
/**
* Put from 1 to 32 bits
* bits Bitstream context
* v, n Value, in range 0 to 2^n - 1, and bits count (1 to 32)
*/
static inline void lc3_put_bits(lc3_bits_t *bits, unsigned v, int n);
/**
* Put arithmetic coder symbol
* bits Bitstream context
* model, s Model distribution and symbol value
*/
static inline void lc3_put_symbol(lc3_bits_t *bits,
const struct lc3_ac_model *model, unsigned s);
/**
* Flush and terminate bitstream writing
* bits Bitstream context
*/
void lc3_flush_bits(lc3_bits_t *bits);
/**
* Get a bit
* bits Bitstream context
*/
static inline int lc3_get_bit(lc3_bits_t *bits);
/**
* Get from 1 to 32 bits
* bits Bitstream context
* n Number of bits to read (1 to 32)
* return The value read
*/
static inline unsigned lc3_get_bits(lc3_bits_t *bits, int n);
/**
* Get arithmetic coder symbol
* bits Bitstream context
* model Model distribution
* return The value read
*/
static inline unsigned lc3_get_symbol(lc3_bits_t *bits,
const struct lc3_ac_model *model);
/* ----------------------------------------------------------------------------
* Inline implementations
* -------------------------------------------------------------------------- */
void lc3_put_bits_generic(lc3_bits_t *bits, unsigned v, int n);
unsigned lc3_get_bits_generic(struct lc3_bits *bits, int n);
void lc3_ac_read_renorm(lc3_bits_t *bits);
void lc3_ac_write_renorm(lc3_bits_t *bits);
/**
* Put a bit
*/
static inline void lc3_put_bit(lc3_bits_t *bits, int v)
{
lc3_put_bits(bits, v, 1);
}
/**
* Put from 1 to 32 bits
*/
static inline void lc3_put_bits(struct lc3_bits *bits, unsigned v, int n)
{
struct lc3_bits_accu *accu = &bits->accu;
if (accu->n + n <= LC3_ACCU_BITS) {
accu->v |= v << accu->n;
accu->n += n;
} else {
lc3_put_bits_generic(bits, v, n);
}
}
/**
* Get a bit
*/
static inline int lc3_get_bit(lc3_bits_t *bits)
{
return lc3_get_bits(bits, 1);
}
/**
* Get from 1 to 32 bits
*/
static inline unsigned lc3_get_bits(struct lc3_bits *bits, int n)
{
struct lc3_bits_accu *accu = &bits->accu;
if (accu->n + n <= LC3_ACCU_BITS) {
int v = (accu->v >> accu->n) & ((1u << n) - 1);
return (accu->n += n), v;
}
else {
return lc3_get_bits_generic(bits, n);
}
}
/**
* Put arithmetic coder symbol
*/
static inline void lc3_put_symbol(
struct lc3_bits *bits, const struct lc3_ac_model *model, unsigned s)
{
const struct lc3_ac_symbol *symbols = model->s;
struct lc3_bits_ac *ac = &bits->ac;
unsigned range = ac->range >> 10;
ac->low += range * symbols[s].low;
ac->range = range * symbols[s].range;
ac->carry |= ac->low >> 24;
ac->low &= 0xffffff;
if (ac->range < 0x10000)
lc3_ac_write_renorm(bits);
}
/**
* Get arithmetic coder symbol
*/
static inline unsigned lc3_get_symbol(
lc3_bits_t *bits, const struct lc3_ac_model *model)
{
const struct lc3_ac_symbol *symbols = model->s;
struct lc3_bits_ac *ac = &bits->ac;
unsigned range = (ac->range >> 10) & 0xffff;
ac->error |= (ac->low >= (range << 10));
if (ac->error)
ac->low = 0;
int s = 16;
if (ac->low < range * symbols[s].low) {
s >>= 1;
s -= ac->low < range * symbols[s].low ? 4 : -4;
s -= ac->low < range * symbols[s].low ? 2 : -2;
s -= ac->low < range * symbols[s].low ? 1 : -1;
s -= ac->low < range * symbols[s].low;
}
ac->low -= range * symbols[s].low;
ac->range = range * symbols[s].range;
if (ac->range < 0x10000)
lc3_ac_read_renorm(bits);
return s;
}
#endif /* __LC3_BITS_H */

129
3rd-party/lc3-google/src/bwdet.c vendored Normal file
View File

@ -0,0 +1,129 @@
/******************************************************************************
*
* 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 "bwdet.h"
/**
* Bandwidth detector
*/
enum lc3_bandwidth lc3_bwdet_run(
enum lc3_dt dt, enum lc3_srate sr, const float *e)
{
/* Bandwidth regions (Table 3.6) */
struct region { int is : 8; int ie : 8; };
static const struct region bws_table[LC3_NUM_DT]
[LC3_NUM_BANDWIDTH-1][LC3_NUM_BANDWIDTH-1] = {
[LC3_DT_7M5] = {
{ { 51, 63+1 } },
{ { 45, 55+1 }, { 58, 63+1 } },
{ { 42, 51+1 }, { 53, 58+1 }, { 60, 63+1 } },
{ { 40, 48+1 }, { 51, 55+1 }, { 57, 60+1 }, { 61, 63+1 } },
},
[LC3_DT_10M] = {
{ { 53, 63+1 } },
{ { 47, 56+1 }, { 59, 63+1 } },
{ { 44, 52+1 }, { 54, 59+1 }, { 60, 63+1 } },
{ { 41, 49+1 }, { 51, 55+1 }, { 57, 60+1 }, { 61, 63+1 } },
},
};
static const int l_table[LC3_NUM_DT][LC3_NUM_BANDWIDTH-1] = {
[LC3_DT_7M5] = { 4, 4, 3, 2 },
[LC3_DT_10M] = { 4, 4, 3, 1 },
};
/* --- Stage 1 ---
* Determine bw0 candidate */
enum lc3_bandwidth bw0 = LC3_BANDWIDTH_NB;
enum lc3_bandwidth bwn = (enum lc3_bandwidth)sr;
if (bwn <= bw0)
return bwn;
const struct region *bwr = bws_table[dt][bwn-1];
for (enum lc3_bandwidth bw = bw0; bw < bwn; bw++) {
int i = bwr[bw].is, ie = bwr[bw].ie;
int n = ie - i;
float se = e[i];
for (i++; i < ie; i++)
se += e[i];
if (se >= (10 << (bw == LC3_BANDWIDTH_NB)) * n)
bw0 = bw + 1;
}
/* --- Stage 2 ---
* Detect drop above cut-off frequency.
* The Tc condition (13) is precalculated, as
* Tc[] = 10 ^ (n / 10) , n = { 15, 23, 20, 20 } */
int hold = bw0 >= bwn;
if (!hold) {
int i0 = bwr[bw0].is, l = l_table[dt][bw0];
float tc = (const float []){
31.62277660, 199.52623150, 100, 100 }[bw0];
for (int i = i0 - l + 1; !hold && i <= i0 + 1; i++) {
hold = e[i-l] > tc * e[i];
}
}
return hold ? bw0 : bwn;
}
/**
* Return number of bits coding the bandwidth value
*/
int lc3_bwdet_get_nbits(enum lc3_srate sr)
{
return (sr > 0) + (sr > 1) + (sr > 3);
}
/**
* Put bandwidth indication
*/
void lc3_bwdet_put_bw(lc3_bits_t *bits,
enum lc3_srate sr, enum lc3_bandwidth bw)
{
int nbits_bw = lc3_bwdet_get_nbits(sr);
if (nbits_bw > 0)
lc3_put_bits(bits, bw, nbits_bw);
}
/**
* Get bandwidth indication
*/
int lc3_bwdet_get_bw(lc3_bits_t *bits,
enum lc3_srate sr, enum lc3_bandwidth *bw)
{
enum lc3_bandwidth max_bw = (enum lc3_bandwidth)sr;
int nbits_bw = lc3_bwdet_get_nbits(sr);
*bw = nbits_bw > 0 ? lc3_get_bits(bits, nbits_bw) : LC3_BANDWIDTH_NB;
return *bw > max_bw ? (*bw = max_bw), -1 : 0;
}

69
3rd-party/lc3-google/src/bwdet.h vendored Normal file
View File

@ -0,0 +1,69 @@
/******************************************************************************
*
* 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 - Bandwidth detector
*
* Reference : Low Complexity Communication Codec (LC3)
* Bluetooth Specification v1.0
*/
#ifndef __LC3_BWDET_H
#define __LC3_BWDET_H
#include "common.h"
#include "bits.h"
/**
* Bandwidth detector (cf. 3.3.5)
* dt, sr Duration and samplerate of the frame
* e Energy estimation per bands
* return Return detected bandwitdth
*/
enum lc3_bandwidth lc3_bwdet_run(
enum lc3_dt dt, enum lc3_srate sr, const float *e);
/**
* Return number of bits coding the bandwidth value
* sr Samplerate of the frame
* return Number of bits coding the bandwidth value
*/
int lc3_bwdet_get_nbits(enum lc3_srate sr);
/**
* Put bandwidth indication
* bits Bitstream context
* sr Samplerate of the frame
* bw Bandwidth detected
*/
void lc3_bwdet_put_bw(lc3_bits_t *bits,
enum lc3_srate sr, enum lc3_bandwidth bw);
/**
* Get bandwidth indication
* bits Bitstream context
* sr Samplerate of the frame
* bw Return bandwidth indication
* return 0: Ok -1: Invalid bandwidth indication
*/
int lc3_bwdet_get_bw(lc3_bits_t *bits,
enum lc3_srate sr, enum lc3_bandwidth *bw);
#endif /* __LC3_BWDET_H */

105
3rd-party/lc3-google/src/common.h vendored Normal file
View File

@ -0,0 +1,105 @@
/******************************************************************************
*
* 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 - Common constants and types
*/
#ifndef __LC3_COMMON_H
#define __LC3_COMMON_H
#include <lc3.h>
#include <limits.h>
#include <string.h>
#include <math.h>
/**
* Macros
* MIN/MAX Minimum and maximum between 2 values
* CLIP Clip a value between low and high limits
* ABS Return the absolute value
*/
#define LC3_MIN(a, b) ( (a) < (b) ? (a) : (b) )
#define LC3_MAX(a, b) ( (a) > (b) ? (a) : (b) )
#define LC3_CLIP(v, min, max) LC3_MIN(LC3_MAX(v, min), max)
#define LC3_ABS(n) ( (n) < 0 ? -(n) : (n) )
/**
* Convert `dt` in us and `sr` in KHz
*/
#define LC3_DT_US(dt) \
( (3 + (dt)) * 2500 )
#define LC3_SRATE_KHZ(sr) \
( (1 + (sr) + ((sr) == LC3_SRATE_48K)) * 8 )
/**
* 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, sr) \
( 20 * (3 + (dt)) * (1 + (sr) + ((sr) == LC3_SRATE_48K)) )
#define LC3_ND(dt, sr) \
( (dt) == LC3_DT_7M5 ? 23 * LC3_NS(dt, sr) / 30 \
: 5 * LC3_NS(dt, sr) / 8 )
#define LC3_NE(dt, sr) \
( 20 * (3 + (dt)) * (1 + (sr)) )
#define LC3_MAX_NE \
LC3_NE(LC3_DT_10M, LC3_SRATE_48K)
#define LC3_NH(sr) \
(18 * LC3_SRATE_KHZ(sr))
/**
* Bandwidth, mapped to Nyquist frequency of samplerates
*/
enum lc3_bandwidth {
LC3_BANDWIDTH_NB = LC3_SRATE_8K,
LC3_BANDWIDTH_WB = LC3_SRATE_16K,
LC3_BANDWIDTH_SSWB = LC3_SRATE_24K,
LC3_BANDWIDTH_SWB = LC3_SRATE_32K,
LC3_BANDWIDTH_FB = LC3_SRATE_48K,
LC3_NUM_BANDWIDTH,
};
/**
* Complex floating point number
*/
struct lc3_complex
{
float re, im;
};
#endif /* __LC3_COMMON_H */

70
3rd-party/lc3-google/src/energy.c vendored Normal file
View File

@ -0,0 +1,70 @@
/******************************************************************************
*
* 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 "energy.h"
#include "tables.h"
/**
* Energy estimation per band
*/
bool lc3_energy_compute(
enum lc3_dt dt, enum lc3_srate sr, const float *x, float *e)
{
static const int n1_table[LC3_NUM_DT][LC3_NUM_SRATE] = {
[LC3_DT_7M5] = { 56, 34, 27, 24, 22 },
[LC3_DT_10M] = { 49, 28, 23, 20, 18 },
};
/* First bands are 1 coefficient width */
int n1 = n1_table[dt][sr];
float e_sum[2] = { 0, 0 };
int iband;
for (iband = 0; iband < n1; iband++) {
*e = x[iband] * x[iband];
e_sum[0] += *(e++);
}
/* Mean the square of coefficients within each band,
* note that 7.5ms 8KHz frame has more bands than samples */
int nb = LC3_MIN(LC3_NUM_BANDS, LC3_NS(dt, sr));
int iband_h = nb - 2*(2 - dt);
const int *lim = lc3_band_lim[dt][sr];
for (int i = lim[iband]; iband < nb; iband++) {
int ie = lim[iband+1];
int n = ie - i;
float sx2 = x[i] * x[i];
for (i++; i < ie; i++)
sx2 += x[i] * x[i];
*e = sx2 / n;
e_sum[iband >= iband_h] += *(e++);
}
for (; iband < LC3_NUM_BANDS; iband++)
*(e++) = 0;
/* Return the near nyquist flag */
return e_sum[1] > 30 * e_sum[0];
}

43
3rd-party/lc3-google/src/energy.h vendored Normal file
View File

@ -0,0 +1,43 @@
/******************************************************************************
*
* 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 - Energy estimation per band
*
* Reference : Low Complexity Communication Codec (LC3)
* Bluetooth Specification v1.0
*/
#ifndef __LC3_ENERGY_H
#define __LC3_ENERGY_H
#include "common.h"
/**
* Energy estimation per band
* dt, sr Duration and samplerate of the frame
* x Input MDCT coefficient
* e Energy estimation per bands
* return True when high energy detected near Nyquist frequency
*/
bool lc3_energy_compute(
enum lc3_dt dt, enum lc3_srate sr, const float *x, float *e);
#endif /* __LC3_ENERGY_H */

570
3rd-party/lc3-google/src/lc3.c vendored Normal file
View File

@ -0,0 +1,570 @@
/******************************************************************************
*
* 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 <lc3.h>
#include "common.h"
#include "bits.h"
#include "attdet.h"
#include "bwdet.h"
#include "ltpf.h"
#include "mdct.h"
#include "energy.h"
#include "sns.h"
#include "tns.h"
#include "spec.h"
#include "plc.h"
/**
* Frame side data
*/
struct side_data {
enum lc3_bandwidth bw;
bool pitch_present;
lc3_ltpf_data_t ltpf;
lc3_sns_data_t sns;
lc3_tns_data_t tns;
lc3_spec_side_t spec;
};
/* ----------------------------------------------------------------------------
* General
* -------------------------------------------------------------------------- */
/**
* Resolve frame duration in us
* us Frame duration in us
* return Frame duration identifier, or LC3_NUM_DT
*/
static enum lc3_dt resolve_dt(int us)
{
return us == 7500 ? LC3_DT_7M5 :
us == 10000 ? LC3_DT_10M : LC3_NUM_DT;
}
/**
* Resolve samplerate in Hz
* hz Samplerate in Hz
* return Sample rate identifier, or LC3_NUM_SRATE
*/
static enum lc3_srate resolve_sr(int hz)
{
return hz == 8000 ? LC3_SRATE_8K : hz == 16000 ? LC3_SRATE_16K :
hz == 24000 ? LC3_SRATE_24K : hz == 32000 ? LC3_SRATE_32K :
hz == 48000 ? LC3_SRATE_48K : LC3_NUM_SRATE;
}
/**
* Return the number of PCM samples in a frame
*/
int lc3_frame_samples(int dt_us, int sr_hz)
{
enum lc3_dt dt = resolve_dt(dt_us);
enum lc3_srate sr = resolve_sr(sr_hz);
if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE)
return -1;
return LC3_NS(dt, sr);
}
/**
* Return the size of frames, from bitrate
*/
int lc3_frame_bytes(int dt_us, int bitrate)
{
if (resolve_dt(dt_us) >= LC3_NUM_DT)
return -1;
if (bitrate < LC3_MIN_BITRATE)
return LC3_MIN_FRAME_BYTES;
if (bitrate > LC3_MAX_BITRATE)
return LC3_MAX_FRAME_BYTES;
int nbytes = ((unsigned)bitrate * dt_us) / (1000*1000*8);
return LC3_CLIP(nbytes, LC3_MIN_FRAME_BYTES, LC3_MAX_FRAME_BYTES);
}
/**
* Resolve the bitrate, from the size of frames
*/
int lc3_resolve_bitrate(int dt_us, int nbytes)
{
if (resolve_dt(dt_us) >= LC3_NUM_DT)
return -1;
if (nbytes < LC3_MIN_FRAME_BYTES)
return LC3_MIN_BITRATE;
if (nbytes > LC3_MAX_FRAME_BYTES)
return LC3_MAX_BITRATE;
int bitrate = ((unsigned)nbytes * (1000*1000*8) + dt_us/2) / dt_us;
return LC3_CLIP(bitrate, LC3_MIN_BITRATE, LC3_MAX_BITRATE);
}
/**
* Return algorithmic delay, as a number of samples
*/
int lc3_delay_samples(int dt_us, int sr_hz)
{
enum lc3_dt dt = resolve_dt(dt_us);
enum lc3_srate sr = resolve_sr(sr_hz);
if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE)
return -1;
return (dt == LC3_DT_7M5 ? 8 : 5) * (LC3_SRATE_KHZ(sr) / 2);
}
/* ----------------------------------------------------------------------------
* Encoder
* -------------------------------------------------------------------------- */
/**
* Input PCM Samples from signed 16 bits
* encoder Encoder state
* pcm, stride Input PCM samples, and count between two consecutives
*/
static void load_s16(
struct lc3_encoder *encoder, const void *_pcm, int stride)
{
const int16_t *pcm = _pcm;
enum lc3_dt dt = encoder->dt;
enum lc3_srate sr = encoder->sr_pcm;
float *xs = encoder->xs;
int ns = LC3_NS(dt, sr);
for (int i = 0; i < ns; i++)
xs[i] = pcm[i*stride];
}
/**
* Input PCM Samples from signed 24 bits
* encoder Encoder state
* pcm, stride Input PCM samples, and count between two consecutives
*/
static void load_s24(
struct lc3_encoder *encoder, const void *_pcm, int stride)
{
const int32_t *pcm = _pcm;
enum lc3_dt dt = encoder->dt;
enum lc3_srate sr = encoder->sr_pcm;
float *xs = encoder->xs;
int ns = LC3_NS(dt, sr);
for (int i = 0; i < ns; i++)
xs[i] = ldexpf(pcm[i*stride], -8);
}
/**
* Frame Analysis
* encoder Encoder state
* nbytes Size in bytes of the frame
* side, xq Return frame data
*/
static void analyze(struct lc3_encoder *encoder,
int nbytes, struct side_data *side, int16_t *xq)
{
enum lc3_dt dt = encoder->dt;
enum lc3_srate sr = encoder->sr;
enum lc3_srate sr_pcm = encoder->sr_pcm;
int ns = LC3_NS(dt, sr_pcm);
int nd = LC3_ND(dt, sr_pcm);
float *xs = encoder->xs;
float *xf = encoder->xf;
/* --- Temporal --- */
bool att = lc3_attdet_run(dt, sr_pcm, nbytes, &encoder->attdet, xs);
side->pitch_present =
lc3_ltpf_analyse(dt, sr_pcm, &encoder->ltpf, xs, &side->ltpf);
/* --- Spectral --- */
float e[LC3_NUM_BANDS];
lc3_mdct_forward(dt, sr_pcm, sr, xs, xf);
memmove(xs - nd, xs + ns-nd, nd * sizeof(float));
bool nn_flag = lc3_energy_compute(dt, sr, xf, e);
if (nn_flag)
lc3_ltpf_disable(&side->ltpf);
side->bw = lc3_bwdet_run(dt, sr, e);
lc3_sns_analyze(dt, sr, e, att, &side->sns, xf, xf);
lc3_tns_analyze(dt, side->bw, nn_flag, nbytes, &side->tns, xf);
lc3_spec_analyze(dt, sr,
nbytes, side->pitch_present, &side->tns,
&encoder->spec, xf, xq, &side->spec);
}
/**
* Encode bitstream
* encoder Encoder state
* side, xq The frame data
* nbytes Target size of the frame (20 to 400)
* buffer Output bitstream buffer of `nbytes` size
*/
static void encode(struct lc3_encoder *encoder,
const struct side_data *side, int16_t *xq, int nbytes, void *buffer)
{
enum lc3_dt dt = encoder->dt;
enum lc3_srate sr = encoder->sr;
enum lc3_bandwidth bw = side->bw;
float *xf = encoder->xf;
lc3_bits_t bits;
lc3_setup_bits(&bits, LC3_BITS_MODE_WRITE, buffer, nbytes);
lc3_bwdet_put_bw(&bits, sr, bw);
lc3_spec_put_side(&bits, dt, sr, &side->spec);
lc3_tns_put_data(&bits, &side->tns);
lc3_put_bit(&bits, side->pitch_present);
lc3_sns_put_data(&bits, &side->sns);
if (side->pitch_present)
lc3_ltpf_put_data(&bits, &side->ltpf);
lc3_spec_encode(&bits,
dt, sr, bw, nbytes, xq, &side->spec, xf);
lc3_flush_bits(&bits);
}
/**
* Return size needed for an encoder
*/
unsigned lc3_encoder_size(int dt_us, int sr_hz)
{
if (resolve_dt(dt_us) >= LC3_NUM_DT ||
resolve_sr(sr_hz) >= LC3_NUM_SRATE)
return 0;
return sizeof(struct lc3_encoder) +
LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz) * sizeof(float);
}
/**
* Setup encoder
*/
struct lc3_encoder *lc3_setup_encoder(
int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
{
if (sr_pcm_hz <= 0)
sr_pcm_hz = sr_hz;
enum lc3_dt dt = resolve_dt(dt_us);
enum lc3_srate sr = resolve_sr(sr_hz);
enum lc3_srate sr_pcm = resolve_sr(sr_pcm_hz);
if (dt >= LC3_NUM_DT || sr_pcm >= LC3_NUM_SRATE || sr > sr_pcm || !mem)
return NULL;
struct lc3_encoder *encoder = mem;
int ns = LC3_NS(dt, sr_pcm);
int nd = LC3_ND(dt, sr_pcm);
*encoder = (struct lc3_encoder){
.dt = dt, .sr = sr,
.sr_pcm = sr_pcm,
.xs = encoder->s + nd,
.xf = encoder->s + nd+ns,
};
memset(encoder->s, 0,
LC3_ENCODER_BUFFER_COUNT(dt_us, sr_pcm_hz) * sizeof(float));
return encoder;
}
/**
* Encode a frame
*/
int lc3_encode(struct lc3_encoder *encoder, enum lc3_pcm_format fmt,
const void *pcm, int stride, int nbytes, void *out)
{
static void (* const load[])(struct lc3_encoder *, const void *, int) = {
[LC3_PCM_FORMAT_S16] = load_s16,
[LC3_PCM_FORMAT_S24] = load_s24,
};
/* --- Check parameters --- */
if (!encoder || nbytes < LC3_MIN_FRAME_BYTES
|| nbytes > LC3_MAX_FRAME_BYTES)
return -1;
/* --- Processing --- */
struct side_data side;
int16_t xq[LC3_NE(encoder->dt, encoder->sr)];
load[fmt](encoder, pcm, stride);
analyze(encoder, nbytes, &side, xq);
encode(encoder, &side, xq, nbytes, out);
return 0;
}
/* ----------------------------------------------------------------------------
* Decoder
* -------------------------------------------------------------------------- */
/**
* Output PCM Samples to signed 16 bits
* decoder Decoder state
* pcm, stride Output PCM samples, and count between two consecutives
*/
static void store_s16(
struct lc3_decoder *decoder, void *_pcm, int stride)
{
int16_t *pcm = _pcm;
enum lc3_dt dt = decoder->dt;
enum lc3_srate sr = decoder->sr_pcm;
float *xs = decoder->xs;
int ns = LC3_NS(dt, sr);
for ( ; ns > 0; ns--, xs++, pcm += stride) {
int s = *xs >= 0 ? (int)(*xs + 0.5f) : (int)(*xs - 0.5f);
*pcm = LC3_CLIP(s, INT16_MIN, INT16_MAX);
}
}
/**
* Output PCM Samples to signed 24 bits
* decoder Decoder state
* pcm, stride Output PCM samples, and count between two consecutives
*/
static void store_s24(
struct lc3_decoder *decoder, void *_pcm, int stride)
{
int32_t *pcm = _pcm;
const int32_t int24_max = (1 << 23) - 1;
const int32_t int24_min = -(1 << 23);
enum lc3_dt dt = decoder->dt;
enum lc3_srate sr = decoder->sr_pcm;
float *xs = decoder->xs;
int ns = LC3_NS(dt, sr);
for ( ; ns > 0; ns--, xs++, pcm += stride) {
int32_t s = *xs >= 0 ? (int32_t)(ldexpf(*xs, 8) + 0.5f)
: (int32_t)(ldexpf(*xs, 8) - 0.5f);
*pcm = LC3_CLIP(s, int24_min, int24_max);
}
}
/**
* Decode bitstream
* decoder Decoder state
* data, nbytes Input bitstream buffer
* side Return the side data
* return 0: Ok < 0: Bitsream error detected
*/
static int decode(struct lc3_decoder *decoder,
const void *data, int nbytes, struct side_data *side)
{
enum lc3_dt dt = decoder->dt;
enum lc3_srate sr = decoder->sr;
float *xf = decoder->xs;
int ns = LC3_NS(dt, sr);
int ne = LC3_NE(dt, sr);
lc3_bits_t bits;
int ret = 0;
lc3_setup_bits(&bits, LC3_BITS_MODE_READ, (void *)data, nbytes);
if ((ret = lc3_bwdet_get_bw(&bits, sr, &side->bw)) < 0)
return ret;
if ((ret = lc3_spec_get_side(&bits, dt, sr, &side->spec)) < 0)
return ret;
lc3_tns_get_data(&bits, dt, side->bw, nbytes, &side->tns);
side->pitch_present = lc3_get_bit(&bits);
if ((ret = lc3_sns_get_data(&bits, &side->sns)) < 0)
return ret;
if (side->pitch_present)
lc3_ltpf_get_data(&bits, &side->ltpf);
if ((ret = lc3_spec_decode(&bits, dt, sr,
side->bw, nbytes, &side->spec, xf)) < 0)
return ret;
memset(xf + ne, 0, (ns - ne) * sizeof(float));
return lc3_check_bits(&bits);
}
/**
* Frame synthesis
* decoder Decoder state
* side Frame data, NULL performs PLC
* nbytes Size in bytes of the frame
*/
static void synthesize(struct lc3_decoder *decoder,
const struct side_data *side, int nbytes)
{
enum lc3_dt dt = decoder->dt;
enum lc3_srate sr = decoder->sr;
enum lc3_srate sr_pcm = decoder->sr_pcm;
int ns = LC3_NS(dt, sr_pcm);
int ne = LC3_NE(dt, sr);
int nh = LC3_NH(sr_pcm);
float *xf = decoder->xs;
float *xg = decoder->xg;
float *xd = decoder->xd;
float *xs = xf;
if (side) {
enum lc3_bandwidth bw = side->bw;
lc3_plc_suspend(&decoder->plc);
lc3_tns_synthesize(dt, bw, &side->tns, xf);
lc3_sns_synthesize(dt, sr, &side->sns, xf, xg);
lc3_mdct_inverse(dt, sr_pcm, sr, xg, xd, xs);
} else {
lc3_plc_synthesize(dt, sr, &decoder->plc, xg, xf);
memset(xf + ne, 0, (ns - ne) * sizeof(float));
lc3_mdct_inverse(dt, sr_pcm, sr, xf, xd, xs);
}
lc3_ltpf_synthesize(dt, sr_pcm, nbytes, &decoder->ltpf,
side && side->pitch_present ? &side->ltpf : NULL, xs);
memmove(xs - nh, xs - nh+ns, nh * sizeof(*xs));
}
/**
* Return size needed for a decoder
*/
unsigned lc3_decoder_size(int dt_us, int sr_hz)
{
if (resolve_dt(dt_us) >= LC3_NUM_DT ||
resolve_sr(sr_hz) >= LC3_NUM_SRATE)
return 0;
return sizeof(struct lc3_decoder) +
LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz) * sizeof(float);
}
/**
* Setup decoder
*/
struct lc3_decoder *lc3_setup_decoder(
int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
{
if (sr_pcm_hz <= 0)
sr_pcm_hz = sr_hz;
enum lc3_dt dt = resolve_dt(dt_us);
enum lc3_srate sr = resolve_sr(sr_hz);
enum lc3_srate sr_pcm = resolve_sr(sr_pcm_hz);
if (dt >= LC3_NUM_DT || sr_pcm >= LC3_NUM_SRATE || sr > sr_pcm || !mem)
return NULL;
struct lc3_decoder *decoder = mem;
int nh = LC3_NH(sr_pcm);
int ns = LC3_NS(dt, sr_pcm);
int nd = LC3_ND(dt, sr_pcm);
*decoder = (struct lc3_decoder){
.dt = dt, .sr = sr,
.sr_pcm = sr_pcm,
.xs = decoder->s + nh,
.xd = decoder->s + nh+ns,
.xg = decoder->s + nh+ns+nd,
};
lc3_plc_reset(&decoder->plc);
memset(decoder->s, 0,
LC3_DECODER_BUFFER_COUNT(dt_us, sr_pcm_hz) * sizeof(float));
return decoder;
}
/**
* Decode a frame
*/
int lc3_decode(struct lc3_decoder *decoder, const void *in, int nbytes,
enum lc3_pcm_format fmt, void *pcm, int stride)
{
static void (* const store[])(struct lc3_decoder *, void *, int) = {
[LC3_PCM_FORMAT_S16] = store_s16,
[LC3_PCM_FORMAT_S24] = store_s24,
};
/* --- Check parameters --- */
if (!decoder)
return -1;
if (in && (nbytes < LC3_MIN_FRAME_BYTES ||
nbytes > LC3_MAX_FRAME_BYTES ))
return -1;
/* --- Processing --- */
struct side_data side;
int ret = !in || (decode(decoder, in, nbytes, &side) < 0);
synthesize(decoder, ret ? NULL : &side, nbytes);
store[fmt](decoder, pcm, stride);
return ret;
}

621
3rd-party/lc3-google/src/ltpf.c vendored Normal file
View File

@ -0,0 +1,621 @@
/******************************************************************************
*
* 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 "ltpf.h"
#include "tables.h"
/* ----------------------------------------------------------------------------
* Resampling
* -------------------------------------------------------------------------- */
/**
* Resample to 12.8 KHz (cf. 3.3.9.3-4) Template
* sr Samplerate source of the frame
* hp50 State of the High-Pass 50 Hz filter
* x [-d..-1] Previous, [0..ns-1] Current samples
* y, n [0..n-1] Output `n` processed samples
*
* The number of previous samples `d` accessed on `x` is :
* d: { 10, 20, 30, 40, 60 } - 1 for samplerates from 8KHz to 48KHz
*/
static inline void resample_12k8_template(const enum lc3_srate sr,
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
{
/* --- Parameters ---
* p: Resampling factor, from 4 to 24
* w: Half width of polyphase filter
*
* bn, an: High-Pass Biquad coefficients,
* with `bn` support of rescaling resampling factor.
* Note that it's an High-Pass filter, so we have `b0 = b2`,
* in the following steps we use `b0` as `b2`. */
const int p = 192 / LC3_SRATE_KHZ(sr);
const int w = 5 * LC3_SRATE_KHZ(sr) / 8;
const int b_scale = p >> (sr == LC3_SRATE_8K);
const float a1 = -1.965293373, b1 = -1.965589417 * b_scale;
const float a2 = 0.965885461, b2 = 0.982794708 * b_scale;
/* --- Resampling ---
* The value `15*8 * n` is divisible by all resampling factors `p`,
* integer and fractionnal position can be determined at compilation
* time while unrolling the loops by 8 samples.
* The biquad filter implementation chosen in the `Direct Form 2`. */
const float *h = lc3_ltpf_h12k8 + 119;
x -= w;
for (int i = 0; i < n; i += 8, x += 120/p)
for (int j = 0; j < 15*8; j += 15) {
float un, yn;
int e, f, k;
e = j / p, f = j % p;
for (un = 0, k = 1-w; k <= w; k++)
un += x[e+k] * h[k*p - f];
yn = b2 * un + hp50->s1;
hp50->s1 = b1 * un - a1 * yn + hp50->s2;
hp50->s2 = b2 * un - a2 * yn;
*(y++) = yn;
}
}
/**
* LTPF Resample to 12.8 KHz implementations for each samplerates
*/
static void resample_8k_12k8(
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
{
resample_12k8_template(LC3_SRATE_8K, hp50, x, y, n);
}
static void resample_16k_12k8(
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
{
resample_12k8_template(LC3_SRATE_16K, hp50, x, y, n);
}
static void resample_24k_12k8(
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
{
resample_12k8_template(LC3_SRATE_24K, hp50, x, y, n);
}
static void resample_32k_12k8(
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
{
resample_12k8_template(LC3_SRATE_32K, hp50, x, y, n);
}
static void resample_48k_12k8(
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
{
resample_12k8_template(LC3_SRATE_48K, hp50, x, y, n);
}
static void (* const resample_12k8[])
(struct lc3_ltpf_hp50_state *, const float *, float *, int ) =
{
[LC3_SRATE_8K ] = resample_8k_12k8,
[LC3_SRATE_16K] = resample_16k_12k8,
[LC3_SRATE_24K] = resample_24k_12k8,
[LC3_SRATE_32K] = resample_32k_12k8,
[LC3_SRATE_48K] = resample_48k_12k8,
};
/**
* Resample to 6.4 KHz (cf. 3.3.9.3-4)
* x [-3..-1] Previous, [0..n-1] Current samples
* y, n [0..n-1] Output `n` processed samples
*/
static void resample_6k4(const float *x, float *y, int n)
{
static const float h[] = { 0.2819382921, 0.2353512128, 0.1236796411 };
float xn2 = x[-3], xn1 = x[-2], x0 = x[-1], x1, x2;
for (const float *ye = y + n; y < ye; xn2 = x0, xn1 = x1, x0 = x2) {
x1 = *(x++); x2 = *(x++);
*(y++) = x0 * h[0] + (xn1 + x1) * h[1] + (xn2 + x2) * h[2];
}
}
/* ----------------------------------------------------------------------------
* Analysis
* -------------------------------------------------------------------------- */
/**
* Return dot product of 2 vectors
* a, b, n The 2 vectors of size `n`
* return sum( a[i] * b[i] ), i = [0..n-1]
*/
static inline float dot(const float *a, const float *b, int n)
{
float v = 0;
while (n--)
v += *(a++) * *(b++);
return v;
}
/**
* Return vector of correlations
* a, b, n The 2 vector of size `n` to correlate
* y, nc Output the correlation vector of size `nc`
*
* The size `n` of input vectors must be multiple of 16
*/
static void correlate(
const float *a, const float *b, int n, float *y, int nc)
{
for (const float *ye = y + nc; y < ye; )
*(y++) = dot(a, b--, n);
}
/**
* Search the maximum value and returns its argument
* x, n The input vector of size `n`
* x_max Return the maximum value
* return Return the argument of the maximum
*/
static int argmax(const float *x, int n, float *x_max)
{
int arg = 0;
*x_max = x[arg = 0];
for (int i = 1; i < n; i++)
if (*x_max < x[i])
*x_max = x[arg = i];
return arg;
}
/**
* Search the maximum weithed value and returns its argument
* x, n The input vector of size `n`
* w_incr Increment of the weight
* x_max, xw_max Return the maximum not weighted value
* return Return the argument of the weigthed maximum
*/
static int argmax_weighted(
const float *x, int n, float w_incr, float *x_max)
{
int arg;
float xw_max = (*x_max = x[arg = 0]);
float w = 1 + w_incr;
for (int i = 1; i < n; i++, w += w_incr)
if (xw_max < x[i] * w)
xw_max = (*x_max = x[arg = i]) * w;
return arg;
}
/**
* Interpolate from pitch detected value (3.3.9.8)
* x, n [-2..-1] Previous, [0..n] Current input
* d The phase of interpolation (0 to 3)
* return The interpolated vector
*
* The size `n` of vectors must be multiple of 4
*/
static void interpolate(const float *x, int n, int d, float *y)
{
static const float h4[][8] = {
{ 2.09880463e-01, 5.83527575e-01, 2.09880463e-01 },
{ 1.06999186e-01, 5.50075002e-01, 3.35690625e-01, 6.69885837e-03 },
{ 3.96711478e-02, 4.59220930e-01, 4.59220930e-01, 3.96711478e-02 },
{ 6.69885837e-03, 3.35690625e-01, 5.50075002e-01, 1.06999186e-01 },
};
const float *h = h4[d];
float x3 = x[-2], x2 = x[-1], x1, x0;
x1 = (*x++);
for (const float *ye = y + n; y < ye; ) {
*(y++) = (x0 = *(x++)) * h[0] + x1 * h[1] + x2 * h[2] + x3 * h[3];
*(y++) = (x3 = *(x++)) * h[0] + x0 * h[1] + x1 * h[2] + x2 * h[3];
*(y++) = (x2 = *(x++)) * h[0] + x3 * h[1] + x0 * h[2] + x1 * h[3];
*(y++) = (x1 = *(x++)) * h[0] + x2 * h[1] + x3 * h[2] + x0 * h[3];
}
}
/**
* Interpolate autocorrelation (3.3.9.7)
* x [-4..-1] Previous, [0..4] Current input
* d The phase of interpolation (-3 to 3)
* return The interpolated value
*/
static float interpolate_4(const float *x, int d)
{
static const float h4[][8] = {
{ 1.53572770e-02, -4.72963246e-02, 8.35788573e-02, 8.98638285e-01,
8.35788573e-02, -4.72963246e-02, 1.53572770e-02, },
{ 2.74547165e-03, 4.59833449e-03, -7.54404636e-02, 8.17488686e-01,
3.30182571e-01, -1.05835916e-01, 2.86823405e-02, -2.87456116e-03 },
{ -3.00125103e-03, 2.95038503e-02, -1.30305021e-01, 6.03297008e-01,
6.03297008e-01, -1.30305021e-01, 2.95038503e-02, -3.00125103e-03 },
{ -2.87456116e-03, 2.86823405e-02, -1.05835916e-01, 3.30182571e-01,
8.17488686e-01, -7.54404636e-02, 4.59833449e-03, 2.74547165e-03 },
};
const float *h = h4[(4+d) % 4];
float y = d < 0 ? x[-4] * *(h++) :
d > 0 ? x[ 4] * *(h+7) : 0;
y += x[-3] * h[0] + x[-2] * h[1] + x[-1] * h[2] + x[0] * h[3] +
x[ 1] * h[4] + x[ 2] * h[5] + x[ 3] * h[6];
return y;
}
/**
* Pitch detection algorithm (3.3.9.5-6)
* ltpf Context of analysis
* x, n [-114..-17] Previous, [0..n-1] Current 6.4KHz samples
* tc Return the pitch-lag estimation
* return True when pitch present
*/
static bool detect_pitch(
struct lc3_ltpf_analysis *ltpf, const float *x, int n, int *tc)
{
float rm1, rm2;
float r[98];
const int r0 = 17, nr = 98;
int k0 = LC3_MAX( 0, ltpf->tc-4);
int nk = LC3_MIN(nr-1, ltpf->tc+4) - k0 + 1;
correlate(x, x - r0, n, r, nr);
int t1 = argmax_weighted(r, nr, -.5/(nr-1), &rm1);
int t2 = k0 + argmax(r + k0, nk, &rm2);
const float *x1 = x - (r0 + t1);
const float *x2 = x - (r0 + t2);
float nc1 = rm1 <= 0 ? 0 :
rm1 / sqrtf(dot(x, x, n) * dot(x1, x1, n));
float nc2 = rm2 <= 0 ? 0 :
rm2 / sqrtf(dot(x, x, n) * dot(x2, x2, n));
int t1sel = nc2 <= 0.85 * nc1;
ltpf->tc = (t1sel ? t1 : t2);
*tc = r0 + ltpf->tc;
return (t1sel ? nc1 : nc2) > 0.6;
}
/**
* Pitch-lag parameter (3.3.9.7)
* x, n [-232..-28] Previous, [0..n-1] Current 12.8KHz samples
* tc Pitch-lag estimation
* pitch The pitch value, in fixed .4
* return The bitstream pitch index value
*/
static int refine_pitch(const float *x, int n, int tc, int *pitch)
{
float r[17], rm;
int e, f;
int r0 = LC3_MAX( 32, 2*tc - 4);
int nr = LC3_MIN(228, 2*tc + 4) - r0 + 1;
correlate(x, x - (r0 - 4), n, r, nr + 8);
e = r0 + argmax(r + 4, nr, &rm);
const float *re = r + (e - (r0 - 4));
float dm = interpolate_4(re, f = 0);
for (int i = 1; i <= 3; i++) {
float d;
if (e >= 127 && ((i & 1) | (e >= 157)))
continue;
if ((d = interpolate_4(re, i)) > dm)
dm = d, f = i;
if (e > 32 && (d = interpolate_4(re, -i)) > dm)
dm = d, f = -i;
}
e -= (f < 0);
f += 4*(f < 0);
*pitch = 4*e + f;
return e < 127 ? 4*e + f - 128 :
e < 157 ? 2*e + (f >> 1) + 126 : e + 283;
}
/**
* LTPF Analysis
*/
bool lc3_ltpf_analyse(enum lc3_dt dt, enum lc3_srate sr,
struct lc3_ltpf_analysis *ltpf, const float *x, struct lc3_ltpf_data *data)
{
/* --- Resampling to 12.8 KHz --- */
int z_12k8 = sizeof(ltpf->x_12k8) / sizeof(float);
int n_12k8 = dt == LC3_DT_7M5 ? 96 : 128;
memmove(ltpf->x_12k8, ltpf->x_12k8 + n_12k8,
(z_12k8 - n_12k8) * sizeof(float));
float *x_12k8 = ltpf->x_12k8 + (z_12k8 - n_12k8);
resample_12k8[sr](&ltpf->hp50, x, x_12k8, n_12k8);
x_12k8 -= (dt == LC3_DT_7M5 ? 44 : 24);
/* --- Resampling to 6.4 KHz --- */
int z_6k4 = sizeof(ltpf->x_6k4) / sizeof(float);
int n_6k4 = n_12k8 >> 1;
memmove(ltpf->x_6k4, ltpf->x_6k4 + n_6k4,
(z_6k4 - n_6k4) * sizeof(float));
float *x_6k4 = ltpf->x_6k4 + (z_6k4 - n_6k4);
resample_6k4(x_12k8, x_6k4, n_6k4);
/* --- Pitch detection --- */
int tc, pitch = 0;
float nc = 0;
bool pitch_present = detect_pitch(ltpf, x_6k4, n_6k4, &tc);
if (pitch_present) {
float u[n_12k8], v[n_12k8];
data->pitch_index = refine_pitch(x_12k8, n_12k8, tc, &pitch);
interpolate(x_12k8, n_12k8, 0, u);
interpolate(x_12k8 - (pitch >> 2), n_12k8, pitch & 3, v);
nc = dot(u, v, n_12k8) / sqrtf(dot(u, u, n_12k8) * dot(v, v, n_12k8));
}
/* --- Activation --- */
if (ltpf->active) {
int pitch_diff =
LC3_MAX(pitch, ltpf->pitch) - LC3_MIN(pitch, ltpf->pitch);
float nc_diff = nc - ltpf->nc[0];
data->active = pitch_present &&
((nc > 0.9) || (nc > 0.84 && pitch_diff < 8 && nc_diff > -0.1));
} else {
data->active = pitch_present &&
( (dt == LC3_DT_10M || ltpf->nc[1] > 0.94) &&
(ltpf->nc[0] > 0.94 && nc > 0.94) );
}
ltpf->active = data->active;
ltpf->pitch = pitch;
ltpf->nc[1] = ltpf->nc[0];
ltpf->nc[0] = nc;
return pitch_present;
}
/* ----------------------------------------------------------------------------
* Synthesis
* -------------------------------------------------------------------------- */
/**
* Synthesis filter template
* ym [-w/2..0] Previous, [0..w-1] Current pitch samples
* xm w-1 previous input samples
* x, n Current samples as input, filtered as output
* c, w Coefficients by pair (num, den), and count of pairs
* fade Fading mode of filter -1: Out 1: In 0: None
*/
static inline void synthesize_template(const float *ym, const float *xm,
float *x, int n, const float (*c)[2], const int w, int fade)
{
float g = (float)(fade <= 0);
float g_incr = (float)((fade > 0) - (fade < 0)) / n;
float u[w];
int i;
ym -= (w >> 1);
/* --- Load previous samples --- */
for (i = 1-w; i < 0; i++) {
float xi = *(xm++), yi = *(ym++);
u[i + w-1] = 0;
for (int k = w-1; k+i >= 0; k--)
u[i+k] += xi * c[k][0] - yi * c[k][1];
}
u[w-1] = 0;
/* --- Process --- */
for (; i < n; i += w) {
for (int j = 0; j < w; j++, g += g_incr) {
float xi = *x, yi = *(ym++);
for (int k = w-1; k >= 0; k--)
u[(j+k)%w] += xi * c[k][0] - yi * c[k][1];
*(x++) = xi - g * u[j];
u[j] = 0;
}
}
}
/**
* Synthesis filter for each samplerates (width of filter)
*/
static void synthesize_4(const float *ym, const float *xm,
float *x, int n, const float (*c)[2], int fade)
{
synthesize_template(ym, xm, x, n, c, 4, fade);
}
static void synthesize_6(const float *ym, const float *xm,
float *x, int n, const float (*c)[2], int fade)
{
synthesize_template(ym, xm, x, n, c, 6, fade);
}
static void synthesize_8(const float *ym, const float *xm,
float *x, int n, const float (*c)[2], int fade)
{
synthesize_template(ym, xm, x, n, c, 8, fade);
}
static void synthesize_12(const float *ym, const float *xm,
float *x, int n, const float (*c)[2], int fade)
{
synthesize_template(ym, xm, x, n, c, 12, fade);
}
static void (* const synthesize[])(
const float *, const float *, float *, int, const float (*)[2], int) =
{
[LC3_SRATE_8K ] = synthesize_4,
[LC3_SRATE_16K] = synthesize_4,
[LC3_SRATE_24K] = synthesize_6,
[LC3_SRATE_32K] = synthesize_8,
[LC3_SRATE_48K] = synthesize_12,
};
/**
* LTPF Synthesis
*/
void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr,
int nbytes, struct lc3_ltpf_synthesis *ltpf,
const struct lc3_ltpf_data *data, float *x)
{
int dt_us = LC3_DT_US(dt);
/* --- Filter parameters --- */
int p_idx = data ? data->pitch_index : 0;
int pitch =
p_idx >= 440 ? (((p_idx ) - 283) << 2) :
p_idx >= 380 ? (((p_idx >> 1) - 63) << 2) + (((p_idx & 1)) << 1) :
(((p_idx >> 2) + 32) << 2) + (((p_idx & 3)) << 0) ;
pitch = (pitch * LC3_SRATE_KHZ(sr) * 10 + 64) / 128;
int nbits = (nbytes*8 * 10000 + (dt_us/2)) / dt_us;
int g_idx = LC3_MAX(nbits / 80, 3 + (int)sr) - (3 + sr);
bool active = data && data->active && g_idx < 4;
int w = LC3_MAX(4, LC3_SRATE_KHZ(sr) / 4);
float c[w][2];
for (int i = 0; i < w; i++) {
float g = active ? 0.4f - 0.05f * g_idx : 0;
c[i][0] = active ? 0.85f * g * lc3_ltpf_cnum[sr][g_idx][i] : 0;
c[i][1] = active ? g * lc3_ltpf_cden[sr][pitch & 3][i] : 0;
}
/* --- Transition handling --- */
int ns = LC3_NS(dt, sr);
int nt = ns / (4 - (dt == LC3_DT_7M5));
float xm[12];
if (active)
memcpy(xm, x + nt-(w-1), (w-1) * sizeof(float));
if (!ltpf->active && active)
synthesize[sr](x - pitch/4, ltpf->x, x, nt, c, 1);
else if (ltpf->active && !active)
synthesize[sr](x - ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
else if (ltpf->active && active && ltpf->pitch == pitch)
synthesize[sr](x - pitch/4, ltpf->x, x, nt, c, 0);
else if (ltpf->active && active) {
synthesize[sr](x - ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
synthesize[sr](x - pitch/4, x - (w-1), x, nt, c, 1);
}
/* --- Remainder --- */
memcpy(ltpf->x, x + ns-(w-1), (w-1) * sizeof(float));
if (active)
synthesize[sr](x - pitch/4 + nt, xm, x + nt, ns-nt, c, 0);
/* --- Update state --- */
ltpf->active = active;
ltpf->pitch = pitch;
memcpy(ltpf->c, c, w * sizeof(ltpf->c[0]));
}
/* ----------------------------------------------------------------------------
* Bitstream data
* -------------------------------------------------------------------------- */
/**
* LTPF disable
*/
void lc3_ltpf_disable(struct lc3_ltpf_data *data)
{
data->active = false;
}
/**
* Return number of bits coding the bitstream data
*/
int lc3_ltpf_get_nbits(bool pitch)
{
return 1 + 10 * pitch;
}
/**
* Put bitstream data
*/
void lc3_ltpf_put_data(lc3_bits_t *bits,
const struct lc3_ltpf_data *data)
{
lc3_put_bit(bits, data->active);
lc3_put_bits(bits, data->pitch_index, 9);
}
/**
* Get bitstream data
*/
void lc3_ltpf_get_data(lc3_bits_t *bits, struct lc3_ltpf_data *data)
{
data->active = lc3_get_bit(bits);
data->pitch_index = lc3_get_bits(bits, 9);
}

107
3rd-party/lc3-google/src/ltpf.h vendored Normal file
View File

@ -0,0 +1,107 @@
/******************************************************************************
*
* 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 - Long Term Postfilter
*
* Reference : Low Complexity Communication Codec (LC3)
* Bluetooth Specification v1.0
*/
#ifndef __LC3_LTPF_H
#define __LC3_LTPF_H
#include "common.h"
#include "bits.h"
/**
* LTPF data
*/
typedef struct lc3_ltpf_data {
bool active;
int pitch_index;
} lc3_ltpf_data_t;
/* ----------------------------------------------------------------------------
* Encoding
* -------------------------------------------------------------------------- */
/**
* LTPF analysis
* dt, sr Duration and samplerate of the frame
* ltpf Context of analysis
* allowed True when activation of LTPF is allowed
* x [-d..-1] Previous, [0..ns-1] Current samples
* data Return bitstream data
* return True when pitch present, False otherwise
*
* The number of previous samples `d` accessed on `x` is :
* d: { 10, 20, 30, 40, 60 } - 1 for samplerates from 8KHz to 48KHz
*/
bool lc3_ltpf_analyse(enum lc3_dt dt, enum lc3_srate sr,
lc3_ltpf_analysis_t *ltpf, const float *x, lc3_ltpf_data_t *data);
/**
* LTPF disable
* data LTPF data, disabled activation on return
*/
void lc3_ltpf_disable(lc3_ltpf_data_t *data);
/**
* Return number of bits coding the bitstream data
* pitch True when pitch present, False otherwise
* return Bit consumption, including the pitch present flag
*/
int lc3_ltpf_get_nbits(bool pitch);
/**
* Put bitstream data
* bits Bitstream context
* data LTPF data
*/
void lc3_ltpf_put_data(lc3_bits_t *bits, const lc3_ltpf_data_t *data);
/* ----------------------------------------------------------------------------
* Decoding
* -------------------------------------------------------------------------- */
/**
* Get bitstream data
* bits Bitstream context
* data Return bitstream data
*/
void lc3_ltpf_get_data(lc3_bits_t *bits, lc3_ltpf_data_t *data);
/**
* LTPF synthesis
* dt, sr Duration and samplerate of the frame
* nbytes Size in bytes of the frame
* ltpf Context of synthesis
* data Bitstream data, NULL when pitch not present
* x [-d..-1] Previous, [0..ns-1] Current, filtered as output
*
* The number of previous samples `d` accessed on `x` is about 18 ms
*/
void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr, int nbytes,
lc3_ltpf_synthesis_t *ltpf, const lc3_ltpf_data_t *data, float *x);
#endif /* __LC3_LTPF_H */

502
3rd-party/lc3-google/src/mdct.c vendored Normal file
View File

@ -0,0 +1,502 @@
/******************************************************************************
*
* 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 "tables.h"
/* ----------------------------------------------------------------------------
* FFT processing
* -------------------------------------------------------------------------- */
/**
* FFT 5 Points template
* s -1: Forward 1: Inverse
* x, y Input and output coefficients, of size 5xn
* n Number of interleaved transform to perform
*/
static inline void xfft_5(const float s,
const struct lc3_complex *x, struct lc3_complex *y, int n)
{
static const float cos1 = 0.3090169944; /* cos(-2Pi 1/5) */
static const float cos2 = -0.8090169944; /* cos(-2Pi 2/5) */
static const float sin1 = -0.9510565163; /* sin(-2Pi 1/5) */
static const float sin2 = -0.5877852523; /* sin(-2Pi 2/5) */
for (int i = 0; i < n; i++, x++, y+= 5) {
struct lc3_complex s14 =
{ x[1*n].re + x[4*n].re, x[1*n].im + x[4*n].im };
struct lc3_complex d14 =
{ x[1*n].re - x[4*n].re, x[1*n].im - x[4*n].im };
struct lc3_complex s23 =
{ x[2*n].re + x[3*n].re, x[2*n].im + x[3*n].im };
struct lc3_complex d23 =
{ x[2*n].re - x[3*n].re, x[2*n].im - x[3*n].im };
y[0].re = x[0].re + s14.re + s23.re;
y[0].im = x[0].im + s14.im + s23.im;
y[1].re = x[0].re + s14.re * cos1 + s * d14.im * sin1
+ s23.re * cos2 + s * d23.im * sin2;
y[1].im = x[0].im + s14.im * cos1 - s * d14.re * sin1
+ s23.im * cos2 - s * d23.re * sin2;
y[2].re = x[0].re + s14.re * cos2 + s * d14.im * sin2
+ s23.re * cos1 - s * d23.im * sin1;
y[2].im = x[0].im + s14.im * cos2 - s * d14.re * sin2
+ s23.im * cos1 + s * d23.re * sin1;
y[3].re = x[0].re + s14.re * cos2 - s * d14.im * sin2
+ s23.re * cos1 + s * d23.im * sin1;
y[3].im = x[0].im + s14.im * cos2 + s * d14.re * sin2
+ s23.im * cos1 - s * d23.re * sin1;
y[4].re = x[0].re + s14.re * cos1 - s * d14.im * sin1
+ s23.re * cos2 - s * d23.im * sin2;
y[4].im = x[0].im + s14.im * cos1 + s * d14.re * sin1
+ s23.im * cos2 + s * d23.re * sin2;
}
}
/**
* FFT Butterfly 3 Points template
* s -1: Forward 1: Inverse
* x, y Input and output coefficients
* twiddles Twiddles factors, determine size of transform
* n Number of interleaved transforms
*/
static inline void xfft_bf3(
const float s, const struct lc3_fft_bf3_twiddles *twiddles,
const struct lc3_complex *x, struct lc3_complex *y, int n)
{
int n3 = twiddles->n3;
const struct lc3_complex (*w0)[2] = twiddles->t;
const struct lc3_complex (*w1)[2] = w0 + n3, (*w2)[2] = w1 + n3;
const struct lc3_complex *x0 = x, *x1 = x0 + n*n3, *x2 = x1 + n*n3;
struct lc3_complex *y0 = y, *y1 = y0 + n3, *y2 = y1 + n3;
for (int i = 0; i < n; i++, y0 += 3*n3, y1 += 3*n3, y2 += 3*n3) {
for (int j = 0; j < n3; j++, x0++, x1++, x2++) {
y0[j].re = x0->re + x1->re * w0[j][0].re + s * x1->im * w0[j][0].im
+ x2->re * w0[j][1].re + s * x2->im * w0[j][1].im;
y0[j].im = x0->im + x1->im * w0[j][0].re - s * x1->re * w0[j][0].im
+ x2->im * w0[j][1].re - s * x2->re * w0[j][1].im;
y1[j].re = x0->re + x1->re * w1[j][0].re + s * x1->im * w1[j][0].im
+ x2->re * w1[j][1].re + s * x2->im * w1[j][1].im;
y1[j].im = x0->im + x1->im * w1[j][0].re - s * x1->re * w1[j][0].im
+ x2->im * w1[j][1].re - s * x2->re * w1[j][1].im;
y2[j].re = x0->re + x1->re * w2[j][0].re + s * x1->im * w2[j][0].im
+ x2->re * w2[j][1].re + s * x2->im * w2[j][1].im;
y2[j].im = x0->im + x1->im * w2[j][0].re - s * x1->re * w2[j][0].im
+ x2->im * w2[j][1].re - s * x2->re * w2[j][1].im;
}
}
}
/**
* FFT Butterfly 2 Points template
* s -1: Forward 1: Inverse
* twiddles Twiddles factors, determine size of transform
* x, y Input and output coefficients
* n Number of interleaved transforms
*/
static inline void xfft_bf2(
const float s, const struct lc3_fft_bf2_twiddles *twiddles,
const struct lc3_complex *x, struct lc3_complex *y, int n)
{
int n2 = twiddles->n2;
const struct lc3_complex *w = twiddles->t;
const struct lc3_complex *x0 = x, *x1 = x0 + n*n2;
struct lc3_complex *y0 = y, *y1 = y0 + n2;
for (int i = 0; i < n; i++, y0 += 2*n2, y1 += 2*n2) {
for (int j = 0; j < n2; j++, x0++, x1++) {
y0[j].re = x0->re + x1->re * w[j].re + s * x1->im * w[j].im;
y0[j].im = x0->im + x1->im * w[j].re - s * x1->re * w[j].im;
y1[j].re = x0->re - x1->re * w[j].re - s * x1->im * w[j].im;
y1[j].im = x0->im - x1->im * w[j].re + s * x1->re * w[j].im;
}
}
}
/**
* Forward FFT 5 Points
* x, y Input and output coefficients, of size 5xn
* n Number of interleaved transform to perform
*/
static void ffft_5(const struct lc3_complex *x, struct lc3_complex *y, int n)
{
xfft_5(-1, x, y, n);
}
/**
* Inverse FFT 5 Points
* x, y Input and output coefficients, of size 5xn
* n Number of interleaved transform to perform
*/
static void ifft_5(const struct lc3_complex *x, struct lc3_complex *y, int n)
{
xfft_5(1, x, y, n);
}
/**
* Forward FFT Butterfly 3 Points
* twiddles Twiddles factors, determine size of transform
* x, y Input and output coefficients
* n Number of interleaved transforms
*/
static void ffft_bf3(const struct lc3_fft_bf3_twiddles *twiddles,
const struct lc3_complex *x, struct lc3_complex *y, int n)
{
xfft_bf3(-1, twiddles, x, y, n);
}
/**
* Inverse FFT Butterfly 3 Points
* twiddles Twiddles factors, determine size of transform
* x, y Input and output coefficients
* n Number of interleaved transforms
*/
static void ifft_bf3(const struct lc3_fft_bf3_twiddles *twiddles,
const struct lc3_complex *x, struct lc3_complex *y, int n)
{
xfft_bf3(1, twiddles, x, y, n);
}
/**
* Forward FFT Butterfly 2 Points
* twiddles Twiddles factors, determine size of transform
* x, y Input and output coefficients
* n Number of interleaved transforms
*/
static void ffft_bf2(const struct lc3_fft_bf2_twiddles *twiddles,
const struct lc3_complex *x, struct lc3_complex *y, int n)
{
xfft_bf2(-1, twiddles, x, y, n);
}
/**
* InverseIFFT Butterfly 2 Points
* twiddles Twiddles factors, determine size of transform
* x, y Input and output coefficients
* n Number of interleaved transforms
*/
static void ifft_bf2(const struct lc3_fft_bf2_twiddles *twiddles,
const struct lc3_complex *x, struct lc3_complex *y, int n)
{
xfft_bf2(1, twiddles, x, y, n);
}
/**
* Perform FFT
* inverse True on inverse transform else forward
* x, y0, y1 Input, and 2 scratch buffers of size `n`
* n Number of points 30, 40, 60, 80, 90, 120, 160, 180, 240
* return The buffer `y0` or `y1` that hold the result
*
* Input `x` can be the same as the `y0` second scratch buffer
*/
static struct lc3_complex *fft(
bool inverse, const struct lc3_complex *x, int n,
struct lc3_complex *y0, struct lc3_complex *y1)
{
struct lc3_complex *y[2] = { y1, y0 };
int i2, i3, is = 0;
/* The number of points `n` can be decomposed as :
*
* n = 5^1 * 3^n3 * 2^n2
*
* for n = 40, 80, 160 n3 = 0, n2 = [3..5]
* n = 30, 60, 120, 240 n3 = 1, n2 = [1..4]
* n = 90, 180 n3 = 2, n2 = [1..2]
*
* Note that the expression `n & (n-1) == 0` is equivalent
* to the check that `n` is a power of 2. */
(inverse ? ifft_5 : ffft_5)(x, y[is], n /= 5);
for (i3 = 0; n & (n-1); i3++, is ^= 1)
(inverse ? ifft_bf3 : ffft_bf3)
(lc3_fft_twiddles_bf3[i3], y[is], y[is ^ 1], n /= 3);
for (i2 = 0; n > 1; i2++, is ^= 1)
(inverse ? ifft_bf2 : ffft_bf2)
(lc3_fft_twiddles_bf2[i2][i3], y[is], y[is ^ 1], n >>= 1);
return y[is];
}
/* ----------------------------------------------------------------------------
* MDCT processing
* -------------------------------------------------------------------------- */
/**
* Windowing of samples before MDCT
* dt, sr Duration and samplerate (size of the transform)
* x [-nd..-1] Previous, [0..ns-1] Current samples
* y Output `ns` windowed samples
*
* The number of previous samples `nd` accessed on `x` is :
* nd: `ns` * 23/30 for 7.5ms frame duration
* nd: `ns` * 5/ 8 for 10ms frame duration
*/
static void mdct_window(
enum lc3_dt dt, enum lc3_srate sr, const float *x, float *y)
{
int ns = LC3_NS(dt, sr), nd = LC3_ND(dt, sr);
const float *w0 = lc3_mdct_win[dt][sr], *w1 = w0 + ns;
const float *w2 = w1, *w3 = w2 + nd;
const float *x0 = x - nd, *x1 = x0 + ns;
const float *x2 = x1, *x3 = x2 + nd;
float *y0 = y + ns/2, *y1 = y0;
while (x0 < x1)
*(--y0) = *(x0++) * *(w0++) - *(--x1) * *(--w1);
for (const float *xe = x2 + ns-nd; x2 < xe; )
*(y1++) = *(x2++) * *(w2++);
while (x2 < x3)
*(y1++) = *(x2++) * *(w2++) + *(--x3) * *(--w3);
}
/**
* Pre-rotate MDCT coefficients of N/2 points, before FFT N/4 points FFT
* def Size and twiddles factors
* x, y Input and output coefficients
*
* `x` and y` can be the same buffer
*/
static void mdct_pre_fft(const struct lc3_mdct_rot_def *def,
const float *x, struct lc3_complex *y)
{
int n4 = def->n4;
const float *x0 = x, *x1 = x0 + 2*n4;
const struct lc3_complex *w0 = def->w, *w1 = w0 + n4;
struct lc3_complex *y0 = y, *y1 = y0 + n4;
while (x0 < x1) {
struct lc3_complex u, uw = *(w0++);
u.re = - *(--x1) * uw.re + *x0 * uw.im;
u.im = *(x0++) * uw.re + *x1 * uw.im;
struct lc3_complex v, vw = *(--w1);
v.re = - *(--x1) * vw.im + *x0 * vw.re;
v.im = - *(x0++) * vw.im - *x1 * vw.re;
*(y0++) = u;
*(--y1) = v;
}
}
/**
* Post-rotate FFT N/4 points coefficients, resulting MDCT N points
* def Size and twiddles factors
* x, y Input and output coefficients
* scale Scale on output coefficients
*
* `x` and y` can be the same buffer
*/
static void mdct_post_fft(const struct lc3_mdct_rot_def *def,
const struct lc3_complex *x, float *y, float scale)
{
int n4 = def->n4, n8 = n4 >> 1;
const struct lc3_complex *w0 = def->w + n8, *w1 = w0 - 1;
const struct lc3_complex *x0 = x + n8, *x1 = x0 - 1;
float *y0 = y + n4, *y1 = y0;
for ( ; y1 > y; x0++, x1--, w0++, w1--) {
float u0 = (x0->im * w0->im + x0->re * w0->re) * scale;
float u1 = (x1->re * w1->im - x1->im * w1->re) * scale;
float v0 = (x0->re * w0->im - x0->im * w0->re) * scale;
float v1 = (x1->im * w1->im + x1->re * w1->re) * scale;
*(y0++) = u0; *(y0++) = u1;
*(--y1) = v0; *(--y1) = v1;
}
}
/**
* Pre-rotate IMDCT coefficients of N points, before FFT N/4 points FFT
* def Size and twiddles factors
* x, y Input and output coefficients
*
* `x` and y` can be the same buffer
*/
static void imdct_pre_fft(const struct lc3_mdct_rot_def *def,
const float *x, struct lc3_complex *y)
{
int n4 = def->n4;
const float *x0 = x, *x1 = x0 + 2*n4;
const struct lc3_complex *w0 = def->w, *w1 = w0 + n4;
struct lc3_complex *y0 = y, *y1 = y0 + n4;
while (x0 < x1) {
float u0 = *(x0++), u1 = *(--x1);
float v0 = *(x0++), v1 = *(--x1);
struct lc3_complex uw = *(w0++), vw = *(--w1);
(y0 )->re = - u1 * uw.re + u0 * uw.im;
(y0++)->im = - u0 * uw.re - u1 * uw.im;
(--y1)->re = - v0 * vw.re + v1 * vw.im;
( y1)->im = - v1 * vw.re - v0 * vw.im;
}
}
/**
* Post-rotate FFT N/4 points coefficients, resulting IMDCT N points
* def Size and twiddles factors
* x, y Input and output coefficients
* scale Scale on output coefficients
*
* `x` and y` can be the same buffer
*/
static void imdct_post_fft(const struct lc3_mdct_rot_def *def,
const struct lc3_complex *x, float *y, float scale)
{
int n4 = def->n4;
const struct lc3_complex *w0 = def->w, *w1 = w0 + n4;
const struct lc3_complex *x0 = x, *x1 = x0 + n4;
float *y0 = y, *y1 = y0 + 2*n4;
while (x0 < x1) {
struct lc3_complex uz = *(x0++), vz = *(--x1);
struct lc3_complex uw = *(w0++), vw = *(--w1);
*(y0++) = (uz.im * uw.im - uz.re * uw.re) * scale;
*(--y1) = (uz.im * uw.re + uz.re * uw.im) * scale;
*(--y1) = (vz.im * vw.im - vz.re * vw.re) * scale;
*(y0++) = (vz.im * vw.re + vz.re * vw.im) * scale;
}
}
/**
* Apply windowing of samples
* dt, sr Duration and samplerate
* x, d Middle half of IMDCT coefficients and delayed samples
* y, d Output samples and delayed ones
*/
static void imdct_window(enum lc3_dt dt, enum lc3_srate sr,
const float *x, float *d, float *y)
{
/* The full MDCT coefficients is given by symmetry :
* T[ 0 .. n/4-1] = -half[n/4-1 .. 0 ]
* T[ n/4 .. n/2-1] = half[0 .. n/4-1]
* T[ n/2 .. 3n/4-1] = half[n/4 .. n/2-1]
* T[3n/4 .. n-1] = half[n/2-1 .. n/4 ] */
int n4 = LC3_NS(dt, sr) >> 1, nd = LC3_ND(dt, sr);
const float *w2 = lc3_mdct_win[dt][sr], *w0 = w2 + 3*n4, *w1 = w0;
const float *x0 = d + nd-n4, *x1 = x0;
float *y0 = y + nd-n4, *y1 = y0, *y2 = d + nd, *y3 = d;
while (y0 > y) {
*(--y0) = *(--x0) - *(x ) * *(w1++);
*(y1++) = *(x1++) + *(x++) * *(--w0);
}
while (y1 < y + nd) {
*(y1++) = *(x1++) + *(x++) * *(--w0);
}
while (y1 < y + 2*n4) {
*(y1++) = *(x ) * *(--w0);
*(--y2) = *(x++) * *(w2++);
}
while (y2 > y3) {
*(y3++) = *(x ) * *(--w0);
*(--y2) = *(x++) * *(w2++);
}
}
/**
* Forward MDCT transformation
*/
void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr,
enum lc3_srate sr_dst, const float *x, float *y)
{
const struct lc3_mdct_rot_def *rot = lc3_mdct_rot[dt][sr];
int nf = LC3_NS(dt, sr_dst);
int ns = LC3_NS(dt, sr);
union { float *f; struct lc3_complex *z; } u = { .f = y };
struct lc3_complex z[ns/2];
mdct_window(dt, sr, x, u.f);
mdct_pre_fft(rot, u.f, u.z);
u.z = fft(false, u.z, ns/2, u.z, z);
mdct_post_fft(rot, u.z, y, sqrtf( (2.f*nf) / (ns*ns) ));
}
/**
* Inverse MDCT transformation
*/
void lc3_mdct_inverse(enum lc3_dt dt, enum lc3_srate sr,
enum lc3_srate sr_src, const float *x, float *d, float *y)
{
const struct lc3_mdct_rot_def *rot = lc3_mdct_rot[dt][sr];
int nf = LC3_NS(dt, sr_src);
int ns = LC3_NS(dt, sr);
struct lc3_complex buffer[ns/2];
struct lc3_complex *z = (struct lc3_complex *)y;
union { float *f; struct lc3_complex *z; } u = { .z = buffer };
imdct_pre_fft(rot, x, z);
z = fft(true, z, ns/2, z, u.z);
imdct_post_fft(rot, z, u.f, sqrtf(2.f / nf));
imdct_window(dt, sr, u.f, d, y);
}

59
3rd-party/lc3-google/src/mdct.h vendored Normal file
View File

@ -0,0 +1,59 @@
/******************************************************************************
*
* 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 - Compute LD-MDCT (Low Delay Modified Discret Cosinus Transform)
*
* Reference : Low Complexity Communication Codec (LC3)
* Bluetooth Specification v1.0
*/
#ifndef __LC3_MDCT_H
#define __LC3_MDCT_H
#include "common.h"
/**
* Forward MDCT transformation
* dt, sr Duration and samplerate (size of the transform)
* sr_dst Samplerate destination, scale transforam accordingly
* x [-nd..-1] Previous, [0..ns-1] Current samples
* y Output `ns` frequency coefficients
*
* The number of previous samples `nd` accessed on `x` is :
* nd: `ns` * 23/30 for 7.5ms frame duration
* nd: `ns` * 5/ 8 for 10ms frame duration
*/
void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr,
enum lc3_srate sr_dst, const float *x, float *y);
/**
* Inverse MDCT transformation
* dt, sr Duration and samplerate (size of the transform)
* sr_src Samplerate source, scale transforam accordingly
* x, d Frequency coefficients and delayed buffer
* y, d Output `ns` samples and `nd` delayed ones
*
* `x` and `y` can be the same buffer
*/
void lc3_mdct_inverse(enum lc3_dt dt, enum lc3_srate sr,
enum lc3_srate sr_src, const float *x, float *d, float *y);
#endif /* __LC3_MDCT_H */

61
3rd-party/lc3-google/src/plc.c vendored Normal file
View File

@ -0,0 +1,61 @@
/******************************************************************************
*
* 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 "plc.h"
/**
* Reset Packet Loss Concealment state
*/
void lc3_plc_reset(struct lc3_plc_state *plc)
{
plc->seed = 24607;
lc3_plc_suspend(plc);
}
/**
* Suspend PLC execution (Good frame received)
*/
void lc3_plc_suspend(struct lc3_plc_state *plc)
{
plc->count = 1;
plc->alpha = 1.0f;
}
/**
* Synthesis of a PLC frame
*/
void lc3_plc_synthesize(enum lc3_dt dt, enum lc3_srate sr,
struct lc3_plc_state *plc, const float *x, float *y)
{
uint16_t seed = plc->seed;
float alpha = plc->alpha;
int ne = LC3_NE(dt, sr);
alpha *= (plc->count < 4 ? 1.0f :
plc->count < 8 ? 0.9f : 0.85f);
for (int i = 0; i < ne; i++) {
seed = (16831 + seed * 12821) & 0xffff;
y[i] = alpha * (seed & 0x8000 ? -x[i] : x[i]);
}
plc->seed = seed;
plc->alpha = alpha;
plc->count++;
}

57
3rd-party/lc3-google/src/plc.h vendored Normal file
View File

@ -0,0 +1,57 @@
/******************************************************************************
*
* 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 - Packet Loss Concealment
*
* Reference : Low Complexity Communication Codec (LC3)
* Bluetooth Specification v1.0
*/
#ifndef __LC3_PLC_H
#define __LC3_PLC_H
#include "common.h"
/**
* Reset PLC state
* plc PLC State to reset
*/
void lc3_plc_reset(lc3_plc_state_t *plc);
/**
* Suspend PLC synthesis (Error-free frame decoded)
* plc PLC State
*/
void lc3_plc_suspend(lc3_plc_state_t *plc);
/**
* Synthesis of a PLC frame
* dt, sr Duration and samplerate of the frame
* plc PLC State
* x Last good spectral coefficients
* y Return emulated ones
*
* `x` and `y` can be the same buffer
*/
void lc3_plc_synthesize(enum lc3_dt dt, enum lc3_srate sr,
lc3_plc_state_t *plc, const float *x, float *y);
#endif /* __LC3_PLC_H */

878
3rd-party/lc3-google/src/sns.c vendored Normal file
View File

@ -0,0 +1,878 @@
/******************************************************************************
*
* 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 "sns.h"
#include "tables.h"
/* ----------------------------------------------------------------------------
* DCT-16
* -------------------------------------------------------------------------- */
/**
* Matrix of DCT-16 coefficients
*
* M[n][k] = 2f cos( Pi k (2n + 1) / 2N )
*
* k = [0..N-1], n = [0..N-1], N = 16
* f = sqrt(1/4N) for k=0, sqrt(1/2N) otherwise
*/
static const float dct16_m[16][16] = {
{ 2.50000000e-01, 3.51850934e-01, 3.46759961e-01, 3.38329500e-01,
3.26640741e-01, 3.11806253e-01, 2.93968901e-01, 2.73300467e-01,
2.50000000e-01, 2.24291897e-01, 1.96423740e-01, 1.66663915e-01,
1.35299025e-01, 1.02631132e-01, 6.89748448e-02, 3.46542923e-02 },
{ 2.50000000e-01, 3.38329500e-01, 2.93968901e-01, 2.24291897e-01,
1.35299025e-01, 3.46542923e-02, -6.89748448e-02, -1.66663915e-01,
-2.50000000e-01, -3.11806253e-01, -3.46759961e-01, -3.51850934e-01,
-3.26640741e-01, -2.73300467e-01, -1.96423740e-01, -1.02631132e-01 },
{ 2.50000000e-01, 3.11806253e-01, 1.96423740e-01, 3.46542923e-02,
-1.35299025e-01, -2.73300467e-01, -3.46759961e-01, -3.38329500e-01,
-2.50000000e-01, -1.02631132e-01, 6.89748448e-02, 2.24291897e-01,
3.26640741e-01, 3.51850934e-01, 2.93968901e-01, 1.66663915e-01 },
{ 2.50000000e-01, 2.73300467e-01, 6.89748448e-02, -1.66663915e-01,
-3.26640741e-01, -3.38329500e-01, -1.96423740e-01, 3.46542923e-02,
2.50000000e-01, 3.51850934e-01, 2.93968901e-01, 1.02631132e-01,
-1.35299025e-01, -3.11806253e-01, -3.46759961e-01, -2.24291897e-01 },
{ 2.50000000e-01, 2.24291897e-01, -6.89748448e-02, -3.11806253e-01,
-3.26640741e-01, -1.02631132e-01, 1.96423740e-01, 3.51850934e-01,
2.50000000e-01, -3.46542923e-02, -2.93968901e-01, -3.38329500e-01,
-1.35299025e-01, 1.66663915e-01, 3.46759961e-01, 2.73300467e-01 },
{ 2.50000000e-01, 1.66663915e-01, -1.96423740e-01, -3.51850934e-01,
-1.35299025e-01, 2.24291897e-01, 3.46759961e-01, 1.02631132e-01,
-2.50000000e-01, -3.38329500e-01, -6.89748448e-02, 2.73300467e-01,
3.26640741e-01, 3.46542923e-02, -2.93968901e-01, -3.11806253e-01 },
{ 2.50000000e-01, 1.02631132e-01, -2.93968901e-01, -2.73300467e-01,
1.35299025e-01, 3.51850934e-01, 6.89748448e-02, -3.11806253e-01,
-2.50000000e-01, 1.66663915e-01, 3.46759961e-01, 3.46542923e-02,
-3.26640741e-01, -2.24291897e-01, 1.96423740e-01, 3.38329500e-01 },
{ 2.50000000e-01, 3.46542923e-02, -3.46759961e-01, -1.02631132e-01,
3.26640741e-01, 1.66663915e-01, -2.93968901e-01, -2.24291897e-01,
2.50000000e-01, 2.73300467e-01, -1.96423740e-01, -3.11806253e-01,
1.35299025e-01, 3.38329500e-01, -6.89748448e-02, -3.51850934e-01 },
{ 2.50000000e-01, -3.46542923e-02, -3.46759961e-01, 1.02631132e-01,
3.26640741e-01, -1.66663915e-01, -2.93968901e-01, 2.24291897e-01,
2.50000000e-01, -2.73300467e-01, -1.96423740e-01, 3.11806253e-01,
1.35299025e-01, -3.38329500e-01, -6.89748448e-02, 3.51850934e-01 },
{ 2.50000000e-01, -1.02631132e-01, -2.93968901e-01, 2.73300467e-01,
1.35299025e-01, -3.51850934e-01, 6.89748448e-02, 3.11806253e-01,
-2.50000000e-01, -1.66663915e-01, 3.46759961e-01, -3.46542923e-02,
-3.26640741e-01, 2.24291897e-01, 1.96423740e-01, -3.38329500e-01 },
{ 2.50000000e-01, -1.66663915e-01, -1.96423740e-01, 3.51850934e-01,
-1.35299025e-01, -2.24291897e-01, 3.46759961e-01, -1.02631132e-01,
-2.50000000e-01, 3.38329500e-01, -6.89748448e-02, -2.73300467e-01,
3.26640741e-01, -3.46542923e-02, -2.93968901e-01, 3.11806253e-01 },
{ 2.50000000e-01, -2.24291897e-01, -6.89748448e-02, 3.11806253e-01,
-3.26640741e-01, 1.02631132e-01, 1.96423740e-01, -3.51850934e-01,
2.50000000e-01, 3.46542923e-02, -2.93968901e-01, 3.38329500e-01,
-1.35299025e-01, -1.66663915e-01, 3.46759961e-01, -2.73300467e-01 },
{ 2.50000000e-01, -2.73300467e-01, 6.89748448e-02, 1.66663915e-01,
-3.26640741e-01, 3.38329500e-01, -1.96423740e-01, -3.46542923e-02,
2.50000000e-01, -3.51850934e-01, 2.93968901e-01, -1.02631132e-01,
-1.35299025e-01, 3.11806253e-01, -3.46759961e-01, 2.24291897e-01 },
{ 2.50000000e-01, -3.11806253e-01, 1.96423740e-01, -3.46542923e-02,
-1.35299025e-01, 2.73300467e-01, -3.46759961e-01, 3.38329500e-01,
-2.50000000e-01, 1.02631132e-01, 6.89748448e-02, -2.24291897e-01,
3.26640741e-01, -3.51850934e-01, 2.93968901e-01, -1.66663915e-01 },
{ 2.50000000e-01, -3.38329500e-01, 2.93968901e-01, -2.24291897e-01,
1.35299025e-01, -3.46542923e-02, -6.89748448e-02, 1.66663915e-01,
-2.50000000e-01, 3.11806253e-01, -3.46759961e-01, 3.51850934e-01,
-3.26640741e-01, 2.73300467e-01, -1.96423740e-01, 1.02631132e-01 },
{ 2.50000000e-01, -3.51850934e-01, 3.46759961e-01, -3.38329500e-01,
3.26640741e-01, -3.11806253e-01, 2.93968901e-01, -2.73300467e-01,
2.50000000e-01, -2.24291897e-01, 1.96423740e-01, -1.66663915e-01,
1.35299025e-01, -1.02631132e-01, 6.89748448e-02, -3.46542923e-02 },
};
/**
* Forward DCT-16 transformation
* x, y Input and output 16 values
*/
static void dct16_forward(const float *x, float *y)
{
for (int i = 0, j; i < 16; i++)
for (y[i] = 0, j = 0; j < 16; j++)
y[i] += x[j] * dct16_m[j][i];
}
/**
* Inverse DCT-16 transformation
* x, y Input and output 16 values
*/
static void dct16_inverse(const float *x, float *y)
{
for (int i = 0, j; i < 16; i++)
for (y[i] = 0, j = 0; j < 16; j++)
y[i] += x[j] * dct16_m[i][j];
}
/* ----------------------------------------------------------------------------
* Scale factors
* -------------------------------------------------------------------------- */
/**
* Scale factors
* dt, sr Duration and samplerate of the frame
* eb Energy estimation per bands
* att 1: Attack detected 0: Otherwise
* scf Output 16 scale factors
*/
static void compute_scale_factors(enum lc3_dt dt, enum lc3_srate sr,
const float *eb, bool att, float *scf)
{
/* Pre-emphasis gain table :
* Ge[b] = 10 ^ (b * g_tilt) / 630 , b = [0..63] */
static const float ge_table[LC3_NUM_SRATE][LC3_NUM_BANDS] = {
[LC3_SRATE_8K] = { /* g_tilt = 14 */
1.00000000e+00, 1.05250029e+00, 1.10775685e+00, 1.16591440e+00,
1.22712524e+00, 1.29154967e+00, 1.35935639e+00, 1.43072299e+00,
1.50583635e+00, 1.58489319e+00, 1.66810054e+00, 1.75567629e+00,
1.84784980e+00, 1.94486244e+00, 2.04696827e+00, 2.15443469e+00,
2.26754313e+00, 2.38658979e+00, 2.51188643e+00, 2.64376119e+00,
2.78255940e+00, 2.92864456e+00, 3.08239924e+00, 3.24422608e+00,
3.41454887e+00, 3.59381366e+00, 3.78248991e+00, 3.98107171e+00,
4.19007911e+00, 4.41005945e+00, 4.64158883e+00, 4.88527357e+00,
5.14175183e+00, 5.41169527e+00, 5.69581081e+00, 5.99484250e+00,
6.30957344e+00, 6.64082785e+00, 6.98947321e+00, 7.35642254e+00,
7.74263683e+00, 8.14912747e+00, 8.57695899e+00, 9.02725178e+00,
9.50118507e+00, 1.00000000e+01, 1.05250029e+01, 1.10775685e+01,
1.16591440e+01, 1.22712524e+01, 1.29154967e+01, 1.35935639e+01,
1.43072299e+01, 1.50583635e+01, 1.58489319e+01, 1.66810054e+01,
1.75567629e+01, 1.84784980e+01, 1.94486244e+01, 2.04696827e+01,
2.15443469e+01, 2.26754313e+01, 2.38658979e+01, 2.51188643e+01 },
[LC3_SRATE_16K] = { /* g_tilt = 18 */
1.00000000e+00, 1.06800043e+00, 1.14062492e+00, 1.21818791e+00,
1.30102522e+00, 1.38949549e+00, 1.48398179e+00, 1.58489319e+00,
1.69266662e+00, 1.80776868e+00, 1.93069773e+00, 2.06198601e+00,
2.20220195e+00, 2.35195264e+00, 2.51188643e+00, 2.68269580e+00,
2.86512027e+00, 3.05994969e+00, 3.26802759e+00, 3.49025488e+00,
3.72759372e+00, 3.98107171e+00, 4.25178630e+00, 4.54090961e+00,
4.84969343e+00, 5.17947468e+00, 5.53168120e+00, 5.90783791e+00,
6.30957344e+00, 6.73862717e+00, 7.19685673e+00, 7.68624610e+00,
8.20891416e+00, 8.76712387e+00, 9.36329209e+00, 1.00000000e+01,
1.06800043e+01, 1.14062492e+01, 1.21818791e+01, 1.30102522e+01,
1.38949549e+01, 1.48398179e+01, 1.58489319e+01, 1.69266662e+01,
1.80776868e+01, 1.93069773e+01, 2.06198601e+01, 2.20220195e+01,
2.35195264e+01, 2.51188643e+01, 2.68269580e+01, 2.86512027e+01,
3.05994969e+01, 3.26802759e+01, 3.49025488e+01, 3.72759372e+01,
3.98107171e+01, 4.25178630e+01, 4.54090961e+01, 4.84969343e+01,
5.17947468e+01, 5.53168120e+01, 5.90783791e+01, 6.30957344e+01 },
[LC3_SRATE_24K] = { /* g_tilt = 22 */
1.00000000e+00, 1.08372885e+00, 1.17446822e+00, 1.27280509e+00,
1.37937560e+00, 1.49486913e+00, 1.62003281e+00, 1.75567629e+00,
1.90267705e+00, 2.06198601e+00, 2.23463373e+00, 2.42173704e+00,
2.62450630e+00, 2.84425319e+00, 3.08239924e+00, 3.34048498e+00,
3.62017995e+00, 3.92329345e+00, 4.25178630e+00, 4.60778348e+00,
4.99358789e+00, 5.41169527e+00, 5.86481029e+00, 6.35586411e+00,
6.88803330e+00, 7.46476041e+00, 8.08977621e+00, 8.76712387e+00,
9.50118507e+00, 1.02967084e+01, 1.11588399e+01, 1.20931568e+01,
1.31057029e+01, 1.42030283e+01, 1.53922315e+01, 1.66810054e+01,
1.80776868e+01, 1.95913107e+01, 2.12316686e+01, 2.30093718e+01,
2.49359200e+01, 2.70237760e+01, 2.92864456e+01, 3.17385661e+01,
3.43959997e+01, 3.72759372e+01, 4.03970086e+01, 4.37794036e+01,
4.74450028e+01, 5.14175183e+01, 5.57226480e+01, 6.03882412e+01,
6.54444792e+01, 7.09240702e+01, 7.68624610e+01, 8.32980665e+01,
9.02725178e+01, 9.78309319e+01, 1.06022203e+02, 1.14899320e+02,
1.24519708e+02, 1.34945600e+02, 1.46244440e+02, 1.58489319e+02 },
[LC3_SRATE_32K] = { /* g_tilt = 26 */
1.00000000e+00, 1.09968890e+00, 1.20931568e+00, 1.32987103e+00,
1.46244440e+00, 1.60823388e+00, 1.76855694e+00, 1.94486244e+00,
2.13874364e+00, 2.35195264e+00, 2.58641621e+00, 2.84425319e+00,
3.12779366e+00, 3.43959997e+00, 3.78248991e+00, 4.15956216e+00,
4.57422434e+00, 5.03022373e+00, 5.53168120e+00, 6.08312841e+00,
6.68954879e+00, 7.35642254e+00, 8.08977621e+00, 8.89623710e+00,
9.78309319e+00, 1.07583590e+01, 1.18308480e+01, 1.30102522e+01,
1.43072299e+01, 1.57335019e+01, 1.73019574e+01, 1.90267705e+01,
2.09235283e+01, 2.30093718e+01, 2.53031508e+01, 2.78255940e+01,
3.05994969e+01, 3.36499270e+01, 3.70044512e+01, 4.06933843e+01,
4.47500630e+01, 4.92111475e+01, 5.41169527e+01, 5.95118121e+01,
6.54444792e+01, 7.19685673e+01, 7.91430346e+01, 8.70327166e+01,
9.57089124e+01, 1.05250029e+02, 1.15742288e+02, 1.27280509e+02,
1.39968963e+02, 1.53922315e+02, 1.69266662e+02, 1.86140669e+02,
2.04696827e+02, 2.25102829e+02, 2.47543082e+02, 2.72220379e+02,
2.99357729e+02, 3.29200372e+02, 3.62017995e+02, 3.98107171e+02 },
[LC3_SRATE_48K] = { /* g_tilt = 30 */
1.00000000e+00, 1.11588399e+00, 1.24519708e+00, 1.38949549e+00,
1.55051578e+00, 1.73019574e+00, 1.93069773e+00, 2.15443469e+00,
2.40409918e+00, 2.68269580e+00, 2.99357729e+00, 3.34048498e+00,
3.72759372e+00, 4.15956216e+00, 4.64158883e+00, 5.17947468e+00,
5.77969288e+00, 6.44946677e+00, 7.19685673e+00, 8.03085722e+00,
8.96150502e+00, 1.00000000e+01, 1.11588399e+01, 1.24519708e+01,
1.38949549e+01, 1.55051578e+01, 1.73019574e+01, 1.93069773e+01,
2.15443469e+01, 2.40409918e+01, 2.68269580e+01, 2.99357729e+01,
3.34048498e+01, 3.72759372e+01, 4.15956216e+01, 4.64158883e+01,
5.17947468e+01, 5.77969288e+01, 6.44946677e+01, 7.19685673e+01,
8.03085722e+01, 8.96150502e+01, 1.00000000e+02, 1.11588399e+02,
1.24519708e+02, 1.38949549e+02, 1.55051578e+02, 1.73019574e+02,
1.93069773e+02, 2.15443469e+02, 2.40409918e+02, 2.68269580e+02,
2.99357729e+02, 3.34048498e+02, 3.72759372e+02, 4.15956216e+02,
4.64158883e+02, 5.17947468e+02, 5.77969288e+02, 6.44946677e+02,
7.19685673e+02, 8.03085722e+02, 8.96150502e+02, 1.00000000e+03 },
};
float e[LC3_NUM_BANDS];
/* --- Copy and padding --- */
int nb = LC3_MIN(lc3_band_lim[dt][sr][LC3_NUM_BANDS], LC3_NUM_BANDS);
int n2 = LC3_NUM_BANDS - nb;
for (int i2 = 0; i2 < n2; i2++)
e[2*i2 + 0] = e[2*i2 + 1] = eb[i2];
memcpy(e + 2*n2, eb + n2, (nb - n2) * sizeof(float));
/* --- Smoothing, pre-emphasis and logarithm --- */
const float *ge = ge_table[sr];
float e0 = e[0], e1 = e[0], e2;
float e_sum = 0;
for (int i = 0; i < LC3_NUM_BANDS-1; ) {
e[i] = (e0 * 0.25 + e1 * 0.5 + (e2 = e[i+1]) * 0.25) * ge[i];
e_sum += e[i++];
e[i] = (e1 * 0.25 + e2 * 0.5 + (e0 = e[i+1]) * 0.25) * ge[i];
e_sum += e[i++];
e[i] = (e2 * 0.25 + e0 * 0.5 + (e1 = e[i+1]) * 0.25) * ge[i];
e_sum += e[i++];
}
e[LC3_NUM_BANDS-1] = (e0 * 0.25 + e1 * 0.75) * ge[LC3_NUM_BANDS-1];
e_sum += e[LC3_NUM_BANDS-1];
float noise_floor = fmaxf(e_sum * (1e-4 / 64), 0x1p-32);
for (int i = 0; i < LC3_NUM_BANDS; i++)
e[i] = log2f(fmaxf(e[i], noise_floor)) * 0.5;
/* --- Grouping & scaling --- */
float scf_sum;
scf[0] = (e[0] + e[4]) * 1./12 +
(e[0] + e[3]) * 2./12 +
(e[1] + e[2]) * 3./12 ;
scf_sum = scf[0];
for (int i = 1; i < 15; i++) {
scf[i] = (e[4*i-1] + e[4*i+4]) * 1./12 +
(e[4*i ] + e[4*i+3]) * 2./12 +
(e[4*i+1] + e[4*i+2]) * 3./12 ;
scf_sum += scf[i];
}
scf[15] = (e[59] + e[63]) * 1./12 +
(e[60] + e[63]) * 2./12 +
(e[61] + e[62]) * 3./12 ;
scf_sum += scf[15];
for (int i = 0; i < 16; i++)
scf[i] = 0.85 * (scf[i] - scf_sum * 1./16);
/* --- Attack handling --- */
if (!att)
return;
float s0, s1 = scf[0], s2 = scf[1], s3 = scf[2], s4 = scf[3];
float sn = s1 + s2;
scf[0] = (sn += s3) * 1./3;
scf[1] = (sn += s4) * 1./4;
scf_sum = scf[0] + scf[1];
for (int i = 2; i < 14; i++, sn -= s0) {
s0 = s1, s1 = s2, s2 = s3, s3 = s4, s4 = scf[i+2];
scf[i] = (sn += s4) * 1./5;
scf_sum += scf[i];
}
scf[14] = (sn ) * 1./4;
scf[15] = (sn -= s1) * 1./3;
scf_sum += scf[14] + scf[15];
for (int i = 0; i < 16; i++)
scf[i] = (dt == LC3_DT_7M5 ? 0.3 : 0.5) *
(scf[i] - scf_sum * 1./16);
}
/**
* Codebooks
* scf Input 16 scale factors
* lf/hfcb_idx Output the low and high frequency codebooks index
*/
static void resolve_codebooks(const float *scf, int *lfcb_idx, int *hfcb_idx)
{
float dlfcb_max = 0, dhfcb_max = 0;
*lfcb_idx = *hfcb_idx = 0;
for (int icb = 0; icb < 32; icb++) {
const float *lfcb = lc3_sns_lfcb[icb];
const float *hfcb = lc3_sns_hfcb[icb];
float dlfcb = 0, dhfcb = 0;
for (int i = 0; i < 8; i++) {
dlfcb += (scf[ i] - lfcb[i]) * (scf[ i] - lfcb[i]);
dhfcb += (scf[8+i] - hfcb[i]) * (scf[8+i] - hfcb[i]);
}
if (icb == 0 || dlfcb < dlfcb_max)
*lfcb_idx = icb, dlfcb_max = dlfcb;
if (icb == 0 || dhfcb < dhfcb_max)
*hfcb_idx = icb, dhfcb_max = dhfcb;
}
}
/**
* Unit energy normalize pulse configuration
* c Pulse configuration
* cn Normalized pulse configuration
*/
static void normalize(const int *c, float *cn)
{
int c2_sum = 0;
for (int i = 0; i < 16; i++)
c2_sum += c[i] * c[i];
float c_norm = 1.f / sqrtf(c2_sum);
for (int i = 0; i < 16; i++)
cn[i] = c[i] * c_norm;
}
/**
* Sub-procedure of `quantize()`, add unit pulse
* x, y, n Transformed residual, and vector of pulses with length
* start, end Current number of pulses, limit to reach
* corr, energy Correlation (x,y) and y energy, updated at output
*/
static void add_pulse(const float *x, int *y, int n,
int start, int end, float *corr, float *energy)
{
for (int k = start; k < end; k++) {
float best_c2 = (*corr + x[0]) * (*corr + x[0]);
float best_e = *energy + 2*y[0] + 1;
int nbest = 0;
for (int i = 1; i < n; i++) {
float c2 = (*corr + x[i]) * (*corr + x[i]);
float e = *energy + 2*y[i] + 1;
if (c2 * best_e > e * best_c2)
best_c2 = c2, best_e = e, nbest = i;
}
*corr += x[nbest];
*energy += 2*y[nbest] + 1;
y[nbest]++;
}
}
/**
* Quantization of codebooks residual
* scf Input 16 scale factors, output quantized version
* lf/hfcb_idx Codebooks index
* c, cn Output 4 pulse configurations candidates, normalized
* shape/gain_idx Output selected shape/gain indexes
*/
static void quantize(const float *scf, int lfcb_idx, int hfcb_idx,
int (*c)[16], float (*cn)[16], int *shape_idx, int *gain_idx)
{
/* --- Residual --- */
const float *lfcb = lc3_sns_lfcb[lfcb_idx];
const float *hfcb = lc3_sns_hfcb[hfcb_idx];
float r[16], x[16];
for (int i = 0; i < 8; i++) {
r[ i] = scf[ i] - lfcb[i];
r[8+i] = scf[8+i] - hfcb[i];
}
dct16_forward(r, x);
/* --- Shape 3 candidate ---
* Project to or below pyramid N = 16, K = 6,
* then add unit pulses until you reach K = 6, over N = 16 */
float xm[16];
float xm_sum = 0;
for (int i = 0; i < 16; i++) {
xm[i] = fabsf(x[i]);
xm_sum += xm[i];
}
float proj_factor = (6 - 1) / fmaxf(xm_sum, 1e-31);
float corr = 0, energy = 0;
int npulses = 0;
for (int i = 0; i < 16; i++) {
c[3][i] = floorf(xm[i] * proj_factor);
npulses += c[3][i];
corr += c[3][i] * xm[i];
energy += c[3][i] * c[3][i];
}
add_pulse(xm, c[3], 16, npulses, 6, &corr, &energy);
npulses = 6;
/* --- Shape 2 candidate ---
* Add unit pulses until you reach K = 8 on shape 3 */
memcpy(c[2], c[3], sizeof(c[2]));
add_pulse(xm, c[2], 16, npulses, 8, &corr, &energy);
npulses = 8;
/* --- Shape 1 candidate ---
* Remove any unit pulses from shape 2 that are not part of 0 to 9
* Update energy and correlation terms accordingly
* Add unit pulses until you reach K = 10, over N = 10 */
memcpy(c[1], c[2], sizeof(c[1]));
for (int i = 10; i < 16; i++) {
c[1][i] = 0;
npulses -= c[2][i];
corr -= c[2][i] * xm[i];
energy -= c[2][i] * c[2][i];
}
add_pulse(xm, c[1], 10, npulses, 10, &corr, &energy);
npulses = 10;
/* --- Shape 0 candidate ---
* Add unit pulses until you reach K = 1, on shape 1 */
memcpy(c[0], c[1], sizeof(c[0]));
add_pulse(xm + 10, c[0] + 10, 6, 0, 1, &corr, &energy);
/* --- Add sign and unit energy normalize --- */
for (int j = 0; j < 16; j++)
for (int i = 0; i < 4; i++)
c[i][j] = x[j] < 0 ? -c[i][j] : c[i][j];
for (int i = 0; i < 4; i++)
normalize(c[i], cn[i]);
/* --- Determe shape & gain index ---
* Search the Mean Square Error, within (shape, gain) combinations */
float mse_min = INFINITY;
*shape_idx = *gain_idx = 0;
for (int ic = 0; ic < 4; ic++) {
const struct lc3_sns_vq_gains *cgains = lc3_sns_vq_gains + ic;
float cmse_min = INFINITY;
int cgain_idx = 0;
for (int ig = 0; ig < cgains->count; ig++) {
float g = cgains->v[ig];
float mse = 0;
for (int i = 0; i < 16; i++)
mse += (x[i] - g * cn[ic][i]) * (x[i] - g * cn[ic][i]);
if (mse < cmse_min) {
cgain_idx = ig,
cmse_min = mse;
}
}
if (cmse_min < mse_min) {
*shape_idx = ic, *gain_idx = cgain_idx;
mse_min = cmse_min;
}
}
}
/**
* Unquantization of codebooks residual
* lf/hfcb_idx Low and high frequency codebooks index
* c Table of normalized pulse configuration
* shape/gain Selected shape/gain indexes
* scf Return unquantized scale factors
*/
static void unquantize(int lfcb_idx, int hfcb_idx,
const float *c, int shape, int gain, float *scf)
{
const float *lfcb = lc3_sns_lfcb[lfcb_idx];
const float *hfcb = lc3_sns_hfcb[hfcb_idx];
float g = lc3_sns_vq_gains[shape].v[gain];
dct16_inverse(c, scf);
for (int i = 0; i < 8; i++)
scf[i] = lfcb[i] + g * scf[i];
for (int i = 8; i < 16; i++)
scf[i] = hfcb[i-8] + g * scf[i];
}
/**
* Sub-procedure of `sns_enumerate()`, enumeration of a vector
* c, n Table of pulse configuration, and length
* idx, ls Return enumeration set
*/
static void enum_mvpq(const int *c, int n, int *idx, bool *ls)
{
int ci, i, j;
/* --- Scan for 1st significant coeff --- */
for (i = 0, c += n; (ci = *(--c)) == 0 ; i++);
*idx = 0;
*ls = ci < 0;
/* --- Scan remaining coefficients --- */
for (i++, j = LC3_ABS(ci); i < n; i++, j += LC3_ABS(ci)) {
if ((ci = *(--c)) != 0) {
*idx = (*idx << 1) | *ls;
*ls = ci < 0;
}
*idx += lc3_sns_mpvq_offsets[i][j];
}
}
/**
* Sub-procedure of `sns_deenumerate()`, deenumeration of a vector
* idx, ls Enumeration set
* npulses Number of pulses in the set
* c, n Table of pulses configuration, and length
*/
static void deenum_mvpq(int idx, bool ls, int npulses, int *c, int n)
{
int i;
/* --- Scan for coefficients --- */
for (i = n-1; i >= 0 && idx; i--) {
int ci = 0;
for (ci = 0; idx < lc3_sns_mpvq_offsets[i][npulses - ci]; ci++);
idx -= lc3_sns_mpvq_offsets[i][npulses - ci];
*(c++) = ls ? -ci : ci;
npulses -= ci;
if (ci > 0) {
ls = idx & 1;
idx >>= 1;
}
}
/* --- Set last significant --- */
int ci = npulses;
if (i-- >= 0)
*(c++) = ls ? -ci : ci;
while (i-- >= 0)
*(c++) = 0;
}
/**
* SNS Enumeration of PVQ configuration
* shape Selected shape index
* c Selected pulse configuration
* idx_a, ls_a Return enumeration set A
* idx_b, ls_b Return enumeration set B (shape = 0)
*/
static void enumerate(int shape, const int *c,
int *idx_a, bool *ls_a, int *idx_b, bool *ls_b)
{
enum_mvpq(c, shape < 2 ? 10 : 16, idx_a, ls_a);
if (shape == 0)
enum_mvpq(c + 10, 6, idx_b, ls_b);
}
/**
* SNS Deenumeration of PVQ configuration
* shape Selected shape index
* idx_a, ls_a enumeration set A
* idx_b, ls_b enumeration set B (shape = 0)
* c Return pulse configuration
*/
static void deenumerate(int shape,
int idx_a, bool ls_a, int idx_b, bool ls_b, int *c)
{
int npulses_a = (const int []){ 10, 10, 8, 6 }[shape];
deenum_mvpq(idx_a, ls_a, npulses_a, c, shape < 2 ? 10 : 16);
if (shape == 0)
deenum_mvpq(idx_b, ls_b, 1, c + 10, 6);
else if (shape == 1)
memset(c + 10, 0, 6 * sizeof(*c));
}
/* ----------------------------------------------------------------------------
* Filtering
* -------------------------------------------------------------------------- */
/**
* Spectral shaping
* dt, sr Duration and samplerate of the frame
* scf_q Quantized scale factors
* inv True on inverse shaping, False otherwise
* x Spectral coefficients
* y Return shapped coefficients
*
* `x` and `y` can be the same buffer
*/
static void spectral_shaping(enum lc3_dt dt, enum lc3_srate sr,
const float *scf_q, bool inv, const float *x, float *y)
{
/* --- Interpolate scale factors --- */
float scf[LC3_NUM_BANDS];
float s0, s1 = inv ? -scf_q[0] : scf_q[0];
scf[0] = scf[1] = s1;
for (int i = 0; i < 15; i++) {
s0 = s1, s1 = inv ? -scf_q[i+1] : scf_q[i+1];
scf[4*i+2] = s0 + 0.125 * (s1 - s0);
scf[4*i+3] = s0 + 0.375 * (s1 - s0);
scf[4*i+4] = s0 + 0.625 * (s1 - s0);
scf[4*i+5] = s0 + 0.875 * (s1 - s0);
}
scf[62] = s1 + 0.125 * (s1 - s0);
scf[63] = s1 + 0.375 * (s1 - s0);
int nb = LC3_MIN(lc3_band_lim[dt][sr][LC3_NUM_BANDS], LC3_NUM_BANDS);
int n2 = LC3_NUM_BANDS - nb;
for (int i2 = 0; i2 < n2; i2++)
scf[i2] = 0.5 * (scf[2*i2] + scf[2*i2+1]);
if (n2 > 0)
memmove(scf + n2, scf + 2*n2, (nb - n2) * sizeof(float));
/* --- Spectral shaping --- */
const int *lim = lc3_band_lim[dt][sr];
for (int i = 0, ib = 0; ib < nb; ib++) {
float g_sns = powf(2, -scf[ib]);
for ( ; i < lim[ib+1]; i++)
y[i] = x[i] * g_sns;
}
}
/* ----------------------------------------------------------------------------
* Interface
* -------------------------------------------------------------------------- */
/**
* SNS analysis
*/
void lc3_sns_analyze(enum lc3_dt dt, enum lc3_srate sr,
const float *eb, bool att, struct lc3_sns_data *data,
const float *x, float *y)
{
/* Processing steps :
* - Determine 16 scale factors from bands energy estimation
* - Get codebooks indexes that match thoses scale factors
* - Quantize the residual with the selected codebook
* - The pulse configuration `c[]` is enumerated
* - Finally shape the spectrum coefficients accordingly */
float scf[16], cn[4][16];
int c[4][16];
compute_scale_factors(dt, sr, eb, att, scf);
resolve_codebooks(scf, &data->lfcb, &data->hfcb);
quantize(scf, data->lfcb, data->hfcb,
c, cn, &data->shape, &data->gain);
unquantize(data->lfcb, data->hfcb,
cn[data->shape], data->shape, data->gain, scf);
enumerate(data->shape, c[data->shape],
&data->idx_a, &data->ls_a, &data->idx_b, &data->ls_b);
spectral_shaping(dt, sr, scf, false, x, y);
}
/**
* SNS synthesis
*/
void lc3_sns_synthesize(enum lc3_dt dt, enum lc3_srate sr,
const lc3_sns_data_t *data, const float *x, float *y)
{
float scf[16], cn[16];
int c[16];
deenumerate(data->shape,
data->idx_a, data->ls_a, data->idx_b, data->ls_b, c);
normalize(c, cn);
unquantize(data->lfcb, data->hfcb, cn, data->shape, data->gain, scf);
spectral_shaping(dt, sr, scf, true, x, y);
}
/**
* Return number of bits coding the bitstream data
*/
int lc3_sns_get_nbits(void)
{
return 38;
}
/**
* Put bitstream data
*/
void lc3_sns_put_data(lc3_bits_t *bits, const struct lc3_sns_data *data)
{
/* --- Codebooks --- */
lc3_put_bits(bits, data->lfcb, 5);
lc3_put_bits(bits, data->hfcb, 5);
/* --- Shape, gain and vectors --- *
* Write MSB bit of shape index, next LSB bits of shape and gain,
* and MVPQ vectors indexes are muxed */
int shape_msb = data->shape >> 1;
lc3_put_bit(bits, shape_msb);
if (shape_msb == 0) {
const int size_a = 2390004;
int submode = data->shape & 1;
int mux_high = submode == 0 ?
2 * (data->idx_b + 1) + data->ls_b : data->gain & 1;
int mux_code = mux_high * size_a + data->idx_a;
lc3_put_bits(bits, data->gain >> submode, 1);
lc3_put_bits(bits, data->ls_a, 1);
lc3_put_bits(bits, mux_code, 25);
} else {
const int size_a = 15158272;
int submode = data->shape & 1;
int mux_code = submode == 0 ?
data->idx_a : size_a + 2 * data->idx_a + (data->gain & 1);
lc3_put_bits(bits, data->gain >> submode, 2);
lc3_put_bits(bits, data->ls_a, 1);
lc3_put_bits(bits, mux_code, 24);
}
}
/**
* Get bitstream data
*/
int lc3_sns_get_data(lc3_bits_t *bits, struct lc3_sns_data *data)
{
/* --- Codebooks --- */
*data = (struct lc3_sns_data){
.lfcb = lc3_get_bits(bits, 5),
.hfcb = lc3_get_bits(bits, 5)
};
/* --- Shape, gain and vectors --- */
int shape_msb = lc3_get_bit(bits);
data->gain = lc3_get_bits(bits, 1 + shape_msb);
data->ls_a = lc3_get_bit(bits);
int mux_code = lc3_get_bits(bits, 25 - shape_msb);
if (shape_msb == 0) {
const int size_a = 2390004;
if (mux_code >= size_a * 14)
return -1;
data->idx_a = mux_code % size_a;
mux_code = mux_code / size_a;
data->shape = (mux_code < 2);
if (data->shape == 0) {
data->idx_b = (mux_code - 2) / 2;
data->ls_b = (mux_code - 2) % 2;
} else {
data->gain = (data->gain << 1) + (mux_code % 2);
}
} else {
const int size_a = 15158272;
if (mux_code >= size_a + 1549824)
return -1;
data->shape = 2 + (mux_code >= size_a);
if (data->shape == 2) {
data->idx_a = mux_code;
} else {
mux_code -= size_a;
data->idx_a = mux_code / 2;
data->gain = (data->gain << 1) + (mux_code % 2);
}
}
return 0;
}

103
3rd-party/lc3-google/src/sns.h vendored Normal file
View File

@ -0,0 +1,103 @@
/******************************************************************************
*
* 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 - Spectral Noise Shaping
*
* Reference : Low Complexity Communication Codec (LC3)
* Bluetooth Specification v1.0
*/
#ifndef __LC3_SNS_H
#define __LC3_SNS_H
#include "common.h"
#include "bits.h"
/**
* Bitstream data
*/
typedef struct lc3_sns_data {
int lfcb, hfcb;
int shape, gain;
int idx_a, idx_b;
bool ls_a, ls_b;
} lc3_sns_data_t;
/* ----------------------------------------------------------------------------
* Encoding
* -------------------------------------------------------------------------- */
/**
* SNS analysis
* dt, sr Duration and samplerate of the frame
* eb Energy estimation per bands, and count of bands
* att 1: Attack detected 0: Otherwise
* data Return bitstream data
* x Spectral coefficients
* y Return shapped coefficients
*
* `x` and `y` can be the same buffer
*/
void lc3_sns_analyze(enum lc3_dt dt, enum lc3_srate sr,
const float *eb, bool att, lc3_sns_data_t *data,
const float *x, float *y);
/**
* Return number of bits coding the bitstream data
* return Bit consumption
*/
int lc3_sns_get_nbits(void);
/**
* Put bitstream data
* bits Bitstream context
* data Bitstream data
*/
void lc3_sns_put_data(lc3_bits_t *bits, const lc3_sns_data_t *data);
/* ----------------------------------------------------------------------------
* Decoding
* -------------------------------------------------------------------------- */
/**
* Get bitstream data
* bits Bitstream context
* data Return SNS data
* return 0: Ok -1: Invalid SNS data
*/
int lc3_sns_get_data(lc3_bits_t *bits, lc3_sns_data_t *data);
/**
* SNS synthesis
* dt, sr Duration and samplerate of the frame
* data Bitstream data
* x Spectral coefficients
* y Return shapped coefficients
*
* `x` and `y` can be the same buffer
*/
void lc3_sns_synthesize(enum lc3_dt dt, enum lc3_srate sr,
const lc3_sns_data_t *data, const float *x, float *y);
#endif /* __LC3_SNS_H */

877
3rd-party/lc3-google/src/spec.c vendored Normal file
View File

@ -0,0 +1,877 @@
/******************************************************************************
*
* 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 "spec.h"
#include "bits.h"
#include "tables.h"
/* ----------------------------------------------------------------------------
* Global Gain / Quantization
* -------------------------------------------------------------------------- */
/**
* Resolve quantized gain index offset
* sr, nbytes Samplerate and size of the frame
* return Gain index offset
*/
static int resolve_gain_offset(enum lc3_srate sr, int nbytes)
{
int g_off = (nbytes * 8) / (10 * (1 + sr));
return 105 + 5*(1 + sr) + LC3_MIN(g_off, 115);
}
/**
* Global Gain Estimation
* dt, sr Duration and samplerate of the frame
* x Spectral coefficients
* nbits_budget Number of bits available coding the spectrum
* nbits_off Offset on the available bits, temporarily smoothed
* g_off Gain index offset
* reset_off Return True when the nbits_off must be reset
* return The quantized gain value
*/
static int estimate_gain(
enum lc3_dt dt, enum lc3_srate sr, const float *x,
int nbits_budget, float nbits_off, int g_off, bool *reset_off)
{
int ne = LC3_NE(dt, sr) >> 2;
float e[ne];
/* --- Energy (dB) by 4 NDCT blocks ---
* For the next steps, add energy offset 28/20 dB,
* and compute the maximum magnitude */
float x_max = 0;
for (int i = 0; i < ne; i++, x += 4) {
float x0 = fabsf(x[0]), x1 = fabsf(x[1]);
float x2 = fabsf(x[2]), x3 = fabsf(x[3]);
x_max = fmaxf(x_max, x0);
x_max = fmaxf(x_max, x1);
x_max = fmaxf(x_max, x2);
x_max = fmaxf(x_max, x3);
float s2 = x0*x0 + x1*x1 + x2*x2 + x3*x3;
e[i] = 28.f/20 * 10 * (s2 > 0 ? log10f(s2) : -10);
}
/* --- Determine gain index --- */
int nbits = nbits_budget + nbits_off + 0.5f;
int g_int = 255 - g_off;
for (int i = 128; i > 0; i >>= 1) {
const float *e_ptr = e + ne-1;
float v = 0;
g_int -= i;
for ( ; e_ptr >= e && *e_ptr < g_int; e_ptr--);
while (e_ptr >= e) {
float e_diff = *(e_ptr--) - g_int;
if (e_diff < 0) {
v += 2.7f * 28.f/20;
} else {
v += e_diff + 7 * 28.f/20;
if (e_diff > 43 * 28.f/20)
v += e_diff - 43 * 28.f/20;
}
}
if (v > nbits * 1.4 * 28./20)
g_int += i;
}
/* --- Limit gain index --- */
int g_min = x_max == 0 ? -g_off :
ceilf(28 * log10f(x_max / (32768 - 0.375f)));
*reset_off = g_int < g_min || x_max == 0;
if (*reset_off)
g_int = g_min;
return g_int;
}
/**
* Global Gain Adjustment
* sr Samplerate of the frame
* g_idx The estimated quantized gain index
* nbits Computed number of bits coding the spectrum
* nbits_budget Number of bits available for coding the spectrum
* return Gain adjust value (-1 to 2)
*/
static int adjust_gain(enum lc3_srate sr,
int g_idx, int nbits, int nbits_budget)
{
/* --- Compute delta threshold --- */
const int *t = (const int [LC3_NUM_SRATE][3]){
{ 80, 500, 850 }, { 230, 1025, 1700 }, { 380, 1550, 2550 },
{ 530, 2075, 3400 }, { 680, 2600, 4250 }
}[sr];
int delta, den = 48;
if (nbits < t[0]) {
delta = 3*(nbits + 48);
} else if (nbits < t[1]) {
int n0 = 3*(t[0] + 48), range = t[1] - t[0];
delta = n0 * range + (nbits - t[0]) * (t[1] - n0);
den *= range;
} else {
delta = LC3_MIN(nbits, t[2]);
}
delta = (delta + den/2) / den;
/* --- Adjust gain --- */
if (nbits < nbits_budget - (delta + 2))
return -(g_idx > 0);
if (nbits > nbits_budget)
return (g_idx < 255) + (g_idx < 254 && nbits >= nbits_budget + delta);
return 0;
}
/**
* Unquantize gain
* g_int Quantization gain value
* return Unquantized gain value
*/
static float unquantize_gain(int g_int)
{
/* Unquantization gain table :
* G[i] = 10 ^ (i / 28) , i = [0..64] */
static const float iq_table[] = {
1.00000000e+00, 1.08571112e+00, 1.17876863e+00, 1.27980221e+00,
1.38949549e+00, 1.50859071e+00, 1.63789371e+00, 1.77827941e+00,
1.93069773e+00, 2.09617999e+00, 2.27584593e+00, 2.47091123e+00,
2.68269580e+00, 2.91263265e+00, 3.16227766e+00, 3.43332002e+00,
3.72759372e+00, 4.04708995e+00, 4.39397056e+00, 4.77058270e+00,
5.17947468e+00, 5.62341325e+00, 6.10540230e+00, 6.62870316e+00,
7.19685673e+00, 7.81370738e+00, 8.48342898e+00, 9.21055318e+00,
1.00000000e+01, 1.08571112e+01, 1.17876863e+01, 1.27980221e+01,
1.38949549e+01, 1.50859071e+01, 1.63789371e+01, 1.77827941e+01,
1.93069773e+01, 2.09617999e+01, 2.27584593e+01, 2.47091123e+01,
2.68269580e+01, 2.91263265e+01, 3.16227766e+01, 3.43332002e+01,
3.72759372e+01, 4.04708995e+01, 4.39397056e+01, 4.77058270e+01,
5.17947468e+01, 5.62341325e+01, 6.10540230e+01, 6.62870316e+01,
7.19685673e+01, 7.81370738e+01, 8.48342898e+01, 9.21055318e+01,
1.00000000e+02, 1.08571112e+02, 1.17876863e+02, 1.27980221e+02,
1.38949549e+02, 1.50859071e+02, 1.63789371e+02, 1.77827941e+02,
1.93069773e+02
};
float g = iq_table[LC3_ABS(g_int) & 0x3f];
for(int n64 = LC3_ABS(g_int) >> 6; n64--; )
g *= iq_table[64];
return g_int >= 0 ? g : 1 / g;
}
/**
* Spectrum quantization
* dt, sr Duration and samplerate of the frame
* g_int Quantization gain value
* x Spectral coefficients, scaled as output
* xq, nq Output spectral quantized coefficients, and count
*/
static void quantize(enum lc3_dt dt, enum lc3_srate sr,
int g_int, float *x, int16_t *xq, int *nq)
{
float g_inv = 1 / unquantize_gain(g_int);
int ne = LC3_NE(dt, sr);
*nq = ne;
for (int i = 0; i < ne; i += 2) {
int16_t x0, x1;
x[i+0] *= g_inv;
x0 = fminf(floorf(fabsf(x[i+0]) + 6.f/16), INT16_MAX);
xq[i+0] = x[i+0] < 0 ? -x0 : x0;
x[i+1] *= g_inv;
x1 = fminf(floorf(fabsf(x[i+1]) + 6.f/16), INT16_MAX);
xq[i+1] = x[i+1] < 0 ? -x1 : x1;
*nq = x0 || x1 ? ne : *nq - 2;
}
}
/**
* Spectrum quantization inverse
* dt, sr Duration and samplerate of the frame
* g_int Quantization gain value
* x, nq Spectral quantized, and count of significants
* return Unquantized gain value
*/
static float unquantize(enum lc3_dt dt, enum lc3_srate sr,
int g_int, float *x, int nq)
{
float g = unquantize_gain(g_int);
int i, ne = LC3_NE(dt, sr);
for (i = 0; i < nq; i++)
x[i] = x[i] * g;
for ( ; i < ne; i++)
x[i] = 0;
return g;
}
/* ----------------------------------------------------------------------------
* Spectrum coding
* -------------------------------------------------------------------------- */
/**
* Resolve High-bitrate mode according size of the frame
* sr, nbytes Samplerate and size of the frame
* return True when High-Rate mode enabled
*/
static int resolve_high_rate(enum lc3_srate sr, int nbytes)
{
return nbytes > 20 * (1 + (int)sr);
}
/**
* Bit consumption
* dt, sr, nbytes Duration, samplerate and size of the frame
* x Spectral quantized coefficients
* n Count of significant coefficients, updated on truncation
* nbits_budget Truncate to stay in budget, when not zero
* p_lsb_mode Return True when LSB's are not AC coded, or NULL
* return The number of bits coding the spectrum
*/
static int compute_nbits(
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
const int16_t *x, int *n, int nbits_budget, bool *p_lsb_mode)
{
int ne = LC3_NE(dt, sr);
/* --- Mode and rate --- */
bool lsb_mode = nbytes >= 20 * (3 + (int)sr);
bool high_rate = resolve_high_rate(sr, nbytes);
/* --- Loop on quantized coefficients --- */
int nbits = 0, nbits_lsb = 0;
uint8_t state = 0;
int nbits_end = 0;
int n_end = 0;
nbits_budget = nbits_budget ? nbits_budget * 2048 : INT_MAX;
for (int i = 0, h = 0; h < 2; h++) {
const uint8_t (*lut_coeff)[4] = lc3_spectrum_lookup[high_rate][h];
for ( ; i < LC3_MIN(*n, (ne + 2) >> (1 - h))
&& nbits <= nbits_budget; i += 2) {
const uint8_t *lut = lut_coeff[state];
int a = LC3_ABS(x[i]), b = LC3_ABS(x[i+1]);
/* --- Sign values --- */
int s = (a != 0) + (b != 0);
nbits += s * 2048;
/* --- LSB values Reduce to 2*2 bits MSB values ---
* Reduce to 2x2 bits MSB values. The LSB's pair are arithmetic
* coded with an escape code followed by 1 bit for each values.
* The LSB mode does not arthmetic code the first LSB,
* add the sign of the LSB when one of pair was at value 1 */
int k = 0;
int m = (a | b) >> 2;
if (m) {
if (lsb_mode) {
nbits += lc3_spectrum_bits[lut[k++]][16] - 2*2048;
nbits_lsb += 2 + (a == 1) + (b == 1);
}
for (m >>= lsb_mode; m; m >>= 1, k++)
nbits += lc3_spectrum_bits[lut[LC3_MIN(k, 3)]][16];
nbits += k * 2*2048;
a >>= k;
b >>= k;
k = LC3_MIN(k, 3);
}
/* --- MSB values --- */
nbits += lc3_spectrum_bits[lut[k]][a + 4*b];
/* --- Update state --- */
if (s && nbits <= nbits_budget) {
n_end = i + 2;
nbits_end = nbits;
}
state = (state << 4) + (k > 1 ? 12 + k : 1 + (a + b) * (k + 1));
}
}
/* --- Return --- */
*n = n_end;
if (p_lsb_mode)
*p_lsb_mode = lsb_mode &&
nbits_end + nbits_lsb * 2048 > nbits_budget;
if (nbits_budget >= INT_MAX)
nbits_end += nbits_lsb * 2048;
return (nbits_end + 2047) / 2048;
}
/**
* Put quantized spectrum
* bits Bitstream context
* dt, sr, nbytes Duration, samplerate and size of the frame
* x Spectral quantized
* nq, lsb_mode Count of significants, and LSB discard indication
*/
static void put_quantized(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
const int16_t *x, int nq, bool lsb_mode)
{
int ne = LC3_NE(dt, sr);
bool high_rate = resolve_high_rate(sr, nbytes);
/* --- Loop on quantized coefficients --- */
uint8_t state = 0;
for (int i = 0, h = 0; h < 2; h++) {
const uint8_t (*lut_coeff)[4] = lc3_spectrum_lookup[high_rate][h];
for ( ; i < LC3_MIN(nq, (ne + 2) >> (1 - h)); i += 2) {
const uint8_t *lut = lut_coeff[state];
bool a_neg = x[i] < 0, b_neg = x[i+1] < 0;
int a = LC3_ABS(x[i]), b = LC3_ABS(x[i+1]);
/* --- LSB values Reduce to 2*2 bits MSB values ---
* Reduce to 2x2 bits MSB values. The LSB's pair are arithmetic
* coded with an escape code and 1 bits for each values.
* The LSB mode discard the first LSB (at this step) */
int m = (a | b) >> 2;
int k = 0, shr = 0;
if (m) {
if (lsb_mode)
lc3_put_symbol(bits,
lc3_spectrum_models + lut[k++], 16);
for (m >>= lsb_mode; m; m >>= 1, k++) {
lc3_put_bit(bits, (a >> k) & 1);
lc3_put_bit(bits, (b >> k) & 1);
lc3_put_symbol(bits,
lc3_spectrum_models + lut[LC3_MIN(k, 3)], 16);
}
a >>= lsb_mode;
b >>= lsb_mode;
shr = k - lsb_mode;
k = LC3_MIN(k, 3);
}
/* --- Sign values --- */
if (a) lc3_put_bit(bits, a_neg);
if (b) lc3_put_bit(bits, b_neg);
/* --- MSB values --- */
a >>= shr;
b >>= shr;
lc3_put_symbol(bits, lc3_spectrum_models + lut[k], a + 4*b);
/* --- Update state --- */
state = (state << 4) + (k > 1 ? 12 + k : 1 + (a + b) * (k + 1));
}
}
}
/**
* Get quantized spectrum
* bits Bitstream context
* dt, sr, nbytes Duration, samplerate and size of the frame
* nq, lsb_mode Count of significants, and LSB discard indication
* xq Return `nq` spectral quantized coefficients
* nf_seed Return the noise factor seed associated
* return 0: Ok -1: Invalid bitstream data
*/
static int get_quantized(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
int nq, bool lsb_mode, float *xq, uint16_t *nf_seed)
{
int ne = LC3_NE(dt, sr);
bool high_rate = resolve_high_rate(sr, nbytes);
*nf_seed = 0;
/* --- Loop on quantized coefficients --- */
uint8_t state = 0;
for (int i = 0, h = 0; h < 2; h++) {
const uint8_t (*lut_coeff)[4] = lc3_spectrum_lookup[high_rate][h];
for ( ; i < LC3_MIN(nq, (ne + 2) >> (1 - h)); i += 2) {
const uint8_t *lut = lut_coeff[state];
/* --- LSB values ---
* Until the symbol read indicates the escape value 16,
* read an LSB bit for each values.
* The LSB mode discard the first LSB (at this step) */
int u = 0, v = 0;
int k = 0, shl = 0;
unsigned s = lc3_get_symbol(bits, lc3_spectrum_models + lut[k]);
if (lsb_mode && s >= 16) {
s = lc3_get_symbol(bits, lc3_spectrum_models + lut[++k]);
shl++;
}
for ( ; s >= 16 && shl < 14; shl++) {
u |= lc3_get_bit(bits) << shl;
v |= lc3_get_bit(bits) << shl;
k += (k < 3);
s = lc3_get_symbol(bits, lc3_spectrum_models + lut[k]);
}
if (s >= 16)
return -1;
/* --- MSB & sign values --- */
int a = s % 4;
int b = s / 4;
u |= a << shl;
v |= b << shl;
xq[i ] = u && lc3_get_bit(bits) ? -u : u;
xq[i+1] = v && lc3_get_bit(bits) ? -v : v;
*nf_seed = (*nf_seed + u * i + v * (i+1)) & 0xffff;
/* --- Update state --- */
state = (state << 4) + (k > 1 ? 12 + k : 1 + (a + b) * (k + 1));
}
}
return 0;
}
/**
* Put residual bits of quantization
* bits Bitstream context
* nbits Maximum number of bits to output
* xq, n Spectral quantized, and count of significants
* xf Scaled spectral coefficients
*/
static void put_residual(lc3_bits_t *bits, int nbits,
const int16_t *xq, int n, const float *xf)
{
for (int i = 0; i < n && nbits > 0; i++) {
if (xq[i] == 0)
continue;
lc3_put_bit(bits, xf[i] >= xq[i]);
nbits--;
}
}
/**
* Get residual bits of quantization
* bits Bitstream context
* nbits Maximum number of bits to output
* x, nq Spectral quantized, and count of significants
*/
static void get_residual(lc3_bits_t *bits, int nbits, float *x, int nq)
{
for (int i = 0; i < nq && nbits > 0; i++) {
if (x[i] == 0)
continue;
if (lc3_get_bit(bits) == 0)
x[i] -= x[i] < 0 ? 5.f/16 : 3.f/16;
else
x[i] += x[i] > 0 ? 5.f/16 : 3.f/16;
nbits--;
}
}
/**
* Put LSB values of quantized spectrum values
* bits Bitstream context
* nbits Maximum number of bits to output
* x, n Spectral quantized, and count of significants
*/
static void put_lsb(lc3_bits_t *bits, int nbits, const int16_t *x, int n)
{
for (int i = 0; i < n && nbits > 0; i += 2) {
bool a_neg = x[i] < 0, b_neg = x[i+1] < 0;
int a = LC3_ABS(x[i]), b = LC3_ABS(x[i+1]);
if ((a | b) >> 2 == 0)
continue;
if (nbits-- > 0)
lc3_put_bit(bits, a & 1);
if (a == 1 && nbits-- > 0)
lc3_put_bit(bits, a_neg);
if (nbits-- > 0)
lc3_put_bit(bits, b & 1);
if (b == 1 && nbits-- > 0)
lc3_put_bit(bits, b_neg);
}
}
/**
* Get LSB values of quantized spectrum values
* bits Bitstream context
* nbits Maximum number of bits to output
* x, nq Spectral quantized, and count of significants
* nf_seed Update the noise factor seed according
*/
static void get_lsb(lc3_bits_t *bits,
int nbits, float *x, int nq, uint16_t *nf_seed)
{
for (int i = 0; i < nq && nbits > 0; i += 2) {
float a = fabsf(x[i]), b = fabsf(x[i+1]);
if (fmaxf(a, b) < 4)
continue;
if (nbits-- > 0 && lc3_get_bit(bits)) {
if (a) {
x[i] += x[i] < 0 ? -1 : 1;
*nf_seed = (*nf_seed + i) & 0xffff;
} else if (nbits-- > 0) {
x[i] = lc3_get_bit(bits) ? -1 : 1;
*nf_seed = (*nf_seed + i) & 0xffff;
}
}
if (nbits-- > 0 && lc3_get_bit(bits)) {
if (b) {
x[i+1] += x[i+1] < 0 ? -1 : 1;
*nf_seed = (*nf_seed + i+1) & 0xffff;
} else if (nbits-- > 0) {
x[i+1] = lc3_get_bit(bits) ? -1 : 1;
*nf_seed = (*nf_seed + i+1) & 0xffff;
}
}
}
}
/* ----------------------------------------------------------------------------
* Noise coding
* -------------------------------------------------------------------------- */
/**
* Estimate noise level
* dt, bw Duration and bandwidth of the frame
* xq, nq Quantized spectral coefficients
* x Quantization scaled spectrum coefficients
* return Noise factor (0 to 7)
*/
static int estimate_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
const int16_t *xq, int nq, const float *x)
{
int bw_stop = (dt == LC3_DT_7M5 ? 60 : 80) * (1 + bw);
int w = 2 + dt;
float sum = 0;
int i, n = 0, z = 0;
for (i = 6*(3 + dt) - w; i < LC3_MIN(nq, bw_stop); i++) {
z = xq[i] ? 0 : z + 1;
if (z > 2*w)
sum += fabs(x[i - w]), n++;
}
for ( ; i < bw_stop + w; i++)
if (++z > 2*w)
sum += fabs(x[i - w]), n++;
int nf = n ? 8 - (int)((16 * sum) / n + 0.5f) : 0;
return LC3_CLIP(nf, 0, 7);
}
/**
* Noise filling
* dt, bw Duration and bandwidth of the frame
* nf, nf_seed The noise factor and pseudo-random seed
* g Quantization gain
* x, nq Spectral quantized, and count of significants
*/
static void fill_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
int nf, uint16_t nf_seed, float g, float *x, int nq)
{
int bw_stop = (dt == LC3_DT_7M5 ? 60 : 80) * (1 + bw);
int w = 2 + dt;
float s = g * (float)(8 - nf) / 16;
int i, z = 0;
for (i = 6*(3 + dt) - w; i < LC3_MIN(nq, bw_stop); i++) {
z = x[i] ? 0 : z + 1;
if (z > 2*w) {
nf_seed = (13849 + nf_seed*31821) & 0xffff;
x[i - w] = nf_seed & 0x8000 ? -s : s;
}
}
for ( ; i < bw_stop + w; i++)
if (++z > 2*w) {
nf_seed = (13849 + nf_seed*31821) & 0xffff;
x[i - w] = nf_seed & 0x8000 ? -s : s;
}
}
/**
* Put noise factor
* bits Bitstream context
* nf Noise factor (0 to 7)
*/
static void put_noise_factor(lc3_bits_t *bits, int nf)
{
lc3_put_bits(bits, nf, 3);
}
/**
* Get noise factor
* bits Bitstream context
* return Noise factor (0 to 7)
*/
static int get_noise_factor(lc3_bits_t *bits)
{
return lc3_get_bits(bits, 3);
}
/* ----------------------------------------------------------------------------
* Encoding
* -------------------------------------------------------------------------- */
/**
* Bit consumption of the number of coded coefficients
* dt, sr Duration, samplerate of the frame
* return Bit consumpution of the number of coded coefficients
*/
static int get_nbits_nq(enum lc3_dt dt, enum lc3_srate sr)
{
int ne = LC3_NE(dt, sr);
return 4 + (ne > 32) + (ne > 64) + (ne > 128) + (ne > 256);
}
/**
* Bit consumption of the arithmetic coder
* dt, sr, nbytes Duration, samplerate and size of the frame
* return Bit consumption of bitstream data
*/
static int get_nbits_ac(enum lc3_dt dt, enum lc3_srate sr, int nbytes)
{
return get_nbits_nq(dt, sr) + 3 + LC3_MIN((nbytes-1) / 160, 2);
}
/**
* Spectrum analysis
*/
void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr,
int nbytes, bool pitch, const lc3_tns_data_t *tns,
struct lc3_spec_analysis *spec, float *x,
int16_t *xq, struct lc3_spec_side *side)
{
bool reset_off;
/* --- Bit budget --- */
const int nbits_gain = 8;
const int nbits_nf = 3;
int nbits_budget = 8*nbytes - get_nbits_ac(dt, sr, nbytes) -
lc3_bwdet_get_nbits(sr) - lc3_ltpf_get_nbits(pitch) -
lc3_sns_get_nbits() - lc3_tns_get_nbits(tns) - nbits_gain - nbits_nf;
/* --- Global gain --- */
float nbits_off = spec->nbits_off + spec->nbits_spare;
nbits_off = fminf(fmaxf(nbits_off, -40), 40);
nbits_off = 0.8 * spec->nbits_off + 0.2 * nbits_off;
int g_off = resolve_gain_offset(sr, nbytes);
int g_int = estimate_gain(dt, sr,
x, nbits_budget, nbits_off, g_off, &reset_off);
/* --- Quantization --- */
quantize(dt, sr, g_int, x, xq, &side->nq);
int nbits = compute_nbits(dt, sr, nbytes, xq, &side->nq, 0, NULL);
spec->nbits_off = reset_off ? 0 : nbits_off;
spec->nbits_spare = reset_off ? 0 : nbits_budget - nbits;
/* --- Adjust gain and requantize --- */
int g_adj = adjust_gain(sr, g_int + g_off, nbits, nbits_budget);
if (g_adj)
quantize(dt, sr, g_adj, x, xq, &side->nq);
side->g_idx = g_int + g_adj + g_off;
nbits = compute_nbits(dt, sr, nbytes,
xq, &side->nq, nbits_budget, &side->lsb_mode);
}
/**
* Put spectral quantization side data
*/
void lc3_spec_put_side(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_srate sr, const struct lc3_spec_side *side)
{
int nbits_nq = get_nbits_nq(dt, sr);
lc3_put_bits(bits, LC3_MAX(side->nq >> 1, 1) - 1, nbits_nq);
lc3_put_bits(bits, side->lsb_mode, 1);
lc3_put_bits(bits, side->g_idx, 8);
}
/**
* Encode spectral coefficients
*/
void lc3_spec_encode(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw, int nbytes,
const int16_t *xq, const lc3_spec_side_t *side, const float *x)
{
bool lsb_mode = side->lsb_mode;
int nq = side->nq;
put_noise_factor(bits, estimate_noise(dt, bw, xq, nq, x));
put_quantized(bits, dt, sr, nbytes, xq, nq, lsb_mode);
int nbits_left = lc3_get_bits_left(bits);
if (lsb_mode)
put_lsb(bits, nbits_left, xq, nq);
else
put_residual(bits, nbits_left, xq, nq, x);
}
/* ----------------------------------------------------------------------------
* Decoding
* -------------------------------------------------------------------------- */
/**
* Get spectral quantization side data
*/
int lc3_spec_get_side(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_srate sr, struct lc3_spec_side *side)
{
int nbits_nq = get_nbits_nq(dt, sr);
int ne = LC3_NE(dt, sr);
side->nq = (lc3_get_bits(bits, nbits_nq) + 1) << 1;
side->lsb_mode = lc3_get_bit(bits);
side->g_idx = lc3_get_bits(bits, 8);
return side->nq > ne ? (side->nq = ne), -1 : 0;
}
/**
* Decode spectral coefficients
*/
int lc3_spec_decode(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw,
int nbytes, const lc3_spec_side_t *side, float *x)
{
bool lsb_mode = side->lsb_mode;
int nq = side->nq;
int ret = 0;
int nf = get_noise_factor(bits);
uint16_t nf_seed;
if ((ret = get_quantized(bits, dt, sr, nbytes,
nq, lsb_mode, x, &nf_seed)) < 0)
return ret;
int nbits_left = lc3_get_bits_left(bits);
if (lsb_mode)
get_lsb(bits, nbits_left, x, nq, &nf_seed);
else
get_residual(bits, nbits_left, x, nq);
int g_int = side->g_idx - resolve_gain_offset(sr, nbytes);
float g = unquantize(dt, sr, g_int, x, nq);
if (nq > 2 || x[0] || x[1] || side->g_idx > 0 || nf < 7)
fill_noise(dt, bw, nf, nf_seed, g, x, nq);
return 0;
}

111
3rd-party/lc3-google/src/spec.h vendored Normal file
View File

@ -0,0 +1,111 @@
/******************************************************************************
*
* 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 - Spectral coefficients encoding/decoding
*
* Reference : Low Complexity Communication Codec (LC3)
* Bluetooth Specification v1.0
*/
#ifndef __LC3_SPEC_H
#define __LC3_SPEC_H
#include "common.h"
#include "tables.h"
#include "bwdet.h"
#include "ltpf.h"
#include "tns.h"
#include "sns.h"
/**
* Spectral quantization side data
*/
typedef struct lc3_spec_side {
int g_idx, nq;
bool lsb_mode;
} lc3_spec_side_t;
/* ----------------------------------------------------------------------------
* Encoding
* -------------------------------------------------------------------------- */
/**
* Spectrum analysis
* dt, sr, nbytes Duration, samplerate and size of the frame
* pitch, tns Pitch present indication and TNS bistream data
* spec Context of analysis
* x Spectral coefficients, scaled as output
* xq, side Return quantization data
*/
void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr,
int nbytes, bool pitch, const lc3_tns_data_t *tns,
lc3_spec_analysis_t *spec, float *x, int16_t *xq, lc3_spec_side_t *side);
/**
* Put spectral quantization side data
* bits Bitstream context
* dt, sr Duration and samplerate of the frame
* side Spectral quantization side data
*/
void lc3_spec_put_side(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_srate sr, const lc3_spec_side_t *side);
/**
* Encode spectral coefficients
* bits Bitstream context
* dt, sr, bw Duration, samplerate, bandwidth
* nbytes and size of the frame
* xq, side Quantization data
* x Scaled spectral coefficients
*/
void lc3_spec_encode(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw, int nbytes,
const int16_t *xq, const lc3_spec_side_t *side, const float *x);
/* ----------------------------------------------------------------------------
* Decoding
* -------------------------------------------------------------------------- */
/**
* Get spectral quantization side data
* bits Bitstream context
* dt, sr Duration and samplerate of the frame
* side Return quantization side data
* return 0: Ok -1: Invalid bandwidth indication
*/
int lc3_spec_get_side(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_srate sr, lc3_spec_side_t *side);
/**
* Decode spectral coefficients
* bits Bitstream context
* dt, sr, bw Duration, samplerate, bandwidth
* nbytes and size of the frame
* side Quantization side data
* x Spectral coefficients
* return 0: Ok -1: Invalid bitstream data
*/
int lc3_spec_decode(lc3_bits_t *bits, enum lc3_dt dt, enum lc3_srate sr,
enum lc3_bandwidth bw, int nbytes, const lc3_spec_side_t *side, float *x);
#endif /* __LC3_SPEC_H */

3526
3rd-party/lc3-google/src/tables.c vendored Normal file

File diff suppressed because it is too large Load Diff

96
3rd-party/lc3-google/src/tables.h vendored Normal file
View File

@ -0,0 +1,96 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#ifndef __LC3_TABLES_H
#define __LC3_TABLES_H
#include "common.h"
#include "bits.h"
/**
* MDCT Twiddles and window coefficients
*/
struct lc3_fft_bf3_twiddles { int n3; const struct lc3_complex (*t)[2]; };
struct lc3_fft_bf2_twiddles { int n2; const struct lc3_complex *t; };
struct lc3_mdct_rot_def { int n4; const struct lc3_complex *w; };
extern const struct lc3_fft_bf3_twiddles *lc3_fft_twiddles_bf3[];
extern const struct lc3_fft_bf2_twiddles *lc3_fft_twiddles_bf2[][3];
extern const struct lc3_mdct_rot_def *lc3_mdct_rot[LC3_NUM_DT][LC3_NUM_SRATE];
extern const float *lc3_mdct_win[LC3_NUM_DT][LC3_NUM_SRATE];
/**
* Limits of bands
*/
#define LC3_NUM_BANDS 64
extern const int lc3_band_lim[LC3_NUM_DT][LC3_NUM_SRATE][LC3_NUM_BANDS+1];
/**
* SNS Quantization
*/
extern const float lc3_sns_lfcb[32][8];
extern const float lc3_sns_hfcb[32][8];
struct lc3_sns_vq_gains {
int count; const float *v;
};
extern const struct lc3_sns_vq_gains lc3_sns_vq_gains[4];
extern const int32_t lc3_sns_mpvq_offsets[][11];
/**
* TNS Arithmetic Coding
*/
extern const struct lc3_ac_model lc3_tns_order_models[];
extern const uint16_t lc3_tns_order_bits[][8];
extern const struct lc3_ac_model lc3_tns_coeffs_models[];
extern const uint16_t lc3_tns_coeffs_bits[][17];
/**
* Long Term Postfilter
*/
extern const float lc3_ltpf_h12k8[240];
extern const float *lc3_ltpf_cnum[LC3_NUM_SRATE][4];
extern const float *lc3_ltpf_cden[LC3_NUM_SRATE][4];
/**
* Spectral Data Arithmetic Coding
*/
extern const uint8_t lc3_spectrum_lookup[2][2][256][4];
extern const struct lc3_ac_model lc3_spectrum_models[];
extern const uint16_t lc3_spectrum_bits[][17];
#endif /* __LC3_TABLES_H */

454
3rd-party/lc3-google/src/tns.c vendored Normal file
View File

@ -0,0 +1,454 @@
/******************************************************************************
*
* 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 "tns.h"
#include "tables.h"
/* ----------------------------------------------------------------------------
* Filter Coefficients
* -------------------------------------------------------------------------- */
/**
* Resolve LPC Weighting indication according bitrate
* dt, nbytes Duration and size of the frame
* return True when LPC Weighting enabled
*/
static bool resolve_lpc_weighting(enum lc3_dt dt, int nbytes)
{
return nbytes < (dt == LC3_DT_7M5 ? 360/8 : 480/8);
}
/**
* Return dot product of 2 vectors
* a, b, n The 2 vectors of size `n`
* return sum( a[i] * b[i] ), i = [0..n-1]
*/
static inline float dot(const float *a, const float *b, int n)
{
float v = 0;
while (n--)
v += *(a++) * *(b++);
return v;
}
/**
* LPC Coefficients
* dt, bw Duration and bandwidth of the frame
* x Spectral coefficients
* gain, a Output the prediction gains and LPC coefficients
*/
static void compute_lpc_coeffs(enum lc3_dt dt, enum lc3_bandwidth bw,
const float *x, float *gain, float (*a)[9])
{
static const int sub_7m5_nb[] = { 9, 26, 43, 60 };
static const int sub_7m5_wb[] = { 9, 46, 83, 120 };
static const int sub_7m5_sswb[] = { 9, 66, 123, 180 };
static const int sub_7m5_swb[] = { 9, 46, 82, 120, 159, 200, 240 };
static const int sub_7m5_fb[] = { 9, 56, 103, 150, 200, 250, 300 };
static const int sub_10m_nb[] = { 12, 34, 57, 80 };
static const int sub_10m_wb[] = { 12, 61, 110, 160 };
static const int sub_10m_sswb[] = { 12, 88, 164, 240 };
static const int sub_10m_swb[] = { 12, 61, 110, 160, 213, 266, 320 };
static const int sub_10m_fb[] = { 12, 74, 137, 200, 266, 333, 400 };
/* --- Normalized autocorrelation --- */
static const float lag_window[] = {
1.00000000e+00, 9.98028026e-01, 9.92135406e-01, 9.82391584e-01,
9.68910791e-01, 9.51849807e-01, 9.31404933e-01, 9.07808230e-01,
8.81323137e-01
};
const int *sub = (const int * const [LC3_NUM_DT][LC3_NUM_SRATE]){
{ sub_7m5_nb, sub_7m5_wb, sub_7m5_sswb, sub_7m5_swb, sub_7m5_fb },
{ sub_10m_nb, sub_10m_wb, sub_10m_sswb, sub_10m_swb, sub_10m_fb },
}[dt][bw];
int nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
const float *xs, *xe = x + *sub;
float r[2][9];
for (int f = 0; f < nfilters; f++) {
float c[9][3];
for (int s = 0; s < 3; s++) {
xs = xe, xe = x + *(++sub);
for (int k = 0; k < 9; k++)
c[k][s] = dot(xs, xs + k, (xe - xs) - k);
}
float e0 = c[0][0], e1 = c[0][1], e2 = c[0][2];
r[f][0] = 3;
for (int k = 1; k < 9; k++)
r[f][k] = e0 == 0 || e1 == 0 || e2 == 0 ? 0 :
(c[k][0]/e0 + c[k][1]/e1 + c[k][2]/e2) * lag_window[k];
}
/* --- Levinson-Durbin recursion --- */
for (int f = 0; f < nfilters; f++) {
float *a0 = a[f], a1[9];
float err = r[f][0], rc;
gain[f] = err;
a0[0] = 1;
for (int k = 1; k < 9; ) {
rc = -r[f][k];
for (int i = 1; i < k; i++)
rc -= a0[i] * r[f][k-i];
rc /= err;
err *= 1 - rc * rc;
for (int i = 1; i < k; i++)
a1[i] = a0[i] + rc * a0[k-i];
a1[k++] = rc;
rc = -r[f][k];
for (int i = 1; i < k; i++)
rc -= a1[i] * r[f][k-i];
rc /= err;
err *= 1 - rc * rc;
for (int i = 1; i < k; i++)
a0[i] = a1[i] + rc * a1[k-i];
a0[k++] = rc;
}
gain[f] /= err;
}
}
/**
* LPC Weighting
* gain, a Prediction gain and LPC coefficients, weighted as output
*/
static void lpc_weighting(float pred_gain, float *a)
{
float gamma = 1. - (1. - 0.85) * (2. - pred_gain) / (2. - 1.5), g = 1;
for (int i = 1; i < 9; i++)
a[i] *= (g *= gamma);
}
/**
* LPC reflection
* a LPC coefficients
* rc Output refelection coefficients
*/
static void lpc_reflection(const float *a, float *rc)
{
float e, b[2][7], *b0, *b1;
rc[7] = a[1+7];
e = 1 - rc[7] * rc[7];
b1 = b[1];
for (int i = 0; i < 7; i++)
b1[i] = (a[1+i] - rc[7] * a[7-i]) / e;
for (int k = 6; k > 0; k--) {
b0 = b1, b1 = b[k & 1];
rc[k] = b0[k];
e = 1 - rc[k] * rc[k];
for (int i = 0; i < k; i++)
b1[i] = (b0[i] - rc[k] * b0[k-1-i]) / e;
}
rc[0] = b1[0];
}
/**
* Quantization of RC coefficients
* rc Refelection coefficients
* rc_order Return order of coefficients
* rc_i Return quantized coefficients
*/
static void quantize_rc(const float *rc, int *rc_order, int *rc_q)
{
/* Quantization table, sin(delta * (i + 0.5)), delta = Pi / 17 */
static float q_thr[] = {
9.22683595e-02, 2.73662990e-01, 4.45738356e-01, 6.02634636e-01,
7.39008917e-01, 8.50217136e-01, 9.32472229e-01, 9.82973100e-01
};
*rc_order = 8;
for (int i = 0; i < 8; i++) {
float rc_m = fabsf(rc[i]);
rc_q[i] = 4 * (rc_m >= q_thr[4]);
for (int j = 0; j < 4 && rc_m >= q_thr[rc_q[i]]; j++, rc_q[i]++);
if (rc[i] < 0)
rc_q[i] = -rc_q[i];
*rc_order = rc_q[i] != 0 ? 8 : *rc_order - 1;
}
}
/**
* Unquantization of RC coefficients
* rc_q Quantized coefficients
* rc_order Order of coefficients
* rc Return refelection coefficients
*/
static void unquantize_rc(const int *rc_q, int rc_order, float rc[8])
{
/* Quantization table, sin(delta * i), delta = Pi / 17 */
static float q_inv[] = {
0.00000000e+00, 1.83749517e-01, 3.61241664e-01, 5.26432173e-01,
6.73695641e-01, 7.98017215e-01, 8.95163302e-01, 9.61825645e-01,
9.95734176e-01
};
int i;
for (i = 0; i < rc_order; i++) {
float rc_m = q_inv[LC3_ABS(rc_q[i])];
rc[i] = rc_q[i] < 0 ? -rc_m : rc_m;
}
}
/* ----------------------------------------------------------------------------
* Filtering
* -------------------------------------------------------------------------- */
/**
* Forward filtering
* dt, bw Duration and bandwidth of the frame
* rc_order, rc Order of coefficients, and coefficients
* x Spectral coefficients, filtered as output
*/
static void forward_filtering(
enum lc3_dt dt, enum lc3_bandwidth bw,
const int rc_order[2], const float rc[2][8], float *x)
{
int nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
int nf = LC3_NE(dt, bw) >> (nfilters - 1);
int i0, ie = 3*(3 + dt);
float s[8] = { 0 };
for (int f = 0; f < nfilters; f++) {
i0 = ie;
ie = nf * (1 + f);
if (!rc_order[f])
continue;
for (int i = i0; i < ie; i++) {
float xi = x[i];
float s0, s1 = xi;
for (int k = 0; k < rc_order[f]; k++) {
s0 = s[k];
s[k] = s1;
s1 = rc[f][k] * xi + s0;
xi += rc[f][k] * s0;
}
x[i] = xi;
}
}
}
/**
* Inverse filtering
* dt, bw Duration and bandwidth of the frame
* rc_order, rc Order of coefficients, and unquantized coefficients
* x Spectral coefficients, filtered as output
*/
static void inverse_filtering(
enum lc3_dt dt, enum lc3_bandwidth bw,
const int rc_order[2], const float rc[2][8], float *x)
{
int nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
int nf = LC3_NE(dt, bw) >> (nfilters - 1);
int i0, ie = 3*(3 + dt);
float s[8] = { 0 };
for (int f = 0; f < nfilters; f++) {
i0 = ie;
ie = nf * (1 + f);
if (!rc_order[f])
continue;
for (int i = i0; i < ie; i++) {
float xi = x[i];
xi -= s[7] * rc[f][7];
for (int k = 6; k >= 0; k--) {
xi -= s[k] * rc[f][k];
s[k+1] = s[k] + rc[f][k] * xi;
}
s[0] = xi;
x[i] = xi;
}
for (int k = 7; k >= rc_order[f]; k--)
s[k] = 0;
}
}
/* ----------------------------------------------------------------------------
* Interface
* -------------------------------------------------------------------------- */
/**
* TNS analysis
*/
void lc3_tns_analyze(enum lc3_dt dt, enum lc3_bandwidth bw,
bool nn_flag, int nbytes, struct lc3_tns_data *data, float *x)
{
/* Processing steps :
* - Determine the LPC (Linear Predictive Coding) Coefficients
* - Check is the filtering is disabled
* - The coefficients are weighted on low bitrates and predicition gain
* - Convert to reflection coefficients and quantize
* - Finally filter the spectral coefficients */
float pred_gain[2], a[2][9];
float rc[2][8];
data->nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
data->lpc_weighting = resolve_lpc_weighting(dt, nbytes);
compute_lpc_coeffs(dt, bw, x, pred_gain, a);
for (int f = 0; f < data->nfilters; f++) {
data->rc_order[f] = 0;
if (nn_flag || pred_gain[f] <= 1.5)
continue;
if (data->lpc_weighting && pred_gain[f] < 2)
lpc_weighting(pred_gain[f], a[f]);
lpc_reflection(a[f], rc[f]);
quantize_rc(rc[f], &data->rc_order[f], data->rc[f]);
unquantize_rc(data->rc[f], data->rc_order[f], rc[f]);
}
forward_filtering(dt, bw, data->rc_order, rc, x);
}
/**
* TNS synthesis
*/
void lc3_tns_synthesize(enum lc3_dt dt, enum lc3_bandwidth bw,
const struct lc3_tns_data *data, float *x)
{
float rc[2][8] = { };
for (int f = 0; f < data->nfilters; f++)
if (data->rc_order[f])
unquantize_rc(data->rc[f], data->rc_order[f], rc[f]);
inverse_filtering(dt, bw, data->rc_order, rc, x);
}
/**
* Bit consumption of bitstream data
*/
int lc3_tns_get_nbits(const struct lc3_tns_data *data)
{
int nbits = 0;
for (int f = 0; f < data->nfilters; f++) {
int nbits_2048 = 2048;
int rc_order = data->rc_order[f];
nbits_2048 += rc_order > 0 ? lc3_tns_order_bits
[data->lpc_weighting][rc_order-1] : 0;
for (int i = 0; i < rc_order; i++)
nbits_2048 += lc3_tns_coeffs_bits[i][8 + data->rc[f][i]];
nbits += (nbits_2048 + (1 << 11) - 1) >> 11;
}
return nbits;
}
/**
* Put bitstream data
*/
void lc3_tns_put_data(lc3_bits_t *bits, const struct lc3_tns_data *data)
{
for (int f = 0; f < data->nfilters; f++) {
int rc_order = data->rc_order[f];
lc3_put_bits(bits, rc_order > 0, 1);
if (rc_order <= 0)
continue;
lc3_put_symbol(bits,
lc3_tns_order_models + data->lpc_weighting, rc_order-1);
for (int i = 0; i < rc_order; i++)
lc3_put_symbol(bits,
lc3_tns_coeffs_models + i, 8 + data->rc[f][i]);
}
}
/**
* Get bitstream data
*/
void lc3_tns_get_data(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_bandwidth bw, int nbytes, lc3_tns_data_t *data)
{
data->nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
data->lpc_weighting = resolve_lpc_weighting(dt, nbytes);
for (int f = 0; f < data->nfilters; f++) {
data->rc_order[f] = lc3_get_bit(bits);
if (!data->rc_order[f])
continue;
data->rc_order[f] += lc3_get_symbol(bits,
lc3_tns_order_models + data->lpc_weighting);
for (int i = 0; i < data->rc_order[f]; i++)
data->rc[f][i] = (int)lc3_get_symbol(bits,
lc3_tns_coeffs_models + i) - 8;
}
}

99
3rd-party/lc3-google/src/tns.h vendored Normal file
View File

@ -0,0 +1,99 @@
/******************************************************************************
*
* 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 - Temporal Noise Shaping
*
* Reference : Low Complexity Communication Codec (LC3)
* Bluetooth Specification v1.0
*/
#ifndef __LC3_TNS_H
#define __LC3_TNS_H
#include "common.h"
#include "bits.h"
/**
* Bitstream data
*/
typedef struct lc3_tns_data {
int nfilters;
bool lpc_weighting;
int rc_order[2];
int rc[2][8];
} lc3_tns_data_t;
/* ----------------------------------------------------------------------------
* Encoding
* -------------------------------------------------------------------------- */
/**
* TNS analysis
* dt, bw Duration and bandwidth of the frame
* nn_flag True when high energy detected near Nyquist frequency
* nbytes Size in bytes of the frame
* data Return bitstream data
* x Spectral coefficients, filtered as output
*/
void lc3_tns_analyze(enum lc3_dt dt, enum lc3_bandwidth bw,
bool nn_flag, int nbytes, lc3_tns_data_t *data, float *x);
/**
* Return number of bits coding the data
* data Bitstream data
* return Bit consumption
*/
int lc3_tns_get_nbits(const lc3_tns_data_t *data);
/**
* Put bitstream data
* bits Bitstream context
* data Bitstream data
*/
void lc3_tns_put_data(lc3_bits_t *bits, const lc3_tns_data_t *data);
/* ----------------------------------------------------------------------------
* Decoding
* -------------------------------------------------------------------------- */
/**
* Get bitstream data
* bits Bitstream context
* dt, bw Duration and bandwidth of the frame
* nbytes Size in bytes of the frame
* data Bitstream data
*/
void lc3_tns_get_data(lc3_bits_t *bits,
enum lc3_dt dt, enum lc3_bandwidth bw, int nbytes, lc3_tns_data_t *data);
/**
* TNS synthesis
* dt, bw Duration and bandwidth of the frame
* data Bitstream data
* x Spectral coefficients, filtered as output
*/
void lc3_tns_synthesize(enum lc3_dt dt, enum lc3_bandwidth bw,
const lc3_tns_data_t *data, float *x);
#endif /* __LC3_TNS_H */

219
src/btstack_lc3_google.c Normal file
View File

@ -0,0 +1,219 @@
/*
* Copyright (C) 2022 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
* GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#define BTSTACK_FILE__ "btstack_lc3_google.c"
/**
* @title LC3 Google Adapter
*/
#include "btstack_config.h"
#include "bluetooth.h"
#include "btstack_lc3_google.h"
#include "btstack_debug.h"
#include <string.h>
static uint16_t lc3_frame_duration_in_us(btstack_lc3_frame_duration_t frame_duration){
switch (frame_duration) {
case BTSTACK_LC3_FRAME_DURATION_7500US:
return 7500;
case BTSTACK_LC3_FRAME_DURATION_10000US:
return 10000;
default:
return 0;
}
}
/* Decoder implementation */
static uint8_t lc3_decoder_google_configure(void * context, uint32_t sample_rate, btstack_lc3_frame_duration_t frame_duration){
btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context;
// map frame duration
uint16_t duration_us = lc3_frame_duration_in_us(frame_duration);
if (duration_us == 0){
return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
}
// store config
instance->sample_rate = sample_rate;
instance->frame_duration = frame_duration;
// config decoder
instance->decoder = lc3_setup_decoder(duration_us, sample_rate, 0, &instance->decoder_mem);
if (instance->decoder == NULL) {
return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
}
return ERROR_CODE_SUCCESS;
}
static uint16_t lc3_decoder_google_get_number_octets_for_bitrate(void * context, uint32_t bitrate){
btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context;
uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration);
if (duration_us == 0){
return 0;
}
return lc3_frame_bytes(duration_us, bitrate);
}
static uint16_t lc3_decoder_google_get_number_samples_per_frame(void * context){
btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context;
uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration);
if (duration_us == 0){
return 0;
}
return lc3_frame_samples(duration_us, instance->sample_rate);
}
static uint8_t lc3_decoder_google_decode(void * context, const uint8_t *bytes, uint16_t byte_count, uint8_t BFI, enum lc3_pcm_format fmt, void * pcm_out, uint16_t stride, uint8_t * BEC_detect){
btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context;
if (BFI){
// bit errors, trigger PLC by passing NULL as buffer
*BEC_detect = 1;
bytes = NULL;
} else {
// no bit errors, regular processing
*BEC_detect = 0;
}
int result = lc3_decode(instance->decoder, (const void *) bytes, byte_count, fmt, pcm_out, stride);
switch (result){
case 0: // success
return ERROR_CODE_SUCCESS;
case -1: // PLC engaged
*BEC_detect = 1;
return ERROR_CODE_SUCCESS;
default:
return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
}
}
static uint8_t lc3_decoder_google_decode_signed_16(void * context, const uint8_t *bytes, uint16_t byte_count, uint8_t BFI, int16_t* pcm_out, uint16_t stride, uint8_t * BEC_detect){
return lc3_decoder_google_decode(context, bytes, byte_count, BFI, LC3_PCM_FORMAT_S16, (void *) pcm_out, stride, BEC_detect);
}
static uint8_t lc3_decoder_google_decode_signed_24(void * context, const uint8_t *bytes, uint16_t byte_count, uint8_t BFI, int32_t* pcm_out, uint16_t stride, uint8_t * BEC_detect) {
return lc3_decoder_google_decode(context, bytes, byte_count, BFI, LC3_PCM_FORMAT_S24, (void *) pcm_out, stride, BEC_detect);
}
static const btstack_lc3_decoder_t btstack_l3c_decoder_google_instance = {
lc3_decoder_google_configure,
lc3_decoder_google_get_number_octets_for_bitrate,
lc3_decoder_google_get_number_samples_per_frame,
lc3_decoder_google_decode_signed_16,
lc3_decoder_google_decode_signed_24
};
const btstack_lc3_decoder_t * btstack_lc3_decoder_google_init_instance(btstack_lc3_decoder_google_t * context){
memset(context, 0, sizeof(btstack_lc3_decoder_google_t));
return &btstack_l3c_decoder_google_instance;
}
/* Encoder implementation */
static uint8_t lc3_encoder_google_configure(void * context, uint32_t sample_rate, btstack_lc3_frame_duration_t frame_duration){
btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context;
// map frame duration
uint16_t duration_us = lc3_frame_duration_in_us(frame_duration);
if (duration_us == 0){
return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
}
// store config
instance->sample_rate = sample_rate;
instance->frame_duration = frame_duration;
// config encoder
instance->encoder = lc3_setup_encoder(duration_us, sample_rate, 0, &instance->encoder_mem);
if (instance->encoder == NULL) {
return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
}
return ERROR_CODE_SUCCESS;
}
static uint32_t lc3_encoder_google_get_bitrate_for_number_of_octets(void * context, uint16_t number_of_octets){
btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context;
// map frame duration
uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration);
if (duration_us == 0){
return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
}
return lc3_resolve_bitrate(duration_us, number_of_octets);
}
static uint16_t lc3_encoder_google_get_number_samples_per_frame(void * context){
btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context;
// map frame duration
uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration);
if (duration_us == 0){
return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
}
return lc3_frame_samples(duration_us, instance->sample_rate);
}
static uint8_t lc3_encoder_google_encode_signed(void * context, enum lc3_pcm_format fmt, const void *pcm_in, uint16_t stride, uint8_t *bytes, uint16_t byte_count) {
btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context;
int result = lc3_encode(instance->encoder, fmt, pcm_in, stride, byte_count, (void*) bytes);
switch (result){
case 0:
return ERROR_CODE_SUCCESS;
default:
return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
}
}
static uint8_t lc3_encoder_google_encode_signed_16(void * context, const int16_t* pcm_in, uint16_t stride, uint8_t *bytes, uint16_t byte_count){
return lc3_encoder_google_encode_signed(context, LC3_PCM_FORMAT_S16, (const void *) pcm_in, stride, bytes, byte_count);
}
static uint8_t lc3_encoder_google_encode_signed_24(void * context, const int32_t* pcm_in, uint16_t stride, uint8_t *bytes, uint16_t byte_count){
return lc3_encoder_google_encode_signed(context, LC3_PCM_FORMAT_S24, (const void *) pcm_in, stride, bytes, byte_count);
}
static const btstack_lc3_encoder_t btstack_l3c_encoder_google_instance = {
lc3_encoder_google_configure,
lc3_encoder_google_get_bitrate_for_number_of_octets,
lc3_encoder_google_get_number_samples_per_frame,
lc3_encoder_google_encode_signed_16,
lc3_encoder_google_encode_signed_24
};
const btstack_lc3_encoder_t * btstack_lc3_encoder_google_init_instance(btstack_lc3_encoder_google_t * context){
memset(context, 0, sizeof(btstack_lc3_encoder_google_t));
return &btstack_l3c_encoder_google_instance;
}

80
src/btstack_lc3_google.h Normal file
View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2022 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
* GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* @title LC3 Google Adapter
*/
#ifndef BTSTACK_LC3_GOOGLE_H
#define BTSTACK_LC3_GOOGLE_H
#include <stdint.h>
#include "lc3.h"
#include "btstack_lc3.h"
#if defined __cplusplus
extern "C" {
#endif
/* API_START */
typedef struct {
lc3_decoder_mem_48k_t decoder_mem;
lc3_decoder_t decoder; // pointer
uint32_t sample_rate;
btstack_lc3_frame_duration_t frame_duration;
} btstack_lc3_decoder_google_t;
typedef struct {
lc3_encoder_mem_48k_t encoder_mem;
lc3_encoder_t encoder; // pointer
uint32_t sample_rate;
btstack_lc3_frame_duration_t frame_duration;
} btstack_lc3_encoder_google_t;
/**
* Init LC3 Decoder Instance
* @param context for EHIMA LC3 decoder
*/
const btstack_lc3_decoder_t * btstack_lc3_decoder_google_init_instance(btstack_lc3_decoder_google_t * context);
/**
* Init LC3 Decoder Instance
* @param context for EHIMA LC3 decoder
*/
const btstack_lc3_encoder_t * btstack_lc3_encoder_google_init_instance(btstack_lc3_encoder_google_t * context);
/* API_END */
#if defined __cplusplus
}
#endif
#endif // BTSTACK_LC3_GOOGLE_H