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