gpt4 book ai didi

java - 如何混合 PCM 音频源(Java)?

转载 作者:搜寻专家 更新时间:2023-11-01 03:02:33 25 4
gpt4 key购买 nike

这是我现在正在使用的:

for (int i = 0, numSamples = soundBytes.length / 2; i < numSamples; i += 2)
{
// Get the samples.
int sample1 = ((soundBytes[i] & 0xFF) << 8) | (soundBytes[i + 1] & 0xFF); // Automatically converts to unsigned int 0...65535
int sample2 = ((outputBytes[i] & 0xFF) << 8) | (outputBytes[i + 1] & 0xFF); // Automatically converts to unsigned int 0...65535

// Normalize for simplicity.
float normalizedSample1 = sample1 / 65535.0f;
float normalizedSample2 = sample2 / 65535.0f;

float normalizedMixedSample = 0.0f;

// Apply the algorithm.
if (normalizedSample1 < 0.5f && normalizedSample2 < 0.5f)
normalizedMixedSample = 2.0f * normalizedSample1 * normalizedSample2;
else
normalizedMixedSample = 2.0f * (normalizedSample1 + normalizedSample2) - (2.0f * normalizedSample1 * normalizedSample2) - 1.0f;

int mixedSample = (int)(normalizedMixedSample * 65535);

// Replace the sample in soundBytes array with this mixed sample.
soundBytes[i] = (byte)((mixedSample >> 8) & 0xFF);
soundBytes[i + 1] = (byte)(mixedSample & 0xFF);
}

据我所知,它是此页面上定义的算法的准确表示:http://www.vttoth.com/CMS/index.php/technical-notes/68

但是,仅将声音与静音(全 0)混合会产生非常明显听起来不正确的声音,也许最好将其描述为更高音调和更响亮。

如果我能帮助确定我是否正确地实现了算法,或者我是否只是需要以不同的方式(不同的算法/方法)来处理它,我将不胜感激?

最佳答案

在链接的文章中,作者假设 AB 代表整个音频流。更具体地说,X 表示流 X 中所有样本的最大绝对值 - 其中 XAB。因此,他的算法所做的是扫描整个两个流以计算每个流的最大绝对样本,然后缩放事物以使输出理论上达到 1.0 的峰值。您需要对数据进行多次传递才能实现此算法,如果您的数据正在流入,那么它根本无法工作。

这是我认为该算法如何工作的示例。它假定样本已经转换为 float ,以解决转换代码错误的问题。我稍后会解释它有什么问题:

 double[] samplesA = ConvertToDoubles(samples1);
double[] samplesB = ConvertToDoubles(samples2);
double A = ComputeMax(samplesA);
double B = ComputeMax(samplesB);

// Z always equals 1 which is an un-useful bit of information.
double Z = A+B-A*B;

// really need to find a value x such that xA+xB=1, which I think is:
double x = 1 / (Math.sqrt(A) * Math.sqrt(B));

// Now mix and scale the samples
double[] samples = MixAndScale(samplesA, samplesB, x);

混合和缩放:

 double[] MixAndScale(double[] samplesA, double[] samplesB, double scalingFactor)
{
double[] result = new double[samplesA.length];
for (int i = 0; i < samplesA.length; i++)
result[i] = scalingFactor * (samplesA[i] + samplesB[i]);
}

计算最大峰值:

double ComputeMaxPeak(double[] samples)
{
double max = 0;
for (int i = 0; i < samples.length; i++)
{
double x = Math.abs(samples[i]);
if (x > max)
max = x;
}
return max;
}

和转换。请注意我是如何使用 short 以便正确维护符号位的:

double[] ConvertToDouble(byte[] bytes)
{
double[] samples = new double[bytes.length/2];
for (int i = 0; i < samples.length; i++)
{
short tmp = ((short)bytes[i*2])<<8 + ((short)(bytes[i*2+1]);
samples[i] = tmp / 32767.0;
}
return samples;
}

关于java - 如何混合 PCM 音频源(Java)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32019246/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com