如何搭配PCM音频源(Java)的? [英] How to mix PCM audio sources (Java)?

查看:171
本文介绍了如何搭配PCM音频源(Java)的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面就是我与现在的工作:

Here's what I'm working with right now:

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);
}

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

From as far as I can tell, it's an accurate representation of the algorithm defined on this page: http://www.vttoth.com/CMS/index.php/technical-notes/68

然而,仅仅混合以沉默声音(全为0),因为很明显不健全的权利健全的结果,也许这是最好的形容为高音调和响亮。

However, just mixing a sound with silence (all 0's) results in a sound that very obviously doesn't sound right, maybe it's best to describe it as higher-pitched and louder.

请问AP preciate确定,如果我正确地实现算法,或者如果我只是需要去了解它以不同的方式(不同的算法/法)帮助?

推荐答案

在链接的文章笔者假设的 A 的重新present整个流音频。更具体的 X 的指流的 X 的所有样品的最大绝对价值 - 在那里的 X 的要么是的 A 的或的。所以什么他的算法所做的是扫描两个流来计算每个的最大绝对样品的整体,然后扩展的东西,使得输出理论上为1.0的峰。你需要做过来的数据多遍为了实现这个算法,如果你的数据在那么它根本无法正常工作流。

In the linked article the author assumes A and B to represent entire streams of audio. More specifically X means the maximum abs value of all of the samples in stream X - where X is either A or B. So what his algorithm does is scans the entirety of both streams to compute the max abs sample of each and then scales things so that the output theoretically peaks at 1.0. You'll need to make multiple passes over the data in order to implement this algorithm and if your data is streaming in then it simply will not work.

下面是我怎么想的算法成功的例子。它假定样本已被转换为浮点数侧跨转换code是错误的问题。我将解释什么是错的后来:

Here is an example of how I think the algorithm to work. It assumes that the samples have already been converted to floating point to side step the issue of your conversion code being wrong. I'll explain what is wrong with it later:

 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;
}

和转换。请注意,我如何使用短,以使符号位正确保养:

And conversion. Notice how I'm using short so that the sign bit is properly maintained:

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;
}

这篇关于如何搭配PCM音频源(Java)的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆