Solved

Play sounds in parallel in C# .net

Posted on 2003-11-16
8
1,054 Views
Last Modified: 2008-01-09
I am writing a .net windows application in C# and want to be able to play multiple small wavefiles in parallel (think of it say as 5 second playtime of a techno music beat that has 3, 4 or 5 different type of drum beats.. all playing at the same time).

All what I found so far is the famous winmm.dll function PlaySound()
the best I could do is play first file with SND_ASYNC and then call function again for the next wavefiles.. but this won't play the waves in parallel instead, it'll play only the last one. If I use SND_SYNC it will make sure a wavefile completes playing before playing the next.

I am stuck please advise.
0
Comment
Question by:raioo
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
8 Comments
 
LVL 22

Expert Comment

by:_TAD_
ID: 9761256


The only way to do what you are trying is to create multiple instances that run at the same time.


So in you will need to call your win api simultaneously from different class instances.

Of course, this may not solve your problem, I would have to create some test scripts to see if it can be done
0
 
LVL 1

Expert Comment

by:alkonaut
ID: 9762587
Use a DirectSound Mixer and it's a piece of cake.

http://www.codeproject.com/cs/media/audio_process.asp
0
 

Author Comment

by:raioo
ID: 9785093
For the DirectSound Mixer I find it a hassle to plug all those classes into my project, plus it seems to take it a while before it generates the output mixed wavefile. In my app, I need to play stuff fast.

_TAD_ I tried playing the sounds from different onject instances but no luck. I heard of threading.. could it be a solution? if yes, how do I use it ? the code that plays the sound look something like:

    public void play_riffs()
    {
      foreach( Riff riff in this.riffs )
      {
           riff.play();
      }
    }

and the play() method is something like:

    public void play()
    {
      /*
      Stream stream = new FileStream( wavefile, FileMode.Open );
     
      byte[] bStr = new Byte[stream.Length];
      stream.Read(bStr, 0, (int)stream.Length);

      PlaySound( bStr,
                 IntPtr.Zero,
                 (int)(sound_flags.SND_ASYNC|sound_flags.SND_MEMORY));
      */

      PlaySound( wavefile, IntPtr.Zero, (int)(sound_flags.SND_ASYNC));
    }


there could be a maximum of 5 riffs (think of them as small beats) playing at the same time (see foreach above). and this could repeat forever..
 
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 22

Expert Comment

by:_TAD_
ID: 9787848



Threading is pretty straight forward.  You have two options with threading.  

1) A simple thread
2) A thread pool

Simple threads are extremely easy to use and monitor, but the down side is that they must have a void method as an entry point.

Threadpools are a bit more complex, and in my opinion tough to use effectively, but the DO allow you to pass an object in as a parameter to its entry method.


That being said, I'll give you a quick example on how to use simple threads.


for(int i = 0; i<10; i++)
{
   Thread myThreadVar = new Thread(new ThreadStart(MyVoidFuncName));
   // Add this next line if you want this thread to die when the program is killed
   // myThreadVar.isBackground = true;
   myThreadVar.Name = "Thread " + i;
   myThreadVar.Start();
}



private void MyVoidFuncName()
{
//Do stuff...
...
..
.

for(int i=0; i<10; i++)
    Console.WriteLine(Thread.CurrentThread.Name + ":   " + i.ToString());

// I no longer need this thread
Thread.Abort();
}



The output will look something like:

Thread1: 1
Thread1: 2
Thread1: 3
Thread2: 1
Thread3: 1
Thread2: 2
Thread1: 4
Thread4: 1
...
etc.

0
 
LVL 22

Accepted Solution

by:
_TAD_ earned 125 total points
ID: 9787963


Thread pooling example, notice that the StateInfo object is passed into the functions.  This StateInfo object is optional and should contain an object that you wish to monitor across all other threads.



            private void ThreadPooling()
            {
                  textBox1.Text = "5";
                  textBox2.Text = "5";
                  textBox3.Text = "5";

                  object txt1, txt2, txt3;


                  Console.WriteLine("Main thread does some work, then sleeps.");

                  
                  // Queue the task.
                  txt1 = (object)1;
                  
       
                  // Queue the task.
                  txt2 = (object)-1;
                  
                  
                  // Queue the task.
                  txt3 = (object)5;
                  
                  ThreadPool.QueueUserWorkItem(new WaitCallback(txt1Proc), txt1);
                  ThreadPool.QueueUserWorkItem(new WaitCallback(txt2Proc), txt2);
                  ThreadPool.QueueUserWorkItem(new WaitCallback(txt3Proc), txt3);

                  while(true)
                  {
                        
                        Thread.Sleep(100);

                  }

                  Console.WriteLine("Main thread exits.");

            }



            // This thread procedure performs the task.
            private void txt1Proc(Object stateInfo)
            {
                  // No state object was passed to QueueUserWorkItem, so
                  // stateInfo is null.
                  int i = 0;
                  while (true)
                  {
                        Console.WriteLine("Hello from Pool " + i++);
                        i = Convert.ToInt32(textBox1.Text);
                        i += (int)stateInfo;

                        Thread.Sleep(i);
                  }

                  
            }

            // This thread procedure performs the task.
            private void txt2Proc(Object stateInfo)
            {
                  // No state object was passed to QueueUserWorkItem, so
                  // stateInfo is null.
                  
                  int i;
                  while (true)
                  {
                        i = Convert.ToInt32(textBox2.Text);
                        i += (int)stateInfo;
                        Console.WriteLine("Thread2: " + i.ToString());

                        Thread.Sleep(100);
                  }

            }
            // This thread procedure performs the task.
            private void txt3Proc(Object stateInfo)
            {
                  // No state object was passed to QueueUserWorkItem, so
                  // stateInfo is null.
                  
                  int i;
                  while (true)
                  {
                        i = Convert.ToInt32(textBox3.Text);
                        i += (int)stateInfo;
                        Console.WriteLine("Thread3: " + i.ToString());

                        Thread.Sleep(100);
                  }

            }
0
 

Author Comment

by:raioo
ID: 9789441
_TAD_ I will try simple threading tonight and see how it goes.. I hope it solves the problem which is the inability of my program to play multiple short wavefiles at the SAME time (which is different than asynchronousely). It seems to me that there is one and only one wave player object (maybe global) that is hidden from by PlaySound(). It also seems that this player object cannot play waves at the same time. I send him the 1st wave, he starts playing it, as soon as I send him the 2nd, he gets confused and stops playing the first and starts playing the last wave I sent it.

If I can just get hold of that wavefile player, I can tell it to play both if it can.. otherwise, I will at least be able to instantiate another wave player and tell him to play the second, third or nth wavefile..

If my theory is right about this stubborn wavefile player object, then threading won't help since all threads will be dealing with this stubborn player.
0

Featured Post

Enroll in May's Course of the Month

May’s Course of the Month is now available! Experts Exchange’s Premium Members and Team Accounts have access to a complimentary course each month as part of their membership—an extra way to increase training and boost professional development.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
linq .concat equivalent with expression syntax 4 43
array not updating 8 42
Inserting LocalDB Table to SQL Server C# 3 51
How do I "share" on social sites? 2 38
Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

738 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question