refactors and customizable time feature

This commit is contained in:
ghaisan
2024-10-09 20:23:53 +07:00
parent b0492aca2e
commit 8ea482b2d6
4 changed files with 91 additions and 46 deletions
+75 -43
View File
@@ -1,8 +1,7 @@
use hound::{self, WavWriter};
use std::collections::HashMap;
use std::f32::consts::PI;
use std::io::Cursor;
use std::{fs, i16, io};
use std::io::{Cursor, Seek, Write};
const SAMPLE_RATE: f32 = 44100.0;
const BITS_PER_SAMPLE: u16 = 16;
@@ -147,7 +146,10 @@ pub fn to_morse(text: &str) -> String {
ret.trim_end().to_string()
}
fn write_freq(writer: &mut WavWriter<io::BufWriter<fs::File>>, freq: f32, duration: f32) {
fn write_freq<W>(writer: &mut WavWriter<W>, freq: f32, duration: f32)
where
W: Write + Seek,
{
let sample_count = (duration * SAMPLE_RATE).ceil() as i32;
for t in (0..sample_count).map(|x| x as f32 / SAMPLE_RATE) {
let sample = (t * freq * 2.0 * PI).sin();
@@ -156,63 +158,93 @@ fn write_freq(writer: &mut WavWriter<io::BufWriter<fs::File>>, freq: f32, durati
}
}
pub fn write_morse(filename: &str, morse: &str) {
let mut writer = hound::WavWriter::create(filename, SPEC).unwrap();
/// Writes given morse code into a `hound:WavWriter`
///
/// # Arguments
///
/// * `pause_between` -> The duration in miliseconds.
/// - `char_time` -> The pause between characters, e.g .- *wait* -..
/// - `words_time` -> The pause between words, or equivalently at '/' characters.
pub fn write_morse<W>(
writer: &mut WavWriter<W>,
morse: &str,
pause_between_char_time: f32,
pause_between_words_time: f32,
) where
W: Write + Seek,
{
for c in morse.chars() {
// We give a margin of 0.5 * UNIT_TIME between dots and dashes
// give 1.5 * UNIT_TIME between characters
// and give 2 * UNIT_TIME between words
if c == '.' {
write_freq(&mut writer, MORSE_FREQ, UNIT_TIME);
write_freq(&mut writer, 0.0, 0.5 * UNIT_TIME);
write_freq(writer, MORSE_FREQ, UNIT_TIME);
write_freq(writer, 0.0, 0.5 * UNIT_TIME); // Silence after dot
} else if c == '-' {
write_freq(&mut writer, MORSE_FREQ, 3.0 * UNIT_TIME);
write_freq(&mut writer, 0.0, 0.5 * UNIT_TIME);
write_freq(writer, MORSE_FREQ, 3.0 * UNIT_TIME);
write_freq(writer, 0.0, 0.5 * UNIT_TIME); // Silence after dash
} else if c == ' ' {
write_freq(&mut writer, 0.0, 1.5 * UNIT_TIME);
// Pause between Characters
write_freq(writer, 0.0, pause_between_char_time);
} else if c == '/' {
write_freq(&mut writer, 0.0, 2.0 * UNIT_TIME);
// Pause between Words
write_freq(writer, 0.0, 2.0 * pause_between_words_time);
} else {
panic!("The morse code given is not valid!");
}
}
write_freq(&mut writer, 0.0, UNIT_TIME); // End padding
write_freq(writer, 0.0, UNIT_TIME); // End padding
}
pub fn write_freq_inmemory(writer: &mut WavWriter<Cursor<&mut Vec<u8>>>, freq: f32, duration: f32) {
let sample_count = (duration * SAMPLE_RATE).ceil() as i32;
for t in (0..sample_count).map(|x| x as f32 / SAMPLE_RATE) {
let sample = (t * freq * 2.0 * PI).sin();
let amplitude = i16::MAX as f32;
writer.write_sample((sample * amplitude) as i16).unwrap();
}
/// Writes given morse code into a wav file
///
/// # Arguments
///
/// * `pause_between` -> The duration in miliseconds.
/// - `char_time` -> The pause between characters, e.g .- *wait* -..
/// - `words_time` -> The pause between words, or equivalently at '/' characters.
pub fn write_morse_to_file(
filename: &str,
morse: &str,
pause_between_char_time: f32,
pause_between_words_time: f32,
) {
// Convert from MS;
let pause_between_char_time = pause_between_char_time / 1000.0;
let pause_between_words_time = pause_between_words_time / 1000.0;
let mut writer = hound::WavWriter::create(filename, SPEC).unwrap();
write_morse(
&mut writer,
morse,
pause_between_char_time,
pause_between_words_time,
);
writer.finalize().unwrap();
}
pub fn write_morse_inmemory(morse: &str) -> Vec<u8> {
/// Writes given morse code into a buffer that is returned
///
/// # Arguments
///
/// * `pause_between` -> The duration in miliseconds.
/// - `char_time` -> The pause between characters, e.g .- *wait* -..
/// - `words_time` -> The pause between words, or equivalently at '/' characters.
pub fn write_morse_in_memory(
morse: &str,
pause_between_char_time: f32,
pause_between_words_time: f32,
) -> Vec<u8> {
let mut buffer = Vec::new(); // Create a buffer to hold the WAV data
{
let mut writer = hound::WavWriter::new(Cursor::new(&mut buffer), SPEC).unwrap();
for c in morse.chars() {
// Writing Morse code frequencies based on the character
if c == '.' {
write_freq_inmemory(&mut writer, MORSE_FREQ, UNIT_TIME);
write_freq_inmemory(&mut writer, 0.0, 0.5 * UNIT_TIME); // Silence after dot
} else if c == '-' {
write_freq_inmemory(&mut writer, MORSE_FREQ, 3.0 * UNIT_TIME);
write_freq_inmemory(&mut writer, 0.0, 0.5 * UNIT_TIME); // Silence after dash
} else if c == ' ' {
write_freq_inmemory(&mut writer, 0.0, 1.5 * UNIT_TIME); // Silence for space
} else if c == '/' {
write_freq_inmemory(&mut writer, 0.0, 2.0 * UNIT_TIME); // Silence for word space
} else {
panic!("The morse code given is not valid!");
}
}
write_freq_inmemory(&mut writer, 0.0, UNIT_TIME); // End padding
writer.finalize().unwrap(); // Finalize the writer
} // The writer goes out of scope here
write_morse(
&mut writer,
morse,
pause_between_char_time,
pause_between_words_time,
);
}
buffer // Return the WAV data as a Vec<u8>
buffer
}
#[cfg(test)]