#codec #compression #ad-hoc

bin+lib adhoc_audio

一个非常基本的音频编解码器,用纯Rust编写

5个版本

0.1.4 2022年10月20日
0.1.3 2021年12月3日
0.1.2 2021年11月30日
0.1.1 2021年11月30日
0.1.0 2021年11月30日

音频类别中排名第392


fluffl使用

MIT/Apache

120KB
3K SLoC

Adhoc Audio

纯Rust编写的音频压缩。它不链接到任何绑定,因此可以构建为wasm32-unknown-unknown。

这是什么?

这是我将拼凑在一起以压缩音频的音频编解码器的集合。我目前正在用它来

  • 在客户端浏览器中压缩麦克风数据(使用此仓库编译为wasm)
  • 将数据发送到服务器(POST请求多部分)
  • 将压缩数据重新编码为标准格式(这里我将使用rust绑定到libavcodec或类似的东西)

目前,只有一个实际压缩音频的编解码器 AdhocCodec 和我编写的WAVE读取器/写入器实用工具 WavCodec

为什么?

在开发我正在编写的WASM应用程序期间,需要压缩从WEBAUDIO api接收的麦克风数据。需要一个纯Rust解决方案,以保持项目的构建步骤简单。据我所知,有一些纯Rust音频 解码器 用于VORBIS(lewton)、MP3(puremp3)等,但大多数这些crate不支持 编码

性能

可能不是非常快,但我还没有真正测试过。编码/解码算法是O(N),因此应该足够快。如果无法满足我的速度要求,我一定会进行优化。`Vec`实现进行分配,因此应该有log(N)次分配。

压缩

压缩节省似乎在20%-70%之间,但我还没有进行广泛的测试以具体说明。然而,编解码器不是有损的,它在更高的“压缩级别”上对音频进行量化,以实现显著的存储空间节省。量化对音频质量的影响不大,我对这个发现感到非常惊讶。

编码示例

use adhoc_audio::{codec::Streamable, AdhocCodec, WavCodec};
use std::fs::File;

fn main() {
    println!("compressing file example..");


    //set up a buffer for reading/writing samples
    let mut samples = [0.0; 1024];

    //open wav file
    let mut wav_reader = WavCodec::load(File::open("./resources/taunt.wav")
        .unwrap()).unwrap();
    
    let mut adhoc = AdhocCodec::new()
        // level 0 means no quantization ,so its basically lossless at level 0
        // levels 1-10 means quantization so compression is better but 
        // quality suffers (dithering is added to compensate)
        .with_compression_level(7)
        // AdhocCodec::with_info(.. ) MUST BE CALLED 
        // before calling encode/decode when you are 
        // creating a new instance of AdhocCodec
        .with_info(wav_reader.info());

    //'decode' wav stream bit-by-bit
    //Note:in this case we are just reading PCM info
    while let Some(samples_read) = wav_reader.decode(&mut samples) {
        //encode wav data bit-by-bit
        //memory is allocated as needed
        adhoc.encode(&samples[0..samples_read]);
    }

    //write compressed audio back to disk
    adhoc
        .save_to(File::create("./resources/taunt.adhoc").unwrap())
        .unwrap();

    println!("taunt.adhoc written to: ./resources");
}

解码示例

use adhoc_audio::{codec::Streamable, AdhocCodec, WavCodec};
use std::fs::File;

fn main() {
    println!("decompressing file from 'compress' example...");

    //set up a buffer for reading/writing samples
    let mut samples = [0.0; 1024];

    //open wav file
    let mut adhoc = AdhocCodec::load(
        File::open("./resources/taunt.adhoc").expect("run example 'compress' before this one"),
    )
    .unwrap();
    
    let mut wav_writer = WavCodec::new(adhoc.info());

    //decode adhoc stream a chunk of samples at a time
    while let Some(samples_read) = adhoc.decode(&mut samples) {
        //encode wav data bit-by-bit
        //memory is allocated as needed
        wav_writer.encode(&samples[0..samples_read]);
    }

    //write compressed audio back to disk
    wav_writer
        .save_to(File::create("./resources/taunt_decompressed.wav").unwrap())
        .unwrap();

    println!("taunt.adhoc written to: ./resources");
}

命令行界面

此包有一个简单的命令行工具,用于在`.wav`和`.adhoc`格式之间转换。

在终端中,只需执行

cargo install --path .

要查看标志选项,请这样做

adhoc_audio -h

压缩

压缩WAV文件的最简单方法如下

adhoc_audio ./resources/taunt.wav 

它将在当前目录创建一个taunt.codec

解压缩

构建第一个示例来解压缩taunt.codec即可

adhoc_audio ./taunt.codec

解压缩后的WAV文件将被写入您的当前工作目录

依赖项

~0.6–1.7MB
~36K SLoC