### FAX Transmission (T.30 Protocol) Source: https://context7.com/freeswitch/spandsp/llms.txt Provides a complete example for sending a FAX using the T.30 protocol, including modem configuration, ECM error correction, and a processing loop. ```c #include /* Phase E completion callback */ void fax_phase_e_handler(void *user_data, int result) { t30_stats_t stats; fax_state_t *fax = (fax_state_t *)user_data; t30_state_t *t30 = fax_get_t30_state(fax); t30_get_transfer_statistics(t30, &stats); printf("FAX completed: %d pages, %d bps, result=%d\n", stats.pages_tx + stats.pages_rx, stats.bit_rate, result); } /* Initialize FAX for sending (calling_party=true) */ fax_state_t *fax = fax_init(NULL, true); t30_state_t *t30 = fax_get_t30_state(fax); /* Set local identification */ t30_set_tx_ident(t30, "+1 555 1234"); t30_set_tx_page_header_info(t30, "My Company Name"); /* Set supported modems (V.17 + V.29 + V.27ter) */ t30_set_supported_modems(t30, T30_SUPPORT_V17 | T30_SUPPORT_V29 | T30_SUPPORT_V27TER); /* Enable ECM for error correction */ t30_set_ecm_capability(t30, true); /* Set the file to send */ t30_set_tx_file(t30, "document.tif", -1, -1); /* Set completion callback */ t30_set_phase_e_handler(t30, fax_phase_e_handler, fax); /* Main FAX processing loop */ int16_t tx_audio[160], rx_audio[160]; while (t30_call_active(t30)) { /* Generate transmit audio */ int tx_samples = fax_tx(fax, tx_audio, 160); send_to_line(tx_audio, tx_samples); /* Process received audio */ receive_from_line(rx_audio, 160); fax_rx(fax, rx_audio, 160); } fax_free(fax); ``` -------------------------------- ### Perform G.711 Audio Companding Source: https://context7.com/freeswitch/spandsp/llms.txt Provides examples for encoding and decoding linear PCM audio to A-law and u-law formats. Includes both inline single-sample conversion and batch processing using state contexts. ```c #include /* Inline conversion functions for single samples */ int16_t linear_sample = 1000; /* Encode to u-law */ uint8_t ulaw_sample = linear_to_ulaw(linear_sample); /* Decode from u-law */ int16_t decoded = ulaw_to_linear(ulaw_sample); /* Encode to A-law */ uint8_t alaw_sample = linear_to_alaw(linear_sample); /* Decode from A-law */ decoded = alaw_to_linear(alaw_sample); /* Transcode between A-law and u-law */ uint8_t transcoded = alaw_to_ulaw(alaw_sample); transcoded = ulaw_to_alaw(ulaw_sample); /* Batch encoding/decoding using context */ g711_state_t *g711_encoder = g711_init(NULL, G711_ULAW); g711_state_t *g711_decoder = g711_init(NULL, G711_ULAW); int16_t pcm_input[160]; uint8_t encoded[160]; int16_t pcm_output[160]; /* Encode 160 samples (20ms) */ int encoded_bytes = g711_encode(g711_encoder, encoded, pcm_input, 160); /* Decode back to linear */ int decoded_samples = g711_decode(g711_decoder, pcm_output, encoded, encoded_bytes); g711_free(g711_encoder); g711_free(g711_decoder); ``` -------------------------------- ### Implement T.38 FAX over IP transmission in C Source: https://context7.com/freeswitch/spandsp/llms.txt Demonstrates how to initialize a T.38 terminal, configure T.30 parameters for FAX transmission, and process T.38 packets within a main loop. It requires the spandsp.h header and handles packet transmission via a callback mechanism. ```c #include /* T.38 packet transmission callback */ int t38_tx_packet_handler(t38_core_state_t *t38, void *user_data, const uint8_t *buf, int len, int count) { /* Send packet via UDP/UDPTL or TCP */ return send_t38_packet(buf, len); } /* Initialize T.38 terminal for sending */ t38_terminal_state_t *t38 = t38_terminal_init(NULL, true, t38_tx_packet_handler, NULL); t30_state_t *t30 = t38_terminal_get_t30_state(t38); /* Configure T.30 layer (same as analog FAX) */ t30_set_tx_ident(t30, "+1 555 1234"); t30_set_tx_file(t30, "document.tif", -1, -1); t30_set_supported_modems(t30, T30_SUPPORT_V17 | T30_SUPPORT_V29 | T30_SUPPORT_V27TER); t30_set_ecm_capability(t30, true); /* Configure T.38 specific options */ t38_terminal_set_config(t38, 0); /* Use default config */ t38_terminal_set_fill_bit_removal(t38, true); /* Get T.38 core for receiving packets */ t38_core_state_t *t38_core = t38_terminal_get_t38_core_state(t38); /* Main processing loop */ while (t30_call_active(t30)) { /* Drive the T.38 engine (call periodically, e.g., every 20ms) */ t38_terminal_send_timeout(t38, 160); /* 160 samples = 20ms */ /* Process received T.38 packets */ uint8_t rx_packet[1000]; int rx_len = receive_t38_packet(rx_packet, sizeof(rx_packet)); if (rx_len > 0) { t38_core_rx_ifp_packet(t38_core, rx_packet, rx_len, 0); } } t38_terminal_free(t38); ``` -------------------------------- ### Generate DTMF Tones with SpanDSP Source: https://context7.com/freeswitch/spandsp/llms.txt Demonstrates how to initialize a DTMF generator, configure tone levels and timing, and process audio buffers for transmission. It uses the dtmf_tx API to queue and output standard telephony keypad signals. ```c #include /* Initialize DTMF generator */ dtmf_tx_state_t *dtmf_tx = dtmf_tx_init(NULL, NULL, NULL); if (dtmf_tx == NULL) { fprintf(stderr, "Failed to initialize DTMF generator\n"); return -1; } /* Configure tone levels: -10 dBm0 low tone, 2 dB twist */ dtmf_tx_set_level(dtmf_tx, -10, 2); /* Set timing: 100ms on, 100ms off */ dtmf_tx_set_timing(dtmf_tx, 100, 100); /* Queue digits to transmit */ dtmf_tx_put(dtmf_tx, "1234567890*#ABCD", -1); /* Generate audio samples */ int16_t audio_buffer[160]; /* 20ms at 8kHz */ int samples_generated; while ((samples_generated = dtmf_tx(dtmf_tx, audio_buffer, 160)) > 0) { /* Process audio_buffer - write to sound card, RTP, file, etc. */ write_audio(audio_buffer, samples_generated); } /* Cleanup */ dtmf_tx_free(dtmf_tx); ``` -------------------------------- ### FAX Reception Implementation Source: https://context7.com/freeswitch/spandsp/llms.txt Demonstrates how to receive a FAX transmission, save it to a TIFF file, and handle modem negotiation and image decompression. ```c #include /* Initialize FAX for receiving (calling_party=false) */ fax_state_t *fax = fax_init(NULL, false); t30_state_t *t30 = fax_get_t30_state(fax); /* Set local identification */ t30_set_rx_ident(t30, "+1 555 5678"); /* Set output file for received FAX */ t30_set_rx_file(t30, "received_fax.tif", -1); /* Configure supported features */ t30_set_supported_modems(t30, T30_SUPPORT_V17 | T30_SUPPORT_V29 | T30_SUPPORT_V27TER); t30_set_supported_compressions(t30, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6); t30_set_supported_resolutions(t30, T4_RESOLUTION_R8_STANDARD | T4_RESOLUTION_R8_FINE); /* Enable silent audio during idle periods */ fax_set_transmit_on_idle(fax, true); /* Process audio bidirectionally */ int16_t tx_audio[160], rx_audio[160]; while (t30_call_active(t30)) { fax_tx(fax, tx_audio, 160); send_to_line(tx_audio, 160); receive_from_line(rx_audio, 160); fax_rx(fax, rx_audio, 160); } /* Get final statistics */ t30_stats_t stats; t30_get_transfer_statistics(t30, &stats); printf("Received %d pages at %d bps\n", stats.pages_rx, stats.bit_rate); fax_free(fax); ``` -------------------------------- ### Implement HDLC Framing with SpanDSP Source: https://context7.com/freeswitch/spandsp/llms.txt Demonstrates how to initialize HDLC transmitters and receivers for bit-stuffing and CRC validation. It covers callback handling for frame reception and transmitter underflow, as well as bit/byte-level data processing. ```c #include /* HDLC frame received callback */ void hdlc_frame_handler(void *user_data, const uint8_t *frame, int len, int ok) { if (ok) { printf("Received valid HDLC frame, %d bytes\n", len); /* Process frame data */ } else if (len > 0) { printf("Received frame with CRC error\n"); } } /* HDLC transmitter underflow callback */ void hdlc_underflow_handler(void *user_data) { printf("HDLC transmitter needs more data\n"); } /* Initialize HDLC receiver with CRC-16, report bad frames, 3 flag preamble */ hdlc_rx_state_t *hdlc_rx = hdlc_rx_init(NULL, false, true, 3, hdlc_frame_handler, NULL); /* Initialize HDLC transmitter with CRC-16, 2 inter-frame flags */ hdlc_tx_state_t *hdlc_tx = hdlc_tx_init(NULL, false, 2, false, hdlc_underflow_handler, NULL); /* Send preamble flags */ hdlc_tx_flags(hdlc_tx, 10); /* Send 10 flag octets */ /* Transmit a frame */ uint8_t frame_data[] = {0xFF, 0x03, 0x00, 0x01, 0x02, 0x03}; hdlc_tx_frame(hdlc_tx, frame_data, sizeof(frame_data)); /* Get bits for transmission (feed to modem) */ int bit; while ((bit = hdlc_tx_get_bit(hdlc_tx)) >= 0) { send_bit_to_modem(bit); } /* Process received bits from modem */ hdlc_rx_put_bit(hdlc_rx, received_bit); /* Get statistics */ hdlc_rx_stats_t stats; hdlc_rx_get_stats(hdlc_rx, &stats); printf("Good frames: %lu, CRC errors: %lu\n", stats.good_frames, stats.crc_errors); hdlc_rx_free(hdlc_rx); hdlc_tx_free(hdlc_tx); ``` -------------------------------- ### Detect Supervisory Tones with SpanDSP Source: https://context7.com/freeswitch/spandsp/llms.txt Shows how to define frequency and cadence patterns for supervisory tones and register a callback function to handle detection events. The process involves creating a descriptor set, adding tone elements, and processing incoming audio buffers. ```c #include /* Tone detection callback */ void tone_detected(void *user_data, int code, int level, int delay) { const char *tone_names[] = {"Unknown", "Dial tone", "Ringback", "Busy"}; if (code >= 0 && code < 4) { printf("Detected: %s (level=%d dBm0, duration=%d ms)\n", tone_names[code], level, delay); } } /* Create tone descriptor set */ super_tone_rx_descriptor_t *desc = super_tone_rx_make_descriptor(NULL); /* Add US dial tone pattern (350+440Hz, continuous) */ int dial_tone = super_tone_rx_add_tone(desc); super_tone_rx_add_element(desc, dial_tone, 350, 440, 500, 0); /* min 500ms, no max */ /* Add US ringback (440+480Hz, 2s on, 4s off) */ int ringback = super_tone_rx_add_tone(desc); super_tone_rx_add_element(desc, ringback, 440, 480, 1800, 2200); /* on segment */ super_tone_rx_add_element(desc, ringback, -1, -1, 3800, 4200); /* off segment */ /* Add US busy (480+620Hz, 500ms on, 500ms off) */ int busy = super_tone_rx_add_tone(desc); super_tone_rx_add_element(desc, busy, 480, 620, 450, 550); /* on */ super_tone_rx_add_element(desc, busy, -1, -1, 450, 550); /* off */ /* Initialize detector */ super_tone_rx_state_t *detector = super_tone_rx_init(NULL, desc, tone_detected, NULL); /* Process audio */ int16_t audio[160]; while (receive_audio(audio, 160) > 0) { super_tone_rx(detector, audio, 160); } super_tone_rx_free(detector); super_tone_rx_free_descriptor(desc); ``` -------------------------------- ### Generate Multi-tone Signals with SpanDSP Source: https://context7.com/freeswitch/spandsp/llms.txt Demonstrates how to initialize tone descriptors for various cadenced signals and generate audio samples using the tone generator state. It covers continuous tones like dial tones and pulsed patterns like ringback and busy signals. ```c #include /* Create a dual-tone descriptor (e.g., US dial tone: 350Hz + 440Hz) */ tone_gen_descriptor_t *dial_tone_desc = tone_gen_descriptor_init(NULL, 350, /* f1: 350 Hz */ -13, /* l1: -13 dBm0 */ 440, /* f2: 440 Hz */ -13, /* l2: -13 dBm0 */ 0, /* d1: continuous (0 = no cadence) */ 0, /* d2: off time */ 0, /* d3: unused */ 0, /* d4: unused */ true); /* repeat */ /* Create a cadenced tone (e.g., US ringback: 440+480Hz, 2s on, 4s off) */ tone_gen_descriptor_t *ringback_desc = tone_gen_descriptor_init(NULL, 440, -19, /* 440 Hz at -19 dBm0 */ 480, -19, /* 480 Hz at -19 dBm0 */ 2000, /* 2000ms on */ 4000, /* 4000ms off */ 0, 0, /* No second cadence segment */ true); /* repeat */ /* Create a busy tone (e.g., US: 480+620Hz, 500ms on, 500ms off) */ tone_gen_descriptor_t *busy_desc = tone_gen_descriptor_init(NULL, 480, -24, 620, -24, 500, 500, 0, 0, true); /* Initialize tone generator */ tone_gen_state_t *tone_gen = tone_gen_init(NULL, dial_tone_desc); /* Generate audio samples */ int16_t audio[160]; int samples; while ((samples = tone_gen(tone_gen, audio, 160)) > 0) { send_audio(audio, samples); } /* Switch to different tone */ tone_gen_init(tone_gen, ringback_desc); tone_gen_free(tone_gen); tone_gen_descriptor_free(dial_tone_desc); ``` -------------------------------- ### Implement FSK Modem Transmitter and Receiver in C Source: https://context7.com/freeswitch/spandsp/llms.txt Configures FSK modem states for various standards like V.21 and Bell 202. It demonstrates bit-based data handling for transmission and reception, including support for framed asynchronous serial modes. ```c #include /* Bit callback for receiver */ void put_bit(void *user_data, int bit) { if (bit == SIG_STATUS_CARRIER_UP) { printf("Carrier detected\n"); } else if (bit == SIG_STATUS_CARRIER_DOWN) { printf("Carrier lost\n"); } else { printf("Received bit: %d\n", bit); } } /* Bit source for transmitter */ int get_bit(void *user_data) { static int bit_count = 0; /* Return data bits, or SIG_STATUS_END_OF_DATA when done */ if (bit_count++ < 100) { return bit_count & 1; /* Alternating pattern */ } return SIG_STATUS_END_OF_DATA; } /* Initialize V.21 channel 1 transmitter */ fsk_tx_state_t *fsk_tx = fsk_tx_init(NULL, &preset_fsk_specs[FSK_V21CH1], get_bit, NULL); fsk_tx_power(fsk_tx, -10.0f); /* Set output level to -10 dBm0 */ /* Initialize V.21 channel 2 receiver */ fsk_rx_state_t *fsk_rx = fsk_rx_init(NULL, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_ASYNC, put_bit, NULL); fsk_rx_set_signal_cutoff(fsk_rx, -45.0f); /* Carrier detect threshold */ /* Generate FSK audio */ int16_t tx_audio[160]; int samples = fsk_tx(fsk_tx, tx_audio, 160); /* Process received audio */ int16_t rx_audio[160]; receive_audio(rx_audio, 160); fsk_rx(fsk_rx, rx_audio, 160); /* For framed mode with start/stop bits (async serial) */ fsk_rx_state_t *fsk_framed = fsk_rx_init(NULL, &preset_fsk_specs[FSK_BELL202], FSK_FRAME_MODE_FRAMED, NULL, NULL); fsk_rx_set_frame_parameters(fsk_framed, 8, 0, 1); /* 8N1 */ fsk_tx_free(fsk_tx); fsk_rx_free(fsk_rx); ``` -------------------------------- ### G.726 ADPCM Codec Implementation Source: https://context7.com/freeswitch/spandsp/llms.txt Shows how to initialize and use the G.726 ADPCM codec with different interworking modes like linear PCM, A-law, and u-law. ```c #include /* Initialize G.726 at 32kbps with linear PCM interworking */ g726_state_t *g726 = g726_init(NULL, 32000, G726_ENCODING_LINEAR, G726_PACKING_NONE); /* For u-law interworking (tandem operation) */ g726_state_t *g726_ulaw = g726_init(NULL, 32000, G726_ENCODING_ULAW, G726_PACKING_NONE); /* For A-law interworking */ g726_state_t *g726_alaw = g726_init(NULL, 32000, G726_ENCODING_ALAW, G726_PACKING_NONE); /* Encode linear PCM to G.726 */ int16_t pcm_input[160]; uint8_t g726_data[80]; /* 32kbps = 4 bits/sample, so half size */ int encoded_bytes = g726_encode(g726, g726_data, pcm_input, 160); /* Decode G.726 to linear PCM */ int16_t pcm_output[160]; int decoded_samples = g726_decode(g726, pcm_output, g726_data, encoded_bytes); g726_free(g726); ``` -------------------------------- ### G.722 Wideband Codec Implementation Source: https://context7.com/freeswitch/spandsp/llms.txt Demonstrates initializing, encoding, and decoding audio using the G.722 wideband codec. It supports various bit rates and optional narrowband compatibility modes. ```c #include /* Initialize G.722 encoder at 64000 bps */ g722_encode_state_t *encoder = g722_encode_init(NULL, 64000, 0); /* Initialize G.722 decoder at 64000 bps */ g722_decode_state_t *decoder = g722_decode_init(NULL, 64000, 0); /* For 8kHz input compatibility, use G722_SAMPLE_RATE_8000 option */ g722_encode_state_t *encoder_8k = g722_encode_init(NULL, 64000, G722_SAMPLE_RATE_8000); /* Encode 16-bit PCM to G.722 */ int16_t pcm_samples[320]; /* 20ms at 16kHz */ uint8_t g722_data[160]; /* Output is half the size */ int encoded_bytes = g722_encode(encoder, g722_data, pcm_samples, 320); /* encoded_bytes = 160 for 64kbps mode */ /* Decode G.722 to PCM */ int16_t decoded_samples[320]; int num_samples = g722_decode(decoder, decoded_samples, g722_data, encoded_bytes); /* num_samples = 320 */ g722_encode_free(encoder); g722_decode_free(decoder); ``` -------------------------------- ### FAX Reception Source: https://context7.com/freeswitch/spandsp/llms.txt Configure and execute a FAX reception process, saving output to TIFF files. ```APIDOC ## FAX Reception ### Description Handles incoming FAX transmissions with automatic modem negotiation and image decompression. ### Request Example ```c fax_state_t *fax = fax_init(NULL, false); t30_set_rx_file(t30, "received_fax.tif", -1); ``` ### Response - **stats** (t30_stats_t) - Statistics containing pages received and final bit rate. ``` -------------------------------- ### Detect DTMF Tones with SpanDSP Source: https://context7.com/freeswitch/spandsp/llms.txt Shows how to detect DTMF signals from an incoming audio stream using the Goertzel algorithm. It supports both callback-based processing and manual polling for detected digits. ```c #include /* Callback for detected digits */ void digit_callback(void *user_data, const char *digits, int len) { printf("Detected DTMF: %.*s\n", len, digits); } /* Initialize DTMF receiver with callback */ dtmf_rx_state_t *dtmf_rx = dtmf_rx_init(NULL, digit_callback, NULL); if (dtmf_rx == NULL) { fprintf(stderr, "Failed to initialize DTMF receiver\n"); return -1; } /* Configure detection parameters: - Enable dial tone filtering - Normal twist: 8 dB - Reverse twist: 4 dB - Threshold: -26 dBm0 */ dtmf_rx_parms(dtmf_rx, true, 8.0f, 4.0f, -26.0f); /* Process incoming audio */ int16_t audio_buffer[160]; while (receive_audio(audio_buffer, 160) > 0) { dtmf_rx(dtmf_rx, audio_buffer, 160); } /* Alternative: poll for digits without callback */ char digits[MAX_DTMF_DIGITS]; size_t digit_count = dtmf_rx_get(dtmf_rx, digits, MAX_DTMF_DIGITS); if (digit_count > 0) { printf("Received %zu digits: %s\n", digit_count, digits); } dtmf_rx_free(dtmf_rx); ``` -------------------------------- ### Perform T.4 FAX Image Compression and Decompression Source: https://context7.com/freeswitch/spandsp/llms.txt Shows how to configure a T.4 receiver to process compressed FAX data and save it to a TIFF file. It includes setting image parameters, handling decoding status, and retrieving transfer statistics. ```c #include /* Initialize T.4 receiver to save FAX pages to TIFF file */ t4_rx_state_t *t4_rx = t4_rx_init(NULL, "received.tif", T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D); /* Configure for incoming FAX parameters */ t4_rx_set_rx_encoding(t4_rx, T4_COMPRESSION_T4_2D); t4_rx_set_image_width(t4_rx, T4_WIDTH_R8_A4); t4_rx_set_x_resolution(t4_rx, T4_X_RESOLUTION_R8); t4_rx_set_y_resolution(t4_rx, T4_Y_RESOLUTION_FINE); /* Start receiving a page */ t4_rx_start_page(t4_rx); /* Feed compressed FAX data (from modem) */ uint8_t compressed_data[1000]; int data_len = receive_fax_data(compressed_data, sizeof(compressed_data)); int status = t4_rx_put(t4_rx, compressed_data, data_len); /* Check decode status */ if (status == T4_DECODE_OK) { printf("Page complete\n"); t4_rx_end_page(t4_rx); } /* Get transfer statistics */ t4_stats_t stats; t4_rx_get_transfer_statistics(t4_rx, &stats); printf("Page %d: %d x %d pixels, %d bad rows\n", stats.pages_transferred, stats.width, stats.length, stats.bad_rows); t4_rx_release(t4_rx); ``` -------------------------------- ### G.726 ADPCM Codec Source: https://context7.com/freeswitch/spandsp/llms.txt Initialize and process audio using the ITU G.726 ADPCM codec with various interworking modes. ```APIDOC ## G.726 ADPCM Codec ### Description Supports 16, 24, 32, and 40 kbps bit rates with A-law, u-law, and linear PCM interworking. ### Request Example ```c g726_state_t *g726 = g726_init(NULL, 32000, G726_ENCODING_LINEAR, G726_PACKING_NONE); int encoded_bytes = g726_encode(g726, g726_data, pcm_input, 160); ``` ### Response - **encoded_bytes** (int) - Number of bytes produced by the ADPCM encoder. ``` -------------------------------- ### G.722 Wideband Codec Source: https://context7.com/freeswitch/spandsp/llms.txt Initialize, encode, and decode audio using the ITU G.722 wideband codec. ```APIDOC ## G.722 Wideband Codec ### Description Provides 7kHz audio bandwidth at 16kHz sample rate, supporting 48, 56, and 64 kbps modes. ### Request Example ```c g722_encode_state_t *encoder = g722_encode_init(NULL, 64000, 0); int encoded_bytes = g722_encode(encoder, g722_data, pcm_samples, 320); ``` ### Response - **encoded_bytes** (int) - Number of bytes produced by the encoder. ``` -------------------------------- ### FAX Transmission (T.30) Source: https://context7.com/freeswitch/spandsp/llms.txt Configure and execute a FAX transmission using the T.30 protocol. ```APIDOC ## FAX Transmission (T.30 Protocol) ### Description Implements a software FAX machine supporting V.17/V.29/V.27ter modems and ECM error correction. ### Request Example ```c fax_state_t *fax = fax_init(NULL, true); t30_set_tx_file(t30, "document.tif", -1, -1); ``` ### Response - **result** (int) - Completion status code passed to the Phase E handler. ``` -------------------------------- ### Perform G.168 Echo Cancellation in C Source: https://context7.com/freeswitch/spandsp/llms.txt Initializes and uses an adaptive echo canceller to remove electrical echoes from audio signals. The process involves updating the canceller with transmit and receive samples to produce a cleaned audio output. ```c #include /* Initialize echo canceller with 128ms tail (1024 samples at 8kHz) */ int tail_length = 1024; /* 128ms */ int adaption_mode = ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP | ECHO_CAN_USE_CNG | ECHO_CAN_USE_TX_HPF | ECHO_CAN_USE_RX_HPF; echo_can_state_t *ec = echo_can_init(tail_length, adaption_mode); if (ec == NULL) { fprintf(stderr, "Failed to initialize echo canceller\n"); return -1; } /* Process audio sample by sample */ int16_t tx_sample, rx_sample, clean_sample; while (audio_available()) { /* tx_sample: audio being sent to far end (reference for echo) */ /* rx_sample: audio received from far end (contains echo) */ tx_sample = get_tx_audio(); rx_sample = get_rx_audio(); /* Apply echo cancellation - returns cleaned receive audio */ clean_sample = echo_can_update(ec, tx_sample, rx_sample); /* Use clean_sample for playback or further processing */ output_audio(clean_sample); } /* Flush (reset) the canceller if needed */ echo_can_flush(ec); /* Change adaption mode dynamically */ echo_can_adaption_mode(ec, ECHO_CAN_USE_ADAPTION); echo_can_free(ec); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.