mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-15 23:42:52 +00:00
Add LC3 codec from Google
This commit is contained in:
parent
9b9478570b
commit
9a19cd7860
2
3rd-party/README.md
vendored
2
3rd-party/README.md
vendored
@ -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
61
3rd-party/lc3-google/Android.bp
vendored
Normal 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",
|
||||
],
|
||||
}
|
||||
|
93
3rd-party/lc3-google/fuzzer/liblc3_fuzzer.cpp
vendored
Normal file
93
3rd-party/lc3-google/fuzzer/liblc3_fuzzer.cpp
vendored
Normal 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
300
3rd-party/lc3-google/include/lc3.h
vendored
Normal 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 */
|
156
3rd-party/lc3-google/include/lc3_private.h
vendored
Normal file
156
3rd-party/lc3-google/include/lc3_private.h
vendored
Normal 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
92
3rd-party/lc3-google/src/attdet.c
vendored
Normal 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
44
3rd-party/lc3-google/src/attdet.h
vendored
Normal 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
375
3rd-party/lc3-google/src/bits.c
vendored
Normal 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
314
3rd-party/lc3-google/src/bits.h
vendored
Normal 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
129
3rd-party/lc3-google/src/bwdet.c
vendored
Normal 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
69
3rd-party/lc3-google/src/bwdet.h
vendored
Normal 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
105
3rd-party/lc3-google/src/common.h
vendored
Normal 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
70
3rd-party/lc3-google/src/energy.c
vendored
Normal 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
43
3rd-party/lc3-google/src/energy.h
vendored
Normal 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
570
3rd-party/lc3-google/src/lc3.c
vendored
Normal 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
621
3rd-party/lc3-google/src/ltpf.c
vendored
Normal 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](<pf->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
107
3rd-party/lc3-google/src/ltpf.h
vendored
Normal 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
502
3rd-party/lc3-google/src/mdct.c
vendored
Normal 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
59
3rd-party/lc3-google/src/mdct.h
vendored
Normal 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
61
3rd-party/lc3-google/src/plc.c
vendored
Normal 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
57
3rd-party/lc3-google/src/plc.h
vendored
Normal 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
878
3rd-party/lc3-google/src/sns.c
vendored
Normal 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
103
3rd-party/lc3-google/src/sns.h
vendored
Normal 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
877
3rd-party/lc3-google/src/spec.c
vendored
Normal 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
111
3rd-party/lc3-google/src/spec.h
vendored
Normal 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
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
96
3rd-party/lc3-google/src/tables.h
vendored
Normal 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
454
3rd-party/lc3-google/src/tns.c
vendored
Normal 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
99
3rd-party/lc3-google/src/tns.h
vendored
Normal 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
219
src/btstack_lc3_google.c
Normal 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
80
src/btstack_lc3_google.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user