#codec #audio #lc3 #no-std

no-std lc3-codec

嵌入式系统LC3音频编解码器的实现(no_std)

2个不稳定版本

0.2.0 2022年6月12日
0.1.0 2022年5月15日

#553嵌入式开发

Apache-2.0

700KB
10K SLoC

lc3-codec

低复杂度通信编解码器。这是针对no_std环境的LC3音频编解码器1.0版本(发布于2020-09-15)的实现。

目前,除了我的测试之外,还没有任何正式的批准或验证方式。我已经对经过验证的编解码器进行了测试,编码和解码都可以处理一些我测试的音乐。出于版权原因,音乐文件未包含在此仓库中。

要开始,请查看lc3_decoder.rslc3_encoder.rs文件。

简介

该代码库的目的是展示现代音频编解码器的工作原理。它被编写为在嵌入式mcu上运行,因此API可能看起来有些笨拙,因为您必须传递预先分配的内存。我的背景不在信号处理领域,我想创建一个我可以阅读和理解的基础代码库。这就是为什么我尽量避免在类似实现中可能看到的简写变量和方法名称。过多的注释是为了我的利益和那些信号处理经验较少的人。

该代码库仍在积极开发中,我正在努力提高性能,简化任何看起来令人困惑的内容。

编码器使用方法

在具有分配器的系统中

# Cargo.toml
lc3-codec = { version = "0.2" }
// setup the encoder
let num_channels = 1;
let sampling_frequency = SamplingFrequency::Hz48000;
let frame_duration = FrameDuration::TenMs;
let (integer_length, scaler_length, complex_length) =
    Lc3Encoder::calc_working_buffer_lengths(num_channels, frame_duration, sampling_frequency);
let mut integer_buf = vec![0; integer_length];
let mut scaler_buf = vec![0.0; scaler_length];
let mut complex_buf = vec![Complex::default(); complex_length];
let mut encoder = Lc3Encoder::new(
    num_channels, frame_duration, sampling_frequency, &mut integer_buf, &mut scaler_buf, &mut complex_buf,
);

// encode a frame of audio on channel 0
let samples_in: Vec<i16> = vec![0; 480];
let mut buf_out: Vec<u8> = vec![0; 150];
encoder.encode_frame(0, &samples_in, &mut buf_out).unwrap();

no_std环境(无分配器)中

# Cargo.toml
lc3-codec = { version = "0.2", default-features = false }
// setup the encoder statically
const NUM_CH: usize = 1;
const DURATION: FrameDuration = FrameDuration::TenMs;
const FREQ: SamplingFrequency = SamplingFrequency::Hz48000;
const BUF_LENGTHS: (usize, usize, usize) = Lc3Encoder::<NUM_CH>::calc_working_buffer_lengths(DURATION, FREQ);
let mut integer_buf = [0; BUF_LENGTHS.0];
let mut scaler_buf = [0.0; BUF_LENGTHS.1];
let mut complex_buf = [Complex::default(); BUF_LENGTHS.2];
let mut encoder =
    Lc3Encoder::<NUM_CH>::new(DURATION, FREQ, &mut integer_buf, &mut scaler_buf, &mut complex_buf);

// encode a frame of audio on channel 0
let samples_in: [i16; 480] = [0; 480];
let mut buf_out: [u8; 150] = [0; 150];
encoder.encode_frame(0, &samples_in, &mut buf_out).unwrap();

解码器使用方法

在具有分配器的系统中

# Cargo.toml
lc3-codec = { version = "0.2" }
// setup decoder
let num_channels = 1;
let sampling_frequency = SamplingFrequency::Hz48000;
let frame_duration = FrameDuration::TenMs;
let (scaler_length, complex_length) =
    Lc3Decoder::calc_working_buffer_lengths(num_channels, frame_duration, sampling_frequency);
let mut scaler_buf = vec![0.0; scaler_length];
let mut complex_buf = vec![Complex::default(); complex_length];
let mut decoder = Lc3Decoder::new(
    num_channels, frame_duration, sampling_frequency, &mut scaler_buf, &mut complex_buf,
);

// decode 16 bit audio on channel 0
let buf_in: Vec<u8> = vec![0; 150];
let mut samples_out: Vec<i16> = vec![0; 480];
decoder.decode_frame(16, 0, &buf_in, &mut samples_out).unwrap();

no_std环境(无分配器)中

# Cargo.toml
lc3-codec = { version = "0.2", default-features = false }
// setup decoder
const NUM_CH: usize = 1;
const FREQ: SamplingFrequency = SamplingFrequency::Hz48000;
const DURATION: FrameDuration = FrameDuration::TenMs;
const SCALER_COMPLEX_LENS: (usize, usize) = Lc3Decoder::calc_working_buffer_lengths(1, DURATION, FREQ);
let mut scaler_buf = [0.0; SCALER_COMPLEX_LENS.0];
let mut complex_buf = [Complex::default(); SCALER_COMPLEX_LENS.1];
let mut decoder = Lc3Decoder::new(NUM_CH, DURATION, FREQ, &mut scaler_buf, &mut complex_buf);

// decode 16 bit audio on channel 0 
let mut samples_out = [0; 480];
let buf_in: [u8; 150] = [0; 150];
decoder.decode_frame(16, 0, &buf_in, &mut samples_out).unwrap();

性能和系统要求

以下是在编写时的一些性能基准。

在PC上:解码器可以在60分钟的压缩音频中解码,耗时5i7-6700K CPU的单一核心上,主频为4.00GHz

在微控制器上:解码器可以在Nordic nrf52840 Cortex M4F MCU上以72MHz运行时,在10 ms的音频(一个帧)中解码,耗时5.4 ms

解码器用于工作缓冲区需要27,564字节的RAM

单元测试

目前实施中的单元测试主要是为了便于重构,帮助我识别对输入和输出数据有重大影响的更改。基本上,我不希望破坏任何事情,这有助于避免这种情况。一旦代码库稍微稳定下来,就会添加更细粒度和有用的测试。

许可证

Copyright 2022 David Haig

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:

https://apache.ac.cn/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.

依赖项

约2.5MB
约58K SLoC