[NotNull] private static MemoryStream NormalizeAudioData(byte[] data) { #if NCRUNCH return(new MemoryStream(data)); #endif //Construct reader which can read the audio (whatever format it is in) var reader = new StreamMediaFoundationReader(new MemoryStream(data)); var sampleProvider = reader.ToSampleProvider(); // find the max peak float max = 0; var buffer = new float[reader.WaveFormat.SampleRate]; int read; do { read = sampleProvider.Read(buffer, 0, buffer.Length); if (read > 0) { max = Math.Max(max, Enumerable.Range(0, read).Select(i => Math.Abs(buffer[i])).Max()); } } while (read > 0); if (Math.Abs(max) < float.Epsilon || max > 1.0f) { throw new InvalidOperationException("Audio normalization failed to find a reasonable peak volume"); } //Write (as wav) with soft clipping and peak volume normalization var output = new MemoryStream((int)(reader.Length * 4)); var input = new SoftClipSampleProvider(new VolumeSampleProvider(sampleProvider) { Volume = 1 / max - 0.05f }); reader.Position = 0; WaveFileWriter.WriteWavFileToStream(output, input.ToWaveProvider16()); return(output); }
public MultichannelAudioPlayer([NotNull] IVoiceChannel voiceChannel, [NotNull] IEnumerable <IChannel> sources) { _voiceChannel = voiceChannel; _threadEvent = new AutoResetEvent(true); _thread = Task.Run(ThreadEntry); //Sample provider which mixes together several sample providers _mixerInput = new MixingSampleProvider(MixingFormat) { ReadFully = true }; //Soft clip using opus var clipper = new SoftClipSampleProvider(_mixerInput.ToMono()); //resample mix format to output format _mixerOutput = new WdlResamplingSampleProvider(clipper, OutputFormat.SampleRate).ToStereo().ToWaveProvider16(); //Add all initial channels to the mixer foreach (var source in sources) { Add(source); } }