This project has moved. For the latest updates, please go here.

Playing dynamically generated floats.

Sep 11, 2016 at 2:25 AM
A lot of the documentation I've seen is gear towards playing audio files (.wav and .mp3) I'm doing something a bit different. My application is generating sound on the fly as floating point numbers in the range of 1.0 to -1.0. Whats the easiest way to go about pushing these values out to the sound card?
Coordinator
Sep 17, 2016 at 2:19 PM
Yes, you can do this in NAudio quite easily. There are two ways. First, create an ISampleProvider implementation and in the Read method provide the number of samples asked for. This is the easiest option and is how the SignalGenerator class works if you want an example.

Alternatively, some applications may be better suited to a separate thread generating audio and putting the raw samples into a BufferedWaveProvider which is supplying the playback device. In this case you need to make sure you are producing audio in real-time so there aren't gaps in the audio, and you don't overfill the buffer.
Sep 17, 2016 at 8:52 PM
Hmm. I can't seem to make heads or tails of the SignalGenerator class or the demo that uses it. I mean I can see it's generating sound data but not where it's feeding it to so that it ultimately makes it to the sound card and speakers.


So I tried using the BufferedWaveProvider but nothing happens. No sound comes out. Is there something I missed? My class looks like this.
public class Speaker_Naudio : Speaker
    {
        BufferedWaveProvider bwp;
        public Speaker_Naudio(short BitsPerSample, short Channels, int SamplesPerSecond)
        {
            bitspersample = BitsPerSample;
            bwp = new BufferedWaveProvider(WaveFormat.CreateALawFormat(SamplesPerSecond, Channels));
        }
        public override bool BufferSoundData(double[] data)
        {
            if (bwp.BufferedBytes < data.Length)
            {
                byte[] bytebuff = FloatsToBytes(data);
                bwp.AddSamples(bytebuff, 0, bytebuff.Length);
                return true;
            }
            return false;
        }
}
Previously I was using XNA but they are dropping support for it so I'm switching away.

This class makes sound.
public class Speaker_XNA : Speaker
    {
        DynamicSoundEffectInstance DynSoundInst;
        public Speaker_XNA(short BitsPerSample, short Channels, int SamplesPerSecond)
        {
            DynSoundInst = new DynamicSoundEffectInstance(SamplesPerSecond, (AudioChannels)Channels);
            FrameworkDispatcher.Update();
            bitspersample = BitsPerSample;
            FrameworkDispatcher.Update();
        }
        override public bool BufferSoundData(double[] data)
        {
            if (DynSoundInst.PendingBufferCount <= 1)
            {
                DynSoundInst.SubmitBuffer(FloatsToBytes(data));
                DynSoundInst.Play();
                return true;
            }
            else
                return false;
        }
    }
Coordinator
Sep 20, 2016 at 12:32 PM
it's really not that hard. The Read method has a float buffer and tells you how many samples it wants. Just generate that number of samples and copy them in.

Then you can play your custom sample provider directly