RawSourceWaveStream volume control and playback time estimation with Naudio

1.3k views Asked by At

I'm using Naudio to play audio samples from memory.

        private RawSourceWaveStream waveStream;
        private MemoryStream ms;
        private int sampleRate = 48000;
        private IWavePlayer wavePlayer;

        //generate sine wave signal
        short[] buffer = new short[(int)Math.Round(sampleRate * 10.00)];
        double amplitude = 0.25 * short.MaxValue;
        double frequency = 1000;
        for (int n = 0; n < buffer.Length; n++)
        {
            buffer[n] = (short)(amplitude * Math.Sin((2 * Math.PI * n * frequency) / sampleRate));
        }
        byte[] byteBuffer = new byte[buffer.Length * sizeof(short)];
        Buffer.BlockCopy(buffer, 0, byteBuffer, 0, byteBuffer.Length);

        //create audio player to play samples from memory
        ms = new MemoryStream(byteBuffer);
        waveStream = new RawSourceWaveStream(ms, new WaveFormat(sampleRate, 16, 1));
        //wavePlayer = new WaveOutEvent();
        wavePlayer = new DirectSoundOut();

        wavePlayer.Init(waveStream);
        wavePlayer.PlaybackStopped += wavePlayer_PlaybackStopped;

I want to control the Volume of RawSourceWaveStream for each stream separately. (I will play multiple streams).

1) It's enough to use wavePlayer.Volume = volumeSlider1.Volume;? It is deprecated.

2) I see that AudioFileReader make use of SampleChannel for Volume control. If i rewrite Read method for RawSourceWaveStream and add Volume Property should this be a good solution?

3) I want playback time estimation as best as possible (at millisecond level). I saw that the time resolution of WaveOutEvent is about hundred of milliseconds. The time resolution of DirectSoundOut is better, but still not enough.

Thank you in advance!

1

There are 1 answers

2
Mark Heath On BEST ANSWER

1) yes you can use WaveOut.Volume. Another option is to use something like VolumeSampleProvider to do the volume in our signal chain rather than on the device

2) No need to rewrite it - call the .ToSampleProvider() extension method and then pass it through a VolumeSampleProvider

3) The Position on your RawSourceStream shows you how far you have read into the file, but not accurately where playback is because some of the audio may still be buffered ready to play. Look at GetPosition() on WaveOut which returns the number of bytes played so far, and is the most accurate option available.