NAudio Error question

Jan 5, 2013 at 4:31 PM

Hello guys, first NAudio library is awsome keep up the good work. :)

So I am using it with one of my project and I have created this class to play a sond when a intersection with rectangle is available :

public class Music
{
 private string fileLocation;
        private IWavePlayer waveout;
        private WaveStream outputStream;
        WaveOutEvent audio ;
        public Drum(string file)
        {
            this.fileLocation = file;
            this.waveout = new WaveOut();
            audio = new WaveOutEvent();         
        }
        static WaveStream CreateInputStream(string name)
        {
            WaveChannel32 inputStream;
            if (name.EndsWith(".wav"))
            {
                WaveStream readerStream = new WaveFileReader(name);
                if (readerStream.WaveFormat.Encoding != WaveFormatEncoding.Pcm)
                {
                    readerStream = WaveFormatConversionStream.CreatePcmStream(readerStream);
                    readerStream = new BlockAlignReductionStream(readerStream);
                }

                if (readerStream.WaveFormat.BitsPerSample != 16)
                {
                    var format = new WaveFormat(readerStream.WaveFormat.SampleRate, 16, readerStream.WaveFormat.Channels);
                    readerStream = new WaveFormatConversionStream(format, readerStream);
                }
                inputStream = new WaveChannel32(readerStream);
            }
            else
            {
                throw new InvalidOperationException("Invalid extension");
            }
            return inputStream;
        }
        public void Play()
        {        
            this.outputStream = CreateInputStream(this.fileLocation);        
            audio.Init(outputStream);
            audio.Play();          
        }
}

the problem is that I get this error when I intersect alot : AlreadyAllocated calling waveOutOpen.

My first question is how to resolve this error with the class above,and if you have time to correct my code will be greate. :)

My second question is: Is it possible to mix the sounds lets say that I have intersected with two rectangles and I want to mix the both sounds together, I now that NAudio have a mixer.


Coordinator
Jan 7, 2013 at 8:48 AM

this is because you are opening the sound card too many times. Probably a better approach would be to open the soundcard only once and mix your audio. In the NAudio WPF Demo project, I have created a Drum Machine demo which shows how this can be done. If you click the source code tab above, you can explore the code and see how the MixingSampleProvider is used for this purpose.

Mark

Jan 15, 2013 at 9:35 AM
Edited Jan 15, 2013 at 9:37 AM

Yes I am using mixer already,but the other problem I am facing is that I don't know how to clear the data entered in the WaveMixerStream32.

but I want after I play the mixed example threw DirectSoundOut() somehow to clean the mixer from all examples.
How can I do this ?

I am adding samples this way : 

 mixer.AddInputStream();
Coordinator
Jan 15, 2013 at 3:09 PM

you'd either need to remove streams from the mixer, or read out of the mixer until you reached the end of the streams. You'd probably be better off using the MixingSampleProvider as WaveMixerStream32 has some quirks.

Jan 15, 2013 at 4:14 PM

Ok I tryed it,but after I add a stream in the mixer how to get the result which I have to play threw DirectSoundOut ?

I saw you example, but I have some problems understanding it. :)

Coordinator
Jan 15, 2013 at 4:28 PM

It needs to become a waveprovider again (I'll intend to make this simpler in a future NAudio)

directSoundOut.Init(new SampleToWaveProvider(mixingSampleProvider))

Jan 18, 2013 at 10:02 PM
Edited Jan 18, 2013 at 10:04 PM

Ok so I have one last question, I hope you dont mind: 

so now I have a timer which update every 10 miliseconds, after the timer starts i do this :


 waveOutDevice.Dispose();           

SoundMixer.waveData.Clear();           

SoundMixer.ClearMixer();

after I have intersection I add WaveStream data into global list which store all the sounds: 

SoundMixer.waveData.Add(placeToPress.ChannelStream);
then I set the channelStream.Position = 0;

when I want to play it I use this :

SoundMixer.AddToMixer();            
waveOutDevice.Init(SoundMixer.MixerPlay()); //this return SampleToWaveProvider
waveOutDevice.Play();// waveOutDevice is DirectSoundOut.


If I add  Thread.Sleep(100); after the whole code I can hear sound,but before this I cant hear nothing, any idea how to do this working
without sleep method ?


Coordinator
Jan 18, 2013 at 10:09 PM

you're disposing the waveOutDevice every 10ms? It needs to be kept alive. Really you should open it once and keep it open for the whole duration of your playback.

Jan 19, 2013 at 8:27 AM

well I removed the Dispose() line but I can hear sound only if I add Thread.Sleep at the end of the timer. :)

Coordinator
Jan 21, 2013 at 6:17 AM

The idea is you create just one device, and only call Init and Play once. Then in your timer, you add inputs to the mixer. Also, starting sounds every 10ms is pretty heavy-duty. You'll be playing 100 sounds after just 1 second unless they are very short.

Feb 7, 2013 at 4:57 PM
ok I tryed to lunch you code examples, but I get alot error and when I try to read the code its a little hard to understand it.
Can you make a simple mixing example with two wave file so when you press a button or something to mix the both sounds ?