/// <summary> /// Mix the audio data to stereo. This also converts the format to PCM32Float. /// </summary> /// <param name="mutes">Channels to mute.</param> /// <param name="isRightChannel">If a channel is to be on the right.</param> /// <param name="isBoth">If channel is both.</param> public void MixToStereo(bool[] mutes = null, bool[] isRightChannel = null, bool[] isBoth = null) { //Test. if (Channels.Count < 3 && mutes == null) { return; } //Get data. if (mutes == null) { mutes = new bool[Channels.Count]; } if (isRightChannel == null) { isRightChannel = new bool[Channels.Count]; for (int i = 0; i < Channels.Count; i++) { if (i % 2 == 1) { isRightChannel[i] = true; } } } if (isBoth == null) { isBoth = new bool[Channels.Count]; if (Channels.Count % 2 != 0) { isBoth[Channels.Count - 1] = true; } } //Test. if (Channels.Count == 0 || mutes.Where(x => false).Count() == 0) { return; } //Organize tracks. List <int> lefts = new List <int>(); List <int> rights = new List <int>(); for (int i = 0; i < mutes.Length; i++) { if (!mutes[i]) { if (isBoth[i]) { lefts.Add(i); rights.Add(i); } else if (isRightChannel[i]) { rights.Add(i); } else { lefts.Add(i); } } } //Convert data. Convert(typeof(PCM32Float), BlockSamples); //Get divisors. double divL = 1 / Math.Sqrt(lefts.Count); double divR = 1 / Math.Sqrt(rights.Count); //Start mixing. List <IAudioEncoding> left = new List <IAudioEncoding>(); List <IAudioEncoding> right = new List <IAudioEncoding>(); for (int i = 0; i < NumBlocks; i++) { List <float> samplesL = new List <float>(); List <float> samplesR = new List <float>(); IAudioEncoding blockL = new PCM32Float(); IAudioEncoding blockR = new PCM32Float(); for (int j = 0; j < Channels[0][i].SampleCount(); j++) { double sampleL = 0; double sampleR = 0; for (int k = 0; k < Channels.Count; k++) { if (!mutes[k]) { if (lefts.Contains(k)) { sampleL += Channels[k][i].ToFloatPCM()[j]; } if (rights.Contains(k)) { sampleR += Channels[k][i].ToFloatPCM()[j]; } } } sampleL /= divL; if (sampleL > 1) { sampleL = 1; } if (sampleL < -1) { sampleL = -1; } samplesL.Add((float)sampleL); sampleR /= divR; if (sampleR > 1) { sampleR = 1; } if (sampleR < -1) { sampleR = -1; } samplesR.Add((float)sampleR); } blockL.FromFloatPCM(samplesL.ToArray()); blockR.FromFloatPCM(samplesR.ToArray()); left.Add(blockL); right.Add(blockR); } //Set data. Channels.Clear(); Channels.Add(left); Channels.Add(right); }
/// <summary> /// Mix the audio data to mono. This also converts the format to PCM32Float. This does not support muting everything. /// </summary> /// <param name="mutes">Channels to mute.</param> public void MixToMono(bool[] mutes = null) { //Test. if (Channels.Count < 2 && mutes == null) { return; } //Get mutes. if (mutes == null) { mutes = new bool[Channels.Count]; } //Test. if (Channels.Count == 0 || mutes.Where(x => x == false).Count() == 0) { return; } //Divisor to make audio not loud. double divisor = 1 / Math.Sqrt(mutes.Where(x => x == false).Count()); //Convert data. Convert(typeof(PCM32Float), BlockSamples); //Start mixing. List <IAudioEncoding> newData = new List <IAudioEncoding>(); for (int i = 0; i < NumBlocks; i++) { List <float> samples = new List <float>(); IAudioEncoding block = new PCM32Float(); for (int j = 0; j < Channels[0][i].SampleCount(); j++) { double sample = 0; for (int k = 0; k < Channels.Count; k++) { if (!mutes[k]) { sample += Channels[k][i].ToFloatPCM()[j]; } } sample /= divisor; if (sample > 1) { sample = 1; } if (sample < -1) { sample = -1; } samples.Add((float)sample); } block.FromFloatPCM(samples.ToArray()); newData.Add(block); } //Set data. Channels.Clear(); Channels.Add(newData); }