PCM音频流多通道分离

预置条件:采样率:48kHz;通道:8通道;采样深度:16bit;帧长:256

1、获得8通道的两个通道数据时:

static int getTwoChannelsFromEightChannels(struct stream_in *in, void *buffer, size_t bytes)
{
    int ret;
    int i, j, rd_round, byte_cnt;
    int size_in_short = bytes / 2;//因为数据采样深度为16bit所以需要对数据长度做减半处理 2= 16/8
    char buf[bytes];
    short tmp_buf[bytes];
    short tmp_short1[size_in_short];
    //short tmp_short2[size_in_short];
    void *resam_buf;

    byte_cnt = 0;
    for (rd_round = 0; rd_round < 4; rd_round++) { //为满足缓存buffer的数据要求,这里选择循环4次
        memset(buf, 0x00, bytes);
        memset(tmp_buf, 0x00, bytes);
        memset(tmp_short1, 0x00, size_in_short);

        ret = pcm_read(in->pcm, buf, bytes);//4次从PCM流中读取数据,其中pcm_read为alsa的标准音频流读接口
        if (ret) {
            ALOGE("%s: pcm_read error %d", __func__, ret);
            return ret;
        }
		memcpy((short *)tmp_buf, (short *)buf, bytes);

        for (i = 0, j = 0; i < size_in_short; i++) {
			if (i % 8 == 2 || i % 8 == 3) {
                tmp_short1[j] = tmp_buf[i];
	            j++;
            }
        }
        memcpy((char *)buffer + byte_cnt, (char *)tmp_short1, j * 2);
        byte_cnt += j * 2;
    }

    return 0;
}

2、获得8通道数据中的1路数据:

static int getOneChannelFromEightChannels(struct stream_in *in, void *buffer, size_t bytes)
{
    int ret;
    int i, j, rd_round, byte_cnt;
    int size_in_short = bytes / 2;
    char buf[bytes];
    short tmp_buf[bytes];
    short tmp_short1[size_in_short];
    //short tmp_short2[size_in_short];

    byte_cnt = 0;
    for (rd_round = 0; rd_round < 8; rd_round++) {
        memset(buf, 0x00, bytes);
        memset(tmp_buf, 0x00, bytes);
        memset(tmp_short1, 0x00, size_in_short);

        ret = pcm_read(in->pcm, buf, bytes);
        if (ret) {
            ALOGE("%s: pcm_read error %d", __func__, ret);
            return ret;
        }

        memcpy((short *)tmp_buf, (short *)buf, bytes);

        for (i = 0, j = 0; i < size_in_short; i++) {
            if (i % 8 == 0) {
                //tmp_short1[j] = tmp_buf[i];
                tmp_short1[j] = timesn_volume(tmp_buf[i]);
                j++;
            }
        }
        memcpy((char *)buffer + byte_cnt, (char *)tmp_short1, j * 2);
        byte_cnt += j * 2;
        //ALOGE("%s: rd_round = %d, j = %d, byte_cnt = %d", __func__, rd_round, j, byte_cnt);
    }

    return 0;
}

3、如果在音频处理中遇到采样率改变的时候:

static int resampleOneChannelsFrom8Channels(struct stream_in *in, void *buffer,size_t bytes)
{
    int ret;
    int i, m, s,rd_round, byte_cnt_m,byte_cnt_s,byte_cnt_b;
    int size_in_short = bytes / 2;
    char buf[bytes];
    short tmp_buf[bytes];
    short tmp_short1[size_in_short];
    short tmp_short2[size_in_short];
	short tmp_short3[bytes];
    ALOGE("resample1channelfrom8channel == %d  bytes == %d", size_in_short,bytes);
    byte_cnt_m = 0;
	byte_cnt_s = 0;
	byte_cnt_b = 0;
    for (rd_round = 0; rd_round < 24; rd_round++) {//由于将采样率重48KHZ->16KHZ同时从8通道变成1通道,故需要进行24循环处理
        memset(buf, 0x00, bytes);
        memset(tmp_buf, 0x00, bytes);
        memset(tmp_short1, 0x00, size_in_short);
		memset(tmp_short2, 0x00, size_in_short);
		memset(tmp_short3, 0x00, bytes);

        ret = pcm_read(in->pcm, buf, bytes);
        if (ret) {
            ALOGE("%s: pcm_read error %d", __func__, ret);
            return ret;
        }
    #if 1
        memcpy((short *)tmp_buf, (short *)buf, bytes);
        for (i = 0, m = 0, s = 0; i < size_in_short; i++) {
            if (i % 8 == 2) {
                tmp_short1[m] = tmp_buf[i];
                m++;
            }
        }
		unsigned int inlen  = bytes/16;
		unsigned int outlen = bytes/8;	
		speex_resampler_process_int(in->dev->resampler_mic,0, (const spx_int16_t *)tmp_short1, &inlen,(short*)in->buffer_mic_16k, &outlen );//调用speex做单通道音频重采样处理48KHZ->16KHZ
		byte_cnt_m += m * 2;
    #else
        for (i = 0; i < bytes; i++) {
            if (i % 16 == 8 || i % 16 == 9 || i % 16 == 10 || i % 16 == 11) {
                *((char *)buffer + byte_cnt) = buf[i];
                byte_cnt++;
            }
        }
    #endif
        //ALOGE("%s: rd_round = %d, j = %d, byte_cnt = %d", __func__, rd_round, j, byte_cnt);
    }

    return 0;
}

4、单通道数据变换成双通道数据处理方式:

static int selectresultTwochannel(void *buffer, size_t bytes,void *buffer_aec)
{
	int ret;
	int i,j;
	int size_in_short = bytes / 2;
	short *bufferByshort = (short*)buffer_aec;//buffer_aec为一个全局buffer变量
	short *bufferByshort1 = (short*)buffer;

	for (i = 0; i < size_in_short; i++) {
		bufferByshort[2*i] =bufferByshort1[i]; 
		bufferByshort[2*i+1] =bufferByshort1[i];
    }

	//ALOGE("selectresultchannel() channel =%d to buffer",channel);
	return 0;
	
}

5、对音量进行简单增益处理:

static short volume = 4;
static void volume_process(const void *buffer, size_t length, short volume)
{
    short *buffer_end = (short *)buffer + length / 2;
    short *pcmData = (short *)buffer;
    int pcmval;

    while (pcmData < buffer_end) {
        pcmval = (short)*pcmData * volume;
        if (pcmval < 32768 && pcmval > -32768) {
            *pcmData = pcmval;
        } else if (pcmval > 32767) {
            *pcmData = 32767;
        } else if (pcmval < -32767) {
            *pcmData = -32767;
        }
        ++pcmData;
    }
}
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值