Quantcast
Channel: NAudio
Viewing all articles
Browse latest Browse all 5831

New Post: Sound won't play in exclusive mode

$
0
0
Neither DirectSoundOut nor WaveOutEvent was an option for me. Both DirectSoundOut and WaveOutEvent made audible pops at the beginning and end of playback on all the machines I used for testing. Wasapi produces no pops with the same audio files on the same test machines.

Here is how I got around the five second cut off with Wasapi used in shared mode in a Windows service.

1) I installed NuGet. http://docs.nuget.org/docs/start-here/installing-nuget
2) I got the latest version of NAudio (1.7.1) using NuGet. https://www.nuget.org/packages/NAudio
3) I used the code from this blog: http://bresleveloper.blogspot.co.il/2012/06/c-service-play-sound-with-naudio.html.
4) I modified that code. The code is reproduced below with my modification, which checks the playstate every second and waits until the file is done playing before exiting the procedure.

I hope this helps someone because getting audio to work nicely in a windows service is a pain.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;

using NAudio.Wave;
using NAudio.CoreAudioApi;
using NAudio.Wave.SampleProviders;

namespace CallAndRead
{
    public interface IInputFileFormatPlugin
    {
        string Name { get; }
        string Extension { get; }
        WaveStream CreateWaveStream(string fileName);
    }

    [Export(typeof(IInputFileFormatPlugin))]
    class WaveInputFilePlugin : IInputFileFormatPlugin
    {
        public string Name
        { get { return "WAV file"; } }
        public string Extension
        { get { return ".wav"; } }

        public WaveStream CreateWaveStream(string fileName)
        {
            WaveStream readerStream = new WaveFileReader(fileName);
            if (readerStream.WaveFormat.Encoding != WaveFormatEncoding.Pcm
                  && readerStream.WaveFormat.Encoding != WaveFormatEncoding.IeeeFloat)
            {
                readerStream = WaveFormatConversionStream.CreatePcmStream(readerStream);
                readerStream = new BlockAlignReductionStream(readerStream);
            }
            return readerStream;
        }
    }

    class WASAPI
    {
        public static void Concatenate(string outputFile, IEnumerable<string> sourceFiles)
        {
            byte[] buffer = new byte[1024];
            WaveFileWriter waveFileWriter = null;
            try
            {
                foreach (string sourceFile in sourceFiles)
                {
                    using (WaveFileReader reader = new WaveFileReader(sourceFile))
                    {
                        if (waveFileWriter == null)
                            waveFileWriter = new WaveFileWriter(outputFile, reader.WaveFormat);
                        else
                        {
                            if (!reader.WaveFormat.Equals(waveFileWriter.WaveFormat))
                                throw new InvalidOperationException(
                                         "Can't concatenate WAV Files that don't share the same format");
                        }
                        int read;
                        while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            waveFileWriter.Write(buffer, 0, read);
                        }
                    }
                }
            }
            finally
            {
                if (waveFileWriter != null)
                    waveFileWriter.Dispose();
            }
        }

        private IWavePlayer waveOut = new WasapiOut(AudioClientShareMode.Shared, 300);
        WaveStream fileWaveStream;
        Action<float> setVolumeDelegate;

        [ImportMany(typeof(IInputFileFormatPlugin))]
        public IEnumerable<IInputFileFormatPlugin> InputFileFormats { get; set; }

        void OnPreVolumeMeter(object sender, StreamVolumeEventArgs e)
        {
            // we know it is stereo
            //w aveformPainter1.AddMax(e.MaxSampleValues[0]);
            //waveformPainter2.AddMax(e.MaxSampleValues[1]);
        }

        public ISampleProvider CreateInputStream(string fileName)
        {
            var plugin = new WaveInputFilePlugin();
            if (plugin == null)
                throw new InvalidOperationException("Unsupported file extension");
            fileWaveStream = plugin.CreateWaveStream(fileName);
            var waveChannel = new SampleChannel(fileWaveStream);
            setVolumeDelegate = (vol) => waveChannel.Volume = vol;
            waveChannel.PreVolumeMeter += OnPreVolumeMeter;
            var postVolumeMeter = new MeteringSampleProvider(waveChannel);
            postVolumeMeter.StreamVolume += OnPostVolumeMeter;
            return postVolumeMeter;
        }

        void OnPostVolumeMeter(object sender, StreamVolumeEventArgs e)
        {
            // we know it is stereo
            //volumeMeter1.Amplitude = e.MaxSampleValues[0];
            //volumeMeter2.Amplitude = e.MaxSampleValues[1];
        }

        public WASAPI(string fileName)
        {
            ISampleProvider sampleProvider = null;
            sampleProvider = CreateInputStream(fileName);
            waveOut.Init(new SampleToWaveProvider(sampleProvider));
            waveOut.Play();
            while (waveOut.PlaybackState == PlaybackState.Playing)
            {
                Thread.Sleep(1000);
            }
            return;
        }
    }
}
To play a file just call this:
CallAndRead.WASAPI Player = new CallAndRead.WASAPI(<string path to audio file>);
Yeah, I know, NUTS! but it works.

-Tom

Viewing all articles
Browse latest Browse all 5831

Latest Images

Trending Articles



Latest Images