C# 混合MP3文件中的两个音频样本

C# 混合MP3文件中的两个音频样本,c#,audio,C#,Audio,通过简单地添加两个音频样本的字节,我无法将两个不同的音频样本混合成一个 经过以下过程后,当我尝试在media player中打开mixed.mp3文件时,它会显示: Windows Media Player在播放文件时遇到问题 下面是我用来混合音频文件的代码: byte[] bytes1,bytes2,final; int length1,length2,max; // Getting byte[] of audio file using ( BinaryReader b = new Bina

通过简单地添加两个音频样本的字节,我无法将两个不同的音频样本混合成一个

经过以下过程后,当我尝试在media player中打开mixed.mp3文件时,它会显示:

Windows Media Player在播放文件时遇到问题

下面是我用来混合音频文件的代码:

byte[] bytes1,bytes2,final;
int length1,length2,max;

// Getting byte[] of audio file
using ( BinaryReader b = new BinaryReader(File.Open("background.mp3" , FileMode.Open)) )
{
    length1 = (int)b.BaseStream.Length;
    bytes1 = b.ReadBytes(length1);
}

using ( BinaryReader b = new BinaryReader(File.Open("voice.mp3" , FileMode.Open)) )
{
    length2 = (int)b.BaseStream.Length;
    bytes2 = b.ReadBytes(length2);
}

// Getting max length
if(length1 > length2){
    max = length1;
}else{
    max = length2;
}

// Initializing output byte[] of max length
final = new byte[max];

// Adding byte1 and byte2 and copying into final
for (int i=0;i<max;i++)
{
    byte b1 , b2;

    if(i < length1){
        b1 = bytes1[i];
    }else{
        b1 = 0;
    }

    if ( i < length2 ){
        b2 = bytes2[i];
    }
    else{
        b2 = 0;
    }

    final[i] = (byte)(b1 + b2);
}

// Writing final[] as an mp3 file
File.WriteAllBytes("mixed.mp3" , final);
字节[]字节1,字节2,最终; 内部长度1,长度2,最大值; //正在获取音频文件的字节[] 使用(BinaryReader b=newBinaryReader(File.Open(“background.mp3”,FileMode.Open))) { length1=(int)b.BaseStream.Length; bytes1=b.ReadBytes(长度1); } 使用(BinaryReader b=新的BinaryReader(File.Open(“voice.mp3”,FileMode.Open))) { length2=(int)b.BaseStream.Length; bytes2=b.ReadBytes(长度2); } //获取最大长度 如果(长度1>长度2){ 最大值=长度1; }否则{ 最大值=长度2; } //正在初始化最大长度的输出字节[] final=新字节[max]; //添加字节1和字节2并复制到最终版本
对于(int i=0;i而言,这很可能是因为在混合MP3文件之前,您不是MP3文件。您只是将样本“添加”在一起,这将导致;您应该首先使用a将MP3文件解码到PCM,然后允许您混合它们

要正确混合样品,您应执行以下操作:

final[i] = (byte)(b1 / 2 + b2 / 2);
否则,您的计算将溢出(另外,我通常建议在操作它们之前将音频标准化为
float
s)。还应注意,您正在混合MP3文件中的所有字节,即,您正在混乱标题(因此WMP拒绝播放您的“混合”文件)。您应该只混合文件的实际音频数据(样本),而不是整个文件

我使用NAudio库提供了一个(注释)工作示例1(它将混合音频导出到wav文件以避免进一步的复杂化):

//如果愿意,您可以通过NuGet获取库。
使用NAudio.波;
...
var fileA=新的音频文件读取器(“输入路径1”);
//计算缓冲区大小,因为我们正在将样本标准化为浮点数
//我们需要通过除以文件的音频字节数来说明这一点
//按其位深度/8。
var bufferA=新浮点[fileA.Length/(fileA.WaveFormat.BitsPerSample/8)];
//现在让我们用示例填充缓冲区。
fileA.Read(bufferA,0,bufferA.Length);
//为另一个文件重新做一遍。
var fileB=新的音频文件读取器(“输入路径2”);
var bufferB=新浮点[fileB.Length/(fileB.WaveFormat.BitsPerSample/8)];
fileB.Read(bufferB,0,bufferB.Length);
//计算最大的文件(比使用“if”更简单)。
var maxLen=(long)Math.Max(bufferA.Length,bufferB.Length);
var final=新字节[maxLen];
//现在,我们将把混合数据保存到wav文件中。
//(编码为MP3时,事情可能会变得有点复杂。)
使用(var writer=new waveilewriter(“输出路径”,fileA.WaveFormat))
{
对于(变量i=0;i


1输入文件必须具有相同的采样率、位深度和通道数,才能正常工作。

您的底注是什么意思?您的意思是代码现在可以工作了吗?这是不可能的。Mp3不是行波数据。像那样添加字节将100%损坏数据。不确定它对您的工作方式解码,进行计算,k记住裁剪(0..255),重新编码。你现在所做的无法工作,因为:mp3是压缩的(除非它只包含振幅数据..我不是这方面的专家)另外,当你在文件级别上工作时,你必须考虑页眉中所有不应该更改的元数据。@ Talhan-Khan:我的答案对你有用吗?@ HealEuraMaIn不。你的答案与我所做的相同,我的意思是只添加字节。
// You can get the library via NuGet if preferred.
using NAudio.Wave;

...

var fileA = new AudioFileReader("Input path 1");

// Calculate our buffer size, since we're normalizing our samples to floats
// we'll need to account for that by dividing the file's audio byte count
// by its bit depth / 8.
var bufferA = new float[fileA.Length / (fileA.WaveFormat.BitsPerSample / 8)];

// Now let's populate our buffer with samples.
fileA.Read(bufferA, 0, bufferA.Length);

// Do it all over again for the other file.
var fileB = new AudioFileReader("Input path 2");
var bufferB = new float[fileB.Length / (fileB.WaveFormat.BitsPerSample / 8)];
fileB.Read(bufferB, 0, bufferB.Length);

// Calculate the largest file (simpler than using an 'if').
var maxLen = (long)Math.Max(bufferA.Length, bufferB.Length);
var final = new byte[maxLen];

// For now, we'll just save our mixed data to a wav file.
// (Things can get a little complicated when encoding to MP3.)
using (var writer = new WaveFileWriter("Output path", fileA.WaveFormat))
{
    for (var i = 0; i < maxLen; i++)
    {
        float a, b;

        if (i < bufferA.Length)
        {
            // Reduce the amplitude of the sample by 2
            // to avoid clipping.
            a = bufferA[i] / 2;
        }
        else
        {
            a = 0;
        }

        if (i < bufferB.Length)
        {
            b = bufferB[i] / 2;
        }
        else
        {
            b = 0;
        }

        writer.WriteSample(a + b);
    }
}