音频项目,涉及到音频的频域图绘制以及音频的保存。
因为前端摄像机一直是实时音视频流的回传,在它的音视频获取回调函数中,不能做太复杂函数处理,否则会影响音视频质量,导致数据缓冲区异常。所以用到了环。
说一下思路:取一块足够长的缓冲区(这块自己计算一下即可,选个合适的长度),作为数据存储区,声明两个指针(读写指针),两个指针独立存在:。
1:当需要往环中写数据时,先判断一下环的有效数据长度,如果有效数据长度大于所设置最大的阈值(我这里用的环的长度减去 读取一帧数据的长度作为最大阈值),此时丢掉即将写入的数据包,直接返回。
2:当需要从环中读取数据时,先判断环的有效数据长度,如果有效长度小于所设置的最小阈值(我这里用的读取一帧数据的长度作为最小阈值),此时读取数据失败,读取线程进入等待挂机状态,隔50ms之后继续读取。
下面贴两个读写的关键代码:
写数据:
void CycQueue::Add(char* data,int len)
{
int curlen = (m_writeindex + m_totsize - m_Readindex)% m_totsize;//当前的数据容量长度
if( curlen > (m_totsize - M_READSIZE))//当前的缓冲区仅剩一帧可以写,此时要等待读取,暂时抛弃一部分数据
return;
if((m_writeindex+len)>m_totsize)//大于总长度
{
int overlen = m_writeindex+len - m_totsize; //超出长度部分
int curlen = len-overlen; //可容纳长度
memcpy(m_Audio+m_writeindex,data,curlen); //写入缓冲区
memcpy(m_Audio,data+curlen,overlen); //写入缓冲区 //覆盖原来
m_writeindex = (m_writeindex+len)%m_totsize; //取余 写指针位置
}else//长度不超出
{
memcpy(m_Audio+m_writeindex,data,len);//写入缓冲区
m_writeindex+=len;
}
return;
}
读数据:
bool CycQueue::Read(char* data,int len) //仅加入缓冲区,别的还是要放在线程里处理
{
int curlen = (m_writeindex + m_totsize - m_Readindex)% m_totsize;//当前的数据容量长度
if( curlen < M_READSIZE ) //当前的缓冲区不足一帧可以读,此时要等待写入数据
return false;
if(m_Readindex + len>m_totsize)//取数据大于长度
{
int overlen = m_Readindex+len - m_totsize; //超出部分长度
int curlen = len-overlen; //可用长度
memcpy(data,m_Audio+m_Readindex,curlen);
memcpy(data+curlen,m_Audio,overlen);
m_Readindex = (m_Readindex + len)%m_totsize; //取余 读指针位置
}else
{
memcpy(data,m_Audio+m_Readindex,len);
m_Readindex+=len;
}
SaveData(data,len);
return true;
}
思路就是一个循环存储的环,不过就只是在环的两头(读、写)加了个控制判断,用来防止数据重叠覆盖,仅记录一下,留待以后方便查找。