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.
-Tom
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







