+ ModulatorFrame::Preamble { tx_delay } => {
+ // TODO: Stop assuming 48 kHz everywhere. 24 kHz should be fine too.
+ let tx_delay_samples = tx_delay as usize * 480;
+ // TxDelay and output latency have the same effect - account for whichever is bigger.
+ // We want our sound card DAC hitting preamble right when PTT fully engages.
+ // The modulator calls the shots here - TNC hands over Preamble and asserts PTT, then
+ // waits to be told when transmission will be complete. This estimate will not be
+ // made and delivered until we generate the EOT frame.
+ self.tx_delay_padding = tx_delay_samples.max(self.output_latency);
+
+ // We should be starting from a filter_win of zeroes
+ // Transmission is effectively smeared by 80 taps and we'll capture that in EOT
+ for dibit in generate_preamble() {
+ self.push_sample(dibit);
+ }
+ }
+ ModulatorFrame::Lsf(lsf_frame) => {
+ for dibit in encode_lsf(&lsf_frame) {
+ self.push_sample(dibit);
+ }
+ }
+ ModulatorFrame::Stream(stream_frame) => {
+ for dibit in encode_stream(&stream_frame) {
+ self.push_sample(dibit);
+ }
+ }
+ ModulatorFrame::Packet(packet_frame) => {
+ for dibit in encode_packet(&packet_frame) {
+ self.push_sample(dibit);
+ }
+ }
+ ModulatorFrame::EndOfTransmission => {
+ for dibit in generate_end_of_transmission() {
+ self.push_sample(dibit);
+ }
+ for _ in 0..80 {
+ // This is not a real symbol value
+ // However we want to flush the filter
+ self.push_sample(0f32);
+ }
+ self.calculate_tx_end = true;