Mercurial > dsp > rdsp
changeset 1:9a493071e98f
Move lib source into a subdir
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Wed, 20 May 2020 23:15:44 -0400 |
parents | e15b331f3209 |
children | 72faa753b634 |
files | Cargo.toml src/fmt.rs src/fmt/cf32.rs src/fmt/cu8.rs src/io.rs src/io/cf32.rs src/io/cu8.rs src/lib.rs src/lib/fmt.rs src/lib/fmt/cf32.rs src/lib/fmt/cu8.rs src/lib/io.rs src/lib/io/cf32.rs src/lib/io/cu8.rs src/lib/lib.rs |
diffstat | 15 files changed, 441 insertions(+), 437 deletions(-) [+] |
line wrap: on
line diff
--- a/Cargo.toml Sat May 09 11:17:08 2020 -0400 +++ b/Cargo.toml Wed May 20 23:15:44 2020 -0400 @@ -5,6 +5,10 @@ edition = "2018" license = "MIT" +[lib] +name = "rdsp" +path = "src/lib/lib.rs" + [dependencies] num-complex = "*" num-traits = "*"
--- a/src/fmt.rs Sat May 09 11:17:08 2020 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -pub mod cf32; -pub mod cu8;
--- a/src/fmt/cf32.rs Sat May 09 11:17:08 2020 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -use std::convert::TryInto; -use super::super::IQSample; - -pub const SAMPLE_SIZE: usize = std::mem::size_of::<f32>() * 2; - -pub fn raw_to_iqsample(sample: &[u8; SAMPLE_SIZE]) -> IQSample { - IQSample::new(f32::from_le_bytes(sample[..4].try_into().unwrap()) as f64, - f32::from_le_bytes(sample[4..].try_into().unwrap()) as f64) -}
--- a/src/fmt/cu8.rs Sat May 09 11:17:08 2020 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -use super::super::IQSample; - -pub const SAMPLE_SIZE: usize = std::mem::size_of::<u8>() * 2; - -pub fn raw_to_iqsample(sample: &[u8; SAMPLE_SIZE]) -> IQSample { - let i = (((sample[0] ^ 0x80) as i8) as f64) / 128.; - let q = (((sample[1] ^ 0x80) as i8) as f64) / 128.; - - IQSample::new(i, q) -} - -#[cfg(test)] -mod tests { - use super::super::super::IQSample; - - /* - * minimum and maximum values we should ever encouter - * - * This is not balanced because we have an even number of possible input values (256) one of - * which must represent 0. This leaves 255 values which cannot be divided in half between - * positive and negative "sides". - */ - const MIN: f64 = -128. / 128.; - const MAX: f64 = 127. / 128.; - - #[test] - fn test_raw_to_iqsample_specific() { - let test_cases = vec![ - ([ 0x80, 0x80 ], IQSample::new(0., 0.)), - ([ 0x00, 0xff ], IQSample::new(MIN, MAX)), - ([ 0xff, 0x00 ], IQSample::new(MAX, MIN)), - ]; - - for (input, expected) in test_cases.iter() { - let got = super::raw_to_iqsample(input); - - assert_eq!(got, *expected); - } - } - - #[test] - fn test_raw_to_iqsample_auto() { - /* convert an i8 to u8 */ - fn cvt(v: i8) -> u8 { - ((v as i16) + 128) as u8 - } - - for i in -128..127 { - for q in -128..127 { - let input = [ cvt(i), cvt(q) ]; - println!("{} {} => {:?}", i,q,input); - let i = (i as f64) / 128.; - let q = (q as f64) / 128.; - - let got = super::raw_to_iqsample(&input); - - assert_eq!(got, IQSample::new(i, q)); - } - } - } -}
--- a/src/io.rs Sat May 09 11:17:08 2020 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -mod cf32; -mod cu8; - -use std::iter::Iterator; -use std::fs::File; -use std::io::BufReader; -use std::path::Path; -use num_traits::identities::Zero; - -pub use self::cf32::CF32File; -pub use self::cu8::CU8File; - -use super::IQSample; - -pub trait IQFile { - type SamplesIter : IQSampleIter + Iterator<Item=IQSample> + Sized; - - fn path(&self) -> &Path; - - /* how many bytes we need for 1 second of data */ - fn capacity(&self, secs: usize) -> usize; - - fn buffered_reader(&self) -> Result<BufReader<File>, std::io::Error> { - let f = File::open(self.path())?; - - Ok(BufReader::with_capacity(self.capacity(1), f)) - } - - fn chunks(&self, chunk_size: usize) -> Result<IQChunkIter<Self::SamplesIter>, std::io::Error> { - Ok(IQChunkIter::new(self.samples()?, chunk_size)) - } - - fn samples(&self) -> Result<Self::SamplesIter, std::io::Error>; -} - -pub trait IQSampleIter : Iterator { } - -pub struct IQChunkIter<T: IQSampleIter<Item=IQSample>> { - samples: T, - chunk: Vec<IQSample>, -} - -impl<T: IQSampleIter<Item=IQSample>> IQChunkIter<T> { - fn new(samples: T, chunk_size: usize) -> IQChunkIter<T> { - let mut chunk = Vec::<IQSample>::with_capacity(chunk_size); - chunk.resize(chunk_size, IQSample::zero()); - - IQChunkIter { - samples: samples, - chunk: chunk, - } - } -} - -impl<T: IQSampleIter<Item=IQSample>> Iterator for IQChunkIter<T> { - type Item = Vec<IQSample>; - - fn next(&mut self) -> Option<Vec<IQSample>> { - let len = self.chunk.len(); - - for i in 0..len { - match self.samples.next() { - None => { return None; }, - Some(v) => { self.chunk[i] = v; }, - } - } - - /* FIXME: ideally we could return a reference to the buffer to avoid a memory allocation copy */ - return Some(self.chunk.clone()) - } -}
--- a/src/io/cf32.rs Sat May 09 11:17:08 2020 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -use std::path::{Path, PathBuf}; -use std::fs::File; -use std::io::BufReader; -use std::io::Read; - -use super::super::fmt::cf32::{SAMPLE_SIZE, raw_to_iqsample}; -use super::super::IQSample; -use super::IQFile; -use super::IQSampleIter; - -pub struct CF32File { - _freq: u64, - rate: u64, - path: PathBuf, -} - -impl CF32File { - pub fn new<P: AsRef<Path>>(fname: P, freq: u64, rate: u64) -> Result<CF32File, std::io::Error> { - let mut path = PathBuf::new(); - path.push(fname); - - Ok(CF32File { - _freq: freq, - rate: rate, - path: path, - }) - } -} - -impl IQFile for CF32File { - type SamplesIter = CF32SampleIter; - - fn path(&self) -> &Path { - self.path.as_path() - } - - fn capacity(&self, secs: usize) -> usize { - (self.rate as usize) * SAMPLE_SIZE * secs - } - - fn samples(&self) -> Result<Self::SamplesIter, std::io::Error> { - let reader = self.buffered_reader()?; - - Ok(CF32SampleIter { - reader: reader, - }) - } -} - -pub struct CF32SampleIter { - reader: BufReader<File>, -} - -impl Iterator for CF32SampleIter { - type Item = IQSample; - - fn next(&mut self) -> Option<IQSample> { - let mut buffer = [0u8; SAMPLE_SIZE]; - - if self.reader.read_exact(&mut buffer).is_err() { - return None; - } - - Some(raw_to_iqsample(&buffer)) - } -} - -impl IQSampleIter for CF32SampleIter { }
--- a/src/io/cu8.rs Sat May 09 11:17:08 2020 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -use std::path::{Path, PathBuf}; -use std::fs::File; -use std::io::BufReader; -use std::io::Read; - -use super::super::fmt::cu8::{SAMPLE_SIZE, raw_to_iqsample}; -use super::super::IQSample; -use super::IQFile; -use super::IQSampleIter; - -pub struct CU8File { - _freq: u64, - rate: u64, - path: PathBuf, -} - -impl CU8File { - pub fn new<P: AsRef<Path>>(fname: P, freq: u64, rate: u64) -> Result<CU8File, std::io::Error> { - let mut path = PathBuf::new(); - path.push(fname); - - Ok(CU8File { - _freq: freq, - rate: rate, - path: path, - }) - } -} - -impl IQFile for CU8File { - type SamplesIter = CU8SampleIter; - - fn path(&self) -> &Path { - self.path.as_path() - } - - fn capacity(&self, secs: usize) -> usize { - (self.rate as usize) * SAMPLE_SIZE * secs - } - - fn samples(&self) -> Result<Self::SamplesIter, std::io::Error> { - let reader = self.buffered_reader()?; - - Ok(CU8SampleIter { - reader: reader, - }) - } -} - -pub struct CU8SampleIter { - reader: BufReader<File>, -} - -impl Iterator for CU8SampleIter { - type Item = IQSample; - - fn next(&mut self) -> Option<IQSample> { - let mut buffer = [0u8; SAMPLE_SIZE]; - - if self.reader.read_exact(&mut buffer).is_err() { - return None; - } - - Some(raw_to_iqsample(&buffer)) - } -} - -impl IQSampleIter for CU8SampleIter { }
--- a/src/lib.rs Sat May 09 11:17:08 2020 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -pub mod io; -pub mod fmt; - -pub type IQSample = num_complex::Complex<f64>;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/fmt.rs Wed May 20 23:15:44 2020 -0400 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +pub mod cf32; +pub mod cu8;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/fmt/cf32.rs Wed May 20 23:15:44 2020 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use std::convert::TryInto; +use super::super::IQSample; + +pub const SAMPLE_SIZE: usize = std::mem::size_of::<f32>() * 2; + +pub fn raw_to_iqsample(sample: &[u8; SAMPLE_SIZE]) -> IQSample { + IQSample::new(f32::from_le_bytes(sample[..4].try_into().unwrap()) as f64, + f32::from_le_bytes(sample[4..].try_into().unwrap()) as f64) +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/fmt/cu8.rs Wed May 20 23:15:44 2020 -0400 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use super::super::IQSample; + +pub const SAMPLE_SIZE: usize = std::mem::size_of::<u8>() * 2; + +pub fn raw_to_iqsample(sample: &[u8; SAMPLE_SIZE]) -> IQSample { + let i = (((sample[0] ^ 0x80) as i8) as f64) / 128.; + let q = (((sample[1] ^ 0x80) as i8) as f64) / 128.; + + IQSample::new(i, q) +} + +#[cfg(test)] +mod tests { + use super::super::super::IQSample; + + /* + * minimum and maximum values we should ever encouter + * + * This is not balanced because we have an even number of possible input values (256) one of + * which must represent 0. This leaves 255 values which cannot be divided in half between + * positive and negative "sides". + */ + const MIN: f64 = -128. / 128.; + const MAX: f64 = 127. / 128.; + + #[test] + fn test_raw_to_iqsample_specific() { + let test_cases = vec![ + ([ 0x80, 0x80 ], IQSample::new(0., 0.)), + ([ 0x00, 0xff ], IQSample::new(MIN, MAX)), + ([ 0xff, 0x00 ], IQSample::new(MAX, MIN)), + ]; + + for (input, expected) in test_cases.iter() { + let got = super::raw_to_iqsample(input); + + assert_eq!(got, *expected); + } + } + + #[test] + fn test_raw_to_iqsample_auto() { + /* convert an i8 to u8 */ + fn cvt(v: i8) -> u8 { + ((v as i16) + 128) as u8 + } + + for i in -128..127 { + for q in -128..127 { + let input = [ cvt(i), cvt(q) ]; + println!("{} {} => {:?}", i,q,input); + let i = (i as f64) / 128.; + let q = (q as f64) / 128.; + + let got = super::raw_to_iqsample(&input); + + assert_eq!(got, IQSample::new(i, q)); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/io.rs Wed May 20 23:15:44 2020 -0400 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +mod cf32; +mod cu8; + +use std::iter::Iterator; +use std::fs::File; +use std::io::BufReader; +use std::path::Path; +use num_traits::identities::Zero; + +pub use self::cf32::CF32File; +pub use self::cu8::CU8File; + +use super::IQSample; + +pub trait IQFile { + type SamplesIter : IQSampleIter + Iterator<Item=IQSample> + Sized; + + fn path(&self) -> &Path; + + /* how many bytes we need for 1 second of data */ + fn capacity(&self, secs: usize) -> usize; + + fn buffered_reader(&self) -> Result<BufReader<File>, std::io::Error> { + let f = File::open(self.path())?; + + Ok(BufReader::with_capacity(self.capacity(1), f)) + } + + fn chunks(&self, chunk_size: usize) -> Result<IQChunkIter<Self::SamplesIter>, std::io::Error> { + Ok(IQChunkIter::new(self.samples()?, chunk_size)) + } + + fn samples(&self) -> Result<Self::SamplesIter, std::io::Error>; +} + +pub trait IQSampleIter : Iterator { } + +pub struct IQChunkIter<T: IQSampleIter<Item=IQSample>> { + samples: T, + chunk: Vec<IQSample>, +} + +impl<T: IQSampleIter<Item=IQSample>> IQChunkIter<T> { + fn new(samples: T, chunk_size: usize) -> IQChunkIter<T> { + let mut chunk = Vec::<IQSample>::with_capacity(chunk_size); + chunk.resize(chunk_size, IQSample::zero()); + + IQChunkIter { + samples: samples, + chunk: chunk, + } + } +} + +impl<T: IQSampleIter<Item=IQSample>> Iterator for IQChunkIter<T> { + type Item = Vec<IQSample>; + + fn next(&mut self) -> Option<Vec<IQSample>> { + let len = self.chunk.len(); + + for i in 0..len { + match self.samples.next() { + None => { return None; }, + Some(v) => { self.chunk[i] = v; }, + } + } + + /* FIXME: ideally we could return a reference to the buffer to avoid a memory allocation copy */ + return Some(self.chunk.clone()) + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/io/cf32.rs Wed May 20 23:15:44 2020 -0400 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use std::path::{Path, PathBuf}; +use std::fs::File; +use std::io::BufReader; +use std::io::Read; + +use super::super::fmt::cf32::{SAMPLE_SIZE, raw_to_iqsample}; +use super::super::IQSample; +use super::IQFile; +use super::IQSampleIter; + +pub struct CF32File { + _freq: u64, + rate: u64, + path: PathBuf, +} + +impl CF32File { + pub fn new<P: AsRef<Path>>(fname: P, freq: u64, rate: u64) -> Result<CF32File, std::io::Error> { + let mut path = PathBuf::new(); + path.push(fname); + + Ok(CF32File { + _freq: freq, + rate: rate, + path: path, + }) + } +} + +impl IQFile for CF32File { + type SamplesIter = CF32SampleIter; + + fn path(&self) -> &Path { + self.path.as_path() + } + + fn capacity(&self, secs: usize) -> usize { + (self.rate as usize) * SAMPLE_SIZE * secs + } + + fn samples(&self) -> Result<Self::SamplesIter, std::io::Error> { + let reader = self.buffered_reader()?; + + Ok(CF32SampleIter { + reader: reader, + }) + } +} + +pub struct CF32SampleIter { + reader: BufReader<File>, +} + +impl Iterator for CF32SampleIter { + type Item = IQSample; + + fn next(&mut self) -> Option<IQSample> { + let mut buffer = [0u8; SAMPLE_SIZE]; + + if self.reader.read_exact(&mut buffer).is_err() { + return None; + } + + Some(raw_to_iqsample(&buffer)) + } +} + +impl IQSampleIter for CF32SampleIter { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/io/cu8.rs Wed May 20 23:15:44 2020 -0400 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use std::path::{Path, PathBuf}; +use std::fs::File; +use std::io::BufReader; +use std::io::Read; + +use super::super::fmt::cu8::{SAMPLE_SIZE, raw_to_iqsample}; +use super::super::IQSample; +use super::IQFile; +use super::IQSampleIter; + +pub struct CU8File { + _freq: u64, + rate: u64, + path: PathBuf, +} + +impl CU8File { + pub fn new<P: AsRef<Path>>(fname: P, freq: u64, rate: u64) -> Result<CU8File, std::io::Error> { + let mut path = PathBuf::new(); + path.push(fname); + + Ok(CU8File { + _freq: freq, + rate: rate, + path: path, + }) + } +} + +impl IQFile for CU8File { + type SamplesIter = CU8SampleIter; + + fn path(&self) -> &Path { + self.path.as_path() + } + + fn capacity(&self, secs: usize) -> usize { + (self.rate as usize) * SAMPLE_SIZE * secs + } + + fn samples(&self) -> Result<Self::SamplesIter, std::io::Error> { + let reader = self.buffered_reader()?; + + Ok(CU8SampleIter { + reader: reader, + }) + } +} + +pub struct CU8SampleIter { + reader: BufReader<File>, +} + +impl Iterator for CU8SampleIter { + type Item = IQSample; + + fn next(&mut self) -> Option<IQSample> { + let mut buffer = [0u8; SAMPLE_SIZE]; + + if self.reader.read_exact(&mut buffer).is_err() { + return None; + } + + Some(raw_to_iqsample(&buffer)) + } +} + +impl IQSampleIter for CU8SampleIter { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/lib.rs Wed May 20 23:15:44 2020 -0400 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +pub mod io; +pub mod fmt; + +pub type IQSample = num_complex::Complex<f64>;