# 三、声道

1. 立体声L,R两个声道组成，我们可以在L，R中分别填充相同的数据或者不同的数据，以达到更强的音质和可以同时在L,R听到不同的声音，排列顺序为

L,R,L,R,L,R,L,R..............

1. 而单声道通常只有一个L，或者R的数据，排列顺序为
L,L,L,L,L,L,L,L.............  或者  R,R,R,R,R,R,R,R,R...........


# 四、音频数据大小计算

16000\*2\*60/1024/1024~=1.83MB


# 五、采样率转换

5.1 分析：

5.2 引发思考：

5.3 解决思考：

10 20 30 40 90 67

．．．．．

5 10 15 20 …

typedef signed char k_sint8; //注意编译把char认为是有符号还是无符号。
typedef char k_int8; //注意编译把char认为是有符号还是无符号。
typedef unsigned char k_uint8;
typedef signed short int  k_int16;
typedef unsigned short int k_uint16;
typedef signed int k_int32;
typedef unsigned int k_uint32;
typedef signed long k_intL32;
typedef unsigned long k_uintL32;
typedef signed long long k_intLL64;
typedef unsigned long long k_uintLL64;
typedef float k_float32;
typedef double k_double64;
static k_int16 s_sample_prev = 0;

void setpresample(k_int16 sampe)
{
s_sample_prev = sampe;
}
void convert8_16k(k_int16 *psi_buff, k_int16* psi_outbuf,k_uint32 ui_samples){

k_uint32 i,j = 2;
k_uint16 us_step = 0;
us_step = ((psi_buff[0] - s_sample_prev)) / 2; //
psi_outbuf[0] = s_sample_prev + us_step;
psi_outbuf[1] = psi_buff[0]; //us_data_pre + (us_step*3)

for(i=1;i<ui_samples;i++){
us_step = (psi_buff[i] - psi_buff[i-1]) / 2;
psi_outbuf[j] =  psi_buff[i-1]+us_step;
psi_outbuf[j+1] =  psi_buff[i];
j+=2;
}
s_sample_prev = psi_buff[i-1];
}


5.4 没有倍数的采样率转换

static void resampleData(const int16_t *sourceData, int32_t sampleRate, uint32_t srcSize, int16_t *destinationData, int32_t newSampleRate,uint32_t dstSize)
{
if (sampleRate == newSampleRate)
{
memcpy(destinationData, sourceData, srcSize * sizeof(int16_t));
return;
}
uint32_t last_pos = srcSize - 1;
//LOGDV("srcSize=%d,dstSize=%d",srcSize,dstSize);
for (uint32_t idx = 0; idx < dstSize; idx++)
{
float index = ((float) idx * sampleRate) / (newSampleRate);
uint32_t p1 = (uint32_t) index;
float coef = index - p1;
uint32_t p2 = (p1 == last_pos) ? last_pos : p1 + 1;
destinationData[idx] = (int16_t) ((1.0f - coef) * sourceData[p1] + coef * sourceData[p2]);
//	LOGDV("index=%f,p1=%d,coef=%f,p2=%d",index,p1,coef,p2);
}
}


# 六、采样位宽转换

6.1 原理

1. 如果我们是低位宽转换为高位宽只需要在每个采样点中增加n个字节，并且为了保证原有的音频数据不失真的情况下，我们只需要在高位补0即可。
2.如果我们是高位宽转换为低位宽只需要在每个采样点中减少n个字节，并且为了保证原有的音频数据不失真的情况下，我们只需要把低位去除即可。

static unsigned char * bitWidthConvert(unsigned char * data, int nLen, int oldBitWidth,int newBitWidth，int trackCount）{
if(oldBitWidth==newBitWidth){
return data;
}
//位宽转换之后，需要改变的数据大小
int changeSize=0;
//位宽转换之后，目标数据的大小
int targetSize=0;
//源数据的采样点count
int samplerRate = (size% (oldBitWidth/8 * trackCount)) ==0 ? ( size/trackCount/ (oldBitWidth/8) ) : (int)( (float)(size/trackCount/(oldBitWidth/8)) +1 );
if(oldBitWidth > newBitWidth){
changeSize = ( (oldBitWidth-newBitWidth) /8 ) *samplerRate;
targetSize = size-changeSize;
}else{//oldBitWidth < newBitWidth
changeSize = ( (newBitWidth-oldBitWidth) /8 ) *samplerRate;
targetSize = size+changeSize;
}

//新的位宽的字节数
int newBitWidthByteCount= newBitWidth/8;
//旧的位宽的字节数
int oldBitWidthByteCount= oldBitWidth/8;
//目标数据
unsigned char * targetBuf = new unsigned char[targetSize];
//LOGDV("tempBitWidthTimes=%d,targetSize=%d,samplerRate=%d",tempBitWidthTimes,targetSize,samplerRate);

//临时的源数据的每个采样点的数据
uint32_t tempData;
//目标数据偏移量
int newBitWidthOffset=0;
int oldBitWidthOffset=0;

// uint32_t* data32bit=(uint32_t*)data;
if (oldBitWidth < newBitWidth){
for (int i = 0; i < samplerRate; ++i) {
memcpy(&tempData,data+oldBitWidthOffset, oldBitWidthByteCount);
oldBitWidthOffset+=oldBitWidthByteCount;
memcpy(targetBuf+newBitWidthOffset,&tempData, newBitWidthByteCount);
newBitWidthOffset+=newBitWidthByteCount;
}
}else{
for (int i = 0; i < samplerRate; ++i) {
memcpy(&tempData,data+oldBitWidthOffset, oldBitWidthByteCount);
//去除低位
tempData =  (tempData >> (oldBitWidth-newBitWidth) );
memcpy(targetBuf+newBitWidthOffset,&tempData, newBitWidthByteCount);
newBitWidthOffset+=newBitWidthByteCount;
}
}
}


# 七、声道转换

7.1原理

1. 双声道转换为单声道，只要取其中一个声道的数据即可，
2. 单声道转换为双声道，只要将单声道数据再复制一份到R的位置即可。

static unsigned char * audioTrackConvert(unsigned char * srcTrackBuf, int srcTrackLen, int nPerSampleBytesPerTrack,bool isSingleConvertDoubleTrack)
{
int targetBuflLen=0;
int offset=0;
unsigned char * targetTrackBuf;
if(isSingleConvertDoubleTrack){//单声道转双声道
targetBuflLen== srcTrackLen * 2;
targetTrackBuf= new unsigned char[targetBuflLen];
for (int i = 0; i < srcTrackLen; i+=nPerSampleBytesPerTrack)
{
for (int j = 0; j < 2; j++)
{
memcpy(targetTrackBuf + offset,
srcTrackBuf + (i*nPerSampleBytesPerTrack), nPerSampleBytesPerTrack);
offset+=nPerSampleBytesPerTrack;
}
}
}else{//双声道转单声道
targetBuflLen== srcTrackLen  /2;
targetTrackBuf= new unsigned char[targetBuflLen];
for (int i = 0; i < targetBuflLen; i+=nPerSampleBytesPerTrack)
{
memcpy(targetTrackBuf + (i*nPerSampleBytesPerTrack),
srcTrackBuf + ((i+1)*nPerSampleBytesPerTrack), nPerSampleBytesPerTrack);
}
}
return targetTrackBuf;
}



©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客