单声道到立体声转换

时间:2011-06-09 12:38:09

标签: c algorithm audio

我在这里遇到以下问题:我得到一个表示音频数据的字节块(uint16_t *),生成它们的设备正在捕获单声道声音,所以很明显我在1声道上有单声道音频数据。我需要将这些数据传递给另一个设备,这是期望交错的立体声数据(因此,2个通道)。我想要做的是基本上复制数据中的1个通道,以便立体声数据的两个通道都包含相同的字节。你能指点我做一个有效的算法吗?

谢谢, F。

5 个答案:

答案 0 :(得分:12)

如果你只想要交错的立体声样本,那么你可以使用这样的函数:

void interleave(const uint16_t * in_L,     // mono input buffer (left channel)
                const uint16_t * in_R,     // mono input buffer (right channel)
                uint16_t * out,            // stereo output buffer
                const size_t num_samples)  // number of samples
{
    for (size_t i = 0; i < num_samples; ++i)
    {
        out[i * 2] = in_L[i];
        out[i * 2 + 1] = in_R[i];
    }
}

要从单个单声道缓冲区生成立体声,那么您只需为in_L和in_R传递相同的指针,例如

interleave(mono_buffer, mono_buffer, stereo_buffer, num_samples);

答案 1 :(得分:2)

向两个通道传递相同的指针?如果违反了restrict规则,请使用memcpy()

很抱歉,但您的问题不是很广泛。 API? OS? CPUArchitectures?

答案 2 :(得分:1)

您可能希望就地进行转换以节省一些内存。取决于有问题的设备有多少内存。所以你可能想要使用这样的东西而不是Paul R的方法:

void interleave(uint16_t buf[], const int len)
{
    for (int i = len / 2 - 1, j = len - 1; i > 0; --i) {
        buf[j--] = buf[i];
        buf[j--] = buf[i];
    }
}

从单声道设备获取声音数据时,您需要分配一个所需大小两倍的缓冲区,并将其传递给单声道设备。这将用单声道音频填充缓冲器的一半。然后将该缓冲区传递给上面的函数,该函数将其转换为立体声。最后,您将缓冲区传递给立体声设备。您可以节省额外的分配,从而减少33%的内存用于转换。

答案 3 :(得分:0)

您将不得不复制缓冲区并复制它。由于你没有告诉我们格式,它是如何终止的,我不能给代码,但它看起来像一个简单的for循环。

int_16* allocateInterleaved(int_16* data, int length)
  int i;
  int *copy = malloc(sizeof(int_16)*length*2);
  if(copy == NULL) {
    /* handle error */
  }
  for(i =0; i<length; i++) {
    copy[2*i] = data[i];
    copy[2*i+1] = data[i]; 
  }
  return copy;
}

原谅任何明显的拼写错误,我的C有点生疏。 typdef以你需要的任何类型签署16bit到int_16。不要忘记释放复制缓冲区,或者更好地重用它。

答案 4 :(得分:0)

您需要对数据进行交织,但是如果帧长度大于1,上述解决方案均无效。以下代码可以说明可变的帧长度。

void Interleave(BYTE* left, BYTE* right, BYTE* stereo,int numSamples_in, int frameSize)
{
    int writeIndex = 0;
    for (size_t j = 0; j < numSamples_in; j++)
    {
        for (int k = 0; k < frameSize; k++)
        {
            int index = j * frameSize + k;

            stereo[k + writeIndex] = left[index];
            stereo[k + writeIndex + frameSize] = right[index];
        }
        writeIndex += 2 * frameSize;
    }
}