Files
story/firmware/echoear-platform-agent/tests/rtc-pcm-host.cjs
T
Codex Local bf1233d5df
ci / verify (push) Canceled after 0s
feat: expand companion platform, device controls, and memoir workflows
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
2026-10-08 10:06:44 +08:00

43 lines
3.6 KiB
JavaScript

// Compile actual PCM packetizer and runtime JSON with ASan/UBSan on a C host.
const fs=require('node:fs'),path=require('node:path');
const root=path.resolve(__dirname,'..');
const read=p=>fs.readFileSync(path.join(root,p),'utf8');
const src=read('components/volc_conv_ai/src/transports/high_quality/src/volc_rtc.c');
const fn=src.slice(src.indexOf('static int __rtc_send_pcm('),src.indexOf('\nint volc_rtc_send('));
const conv=read('components/application/service/conv_service/src/volc_conv.c');
const config=conv.slice(conv.indexOf('#define CONV_AI_CONFIG_FORMAT'),conv.indexOf('#define CONV_SERVICE_TIMEOUT'));
const jsonDir=path.join(process.env.IDF_PATH||'E:/Codex/toolchains/esp-idf-v5.5.1','components/json/cJSON');
process.stdout.write(fs.readFileSync(path.join(jsonDir,'cJSON.h'),'utf8')+'\n'+fs.readFileSync(path.join(jsonDir,'cJSON.c'),'utf8').replace('#include "cJSON.h"','')+`
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#define ESP_PLATFORM 1
#define ESP_AUDIO_ERR_OK 0
#define AUDIO_DATA_TYPE_PCM 5
#define AUDIO_DATA_TYPE_OPUS 1
typedef struct {int data_type;} audio_frame_info_t;
typedef struct {uint8_t *buffer;uint32_t len;} esp_audio_enc_in_frame_t;
typedef struct {uint8_t *buffer;uint32_t len,encoded_bytes;} esp_audio_enc_out_frame_t;
typedef struct {void *rtc; const char *p_channel_name; uint8_t pcm_frame[640]; size_t pcm_used;void *opus_encoder;uint8_t *opus_packet;int opus_packet_size;} rtc_impl_t;
static uint8_t received[64000]; static size_t used; static int fail;
static int esp_opus_enc_process(void *h,esp_audio_enc_in_frame_t *in,esp_audio_enc_out_frame_t *out){assert(in->len==640 && out->len==640);memcpy(out->buffer,in->buffer,640);out->encoded_bytes=640;return 0;}
static int byte_rtc_send_audio_data(void *r,const char *ch,const void *p,size_t n,audio_frame_info_t *info) {
assert(n==640 && (info->data_type==AUDIO_DATA_TYPE_PCM || info->data_type==AUDIO_DATA_TYPE_OPUS)); if(fail)return -7;
assert(used+n<=sizeof(received)); memcpy(received+used,p,n); used+=n; return 0;
}
`+fn+'\n'+config+`
int main(void) {
uint8_t input[64000]; for(size_t i=0;i<sizeof(input);i++)input[i]=(uint8_t)i;
for(int encoded=0;encoded<2;encoded++)for(size_t chunk=1;chunk<=4097;chunk+=137) {
uint8_t packet[640];rtc_impl_t rtc={.opus_encoder=encoded?(void*)1:NULL,.opus_packet=packet,.opus_packet_size=sizeof(packet)}; used=0;
for(size_t pos=0;pos<sizeof(input);) {size_t n=sizeof(input)-pos;if(n>chunk)n=chunk;assert(__rtc_send_pcm(&rtc,input+pos,n)==0);pos+=n;}
assert(rtc.pcm_used==0 && used==sizeof(input));assert(!memcmp(input,received,sizeof(input)));
}
rtc_impl_t rtc={0};fail=1;assert(__rtc_send_pcm(&rtc,input,1920)==-7);assert(rtc.pcm_used==0);fail=0;
char buf[1024];int n=snprintf(buf,sizeof(buf),CONV_AI_CONFIG_FORMAT,"instance","product","secret","device");assert(n>0 && (size_t)n<sizeof(buf));
cJSON *cfg=cJSON_Parse(buf);assert(cfg);cJSON *params=cJSON_GetObjectItem(cJSON_GetObjectItem(cfg,"rtc"),"params");assert(cJSON_IsArray(params));
int opus=0;cJSON *p; cJSON_ArrayForEach(p,params) {cJSON *j=cJSON_Parse(cJSON_GetStringValue(p));assert(j);cJSON *a=cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(j,"audio"),"codec"),"opus");if(a){opus++;assert(cJSON_GetNumberValue(cJSON_GetObjectItem(a,"s_sample_rate"))==48000);assert(cJSON_GetNumberValue(cJSON_GetObjectItem(a,"s_samples_per_frame"))==960);assert(cJSON_GetNumberValue(cJSON_GetObjectItem(a,"r_sample_rate"))==48000);assert(cJSON_GetNumberValue(cJSON_GetObjectItem(a,"r_samples_per_frame"))==960);}cJSON_Delete(j);}
assert(opus==1);cJSON_Delete(cfg);puts("RTC PCM packetizer and runtime JSON: PASS");return 0;
}
`);