| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718 |
- // in Asterisk pjsip.conf, under 1001, set direct_media=no
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <math.h>
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "esp_wifi.h"
- #include "esp_event.h"
- #include "esp_log.h"
- #include "nvs_flash.h"
- #include "lwip/sockets.h"
- #include <stdbool.h>
- #include "esp_rom_md5.h"
- #include "bsp_board.h"
- #include "tca9555_driver.h"
- #include "freertos/semphr.h"
- /*
- #include "esp_audio_enc_default.h"
- #include "esp_audio_enc.h"
- #include "esp_audio_dec_default.h"
- #include "esp_audio_dec.h"
- #include "esp_g711_enc.h"
- #include "esp_g711_dec.h"*/
- #define ESP32_IP "192.168.68.69"
- #define RTP_PORT 4000
- #define WIFI_SSID "TOCHTECH"
- #define WIFI_PASS "Smarturns2017"
- #define ASTERISK_IP "192.168.68.61"
- #define SIP_PORT 5060
- #define SIP_LOCAL_IP "0.0.0.0"
- #define SIP_LOCAL_PORT 5062
- #define SIP_USER "1001"
- #define SIP_PASSWORD "secret123"
- #define SAMPLE_RATE 16000
- #define RTP_SAMPLE_RATE 8000
- #define SAMPLES_PER_PACKET 160
- #define TONE_FREQ 1000
- #define AEC_FRAME_SAMPLES 256
- //#define AEC_OUTPUT_SAMPLES 320
- #define RTP_SAMPLES 160
- #define MIC_BLOCK_SAMPLES 320
- #define REF_BLOCK_SAMPLES 320
- #define REF_BUFFER_SAMPLES 4096
- #define MIC_BUFFER_SAMPLES 2048
- //
- #define MIC_FRAME_SAMPLES 160
- #define REF_DELAY_SAMPLES 320
- #define AEC_DELAY_SAMPLES 320
- static size_t ref_delay_count = AEC_DELAY_SAMPLES;
- static uint64_t mic_total_processed = 0;
- static uint64_t ref_total_written = 0;
- static int16_t ref_delay_buffer[AEC_DELAY_SAMPLES];
- static int16_t ref_buffer[REF_BUFFER_SAMPLES];
- static size_t ref_write = 0;
- static size_t ref_read = 0;
- static size_t ref_count = 0;
- static size_t ref_delay_write = 0;
- //static size_t ref_delay_count = 0;
- static int16_t mic_aec_buffer[AEC_FRAME_SAMPLES];
- static int16_t ref_aec_buffer[AEC_FRAME_SAMPLES];
- static int16_t aec_output_buffer[MIC_BUFFER_SAMPLES];
- static size_t aec_output_count = 0;
- static int32_t mic_buffer[320];
- static int16_t mic_pcm16[RTP_SAMPLES];
- static SemaphoreHandle_t aec_mutex = NULL;
- static int16_t ref_pending[AEC_FRAME_SAMPLES];
- static size_t ref_pending_count = 0;
- #include "esp_afe_config.h"
- #include "esp_afe_sr_iface.h"
- #include "esp_afe_sr_models.h"
- #include "esp_afe_aec.h"
- static int16_t mic_fifo[MIC_BUFFER_SAMPLES];
- static int16_t ref_fifo[MIC_BUFFER_SAMPLES];
- static size_t mic_fifo_count = 0;
- static size_t ref_fifo_count = 0;
- static uint8_t payload[MIC_FRAME_SAMPLES];
- static uint8_t rx_packet[172];
- static int16_t speaker_pcm[160];
- static const char *TAG = "SIP";
- volatile bool wifi_ready = false;
- static int s_rtp_sock = -1;
- static struct sockaddr_in s_rtp_peer = {0};
- static uint16_t s_rtp_peer_port = 0;
- static volatile bool call_active = false;
- static volatile bool s_audio_hw_ready = false;
- static afe_aec_handle_t *aec_handle = NULL;
- esp_err_t esp_get_feed_data(
- bool is_get_raw_channel,
- int16_t *buffer,
- int buffer_len);
- esp_err_t esp_audio_play(const int16_t *data,
- int length,
- uint32_t ticks_to_wait);
- esp_err_t sip_media_init(void);
- static void rtp_tx_task(void *pvParameters);
- static void rtp_rx_task(void *pvParameters);
- static void s_aec_process(
- int16_t *mic,
- int16_t *ref
- //int samples
- );
- static bool aec_reference_get(
- int16_t *out,
- size_t count
- );
- /* ================= AEC ================= */
- static bool aec_reference_push(
- const int16_t *samples,
- size_t count)
- {
- if (samples == NULL || count == 0)
- return false;
-
- if (ref_count + count > REF_BUFFER_SAMPLES)
- {
- ESP_LOGE(
- TAG,
- "AEC REF OVERFLOW: count=%u incoming=%u",
- (unsigned)ref_count,
- (unsigned)count
- );
- return false;
- }
- for (size_t i = 0; i < count; i++)
- {
- ref_buffer[ref_write] = samples[i];
- ref_write++;
- if (ref_write >= REF_BUFFER_SAMPLES)
- ref_write = 0;
- ref_count++;
- ref_total_written++;
- }
- ESP_LOGI(
- TAG,
- "AEC REF PUSH: count=%u fifo=%u total=%llu",
- (unsigned)count,
- (unsigned)ref_count,
- (unsigned long long)ref_total_written
- );
- return true;
- }
- static bool aec_reference_get(
- int16_t *out,
- size_t count)
- {
-
- size_t required =
- AEC_DELAY_SAMPLES + count;
- if (ref_count < AEC_DELAY_SAMPLES + count)
- {
- return false;
- }
- for (size_t i = 0; i < count; i++)
- {
- out[i] = ref_buffer[ref_read];
- ref_read++;
- if (ref_read >= REF_BUFFER_SAMPLES)
- ref_read = 0;
- }
- ref_count -= count;
- return true;
- }
- bool aec_init(void)
- {
- memset(ref_buffer, 0, sizeof(ref_buffer));
- ref_write = 0;
- ref_read = 0;
- ref_count = 0;
- ref_pending_count = 0;
- memset(ref_pending, 0, sizeof(ref_pending));
- ref_total_written = 0;
- mic_total_processed = 0;
- aec_output_count = 0;
- aec_handle = afe_aec_create(
- "MR",
- 4,
- AFE_TYPE_VC,
- AFE_MODE_HIGH_PERF
- );
- if (aec_handle == NULL)
- {
- ESP_LOGE(TAG, "AEC init failed");
- return false;
- }
- ESP_LOGI(
- TAG,
- "AEC initialized: frame_size=%d sample_rate=%d",
- aec_handle->frame_size,
- SAMPLE_RATE
- );
- if (aec_handle->frame_size != AEC_FRAME_SAMPLES)
- {
- ESP_LOGE(
- TAG,
- "AEC frame mismatch: handle=%d expected=%d",
- aec_handle->frame_size,
- AEC_FRAME_SAMPLES
- );
- afe_aec_destroy(aec_handle);
- aec_handle = NULL;
- return false;
- }
- return true;
- }
- static void s_aec_process(
- int16_t *mic,
- int16_t *ref)
- {
- if (aec_handle == NULL)
- return;
- int16_t input[AEC_FRAME_SAMPLES * 2];
- int16_t output[AEC_FRAME_SAMPLES];
- for (int i = 0; i < AEC_FRAME_SAMPLES; i++)
- {
- input[2 * i] = mic[i];
- input[2 * i + 1] = ref[i];
- }
- afe_aec_process(
- aec_handle,
- input,
- output
- );
- if (aec_output_count + AEC_FRAME_SAMPLES >
- MIC_BUFFER_SAMPLES)
- {
- ESP_LOGE(
- TAG,
- "AEC OUTPUT FIFO OVERFLOW: "
- "count=%u adding=%u max=%u",
- (unsigned)aec_output_count,
- (unsigned)AEC_FRAME_SAMPLES,
- (unsigned)MIC_BUFFER_SAMPLES
- );
- return;
- }
- memcpy(
- &aec_output_buffer[aec_output_count],
- output,
- AEC_FRAME_SAMPLES * sizeof(int16_t)
- );
- aec_output_count += AEC_FRAME_SAMPLES;
- }
- void aec_deinit()
- {
- if(aec_handle)
- {
- afe_aec_destroy(aec_handle);
- aec_handle=NULL;
- }
- }
- static bool process_aec_320(
- const int16_t *mic320,
- int16_t *out320)
- {
- static int16_t mic_pending[AEC_FRAME_SAMPLES];
- static size_t mic_pending_count = 0;
- static int16_t ref_pending[AEC_FRAME_SAMPLES];
- static size_t ref_pending_count = 0;
- size_t input_pos = 0;
- while (input_pos < MIC_BLOCK_SAMPLES)
- {
- if (mic_pending_count == AEC_FRAME_SAMPLES)
- {
- int16_t ref_frame[AEC_FRAME_SAMPLES];
- if (!aec_reference_get(
- ref_frame,
- AEC_FRAME_SAMPLES))
- {
- ESP_LOGW(
- TAG,
- "AEC waiting for reference: "
- "fifo=%u need=%u",
- (unsigned)ref_count,
- (unsigned)(
- AEC_DELAY_SAMPLES +
- AEC_FRAME_SAMPLES)
- );
- break;
- }
- ESP_LOGI(
- TAG,
- "AEC PROCESS: mic=256 ref=256 "
- "ref_remaining=%u",
- (unsigned)ref_count
- );
- s_aec_process(
- mic_pending,
- ref_frame
- );
- mic_total_processed += AEC_FRAME_SAMPLES;
- mic_pending_count = 0;
- continue;
- }
- size_t needed =
- AEC_FRAME_SAMPLES -
- mic_pending_count;
- size_t available =
- MIC_BLOCK_SAMPLES -
- input_pos;
- size_t copy_count =
- (needed < available)
- ? needed
- : available;
- memcpy(
- &mic_pending[mic_pending_count],
- &mic320[input_pos],
- copy_count * sizeof(int16_t)
- );
- mic_pending_count += copy_count;
- input_pos += copy_count;
- }
- if (aec_output_count < MIC_BLOCK_SAMPLES)
- {
- return false;
- }
- memcpy(
- out320,
- aec_output_buffer,
- MIC_BLOCK_SAMPLES * sizeof(int16_t)
- );
- size_t remaining =
- aec_output_count -
- MIC_BLOCK_SAMPLES;
- if (remaining > 0)
- {
- memmove(
- aec_output_buffer,
- &aec_output_buffer[MIC_BLOCK_SAMPLES],
- remaining * sizeof(int16_t)
- );
- }
- aec_output_count = remaining;
- return true;
- }
- static void downsample_16k_to_8k(
- const int16_t *input,
- int16_t *output)
- {
- for (int i = 0; i < 160; i++)
- {
-
- output[i] = input[i * 2];
- }
- }
- /* ================= WIFI ================= */
- static void wifi_event_handler(void *arg, esp_event_base_t event_base,
- int32_t event_id, void *event_data)
- {
- if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
- esp_wifi_connect();
- }
- else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
- ESP_LOGI(TAG, "WiFi disconnected, retrying...");
- wifi_ready = false;
- esp_wifi_connect();
- }
- else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
- ESP_LOGI(TAG, "WiFi connected!");
- wifi_ready = true;
- }
- esp_netif_ip_info_t ip;
- esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ip);
- ESP_LOGI(TAG, "ESP32 IP: " IPSTR, IP2STR(&ip.ip));
- }
- void wifi_init(void)
- {
- nvs_flash_init();
- esp_netif_init();
- esp_event_loop_create_default();
- esp_netif_create_default_wifi_sta();
- wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
- esp_wifi_init(&cfg);
- esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL);
- esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL);
- wifi_config_t wifi_config = {
- .sta = {
- .ssid = WIFI_SSID,
- .password = WIFI_PASS,
- },
- };
- esp_wifi_set_mode(WIFI_MODE_STA);
- esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
- esp_wifi_start();
- }
- /* ================= MD5 HELPERS ================= */
- static void md5_calc(const unsigned char *input, size_t len, unsigned char output[16])
- {
- md5_context_t ctx;
- esp_rom_md5_init(&ctx);
- esp_rom_md5_update(&ctx, input, len);
- esp_rom_md5_final(output, &ctx);
- }
- static void md5_to_hex(unsigned char *md5, char *out)
- {
- for (int i = 0; i < 16; i++) {
- sprintf(out + i * 2, "%02x", md5[i]);
- }
- }
- /* ================= SIP DIGEST ================= */
- void sip_compute_response(
- const char *username,
- const char *realm,
- const char *password,
- const char *nonce,
- const char *uri,
- char *out_response)
- {
- unsigned char ha1_md5[16], ha2_md5[16], final_md5[16];
- char ha1_hex[64], ha2_hex[64], final_str[256];
- char ha1[128], ha2[128];
- snprintf(ha1, sizeof(ha1), "%s:%s:%s", username, realm, password);
- md5_calc((unsigned char*)ha1, strlen(ha1), ha1_md5);
- md5_to_hex(ha1_md5, ha1_hex);
- snprintf(ha2, sizeof(ha2), "REGISTER:%s", uri);
- md5_calc((unsigned char*)ha2, strlen(ha2), ha2_md5);
- md5_to_hex(ha2_md5, ha2_hex);
- snprintf(final_str, sizeof(final_str),
- "%s:%s:%s", ha1_hex, nonce, ha2_hex);
- md5_calc((unsigned char*)final_str, strlen(final_str), final_md5);
- md5_to_hex(final_md5, out_response);
- }
- /* ================= SIP HELPERS ================= */
- static bool sip_extract_header(const char *msg, const char *header, char *out, size_t out_len)
- {
- const char *start = strstr(msg, header);
- if (!start) {
- return false;
- }
- start += strlen(header);
- while (*start == ' ' || *start == '\t') {
- start++;
- }
- const char *end = start;
- while (*end != '\0' && *end != '\r' && *end != '\n') {
- end++;
- }
- size_t len = (size_t)(end - start);
- if (len >= out_len) {
- len = out_len - 1;
- }
- memcpy(out, start, len);
- out[len] = '\0';
- return true;
- }
- static void sip_send_200_ok(int sock, const struct sockaddr_in *remote, const char *sip_msg,
- const char *sdp_body, size_t sdp_len)
- {
- char via[512] = {0};
- char from[256] = {0};
- char to[256] = {0};
- char callid[256] = {0};
- char cseq[128] = {0};
- char response[4096];
- if (!sip_extract_header(sip_msg, "Via:", via, sizeof(via))) {
- snprintf(via, sizeof(via), "SIP/2.0/UDP %s:%d", SIP_LOCAL_IP, SIP_LOCAL_PORT);
- }
- if (!sip_extract_header(sip_msg, "From:", from, sizeof(from))) {
- snprintf(from, sizeof(from), "<sip:%s@%s>", SIP_USER, ASTERISK_IP);
- }
- if (!sip_extract_header(sip_msg, "To:", to, sizeof(to))) {
- snprintf(to, sizeof(to), "<sip:%s@%s>", SIP_USER, ASTERISK_IP);
- }
- if (!sip_extract_header(sip_msg, "Call-ID:", callid, sizeof(callid))) {
- snprintf(callid, sizeof(callid), "esp32-call");
- }
- if (!sip_extract_header(sip_msg, "CSeq:", cseq, sizeof(cseq))) {
- snprintf(cseq, sizeof(cseq), "1 REGISTER");
- }
- int body_len = sdp_body ? (int)sdp_len : 0;
- int written = snprintf(response, sizeof(response),
- "SIP/2.0 200 OK\r\n"
- "Via: %s\r\n"
- "From: %s\r\n"
- "To: %s;tag=esp32\r\n"
- "Call-ID: %s\r\n"
- "CSeq: %s\r\n"
- "Contact: <sip:%s@%s:%d>\r\n"
- "%s"
- "Content-Length: %d\r\n"
- "\r\n"
- "%s",
- via,
- from,
- to,
- callid,
- cseq,
- SIP_USER,
- ESP32_IP,
- SIP_LOCAL_PORT,
- sdp_body ? "Content-Type: application/sdp\r\n" : "",
- body_len,
- sdp_body ? sdp_body : "");
- if (written < 0 || written >= (int)sizeof(response)) {
- ESP_LOGW(TAG, "SIP 200 OK response too large");
- return;
- }
- sendto(sock, response, (size_t)written, 0,
- (struct sockaddr *)remote, sizeof(*remote));
- }
- static void sip_build_sdp(char *out, size_t out_len)
- {
- snprintf(out, out_len,
- "v=0\r\n"
- "o=ESP32 1234 1234 IN IP4 %s\r\n"
- "s=ESP32 SIP Call\r\n"
- "c=IN IP4 %s\r\n"
- "t=0 0\r\n"
- "m=audio %d RTP/AVP 0\r\n"
- "a=rtpmap:0 PCMU/8000\r\n"
- "a=ptime:20\r\n"
- "a=sendrecv\r\n",
- ESP32_IP,
- ESP32_IP,
- RTP_PORT);
- }
- static bool sip_extract_rtp_port(const char *msg, uint16_t *out_port)
- {
- const char *m = strstr(msg, "m=audio ");
- if (!m) {
- return false;
- }
- m += strlen("m=audio ");
- char port_buf[16] = {0};
- size_t i = 0;
- while (*m && *m != ' ' && *m != '\r' && *m != '\n' && i < sizeof(port_buf) - 1) {
- port_buf[i++] = *m++;
- }
- port_buf[i] = '\0';
- *out_port = (uint16_t)atoi(port_buf);
- return *out_port != 0;
-
- }
- /* ================= RTP TX ================= */
- static bool rtp_socket_init(void)
- {
- if (s_rtp_sock >= 0)
- return true;
- s_rtp_sock = socket(
- AF_INET,
- SOCK_DGRAM,
- IPPROTO_UDP
- );
- if (s_rtp_sock < 0)
- {
- ESP_LOGE(
- TAG,
- "RTP socket failed errno=%d",
- errno
- );
- return false;
- }
- struct sockaddr_in local_rtp = {0};
- local_rtp.sin_family = AF_INET;
- local_rtp.sin_port = htons(RTP_PORT);
- local_rtp.sin_addr.s_addr = htonl(INADDR_ANY);
- if (bind(
- s_rtp_sock,
- (struct sockaddr *)&local_rtp,
- sizeof(local_rtp)) < 0)
- {
- ESP_LOGE(
- TAG,
- "RTP bind failed errno=%d",
- errno
- );
- close(s_rtp_sock);
- s_rtp_sock = -1;
- return false;
- }
- ESP_LOGI(
- TAG,
- "RTP socket ready on port %d",
- RTP_PORT
- );
- return true;
- }
- static bool microphone_read_320(int16_t *out)
- {
- int16_t buffer1[320];
- int16_t buffer2[320];
- esp_err_t ret;
- ret = esp_get_feed_data(
- false,
- buffer1,
- sizeof(buffer1));
- if (ret != ESP_OK)
- {
- ESP_LOGE(TAG,
- "mic read 1 failed: %s",
- esp_err_to_name(ret));
- return false;
- }
- ret = esp_get_feed_data(
- false,
- buffer2,
- sizeof(buffer2));
- if (ret != ESP_OK)
- {
- ESP_LOGE(TAG,
- "mic read 2 failed: %s",
- esp_err_to_name(ret));
- return false;
- }
- /* ================= MIC CHANNEL DEBUG ================= */
- int max_l = 0;
- int max_r = 0;
- for (int i = 0; i < 160; i++)
- {
- int l = abs(buffer1[i * 2]);
- int r = abs(buffer1[i * 2 + 1]);
- if (l > max_l)
- max_l = l;
- if (r > max_r)
- max_r = r;
- }
- ESP_LOGI(TAG,
- "MIC channels: L=%d R=%d",
- max_l,
- max_r);
- for (int i = 0; i < 160; i++)
- {
- out[i] = buffer1[i * 2];
- out[160 + i] = buffer2[i * 2];
- }
- return true;
- }
- static uint8_t linear2ulaw(int16_t pcm)
- {
- const int16_t BIAS = 0x84;
- const int16_t CLIP = 32635;
- uint8_t mask;
- uint8_t seg;
- uint8_t uval;
- int16_t sample = pcm;
- if (sample < 0)
- {
- sample = -sample;
- mask = 0x7F;
- }
- else
- {
- mask = 0xFF;
- }
- if (sample > CLIP)
- sample = CLIP;
- sample += BIAS;
- if (sample <= 0xFF)
- seg = 0;
- else if (sample <= 0x1FF)
- seg = 1;
- else if (sample <= 0x3FF)
- seg = 2;
- else if (sample <= 0x7FF)
- seg = 3;
- else if (sample <= 0xFFF)
- seg = 4;
- else if (sample <= 0x1FFF)
- seg = 5;
- else if (sample <= 0x3FFF)
- seg = 6;
- else
- seg = 7;
- uval = (seg << 4) |
- ((sample >> (seg + 3)) & 0x0F);
- return uval ^ mask;
- }
- static int16_t ulaw2linear(uint8_t u_val)
- {
- u_val = ~u_val;
- int t = ((u_val & 0x0F) << 3) + 0x84;
- t <<= ((unsigned)u_val & 0x70) >> 4;
- if (u_val & 0x80)
- return 0x84 - t;
- else
- return t - 0x84;
- }
- static void sip_send_rtp_packet(void)
- {
- static uint16_t seq = 0;
- static uint32_t timestamp = 0;
- if (s_rtp_peer_port == 0)
- {
- ESP_LOGW(TAG, "No RTP peer");
- return;
- }
- if (s_rtp_sock < 0)
- {
- ESP_LOGE(TAG, "RTP socket not initialized");
- return;
- }
- static int16_t mic320[320];
- static int16_t aec320[320];
- if (!microphone_read_320(mic320))
- return;
- int raw_mic_max = 0;
- for (int i = 0; i < 320; i++)
- {
- int v = abs(mic320[i]);
- if (v > raw_mic_max)
- raw_mic_max = v;
- }
- ESP_LOGI(TAG,
- "MIC16 max=%d first=%d %d %d %d",
- raw_mic_max,
- mic320[0],
- mic320[1],
- mic320[2],
- mic320[3]);
- xSemaphoreTake(aec_mutex, portMAX_DELAY);
- bool ready = process_aec_320(
- mic320,
- aec320);
- xSemaphoreGive(aec_mutex);
- if (!ready)
- {
- return;
- }
- downsample_16k_to_8k(
- aec320,
- mic_pcm16);
- int max = 0;
- for (int i = 0; i < RTP_SAMPLES; i++)
- {
- int value = abs(mic_pcm16[i]);
- if (value > max)
- max = value;
- }
- ESP_LOGI(
- "MIC",
- "AEC output max=%d first=%d %d %d %d",
- max,
- mic_pcm16[0],
- mic_pcm16[1],
- mic_pcm16[2],
- mic_pcm16[3]);
-
- uint8_t payload[RTP_SAMPLES];
- for (int i = 0; i < RTP_SAMPLES; i++)
- {
- payload[i] = linear2ulaw(
- mic_pcm16[i]);
- }
- uint8_t packet[12 + RTP_SAMPLES];
- memset(packet, 0, sizeof(packet));
- packet[0] = 0x80;
- packet[1] = 0x00;
- packet[2] = seq >> 8;
- packet[3] = seq & 0xff;
- packet[4] = timestamp >> 24;
- packet[5] = timestamp >> 16;
- packet[6] = timestamp >> 8;
- packet[7] = timestamp;
- uint32_t ssrc = 0x12345678;
- packet[8] = (ssrc >> 24) & 0xff;
- packet[9] = (ssrc >> 16) & 0xff;
- packet[10] = (ssrc >> 8) & 0xff;
- packet[11] = ssrc & 0xff;
- memcpy(
- packet + 12,
- payload,
- RTP_SAMPLES);
- struct sockaddr_in peer = s_rtp_peer;
- peer.sin_port = htons(
- s_rtp_peer_port);
- int ret = sendto(
- s_rtp_sock,
- packet,
- sizeof(packet),
- 0,
- (struct sockaddr *)&peer,
- sizeof(peer));
- if (ret < 0)
- {
- ESP_LOGE(
- TAG,
- "RTP send failed errno=%d",
- errno);
- }
- seq++;
- timestamp += RTP_SAMPLES;
- }
- static void rtp_tx_task(void *pvParameters)
- {
- ESP_LOGI(TAG, "RTP TX started");
- TickType_t last_wake = xTaskGetTickCount();
- while(call_active)
- {/*ESP_LOGI(TAG, "RTP loop");*/
- sip_send_rtp_packet();
- vTaskDelayUntil(
- &last_wake,
- pdMS_TO_TICKS(20)
- );
- }
- ESP_LOGI(TAG, "RTP TX stopped");
- vTaskDelete(NULL);
- }
- // ================= RTP RX =================
- static void rtp_rx_task(void *pvParameters)
- {
- ESP_LOGI(TAG, "RTP RX started");
- while (call_active)
- {
- struct sockaddr_in src;
- socklen_t len = sizeof(src);
- int n = recvfrom(
- s_rtp_sock,
- rx_packet,
- sizeof(rx_packet),
- 0,
- (struct sockaddr *)&src,
- &len
- );
- if (n < 0)
- {
- ESP_LOGE(TAG,
- "recvfrom failed errno=%d",
- errno);
- continue;
- }
- /*
- ESP_LOGI(TAG,
- "Received RTP packet (%d bytes)",
- n);
- */
- if (n <= 12)
- {
- ESP_LOGW(TAG, "Packet too small");
- continue;
- }
- /*
- ESP_LOGI(TAG,
- "RTP Header: %02X %02X %02X %02X",
- rx_packet[0],
- rx_packet[1],
- rx_packet[2],
- rx_packet[3]);
- ESP_LOGI(TAG,
- "RTP Payload: %02X %02X %02X %02X %02X %02X %02X %02X",
- rx_packet[12],
- rx_packet[13],
- rx_packet[14],
- rx_packet[15],
- rx_packet[16],
- rx_packet[17],
- rx_packet[18],
- rx_packet[19]);
- */
- int payload_size = n - 12;
- if (payload_size > SAMPLES_PER_PACKET)
- {
- payload_size = SAMPLES_PER_PACKET;
- }
- int16_t play_buf[640];
-
- int16_t ref_frame[320];
- for (int i = 0; i < payload_size; i++)
- {
- int16_t s1 =
- ulaw2linear(rx_packet[12 + i]);
- int16_t s2 = s1;
- if (i < payload_size - 1)
- {
- int16_t next =
- ulaw2linear(
- rx_packet[12 + i + 1]);
- s2 = (s1 + next) / 2;
- }
- play_buf[4 * i + 0] = s1;
- play_buf[4 * i + 1] = s1;
- play_buf[4 * i + 2] = s2;
- play_buf[4 * i + 3] = s2;
- ref_frame[2 * i + 0] = s1;
- ref_frame[2 * i + 1] = s2;
- }
- xSemaphoreTake(
- aec_mutex,
- portMAX_DELAY);
- size_t ref_samples = payload_size * 2;
- size_t ref_pos = 0;
- while (ref_pos < ref_samples)
- {
- size_t needed =
- AEC_FRAME_SAMPLES - ref_pending_count;
- size_t available =
- ref_samples - ref_pos;
- size_t copy_count =
- (needed < available)
- ? needed
- : available;
- memcpy(
- &ref_pending[ref_pending_count],
- &ref_frame[ref_pos],
- copy_count * sizeof(int16_t)
- );
- ref_pending_count += copy_count;
- ref_pos += copy_count;
- if (ref_pending_count == AEC_FRAME_SAMPLES)
- {
- aec_reference_push(
- ref_pending,
- AEC_FRAME_SAMPLES
- );
- ref_pending_count = 0;
- }
- }
- uint64_t ref_written =
- ref_total_written;
- size_t ref_level =
- ref_count;
- xSemaphoreGive(
- aec_mutex);
- ESP_LOGI(
- TAG,
- "AEC REF: pushed=%d fifo=%d",
- payload_size * 2,
- (int)ref_level);
- ESP_LOGI(
- TAG,
- "AEC REF PUSH: samples=%d "
- "ref_count=%d total_written=%llu",
- payload_size * 2,
- (int)ref_level,
- (unsigned long long)ref_written);
-
- esp_err_t ret = esp_audio_play(
- play_buf,
- payload_size * 4 * sizeof(int16_t),
- portMAX_DELAY
- );
- /*
- ESP_LOGI(TAG,
- "esp_audio_play() = %s",
- esp_err_to_name(ret));*/
- }
- ESP_LOGI(TAG, "RTP RX stopped");
- vTaskDelete(NULL);
- }
- /* ================= SIP TASK ================= */
- void sip_register_task(void *pvParameters)
- {
- struct sockaddr_in server = {0};
- server.sin_family = AF_INET;
- server.sin_port = htons(SIP_PORT);
- server.sin_addr.s_addr = inet_addr(ASTERISK_IP);
- int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- struct sockaddr_in local_addr = {0};
- local_addr.sin_family = AF_INET;
- local_addr.sin_port = htons(SIP_LOCAL_PORT);
- local_addr.sin_addr.s_addr = INADDR_ANY;
- if (bind(sock,
- (struct sockaddr *)&local_addr,
- sizeof(local_addr)) < 0) {
- ESP_LOGE(TAG, "Failed to bind SIP port %d", SIP_LOCAL_PORT);
- close(sock);
- vTaskDelete(NULL);
- return;
- }
- ESP_LOGI(TAG, "SIP listening on UDP %d", SIP_LOCAL_PORT);
- if (sock < 0) {
- ESP_LOGE(TAG, "Socket failed");
- vTaskDelete(NULL);
- return;
- }
- struct timeval timeout = {
- .tv_sec = 300,
- .tv_usec = 0
- };
- setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
- /* ================= FIRST REGISTER ================= */
- char register_msg[512];
- snprintf(register_msg, sizeof(register_msg),
- "REGISTER sip:%s SIP/2.0\r\n"
- "Via: SIP/2.0/UDP %s:%d\r\n"
- "From: <sip:%s@%s>;tag=1234\r\n"
- "To: <sip:%s@%s>\r\n"
- "Call-ID: esp32-0001\r\n"
- "CSeq: 1 REGISTER\r\n"
- "Contact: <sip:%s@%s:%d>\r\n"
- "Expires: 300\r\n"
- "Content-Length: 0\r\n"
- "\r\n",
- ASTERISK_IP,
- SIP_LOCAL_IP,
- SIP_LOCAL_PORT,
- SIP_USER,
- ASTERISK_IP,
- SIP_USER,
- ASTERISK_IP,
- SIP_USER,
- SIP_LOCAL_IP,
- SIP_LOCAL_PORT);
- ESP_LOGI(TAG, "Sending REGISTER...");
- sendto(sock, register_msg, strlen(register_msg), 0,
- (struct sockaddr*)&server, sizeof(server));
- /* ================= RECEIVE 401 / 200 ================= */
- char response[1024];
- socklen_t addr_len = sizeof(server);
- bool registered = false;
- while (!registered) {
- int len = recvfrom(sock, response, sizeof(response) - 1, 0,
- (struct sockaddr *)&server, &addr_len);
- if (len <= 0) {
- ESP_LOGE(TAG, "No response");
- close(sock);
- vTaskDelete(NULL);
- return;
- }
- response[len] = '\0';
- // printf("SIP RESPONSE:\n%s\n", response);
- ESP_LOGI(TAG, "Received SIP response (%d bytes)", len);
- if (strstr(response, "SIP/2.0 401")) {
- char sip_nonce[256] = {0};
- char sip_realm[128] = {0};
- char *n = strstr(response, "nonce=\"");
- if (n) {
- n += 7;
- char *end = strchr(n, '"');
- if (end) {
- size_t nlen = end - n;
- if (nlen < sizeof(sip_nonce)) {
- strncpy(sip_nonce, n, nlen);
- sip_nonce[nlen] = '\0';
- }
- }
- }
- char *r = strstr(response, "realm=\"");
- if (r) {
- r += 7;
- char *rend = strchr(r, '"');
- if (rend) {
- size_t rlen = rend - r;
- if (rlen < sizeof(sip_realm)) {
- strncpy(sip_realm, r, rlen);
- sip_realm[rlen] = '\0';
- }
- }
- }
- if (sip_realm[0] == '\0' || sip_nonce[0] == '\0') {
- ESP_LOGE(TAG, "Missing realm or nonce in challenge");
- close(sock);
- vTaskDelete(NULL);
- return;
- }
- ESP_LOGI(TAG, "Nonce: %s", sip_nonce);
- ESP_LOGI(TAG, "Realm: %s", sip_realm);
- char response_hash[64];
- char sip_uri[64];
- snprintf(sip_uri, sizeof(sip_uri), "sip:%s", ASTERISK_IP);
- sip_compute_response(
- SIP_USER,
- sip_realm,
- SIP_PASSWORD,
- sip_nonce,
- sip_uri,
- response_hash
- );
- char auth[1024];
- snprintf(auth, sizeof(auth),
- "REGISTER sip:%s SIP/2.0\r\n"
- "Via: SIP/2.0/UDP %s:%d\r\n"
- "From: <sip:%s@%s>;tag=1234\r\n"
- "To: <sip:%s@%s>\r\n"
- "Call-ID: esp32-0001\r\n"
- "CSeq: 2 REGISTER\r\n"
- "Contact: <sip:%s@%s:%d>\r\n"
- "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"sip:%s\", response=\"%s\"\r\n"
- "Expires: 300\r\n"
- "Content-Length: 0\r\n"
- "\r\n",
- ASTERISK_IP,
- SIP_LOCAL_IP,
- SIP_LOCAL_PORT,
- SIP_USER,
- ASTERISK_IP,
- SIP_USER,
- ASTERISK_IP,
- SIP_USER,
- SIP_LOCAL_IP,
- SIP_LOCAL_PORT,
- SIP_USER,
- sip_realm,
- sip_nonce,
- ASTERISK_IP,
- response_hash);
- ESP_LOGI(TAG, "Sending AUTH REGISTER...");
- sendto(sock, auth, strlen(auth), 0,
- (struct sockaddr *)&server, sizeof(server));
- }
- else if (strstr(response, "SIP/2.0 200")) {
- registered = true;
- }
- else if (strstr(response, "SIP/2.0 486")) {
- ESP_LOGW(TAG, "Server returned 486 Busy");
- }
- else {
- ESP_LOGI(TAG, "Ignoring SIP response");
- }
- }
- if (!registered) {
- ESP_LOGW(TAG, "Registration was not completed");
- close(sock);
- vTaskDelete(NULL);
- return;
- }
- ESP_LOGI(TAG, "🎉 SIP REGISTER SUCCESS");
- ESP_LOGI(TAG, "stack remaining: %u",
- uxTaskGetStackHighWaterMark(NULL));
- /* =====================================================
- * KEEP SOCKET OPEN AND WAIT FOR SIP REQUESTS
- * ===================================================== */
- ESP_LOGI(TAG, "Waiting for incoming SIP requests...");
- while (1) {
- char rx_buf[2048];
- int rx_len = recvfrom(sock,
- rx_buf,
- sizeof(rx_buf) - 1,
- 0,
- (struct sockaddr *)&server,
- &addr_len);
- if (rx_len <= 0) {
- continue;
- }
- rx_buf[rx_len] = '\0';
- ESP_LOGI(TAG, "\n===== RAW INVITE =====\n%s\n=======================\n", rx_buf);
- // printf("\n========================================\n");
- // printf("SIP MESSAGE RECEIVED:\n");
- // printf("%s\n", rx_buf);
- ESP_LOGI(TAG, "Received SIP packet (%d bytes)", rx_len);
- // printf("========================================\n");
- if (strncmp(rx_buf, "REGISTER ", 9) == 0) {
- ESP_LOGI(TAG, "Received REGISTER; sending 200 OK");
- sip_send_200_ok(sock, &server, rx_buf, NULL, 0);
- continue;
- }
- else if (strncmp(rx_buf, "INVITE ", 7) == 0) {
- ESP_LOGI(TAG, "📞 Incoming INVITE");
- char *test = strstr(rx_buf, "m=audio");
- if(test)
- {
- ESP_LOGI(TAG, "Found m=audio SDP:");
- ESP_LOGI(TAG, "%s", test);
- }
- else
- {
- ESP_LOGE(TAG, "No m=audio found");
- }
- /* ================= EXTRACT SIP HEADERS ================= */
- char via[512] = {0};
- char from[256] = {0};
- char to[256] = {0};
- char callid[256] = {0};
- char cseq[128] = {0};
- char *header = NULL;
- header = strstr(rx_buf, "Via:");
- if (header) {
- sscanf(header, "Via: %511[^\r\n]", via);
- }
- header = strstr(rx_buf, "From:");
- if (header) {
- sscanf(header, "From: %255[^\r\n]", from);
- }
- header = strstr(rx_buf, "To:");
- if (header) {
- sscanf(header, "To: %255[^\r\n]", to);
- }
- header = strstr(rx_buf, "Call-ID:");
- if (header) {
- sscanf(header, "Call-ID: %255[^\r\n]", callid);
- }
- header = strstr(rx_buf, "CSeq:");
- if (header) {
- sscanf(header, "CSeq: %127[^\r\n]", cseq);
- }
- /* ================= SEND 100 TRYING ================= */
- char trying[4096];
- snprintf(trying, sizeof(trying),
- "SIP/2.0 100 Trying\r\n"
- "Via: %s\r\n"
- "From: %s\r\n"
- "To: %s\r\n"
- "Call-ID: %s\r\n"
- "CSeq: %s\r\n"
- "Content-Length: 0\r\n"
- "\r\n",
- via,
- from,
- to,
- callid,
- cseq);
- sendto(sock,
- trying,
- strlen(trying),
- 0,
- (struct sockaddr *)&server,
- sizeof(server));
- ESP_LOGI(TAG, "100 Trying sent");
- ESP_LOGI(TAG, "stack remaining: %u",
- uxTaskGetStackHighWaterMark(NULL));
- char ok[4096];
- char sdp[1024];
- sip_build_sdp(sdp, sizeof(sdp));
- if (sip_extract_rtp_port(rx_buf, &s_rtp_peer_port))
- {
- s_rtp_peer.sin_family = AF_INET;
- s_rtp_peer.sin_port =
- htons(s_rtp_peer_port);
- s_rtp_peer.sin_addr.s_addr =
- inet_addr(ASTERISK_IP);
- ESP_LOGI(
- TAG,
- "RTP peer port=%d",
- s_rtp_peer_port
- );
- if (!rtp_socket_init())
- {
- ESP_LOGE(
- TAG,
- "RTP socket initialization failed"
- );
- continue;
- }
- }
- snprintf(ok, sizeof(ok),
- "SIP/2.0 200 OK\r\n"
- "Via: %s\r\n"
- "From: %s\r\n"
- "To: %s;esp32\r\n"
- "Call-ID: %s\r\n"
- "CSeq: %s\r\n"
- "Contact: <sip:%s@%s:%d>\r\n"
- "Content-Type: application/sdp\r\n"
- "Content-Length: %d\r\n"
- "\r\n"
- "%s",
- via,
- from,
- to,
- callid,
- cseq,
- SIP_USER,
- ESP32_IP,
- SIP_LOCAL_PORT,
- strlen(sdp),
- sdp);
- ESP_LOGI(TAG, "\n========== 200 OK ==========\n%s\n============================\n", ok);
- sendto(sock,
- ok,
- strlen(ok),
- 0,
- (struct sockaddr *)&server,
- sizeof(server));
- ESP_LOGI(TAG, "200 OK sent");
- }
- else if (strncmp(rx_buf, "OPTIONS ", 8) == 0) {
- ESP_LOGI(TAG, "Received OPTIONS");
- }
- else if (strncmp(rx_buf, "ACK ", 4) == 0)
- {
- ESP_LOGI(TAG, "Received ACK");
- uint8_t test_values[] = {0xFF, 0x7F, 0x00, 0x80};
- for(int i = 0; i < 4; i++)
- {
- ESP_LOGI(TAG,
- "ulaw %02X -> %d",
- test_values[i],
- ulaw2linear(test_values[i]));
- }
- if (!call_active)
- {
- if (s_rtp_sock < 0)
- {
- ESP_LOGE(
- TAG,
- "Cannot start RTP: socket not initialized"
- );
- continue;
- }
- if (s_rtp_peer_port == 0)
- {
- ESP_LOGE(
- TAG,
- "Cannot start RTP: peer port unknown"
- );
- continue;
- }
- call_active = true;
- BaseType_t tx_ret = xTaskCreate(
- rtp_tx_task,
- "rtp_tx",
- 16384,
- NULL,
- 5,
- NULL
- );
- BaseType_t rx_ret = xTaskCreate(
- rtp_rx_task,
- "rtp_rx",
- 16384,
- NULL,
- 5,
- NULL
- );
- ESP_LOGI(
- TAG,
- "RTP tasks: TX=%d RX=%d",
- tx_ret,
- rx_ret
- );
- }
-
- }
- else if (strncmp(rx_buf, "BYE ", 4) == 0)
- {
- ESP_LOGI(TAG, "Received BYE");
- call_active = false;
- sip_send_200_ok(sock, &server, rx_buf, NULL, 0);
- }
- else {
- ESP_LOGI(TAG, "Unknown SIP message");
- }
- }
- close(sock);
- vTaskDelete(NULL);
- }
- esp_err_t sip_media_init(void)
- {
- if (s_audio_hw_ready) {
- return ESP_OK;
- }
- aec_mutex = xSemaphoreCreateMutex();
- if (aec_mutex == NULL)
- {
- ESP_LOGE(TAG, "AEC mutex failed");
- return ESP_FAIL;
- }
- ESP_LOGI(TAG, "AEC mutex=%p", aec_mutex);
- esp_err_t ret = esp_board_init(16000, 2, 32);
- if (ret != ESP_OK)
- {
- ESP_LOGE(TAG,
- "esp_board_init failed: %s",
- esp_err_to_name(ret));
- return ret;
- }
- tca9555_driver_init();
- aec_init();
- s_audio_hw_ready = true;
- ESP_LOGI(TAG,
- "Audio board initialized for live RTP media");
- return ESP_OK;
- }
|