1use crate::image::Robot36Image;
2use core::ops::Mul;
3use num_complex::Complex;
4
5pub struct Encoder {
7 image: Robot36Image,
8 rate: u64,
9 y_ticks: u64,
10 uv_ticks: u64,
11 sync_porch_ticks: u64,
12 porch_ticks: u64,
13 horizontal_sync_ticks: u64,
14 seperator_ticks: u64,
15}
16
17const SYNC_PORCH_SECS: f64 = 0.003;
18const PORCH_SECS: f64 = 0.0015;
19const Y_SECS: f64 = 0.088;
20const UV_SECS: f64 = 0.044;
21const HORIZONTAL_SYNC_SECS: f64 = 0.009;
22const SEPARATOR_SECS: f64 = 0.0045;
23
24impl Encoder {
25 pub fn new(image: Robot36Image, rate: u64) -> Self {
28 Encoder {
29 image,
30 rate,
31 y_ticks: (rate as f64 * Y_SECS) as u64,
32 uv_ticks: (rate as f64 * UV_SECS) as u64,
33 sync_porch_ticks: (rate as f64 * SYNC_PORCH_SECS) as u64,
34 porch_ticks: (rate as f64 * PORCH_SECS) as u64,
35 horizontal_sync_ticks: (rate as f64 * HORIZONTAL_SYNC_SECS) as u64,
36 seperator_ticks: (rate as f64 * SEPARATOR_SECS) as u64,
37 }
38 }
39
40 pub fn encode(&self) -> impl Iterator<Item = i16> + '_ {
43 Signal::new(
44 ComplexOscilator::new(self.rate),
45 self.vis_header().chain(self.codificated_image()),
46 )
47 }
48
49 fn vis_header(&self) -> impl Iterator<Item = f64> + '_ {
50 let header_frequencies: Vec<(f64, f64)> = vec![
51 (self.rate as f64 * 0.3, 0.0),
52 (1900.0, 0.3),
53 (1200.0, 0.01),
54 (1900.0, 0.3),
55 (1200.0, 0.03),
56 (1300.0, 0.03),
57 (1300.0, 0.03),
58 (1300.0, 0.03),
59 (1100.0, 0.03),
60 (1300.0, 0.03),
61 (1300.0, 0.03),
62 (1300.0, 0.03),
63 (1100.0, 0.03),
64 (1200.0, 0.03),
65 ];
66 header_frequencies.into_iter().flat_map(|frequency| {
67 get_frequency_iter((self.rate as f64 * frequency.1) as u64, frequency.0)
68 })
69 }
70
71 fn codificated_image(&self) -> impl Iterator<Item = f64> + '_ {
72 (0..self.image.get_height()).step_by(2).flat_map(|y| {
73 get_frequency_iter(self.horizontal_sync_ticks, 1200.0)
74 .chain(get_frequency_iter(self.sync_porch_ticks, 1500.0))
75 .chain(self.add_y_scan(y))
76 .chain(get_frequency_iter(self.seperator_ticks, 1500.0))
77 .chain(get_frequency_iter(self.porch_ticks, 1900.0))
78 .chain(self.add_v_scan(y))
79 .chain(get_frequency_iter(self.horizontal_sync_ticks, 1200.0))
80 .chain(get_frequency_iter(self.sync_porch_ticks, 1500.0))
81 .chain(self.add_y_scan(y + 1))
82 .chain(get_frequency_iter(self.seperator_ticks, 2300.0))
83 .chain(get_frequency_iter(self.porch_ticks, 1900.0))
84 .chain(self.add_u_scan(y + 1))
85 })
86 }
87
88 fn add_y_scan(&self, y: usize) -> impl Iterator<Item = f64> + '_ {
89 (0..self.y_ticks).map(move |tick| {
90 let x = self.get_x_position(tick, self.y_ticks);
91 1500.0 + 800.0 * f64::from(self.image.get_y(x, y)) / 255.0
92 })
93 }
94
95 fn add_v_scan(&self, y: usize) -> impl Iterator<Item = f64> + '_ {
96 (0..self.uv_ticks).map(move |tick| {
97 let x0 = self.get_x_position(tick, self.uv_ticks);
98 let x1 = (x0 + 1).max(self.image.get_width() - 1);
99 let yuv_v = ((u16::from(self.image.get_v(x0, y)) + u16::from(self.image.get_v(x1, y)))
100 / 2) as f64;
101 1500.0 + 800.0 * (yuv_v / 255.0)
102 })
103 }
104
105 fn add_u_scan(&self, y: usize) -> impl Iterator<Item = f64> + '_ {
106 (0..self.uv_ticks).map(move |tick| {
107 let x0 = self.get_x_position(tick, self.uv_ticks);
108 let x1 = (x0 + 1).max(self.image.get_width() - 1);
109 let yuv_u = ((u16::from(self.image.get_u(x0, y - 1))
110 + u16::from(self.image.get_u(x1, y - 1)))
111 / 2) as f64;
112 1500.0 + 800.0 * (yuv_u / 255.0)
113 })
114 }
115
116 fn get_x_position(&self, tick: u64, ticks: u64) -> usize {
117 ((self.image.get_width() - 1) as f64 * tick as f64 / ticks as f64) as usize
118 }
119}
120
121fn get_frequency_iter(number_of_ticks: u64, frequency: f64) -> impl Iterator<Item = f64> {
122 (0..number_of_ticks).map(move |_| frequency)
123}
124
125struct ComplexOscilator {
126 complex_number: Complex<f64>,
127 hz_2_rad: f64,
128}
129
130impl ComplexOscilator {
131 pub fn new(rate: u64) -> Self {
132 Self {
133 complex_number: Complex::new(0.5, 0.5),
134 hz_2_rad: (2.0 * std::f64::consts::PI as f64) / rate as f64,
135 }
136 }
137
138 pub fn add_freq(&mut self, freq: f64) {
139 let exponetial: Complex<f64> = Complex::new(0.0, freq * self.hz_2_rad);
140 self.complex_number = self.complex_number.mul(exponetial.exp());
141 }
142}
143
144struct Signal<T>
145where
146 T: Iterator<Item = f64>,
147{
148 complex_oscilator: ComplexOscilator,
149 frequencies: T,
150}
151
152impl<T> Signal<T>
153where
154 T: Iterator<Item = f64>,
155{
156 pub fn new(complex_oscilator: ComplexOscilator, frequencies: T) -> Self {
157 Self {
158 complex_oscilator,
159 frequencies,
160 }
161 }
162}
163
164impl<T> Iterator for Signal<T>
165where
166 T: Iterator<Item = f64>,
167{
168 type Item = i16;
169 fn next(&mut self) -> Option<Self::Item> {
170 match self.frequencies.next() {
171 None => None,
172 Some(freq) => {
173 self.complex_oscilator.add_freq(freq);
174 Some((self.complex_oscilator.complex_number.re * std::i16::MAX as f64) as i16)
175 }
176 }
177 }
178}