Thread 中讨论的其他器件:CC3200AUDBOOST、 CC1354P10、 CC3200
工具/软件:
好!
我正在开发一个基于网状网络的对讲机项目、该项目使用 TI LaunchPad 和 CC3200AUDBOOST 音频 BoosterPack。 我取得了良好的进展、但我目前卡在压缩麦克风输入并通过射频发送。 我非常感谢任何指导或建议!
目标
- 从读取音频 单声道麦克风 使用 I2S 在 CC3200AUDBOOST 上输入。
- 压缩音频数据(当前目标是 ADPCM 或类似的轻量级编解码器)。
- 使用通过射频(每20ms)发送255字节数据包 CC1354P10 LaunchPad 和 rfechorx/rfechotx 框架。
- 在接收端、通过解压缩和播放音频 3.5mm 扬声器输出 进行评估。
电流设置
- 消息流
i2secho.c
用作音频 I/O 的基础。 - 采样速率: 8kHz 、单声道。
- 射频数据包:
PAYLOAD_LENGTH 255
// 20ms
PACKET_INTERVAL (uint32_t)(40000 * 0.2f)
- 现在、我将成功发送和解码简单的测试音调(如0xAA/0x55模式)。 然而、我不确定如何以最佳方式构建真实的音频输入→压缩→打包。
发送模式示例(当前占位符音调)
//更新 LCD 和 LED
updateLCD (LCD_Transmission、0);
GPIO_TOGGLE (CONFIG_GPIO_GLED);
GPIO_WRITE (CONFIG_GPIO_RLED、CONFIG_GPIO_LED_OFF);
//准备数据包标头
txPacket[0]= walkie_ID;//第一个字节是 walkie ID
txPacket[1]=(uint8_t)(seqNumber >> 8);
txPacket[2]=(uint8_t)(seqNumber++);
//用一个简单的模式填充数据包的其余部分
//这将是一种表示音频的模式
for (int i = 3;i < payload_length;i++){
//创建重复图形(在0xAA 和0x55之间交替)
txPacket[i]=(i % 2)? 0xAA:0x55;
}
//发送数据包
*curtime += packet_interval;
RF_cmdPropTx.StartTime =*curtime;
RF_runCmd (rfHandle、(RF_Op*)&RF_cmdPropTx、RF_PriorityNormal、NULL、RF_EventCmdDone);
}
接收模式示例
目前、我模拟将此音调解码为样本、但它是占位符逻辑:
//检索数据包
currentDataEntry = RFQueue_getDataEntry ();
packetLength =*(uint8_t *)(&(currentDataEntry->data));
packetDataPointer =(uint8_t *)(&(currentDataEntry->data)+ 1);
memcpy (rxPacket、packetDataPointer、(packetLength + 1));
RFQueue_nextEntry();
//提取发件人 ID
uint8_t SenderID = rxPacket[0];
//如果这是我们自己的数据包或无效的发件人、则跳过处理
if (SenderID == walkie_ID || SenderID == 0){
return;//不处理我们自己的数据包
}
//如果需要、更新 LCD
if (currentLCDState!= LCD_Receiving){
updateLCD (LCD_Receiving、SenderID);
}
//确保音频播放处于活动状态
if (!i2sWriteRunning){
//确保扬声器已取消静音并且已设置音量
AudioCodec 扬声器 Unmute (AudioCodec _TI_3254、output_option);
AudioCodec 扬声器 VolCtrl (AudioCodec _TI_3254、output_option、100);
//启动 I2S 写入过程
I2S_startWrite (i2sHandle);
i2sWriteRunning = true;
}
//获取一个缓冲区以写入样本
I2S_Transaction *事务=(I2S_Transaction *) List_Get (&i2sWriteList);
如果(事务!=空){
//获取指向音频缓冲区的指针
int16_t *audioBuffer =(int16_t *)事务->bufPtr;
int bufferSize =事务-> bufSize / sizeof (int16_t);
//计算我们可以从数据包数据创建的样本数
//跳过前3个字节(发送方 ID 和序列号)
int dataBytes = packetLength - 3;
INT numSamples = 0;
//将原始数据包数据转换为音频样本
//数据包中的每个字节将创建两个音频样本
对于(int i = 0;i < dataBytes && numSamples < bufferSize - 1;I++){
uint8_t dataByte = rxPacket[i + 3];//跳过标头字节
//将前4位转换为样本
int16_t SAMPLE1 =(DataByte 和0x0F)* 2048 - 16384;//扩展至音频范围
audioBuffer[numSamples++]= Sample1;
//将第二个4位转换为样本
int16_t SAMPLE2 =(dataByte >> 4)* 2048 - 16384;//扩展至音频范围
audioBuffer[numSamples++]= Sample2;
}
//如果我们没有得到足够的数据、请静默填写其余部分
while (numSamples < buffersize){
AudioBuffer[numSamples++]= 0;
}
//更新事务大小
事务->bufSize = numSamples * sizeof (int16_t);
//添加以写入播放列表
list_put (&i2sWriteList、(List_Elem *)事务);
//设置 I2S 写入队列标头
I2S_Transaction * head =(I2S_Transaction *) List_head (&i2sWriteList);
如果(head != NULL){
I2S_setWriteQueueHead (i2sHandle、head);
}
}
}
我的主要问题
- 从 I2S 麦克风实时读取、压缩和传输音频样本的最佳方法是什么?
- 是 ADPCM 这里是一个不错的选择?
- 我是否应该将504个 PCM 样本压缩为252个 ADPCM 字节以适应每个数据包?
- 假设一个射频数据包=一帧压缩音频(例如20ms)是否安全?
- 有什么提示可以让压缩/解压缩功能可靠地处理丢弃的数据包?
感谢任何帮助!
如果有用、我很乐意分享我的 ADPCM 代码或完整的项目设置。 提前感谢任何人通过 Sub-GHz 网状网络或类似项目进行音频流式传输!