This project has moved and is read-only. For the latest updates, please go here.

SineWave has gaps when used with wavechannel32 and wavemixerstream32

Mar 3, 2011 at 9:32 AM

Hi@all,

i have adopted mark's example for creating a sinewave. http://mark-dot-net.blogspot.com/2009/10/playback-of-sine-wave-in-naudio.html

This works great when i directly put it into an waveout stream. 

What i wanted to have was panning and volume adjustment. For that i created an SineStream passed it to an Wave32To16Stream and this into an WaveChannel32 object. The WaveChannel32 object is given to an WaveMixerStream32 object and this is given to the WaveOut Stream. Now i have a few gaps in my sine signal. 

Can anyone explain what i'm doing wrong?

Any help is highly appreciated.

ralph

 

Here is my code

 

-- MY DLL

using System;
using NAudio.Wave;

namespace SoundGenerator.Streams {
    public class SineWaveStream : ComputedWaveStreamProvider {
        private long length = 100000000;

        int sample;

        public float Frequency { get; set; }
        public float Amplitude { get; set; }        

        public override int Read(float[] buffer, int offset, int sampleCount) {
            var sampleRate = WaveFormat.SampleRate;
            for (var n = 0; n < sampleCount; n++) {
                buffer[n + offset] = (float)(Amplitude * Math.Sin((2 * Math.PI * sample * Frequency) / sampleRate));
                sample++;
                if (sample >= sampleRate) sample = 0;
            }
            return sampleCount;
        }

        public override long Length {
            get { return length; }
        }

        public override long Position { get; set; }
    }
}

using NAudio.Wave;

namespace SoundGenerator.Streams {
    public abstract class ComputedWaveStreamProvider : WaveStream {
        private WaveFormat waveFormat;

        protected ComputedWaveStreamProvider()
            : this(44100, 1) {
        }

        protected ComputedWaveStreamProvider(int sampleRate, int channels) {
            SetWaveFormat(sampleRate, channels);
        }

        public void SetWaveFormat(int sampleRate, int channels) {
            waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channels);
        }

        public override int Read(byte[] buffer, int offset, int count) {
            var waveBuffer = new WaveBuffer(buffer);
            var samplesRequired = count / 4;
            var samplesRead = Read(waveBuffer.FloatBuffer, offset / 4, samplesRequired);
            return samplesRead * 4;
        }

        public abstract int Read(float[] buffer, int offset, int sampleCount);

        public override WaveFormat WaveFormat { get { return waveFormat; } }

    }
}


using System.Collections;
using NAudio.Wave;
using SoundGenerator.Streams;

namespace SoundGenerator {
    public static class StreamFactory {

        public static SineWaveStream GetSineWaveStream(float frequency, float amplitude) {
            // create a sine wave stream
            return new SineWaveStream { Frequency = frequency, Amplitude = amplitude };            
        }

        public static WaveChannel32 GetChannel(WaveStream stream, float volume){           
            // Cast Ieee Stream to PCM Stream. needed for WaveChannel32
            var stream16 = new Wave32To16Stream(stream);

            // create channel to have panning and volume
            return new WaveChannel32(stream16) {Position = 0, Volume = volume};
        }

        public static WaveMixerStream32 GetMixer(IEnumerable streams) {
            var mixer = new WaveMixerStream32 { AutoStop = false };
            foreach (WaveStream stream in streams){
                mixer.AddInputStream(stream);
            }
            return mixer;
        }
    }
}

-- GUI CODE

private void StartStopSineWaveStream() {
            if (waveOut == null) {
                // create mixer
                mixer = StreamFactory.GetMixer(new List<WaveStream>());

                if(checkBoxTone1.IsChecked == true){
                    AddTone1();
                }
                
                // play streams on soundcard
                waveOut = new WaveOut();
                waveOut.Init(mixer);
                waveOut.Play();               
            } else {
                waveOut.Stop();
                waveOut.Dispose();
                waveOut = null;
            }
        }
                   

        private void AddTone1(){
            sineWaveStream1 = StreamFactory.GetSineWaveStream((float)SliderFrequency1.Value, (float)SliderAmplitude1.Value);
            channel1 = StreamFactory.GetChannel(sineWaveStream1, (float)SliderVolume1.Value);
            mixer.AddInputStream(channel1);
        }