Full encoding chain is working
This commit is contained in:
parent
39d4c602f4
commit
3d994125a1
|
@ -1,14 +1,183 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.71"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libpulse-binding"
|
||||||
|
version = "2.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35b35c3c377b537d044107ff0830b4e5ae32a5c106289977a04b3387a143e994"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"libpulse-sys",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libpulse-simple-binding"
|
||||||
|
version = "2.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4ef3ce750cdbce60fc96aac1f6dad84d67419d2307a05a27b73700f1f5d33e0"
|
||||||
|
dependencies = [
|
||||||
|
"libpulse-binding",
|
||||||
|
"libpulse-simple-sys",
|
||||||
|
"libpulse-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libpulse-simple-sys"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a48e779375c1d6e8b8d2fcbca67cc2f3208d447f17215f8ea600d6a58ccc6a56"
|
||||||
|
dependencies = [
|
||||||
|
"libpulse-sys",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libpulse-sys"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa9559e91871e5f820c3b4e181b8c8f3ebd0b7839c92943802caf0f1477fdc27"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab3e176191bc4faad357e3122c4747aa098ac880e88b168f106386128736cf4a"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b05ad05bd8977050b171b3f6b48175fea6e0565b7981059b486075e1026a9fb5"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.41"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5b4d7360f362cfb50dde8143501e6940b22f644be75a4cc90b2d81968908138"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rusty-dsp"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libpulse-binding",
|
||||||
|
"libpulse-simple-binding",
|
||||||
|
"num",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusty-tty"
|
name = "rusty-tty"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"rusty-dsp",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
|
@ -8,3 +8,4 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lazy_static = "*"
|
lazy_static = "*"
|
||||||
|
rusty-dsp = {path = "../rusty-dsp"}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
extern crate rusty_dsp;
|
||||||
|
|
||||||
|
use rusty_dsp::error::DspError;
|
||||||
|
|
||||||
const LETTERS: &[u8] = b"\0E\nA SIU\rDRJNFCKTZLWHYPQOBG\0MXV\0";
|
const LETTERS: &[u8] = b"\0E\nA SIU\rDRJNFCKTZLWHYPQOBG\0MXV\0";
|
||||||
const FIGURES: &[u8] = b"\03\n- \x0787\r\x054',!:(5\")2#6019?&\0./;\0";
|
const FIGURES: &[u8] = b"\03\n- \x0787\r\x054',!:(5\")2#6019?&\0./;\0";
|
||||||
|
|
||||||
|
@ -50,7 +54,7 @@ enum ShiftState {
|
||||||
Figures,
|
Figures,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Encoder<'a> {
|
pub struct Encoder<'a> {
|
||||||
shift_state: ShiftState,
|
shift_state: ShiftState,
|
||||||
buffer: Option<u8>,
|
buffer: Option<u8>,
|
||||||
iterator: Box<dyn Iterator<Item = u8> + 'a>,
|
iterator: Box<dyn Iterator<Item = u8> + 'a>,
|
||||||
|
@ -70,7 +74,7 @@ impl<'a> Encoder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for Encoder<'a> {
|
impl<'a> Iterator for Encoder<'a> {
|
||||||
type Item = Result<u8, u8>;
|
type Item = Result<u8, DspError>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if let Some(c) = self.buffer {
|
if let Some(c) = self.buffer {
|
||||||
|
@ -108,17 +112,20 @@ impl<'a> Iterator for Encoder<'a> {
|
||||||
|
|
||||||
Some(Ok(SHIFT_FIGURES))
|
Some(Ok(SHIFT_FIGURES))
|
||||||
}
|
}
|
||||||
(None, None, _) => Some(Err(byte)),
|
(None, None, _) => Some(Err(DspError::Error(format!(
|
||||||
|
"Unable to decode symbol: {:?}",
|
||||||
|
&byte
|
||||||
|
)))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode(msg: &str) -> Result<Vec<u8>, u8> {
|
pub fn encode(msg: &str) -> Result<Vec<u8>, DspError> {
|
||||||
let encoder = Encoder::from(msg.to_ascii_uppercase().into_bytes().into_iter());
|
let encoder = Encoder::from(msg.to_ascii_uppercase().into_bytes().into_iter());
|
||||||
encoder.collect()
|
encoder.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Decoder<'a> {
|
pub struct Decoder<'a> {
|
||||||
shift_state: ShiftState,
|
shift_state: ShiftState,
|
||||||
iterator: Box<dyn Iterator<Item = u8> + 'a>,
|
iterator: Box<dyn Iterator<Item = u8> + 'a>,
|
||||||
}
|
}
|
||||||
|
@ -138,7 +145,7 @@ impl<'a> Decoder<'a> {
|
||||||
impl<'a> Iterator for Decoder<'a> {
|
impl<'a> Iterator for Decoder<'a> {
|
||||||
// Option<Result<u8, u8>> for nice error handling if somebody wants to use collect
|
// Option<Result<u8, u8>> for nice error handling if somebody wants to use collect
|
||||||
// See https://doc.rust-lang.org/stable/rust-by-example/error/iter_result.html
|
// See https://doc.rust-lang.org/stable/rust-by-example/error/iter_result.html
|
||||||
type Item = Result<u8, u8>;
|
type Item = Result<u8, DspError>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let mut byte = match self.iterator.next() {
|
let mut byte = match self.iterator.next() {
|
||||||
|
@ -167,18 +174,24 @@ impl<'a> Iterator for Decoder<'a> {
|
||||||
match (byte, self.shift_state) {
|
match (byte, self.shift_state) {
|
||||||
(c, ShiftState::Letters) => match letter_from_code(c) {
|
(c, ShiftState::Letters) => match letter_from_code(c) {
|
||||||
Some(l) => Some(Ok(l)),
|
Some(l) => Some(Ok(l)),
|
||||||
None => Some(Err(c)),
|
None => Some(Err(DspError::Error(format!(
|
||||||
|
"Unable to decode symbol: {:?}",
|
||||||
|
c
|
||||||
|
)))),
|
||||||
},
|
},
|
||||||
(c, ShiftState::Figures) => match figure_from_code(c) {
|
(c, ShiftState::Figures) => match figure_from_code(c) {
|
||||||
Some(f) => Some(Ok(f)),
|
Some(f) => Some(Ok(f)),
|
||||||
None => Some(Err(c)),
|
None => Some(Err(DspError::Error(format!(
|
||||||
|
"Unable to decode symbol: {:?}",
|
||||||
|
c
|
||||||
|
)))),
|
||||||
},
|
},
|
||||||
(_, ShiftState::None) => panic!("Shift state is expectedly None"),
|
(_, ShiftState::None) => panic!("Shift state is expectedly None"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode(msg: &[u8]) -> Result<String, u8> {
|
pub fn decode(msg: &[u8]) -> Result<String, DspError> {
|
||||||
let decoder = Decoder::from(msg.iter().copied());
|
let decoder = Decoder::from(msg.iter().copied());
|
||||||
match decoder.collect() {
|
match decoder.collect() {
|
||||||
Ok(v) => Ok(String::from_utf8(v).unwrap()),
|
Ok(v) => Ok(String::from_utf8(v).unwrap()),
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
extern crate rusty_dsp;
|
||||||
|
|
||||||
|
use rusty_dsp::error::DspError;
|
||||||
|
|
||||||
|
pub struct BitGenerator<'a> {
|
||||||
|
bit_pos: usize,
|
||||||
|
current_byte: u8,
|
||||||
|
iterator: Box<dyn Iterator<Item = Result<u8, DspError>> + 'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BitGenerator<'a> {
|
||||||
|
pub fn from<I>(iterator: I) -> BitGenerator<'a>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = Result<u8, DspError>> + 'a,
|
||||||
|
{
|
||||||
|
BitGenerator {
|
||||||
|
bit_pos: 0,
|
||||||
|
current_byte: 0,
|
||||||
|
iterator: Box::new(iterator),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for BitGenerator<'a> {
|
||||||
|
type Item = Result<bool, DspError>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.bit_pos == 0 {
|
||||||
|
let byte = match self.iterator.next() {
|
||||||
|
None => return None,
|
||||||
|
Some(Err(e)) => return Some(Err(e)),
|
||||||
|
Some(Ok(b)) => b,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.current_byte = 0b11000000 | (byte << 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
let bit = (self.current_byte & (1 << self.bit_pos)) != 0;
|
||||||
|
self.bit_pos = (self.bit_pos + 1) % 8;
|
||||||
|
|
||||||
|
Some(Ok(bit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bitgenerator() {
|
||||||
|
let input = vec![0b11111, 0b01010, 0b00000];
|
||||||
|
|
||||||
|
let generator = BitGenerator::from(input.into_iter().map(|x| Ok(x)));
|
||||||
|
|
||||||
|
let result_data: Result<Vec<bool>, DspError> = generator.collect();
|
||||||
|
assert_eq!(
|
||||||
|
result_data,
|
||||||
|
Ok(vec![
|
||||||
|
true, true, true, true, true, true, true, true, true, false, true, false, true,
|
||||||
|
false, true, true, true, false, false, false, false, false, true, true
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
extern crate rusty_dsp;
|
||||||
|
|
||||||
|
use rusty_dsp::error::DspError;
|
||||||
|
|
||||||
|
pub struct BitUpsampler<'a> {
|
||||||
|
bit_length: f64,
|
||||||
|
current_bit_length: usize,
|
||||||
|
pos: usize,
|
||||||
|
residual_error: f64,
|
||||||
|
current_bit: bool,
|
||||||
|
iterator: Box<dyn Iterator<Item = Result<bool, DspError>> + 'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BitUpsampler<'a> {
|
||||||
|
pub fn from<I>(iterator: I, sampling_rate: f64, baud_rate: f64) -> BitUpsampler<'a>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = Result<bool, DspError>> + 'a,
|
||||||
|
{
|
||||||
|
BitUpsampler {
|
||||||
|
bit_length: sampling_rate / baud_rate,
|
||||||
|
current_bit_length: 0,
|
||||||
|
residual_error: 0.0,
|
||||||
|
pos: 0,
|
||||||
|
current_bit: false,
|
||||||
|
iterator: Box::new(iterator),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for BitUpsampler<'a> {
|
||||||
|
type Item = Result<bool, DspError>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.pos >= self.current_bit_length {
|
||||||
|
self.current_bit = match self.iterator.next() {
|
||||||
|
None => return None,
|
||||||
|
Some(Err(e)) => return Some(Err(e)),
|
||||||
|
Some(Ok(b)) => b,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.current_bit_length = self.bit_length.floor() as usize;
|
||||||
|
self.residual_error += self.bit_length - self.bit_length.floor();
|
||||||
|
if self.residual_error >= 1.0 {
|
||||||
|
self.residual_error -= 1.0;
|
||||||
|
self.current_bit_length += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pos += 1;
|
||||||
|
Some(Ok(self.current_bit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_baurate_error_correction() {
|
||||||
|
let input = vec![true, false, true, false];
|
||||||
|
|
||||||
|
let upsampler = BitUpsampler::from(input.into_iter().map(|x| Ok(x)), 10.0, 4.0);
|
||||||
|
|
||||||
|
let result_data: Result<Vec<bool>, DspError> = upsampler.collect();
|
||||||
|
assert_eq!(
|
||||||
|
result_data,
|
||||||
|
Ok(vec![
|
||||||
|
true, true, false, false, false, true, true, false, false, false
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
20
src/main.rs
20
src/main.rs
|
@ -1,8 +1,26 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
extern crate rusty_dsp;
|
||||||
|
|
||||||
|
use rusty_dsp::multiply::MultiplyConst;
|
||||||
|
use rusty_dsp::sinks::SoundCardSink;
|
||||||
|
use rusty_dsp::sources::VFOSource;
|
||||||
|
|
||||||
mod baudot;
|
mod baudot;
|
||||||
|
mod bitgenerator;
|
||||||
|
mod bitupsampler;
|
||||||
|
mod symbolgenerator;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
let data = " kaufen sie jede woche vier gute bequeme pelze xy 1234567890 ";
|
||||||
|
|
||||||
|
let encoder = baudot::Encoder::from(data.to_ascii_uppercase().into_bytes().into_iter());
|
||||||
|
let bitgenerator = bitgenerator::BitGenerator::from(encoder);
|
||||||
|
let bitresampler = bitupsampler::BitUpsampler::from(bitgenerator, 48000.0, 45.5);
|
||||||
|
let symbolgenerator = symbolgenerator::SymbolGenerator::from(bitresampler, 2125.0, 1955.0);
|
||||||
|
let source = VFOSource::new(symbolgenerator, 48000.0);
|
||||||
|
let mult = MultiplyConst::from(source, 0.3);
|
||||||
|
let mut sink = SoundCardSink::from(mult, 48000);
|
||||||
|
|
||||||
|
sink.start().unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
extern crate rusty_dsp;
|
||||||
|
|
||||||
|
use rusty_dsp::error::DspError;
|
||||||
|
|
||||||
|
pub struct SymbolGenerator<'a> {
|
||||||
|
space_freq: f32,
|
||||||
|
mark_freq: f32,
|
||||||
|
iterator: Box<dyn Iterator<Item = Result<bool, DspError>> + 'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SymbolGenerator<'a> {
|
||||||
|
pub fn from<I>(iterator: I, space_freq: f32, mark_freq: f32) -> SymbolGenerator<'a>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = Result<bool, DspError>> + 'a,
|
||||||
|
{
|
||||||
|
SymbolGenerator {
|
||||||
|
space_freq: space_freq,
|
||||||
|
mark_freq: mark_freq,
|
||||||
|
iterator: Box::new(iterator),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for SymbolGenerator<'a> {
|
||||||
|
type Item = Result<f32, DspError>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
match self.iterator.next() {
|
||||||
|
Some(Ok(b)) => {
|
||||||
|
if b {
|
||||||
|
Some(Ok(self.mark_freq))
|
||||||
|
} else {
|
||||||
|
Some(Ok(self.space_freq))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
Some(Err(e)) => Some(Err(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_symbolgenerator() {
|
||||||
|
let input = vec![true, false, true];
|
||||||
|
|
||||||
|
let generator = SymbolGenerator::from(input.into_iter().map(|x| Ok(x)), 23000.0, 42000.0);
|
||||||
|
|
||||||
|
let result_data: Result<Vec<f32>, DspError> = generator.collect();
|
||||||
|
assert_eq!(result_data, Ok(vec![42000.0, 23000.0, 42000.0]));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue