ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-06-28 12:49:40  阅读:323  来源: 互联网

标签:java audio signal-processing pcm mixing


这就是我现在正在使用的内容:

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)会产生非常明显听起来不正确的声音,也许最好将其描述为更高音和更响亮.

非常感谢帮助确定我是否正确地实现了算法,或者我是否只需要以不同的方式(不同的算法/方法)来实现它?

解决方法:

在链接的文章中,作者假设A和B代表整个音频流.更具体地说,X表示流X中所有样本的最大abs值 – 其中X是A或B.所以他的算法所做的是扫描两个流的全部以计算每个流的最大abs样本然后进行比例缩放输出理论上达到峰值1.0.您需要对数据进行多次传递才能实现此算法,如果您的数据是流式传输,则它将无法正常工作.

这是我认为算法如何工作的一个例子.它假定样本已经转换为浮点到侧面步骤,转换代码的问题是错误的.我稍后会解释它有什么问题:

 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,audio,signal-processing,pcm,mixing
来源: https://codeday.me/bug/20190628/1315593.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有