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
Generated
+1 -1
View File
@@ -10,7 +10,7 @@ checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f"
[[package]] [[package]]
name = "morse_rs" name = "morse_rs"
version = "0.1.2" version = "0.1.3"
dependencies = [ dependencies = [
"hound", "hound",
] ]
+1 -1
View File
@@ -2,7 +2,7 @@
name = "morse_rs" name = "morse_rs"
description = "A simple morse code translator, with the abilty to write to WAV files using Hound." description = "A simple morse code translator, with the abilty to write to WAV files using Hound."
license = "MIT" license = "MIT"
version = "0.1.2" version = "0.1.3"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
+14 -1
View File
@@ -18,7 +18,7 @@ morse_rs = "0.1.2"
## Usage ## Usage
converts a string to morse then writes the encoded message into a wav file. Converts a string to morse then writes the encoded message into a wav file.
```rust ```rust
use morse_rs::{to_morse, write_morse}; use morse_rs::{to_morse, write_morse};
@@ -31,6 +31,19 @@ fn main() {
} }
``` ```
We can also write the morse into a buffer in memory
```rust
use morse_rs::{to_morse, write_morse};
fn main() {
let my_message = "attack at noon";
let morse = to_morse_inmemory(my_message);
write_morse("my_message.wav", &morse);
}
```
## TODO ## TODO
- Decode morse from sound - Decode morse from sound
- Add proper rust like error return types - Add proper rust like error return types
+75 -43
View File
@@ -1,8 +1,7 @@
use hound::{self, WavWriter}; use hound::{self, WavWriter};
use std::collections::HashMap; use std::collections::HashMap;
use std::f32::consts::PI; use std::f32::consts::PI;
use std::io::Cursor; use std::io::{Cursor, Seek, Write};
use std::{fs, i16, io};
const SAMPLE_RATE: f32 = 44100.0; const SAMPLE_RATE: f32 = 44100.0;
const BITS_PER_SAMPLE: u16 = 16; const BITS_PER_SAMPLE: u16 = 16;
@@ -147,7 +146,10 @@ pub fn to_morse(text: &str) -> String {
ret.trim_end().to_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; let sample_count = (duration * SAMPLE_RATE).ceil() as i32;
for t in (0..sample_count).map(|x| x as f32 / SAMPLE_RATE) { for t in (0..sample_count).map(|x| x as f32 / SAMPLE_RATE) {
let sample = (t * freq * 2.0 * PI).sin(); 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) { /// Writes given morse code into a `hound:WavWriter`
let mut writer = hound::WavWriter::create(filename, SPEC).unwrap(); ///
/// # 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() { 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 == '.' { if c == '.' {
write_freq(&mut writer, MORSE_FREQ, UNIT_TIME); write_freq(writer, MORSE_FREQ, UNIT_TIME);
write_freq(&mut writer, 0.0, 0.5 * UNIT_TIME); write_freq(writer, 0.0, 0.5 * UNIT_TIME); // Silence after dot
} else if c == '-' { } else if c == '-' {
write_freq(&mut writer, MORSE_FREQ, 3.0 * UNIT_TIME); write_freq(writer, MORSE_FREQ, 3.0 * UNIT_TIME);
write_freq(&mut writer, 0.0, 0.5 * UNIT_TIME); write_freq(writer, 0.0, 0.5 * UNIT_TIME); // Silence after dash
} else if c == ' ' { } 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 == '/' { } 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 { } else {
panic!("The morse code given is not valid!"); 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) { /// Writes given morse code into a wav file
let sample_count = (duration * SAMPLE_RATE).ceil() as i32; ///
for t in (0..sample_count).map(|x| x as f32 / SAMPLE_RATE) { /// # Arguments
let sample = (t * freq * 2.0 * PI).sin(); ///
let amplitude = i16::MAX as f32; /// * `pause_between` -> The duration in miliseconds.
writer.write_sample((sample * amplitude) as i16).unwrap(); /// - `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 buffer = Vec::new(); // Create a buffer to hold the WAV data
{ {
let mut writer = hound::WavWriter::new(Cursor::new(&mut buffer), SPEC).unwrap(); let mut writer = hound::WavWriter::new(Cursor::new(&mut buffer), SPEC).unwrap();
for c in morse.chars() { write_morse(
// Writing Morse code frequencies based on the character &mut writer,
if c == '.' { morse,
write_freq_inmemory(&mut writer, MORSE_FREQ, UNIT_TIME); pause_between_char_time,
write_freq_inmemory(&mut writer, 0.0, 0.5 * UNIT_TIME); // Silence after dot pause_between_words_time,
} 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
buffer // Return the WAV data as a Vec<u8> buffer
} }
#[cfg(test)] #[cfg(test)]