private void SetupAudioChain() { /* Obtain output device to read the rendering samplerate and initialize the mixer stream * with the target samplerate to avoid NAudio's internal ResamplerDmoStream for the target * samplerate conversion. ResamplerDmoStream works strangely and often requests zero bytes * from the audio pipeline which makes the playback stop and screws up the whole playback * in Aurio. */ MMDeviceEnumerator enumerator = new MMDeviceEnumerator(); MMDevice mmdevice = enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Console); Console.WriteLine("audio playback endpoint: " + mmdevice.FriendlyName); Console.WriteLine("format: " + mmdevice.AudioClient.MixFormat); // init mixer stream with device playback samplerate audioMixer = new MixerStream(2, DefaultSampleRate); audioVolumeControlStream = new VolumeControlStream(audioMixer); audioVolumeMeteringStream = new VolumeMeteringStream(audioVolumeControlStream); dataMonitorStream = new DataMonitorStream(audioVolumeMeteringStream); dataMonitorStream.DataRead += new EventHandler <StreamDataMonitorEventArgs>(dataMonitorStream_DataRead); VolumeClipStream volumeClipStream = new VolumeClipStream(dataMonitorStream); // resample to playback output samplerate audioOutputStream = new ResamplingStream(volumeClipStream, ResamplingQuality.Medium, mmdevice.AudioClient.MixFormat.SampleRate); audioOutput = new WasapiOut(global::NAudio.CoreAudioApi.AudioClientShareMode.Shared, true, 200); audioOutput.PlaybackStopped += new EventHandler <StoppedEventArgs>( delegate(object sender, StoppedEventArgs e) { OnCurrentTimeChanged(); Pause(); OnPlaybackPaused(); }); audioOutput.Init(new NAudioSinkStream(audioOutputStream)); }
private void btnPlay_Click(object sender, RoutedEventArgs e) { if (wavePlayer != null) { wavePlayer.Dispose(); } debugStreamController = new DebugStreamController(); MixerStream mixer = new MixerStream(2, 44100); foreach (AudioTrack audioTrack in trackListBox.Items) { WaveFileReader reader = new WaveFileReader(audioTrack.FileInfo.FullName); IeeeStream channel = new IeeeStream(new DebugStream(new NAudioSourceStream(reader), debugStreamController)); //ResamplingStream res = new ResamplingStream(new DebugStream(channel, debugStreamController), ResamplingQuality.SincBest, 22050); TimeWarpStream warp = new TimeWarpStream(new DebugStream(channel, debugStreamController)); //warp.Mappings.Add(new TimeWarp { From = new TimeSpan(audioTrack.Length.Ticks / 10 * 4), To = new TimeSpan(audioTrack.Length.Ticks / 9) }); //warp.Mappings.Add(new TimeWarp { From = new TimeSpan(audioTrack.Length.Ticks / 10 * 5), To = new TimeSpan(audioTrack.Length.Ticks / 9 * 2) }); //warp.Mappings.Add(new TimeWarp { From = new TimeSpan(audioTrack.Length.Ticks / 10 * 10), To = new TimeSpan(audioTrack.Length.Ticks / 9 * 3) }); // necessary to control each track individually VolumeControlStream volumeControl = new VolumeControlStream(new DebugStream(warp, debugStreamController)) { Mute = audioTrack.Mute, Volume = audioTrack.Volume }; // when the AudioTrack.Mute property changes, just set it accordingly on the audio stream audioTrack.MuteChanged += new EventHandler <ValueEventArgs <bool> >( delegate(object vsender, ValueEventArgs <bool> ve) { volumeControl.Mute = ve.Value; }); // when the AudioTrack.Solo property changes, we have to react in different ways: audioTrack.SoloChanged += new EventHandler <ValueEventArgs <bool> >( delegate(object vsender, ValueEventArgs <bool> ve) { AudioTrack senderTrack = (AudioTrack)vsender; bool isOtherTrackSoloed = false; foreach (AudioTrack vaudioTrack in trackListBox.Items) { if (vaudioTrack != senderTrack && vaudioTrack.Solo) { isOtherTrackSoloed = true; break; } } /* if there's at least one other track that is soloed, we set the mute property of * the current track to the opposite of the solo property: * - if the track is soloed, we unmute it * - if the track is unsoloed, we mute it */ if (isOtherTrackSoloed) { senderTrack.Mute = !ve.Value; } /* if this is the only soloed track, we mute all other tracks * if this track just got unsoloed, we unmute all other tracks */ else { foreach (AudioTrack vaudioTrack in trackListBox.Items) { if (vaudioTrack != senderTrack && !vaudioTrack.Solo) { vaudioTrack.Mute = ve.Value; } } } }); // when the AudioTrack.Volume property changes, just set it accordingly on the audio stream audioTrack.VolumeChanged += new EventHandler <ValueEventArgs <float> >( delegate(object vsender, ValueEventArgs <float> ve) { volumeControl.Volume = ve.Value; }); mixer.Add(new DebugStream(volumeControl)); } VolumeControlStream volumeControlStream = new VolumeControlStream(new DebugStream(mixer, debugStreamController)) { Volume = (float)volumeSlider.Value }; VolumeMeteringStream volumeMeteringStream = new VolumeMeteringStream(new DebugStream(volumeControlStream, debugStreamController), 5000); volumeMeteringStream.StreamVolume += new EventHandler <StreamVolumeEventArgs>(meteringStream_StreamVolume); VolumeClipStream volumeClipStream = new VolumeClipStream(new DebugStream(volumeMeteringStream, debugStreamController)); playbackStream = volumeClipStream; wavePlayer = new WaveOut(); wavePlayer.DesiredLatency = 250; wavePlayer.Init(new NAudioSinkStream(new DebugStream(playbackStream, debugStreamController))); // master volume setting volumeSlider.ValueChanged += new RoutedPropertyChangedEventHandler <double>( delegate(object vsender, RoutedPropertyChangedEventArgs <double> ve) { volumeControlStream.Volume = (float)ve.NewValue; }); lblTotalPlaybackTime.Content = TimeUtil.BytesToTimeSpan(playbackStream.Length, playbackStream.Properties); playbackSeeker.Maximum = TimeUtil.BytesToTimeSpan(playbackStream.Length, playbackStream.Properties).TotalSeconds; wavePlayer.Play(); }