diff --git a/Cargo.lock b/Cargo.lock index 706ed81..9c0e4a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" [[package]] name = "morse_rs" -version = "0.1.2" +version = "0.1.3" dependencies = [ "hound", ] diff --git a/Cargo.toml b/Cargo.toml index 139c3c8..891b18c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "morse_rs" description = "A simple morse code translator, with the abilty to write to WAV files using Hound." license = "MIT" -version = "0.1.2" +version = "0.1.3" edition = "2021" [dependencies] diff --git a/README.md b/README.md index 29fcf80..ec09f11 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ morse_rs = "0.1.2" ## 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 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 - Decode morse from sound - Add proper rust like error return types diff --git a/src/lib.rs b/src/lib.rs index a7e934f..e1b39d9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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>, freq: f32, duration: f32) { +fn write_freq(writer: &mut WavWriter, 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>, 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( + writer: &mut WavWriter, + 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>>, 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 { +/// 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 { 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 + buffer } #[cfg(test)]