我有问题通过简单地添加两个音频样本的字节将两个不同的音频样本混合成一个.
在下面的过程中,当我尝试在媒体播放器中打开mixed.mp3文件时,它说:
Windows Media Player encountered a problem while playing the file.
- 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);
解决方法
这很可能是因为在混合之前你不是MP3文件的
decoding.而你只是“将”样本加在一起,这将导致
clipping;您应该首先使用
library将MP3文件解码为PCM,这样您就可以将它们混合使用.
要正确混合样品,您应该这样做:
- final[i] = (byte)(b1 / 2 + b2 / 2);
否则你的计算会溢出(另外,我通常建议在操作它们之前将音频标准化为浮点数).还应该注意的是,你正在混合MP3文件中的所有字节,即你正在弄乱标题(因此WMP拒绝播放你的“混合”文件).您应该只混合文件的实际音频数据(样本),而不是整个文件.
我已经使用NAudio库提供了一个(注释)工作示例1(它将混合音频导出到wav文件以避免进一步的复杂化):
- // 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,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,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);
- }
- }
1输入文件必须具有相同的采样率,位深度和通道数,才能使其正常工作.