音频处理中交织与非交织数据转换的几种方法

Posted talkaudiodev

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了音频处理中交织与非交织数据转换的几种方法相关的知识,希望对你有一定的参考价值。

当音频的声道数多于一个时,音频数据的存放有两种格式,即交织的(interleave)和非交织的(non-interleave)。以最常见的双声道为例,交织和非交织的音频数据存放如下图:

 技术图片

上图中L表示左声道数据,R表示右声道数据,整数1、2等表示第几个采样点,这样L1就表示左声道的第一个采样点数据。从上图看出,所谓交织的是指一个采样点的两个声道的数据依次放在一起,非交织的是指先放左声道的所有采样点的数据,再放右声道的所有采样点的数据。

 

在音频处理时,有时需要交织的数据,而有时又需要非交织的数据,这样就存在两种数据格式之间的转换。本文就讲讲这两种数据格式转换的两种方法,第一种是常规的简单的方法,第二种是巧妙的省memory的方法。

 

1,  常规方法

1.1   interleave 转 non-interleave

先动态申请一块memory(大小等于采样点数),把右声道的数据放在这块动态申请的memory上,同时把左声道的数据放在原buffer的前一半。然后再把动态memory上的右声道的数据放到原buffer的后一半,这样就完成了interleave到non-interleave的转换。C语言的实现代码如下:

 

int interleave2noninterleave(short *buf, int count)
{
    int i;
    short *temp;

    if(buf == NULL) {
        printf("input point buf is NULL 
");
        return -1;
    }
    
    temp = (short *)malloc(sizeof(short) * count);
    if(temp == NULL) {
        printf("memory alloc failed 
");
        return -1;
    }

    for(i = 0; i < count; i++)
    {
        temp[i] = buf[2 * i + 1];
        buf[i] = buf[2 * i];
    }

    for(i = 0; i < count; i++)
    {
        buf[count + i] = temp[i];
    }

    if(temp != NULL) {
        free(temp);
        temp = NULL;
    }

    return 0;
}  

 

1.2   non-interleave 转interleave

同样先动态申请一块memory(大小等于采样点数),把原buffer前一半的(即左声道的)数据放在这块动态申请的memory上。然后再把动态memory上的左声道的数据放到原buffer的奇数位置上,把原buffer后一半的(即右声道的)数据放到原buffer的偶数位置上,这样就完成了non-interleave到interleave的转换。C语言的实现代码如下:

 

int noninterleave2interleave(short *buf, int count)
{
    int i;
    short *temp;

    if(buf == NULL) {
        printf("input point buf is NULL 
");
        return -1;
    }
    
    temp = (short *)malloc(sizeof(short) * count);
    if(temp == NULL) {
        printf("memory alloc failed 
");
        return -1;
    }

    for(i = 0; i < count; i++)
    {
        temp[i] = buf[i];
    }

    for(i = 0; i < count; i++)
    {
        buf[2 * i] = temp[i];
        buf[2 * i + 1] = buf[count + i];

    }

    if(temp != NULL) {
        free(temp);
        temp = NULL;
    }

    return 0;
}

 

由于常规方法比较简单,这里就不详述了。

 

2, 省memory的巧妙方法

2.1 interleave 转 non-interleave

这里为了讲清楚,左右声道各有四个采样点,更多点也是一样处理。处理过程如下图:

 技术图片

第一步,将L2放在临时变量里,R1向后移一位置,再将临时变量的值(即L2)放在原buffer第二位置上;第二步,将L3放在临时变量里,R1和R2向后移一位置,再将临时变量的值(即L3)放在原buffer第三位置上;将L4放在临时变量里,R1、R2和R3向后移一位置,再将临时变量的值(即L4)放在原buffer第四位置上。这样就完成了interleave到non-interleave的转换。C语言的实现代码如下:

 

int interleave2noninterleave(short *buf, int count)
{
    int i,j;
    short temp;

    if(buf == NULL) {
        printf("input point buf is NULL 
");
        return -1;
    }
    
    for(i = 1; i < count; i++)
    {
        temp = buf[2*i];
        for(j = 0; j < i; j++)
            buf[2*i - j] = buf[2*i - j -1];
        buf[i] = temp;
    }

    return 0;
}

 

2.2 non-interleave 转interleave

这里为了讲清楚,同样左右声道各有四个采样点,更多点也是一样处理。处理过程如下图:

 技术图片

 

第一步,将R1放在临时变量里,L2、L3和L4向后移一位置,再将临时变量的值(即R1)放在原buffer第二位置上;第二步,将R2放在临时变量里,L3和L4向后移一位置,再将临时变量的值(即R2)放在原buffer第四位置上;第三步,将R3放在临时变量里,L4向后移一位置,再将临时变量的值(即R3)放在原buffer第六位置上。这样就完成了non-interleave到interleave的转换。C语言的实现代码如下:

 

int noninterleave2interleave(short *buf, int count)
{
    int i,j;
    short temp;

    if(buf == NULL) {
        printf("input point buf is NULL 
");
        return -1;
    }
    
    for(i = 0; i < count; i++) {
        temp = buf[count + i];
        for(j = 0; j < count - 1 - i; j++)
            buf[count + i - j] = buf[count + i - j -1];
        buf[2 * i + 1] = temp;
    }

    return 0;
}

 

第二种方法相对第一种少用了一块memory,更简洁,尤其适用于memory资源紧张的硬件环境里,比如DSP上,但是不如第一种通俗易懂。到底用哪一种,就取决于硬件资源了。

以上是关于音频处理中交织与非交织数据转换的几种方法的主要内容,如果未能解决你的问题,请参考以下文章

解交织 PCM (*.wav) 立体声音频数据

采用交织技术的目的以及实现方式

3D视频上下转化左右交织格式YUV

FPGA教程案例39通信案例9——基于FPGA的交织-解交织数据传输

如何在 SSE 中解交织图像通道

交织 SAS 数据集(按常见患者编号)