#stream #wave #wav #data-stream #treat

stream-wave-parser

The stream-wave-parser is a crate that treats a stream from WAVE file

2 releases

0.1.2 Sep 24, 2024
0.1.1 Sep 23, 2024
0.1.0 Sep 23, 2024

#445 in Asynchronous

Download history 144/week @ 2024-09-17 295/week @ 2024-09-24 89/week @ 2024-10-01 17/week @ 2024-10-08

81 downloads per month

MIT/Apache

230KB
595 lines

stream-wave-parser

The stream-wave-parser is a crate that treats a stream from WAVE file.

You can create a WaveStream from impl Stream<Item = Result<Vec<u8>>> that is WAVE data. (e.g. An input stream data is typically from reqwest::Response::bytes_stream().)

The WaveStream provides a spec() method that returns WAVE metadata (sample_rate, bits_per_sample, etc.). And the WaveStream also provides into_data() that is the stream of the data in data chunk.

Mixer

You can create a WaveChannelMixer that converts multiple channels data into a single channel data.

Usages

use stream_wave_parser::WaveStream;
use futures_util::StreamExt as _;
use futures_util::stream::iter;

#[tokio::main]
async fn main() {
    // create wave stream.
    let chunks = create_sine_wave()
        .chunks(256)
        .map(|x| Ok(x.iter().cloned().collect::<Vec<_>>()))
        .collect::<Vec<_>>();
    let stream = iter(chunks);

    // read stream by `WaveStream`.
    let mut stream = WaveStream::new(stream);
    let spec = stream.spec().await.unwrap();
    assert_eq!(spec.pcm_format, 1);
    assert_eq!(spec.channels, 1);
    assert_eq!(spec.sample_rate, 8000);
    assert_eq!(spec.bits_per_sample, 16);

    let data_size = 16000; // 8000 samples x 2 Bytes (16 bits per sample)
    let mut data = stream.into_data().await;
    let mut size = 0;
    while let Some(chunk) = data.next().await {
        let chunk = chunk.unwrap();
        size += chunk.len();
    }
    assert_eq!(data_size, size as u32);
}

/// create sine wave (440 Hz 1 seconds)
fn create_sine_wave() -> Vec<u8> {
    use std::f32::consts::PI;

    let data_chunk = (0..)
        .enumerate()
        .map(|(_, idx)| {
            let t = idx as f32 / 8000.0;
            let sample = (t * 440. * 2. * PI).sin();
            ((sample * i16::MAX as f32) as i16).to_le_bytes()
        })
        .take(8000)
        .flatten()
        .collect::<Vec<u8>>();

    let mut wave = vec![];
    let riff_length = ((data_chunk.len() + 36) as u32).to_le_bytes();
    wave.extend(b"RIFF");
    wave.extend(riff_length);
    wave.extend(b"WAVE");
    wave.extend(b"fmt ");
    wave.extend(16u32.to_le_bytes());    // `fmt ` chunk size
    wave.extend(1u16.to_le_bytes());     // PCM format
    wave.extend(1u16.to_le_bytes());     // channels
    wave.extend(8000u32.to_le_bytes());  // sample rate
    wave.extend(16000u32.to_le_bytes()); // bit rate
    wave.extend(2u16.to_le_bytes());     // block size
    wave.extend(16u16.to_le_bytes());    // bits per sample

    wave.extend(b"data");
    wave.extend((data_chunk.len() as u32).to_le_bytes());
    wave.extend(data_chunk);

    wave
}

Dependencies

~530–710KB
~14K SLoC