]> code.octet-stream.net Git - m17rt/blob - demod/src/main.rs
78ff2b0732086a4ea0911b57ecd70274b095d19e
[m17rt] / demod / src / main.rs
1 use cpal::traits::DeviceTrait;
2 use cpal::traits::HostTrait;
3 use cpal::traits::StreamTrait;
4 use cpal::{SampleFormat, SampleRate};
5 use log::debug;
6 use m17core::{
7 modem::{Demodulator, SoftDemodulator},
8 protocol::{Frame, LichCollection},
9 };
10 use std::{fs::File, io::Read};
11
12 pub fn run_my_decode() {
13 let file = File::open("../../Data/test_vk7xt.rrc").unwrap();
14 let mut input = file;
15 let mut baseband = vec![];
16 input.read_to_end(&mut baseband).unwrap();
17
18 let mut lich = LichCollection::new();
19 let mut codec2_data = vec![];
20 let mut modem = SoftDemodulator::new();
21
22 for pair in baseband.chunks(2) {
23 let sample: i16 = i16::from_le_bytes([pair[0], pair[1]]);
24 if let Some(frame) = modem.demod(sample) {
25 debug!("Modem demodulated frame: {:?}", frame);
26 if let Frame::Stream(s) = frame {
27 for b in s.stream_data {
28 codec2_data.push(b);
29
30 let valid_before = lich.valid_segments();
31 lich.set_segment(s.lich_idx, s.lich_part);
32 let valid_after = lich.valid_segments();
33 if valid_before != valid_after {
34 debug!("Valid lich segments: {}", lich.valid_segments());
35 }
36 if valid_before == 5 && valid_after == 6 {
37 if let Some(l) = lich.try_assemble() {
38 debug!("Assembled complete lich: {l:?}");
39 }
40 }
41 }
42 if s.end_of_stream {
43 debug!("len of codec2 data: {}", codec2_data.len());
44 assert_eq!(codec2_data.len(), 1504);
45
46 let samples =
47 m17codec2::decode_codec2(&codec2_data, "../../Data/speech_out.raw");
48 let host = cpal::default_host();
49 let def = host.default_output_device().unwrap();
50 let mut configs = def.supported_output_configs().unwrap();
51 let config = configs
52 .find(|c| c.channels() == 1 && c.sample_format() == SampleFormat::I16)
53 .unwrap()
54 .with_sample_rate(SampleRate(8000));
55 let mut counter = 0;
56 let mut index = 0;
57 let stream = def
58 .build_output_stream(
59 &config.into(),
60 move |data: &mut [i16], info: &cpal::OutputCallbackInfo| {
61 debug!(
62 "callback {:?} playback {:?}",
63 info.timestamp().callback,
64 info.timestamp().playback
65 );
66 println!(
67 "iteration {counter} asked for {} samples at time {}",
68 data.len(),
69 std::time::SystemTime::now()
70 .duration_since(std::time::UNIX_EPOCH)
71 .unwrap()
72 .as_millis()
73 );
74 counter += 1;
75 let qty = data.len().min(samples.len() - index);
76 println!("providing {qty} samples");
77 data[0..qty].copy_from_slice(&samples[index..(index + qty)]);
78 index += qty;
79 },
80 move |_e| {
81 println!("error occurred");
82 },
83 None,
84 )
85 .unwrap();
86 stream.play().unwrap();
87
88 std::thread::sleep(std::time::Duration::from_secs(10));
89 }
90 }
91 }
92 }
93 }
94
95 pub fn cpal_test() {
96 let host = cpal::default_host();
97 for d in host.devices().unwrap() {
98 println!("Found card: {:?}", d.name().unwrap());
99 }
100 let def = host.default_output_device().unwrap();
101 println!("the default output device is: {}", def.name().unwrap());
102
103 for c in def.supported_output_configs().unwrap() {
104 println!("config supported: {:?}", c);
105 }
106
107 println!("all supported output configs shown");
108 }
109
110 fn main() {
111 env_logger::init();
112 run_my_decode();
113 //cpal_test();
114 }