reading of wav files is ready

This commit is contained in:
Данила Горнушко 2024-05-27 18:55:07 +03:00
parent c9f1c0968e
commit ced5884733
3 changed files with 40 additions and 6 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
/target
/out/

View file

@ -3,6 +3,7 @@
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/out" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />

View file

@ -1,15 +1,15 @@
use anyhow::{Context, Result};
use clap::Parser;
use crc::{Crc, CRC_16_IBM_3740};
use hound::{SampleFormat, WavSpec, WavWriter};
use log::{debug, error, info, LevelFilter};
use serialport::SerialPort;
use std::collections::HashMap;
use std::io::{BufRead, BufReader, Read, Write};
use std::slice;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;
use hound::{WavSpec, SampleFormat, WavWriter};
use std::fs::File;
use std::time::{SystemTime, UNIX_EPOCH};
const MAX_DATA_LEN: usize = 1024 * 2 + 4 + 2;
@ -70,7 +70,7 @@ fn main() {
channels: 1,
sample_rate: get_sample_rate(&mut port, args.device_id),
bits_per_sample: 16,
sample_format: hound::SampleFormat::Int,
sample_format: SampleFormat::Int,
};
info!("Starting main loop...");
@ -106,6 +106,22 @@ fn main() {
match get_chunk(&mut port, args.device_id, args.baud_rate, winsize) {
Some(data) => {
info!("Received new data with len: {}", data.len());
let timestamp_ms = current_timestamp_ms();
let filename = format!("./out/wave_{}.wav", timestamp_ms);
// Create a new WAV file
let mut writer = WavWriter::create(&filename, spec)
.expect("Can't create new WAV file!");
let mut i16_writer = writer.get_i16_writer(data.len() as u32);
for sample in data {
unsafe {
i16_writer.write_sample_unchecked(sample);
}
}
i16_writer.flush().expect("Something went wrong while writing WAV file");
info!("WAV file {} has been written.", filename);
err_counter = err_counter.saturating_sub(1);
last_chunk_id = cur_chunk_id;
}
@ -286,7 +302,7 @@ fn get_chunk(
id: u32,
baud_rate: u32,
win_size: usize,
) -> Option<Vec<u8>> {
) -> Option<Vec<i16>> {
let command = format!("@{} convbuf\n", id);
debug!("Writing convbuf to the serial port");
port.write_all(command.as_bytes())
@ -335,7 +351,9 @@ fn get_chunk(
None
} else {
debug!("CRC is correct!");
Some(data_buf.to_vec())
// converting raw bytes to correct format
Some(convert_to_i16(data_buf))
}
}
_ => {
@ -345,6 +363,19 @@ fn get_chunk(
}
}
fn convert_to_i16(buffer: &[u8]) -> Vec<i16> {
assert_eq!(buffer.len() % 2, 0, "Buffer length must be a multiple of 2.");
let len = buffer.len() / 2; // Number of i16 elements
let ptr = buffer.as_ptr() as *const i16;
// Safety: We are transmuting the buffer from u8 to i16, ensuring that the types have the same size
// and alignment requirements. We also ensure that the buffer length is valid for transmuting.
unsafe {
let i16_slice = slice::from_raw_parts(ptr, len);
i16_slice.to_vec() // Convert the slice to a Vec<i16>
}
}
fn header_is_ok(vec: &[u8]) -> bool {
vec.get(0..4)
.map(|bytes| u32::from_be_bytes(bytes.try_into().unwrap()))
@ -358,7 +389,8 @@ fn exp_buf_size(win_size: usize) -> usize {
fn current_timestamp_ms() -> u128 {
let start = SystemTime::now();
let since_the_epoch = start.duration_since(UNIX_EPOCH)
let since_the_epoch = start
.duration_since(UNIX_EPOCH)
.expect("Time went backwards");
since_the_epoch.as_millis()
}