Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Play two sound at once.


  • Please log in to reply
9 replies to this topic
Eedis
  • Members
  • 1775 posts
  • Last active: Aug 14 2015 06:33 PM
  • Joined: 12 Jun 2009
I was wondering how I could play two sounds at once.

SoundPlay, C:\ThisSound.wav
SoundPlay, C:\AndThis.wav

I want to play both of the sounds at the same time. Well, for a better explanation. "ThisSound.wav'' is about 5 seconds long and "AndThis.wav" is about 2 seconds long. But once it plays "AndThis.wav" it cuts off "ThisSound.wav" from finishing.

I can't use the Wait param because I want them to play at the same time.

I've solved this before by making them into two completely different scripts, the second having that simple command and use #Include, but I was wanting an easier, more cleaner, way of doing it and I don't think it'd work with compiled EXE's.

Any suggestions would be great.
AutoHotkey state, the forum, Poly, and Drainx1. The short story.
I love my wife, my life, my atomic-match; for giving me the greatest gift a man could ask for, such a perfect and beautiful little girl.
9rjbjc.png

Leef_me
  • Moderators
  • 8510 posts
  • Last active: Sep 10 2015 05:50 AM
  • Joined: 08 Apr 2009
Soundplay appears to be monophonic -- one voice

I tried settimer to launch a 2nd thread, but it operates that same way, that is the 2nd instance of SoundPlay, 'ends' the playback of the first.

The only way I was able to generate to 'overlaping' voices was to run a 2nd script.
; script1.ahk

#SingleInstance force

a=ThisSound.wav 
b=AndThis.wav

FileInstall, script2.exe, script2.exe, 0
FileInstall,%a%,%a%,0
FileInstall,%b%,%b%,0
sleep, 1000


;run, script2.ahk
run, script2.exe

SoundPlay, %a%
return

esc::exitapp

; script2.ahk

#SingleInstance force

a=ThisSound.wav 
b=AndThis.wav

FileInstall, script2.exe, script2.exe, 0
FileInstall,%a%,%a%,0
FileInstall,%b%,%b%,0
sleep, 1000


;run, script2.ahk
;run, script2.exe

;SoundPlay, %a%
SoundPlay, %b%
return

esc::exitapp



MasterFocus
  • Moderators
  • 4323 posts
  • Last active: Jan 28 2016 01:38 AM
  • Joined: 08 Apr 2009
- Playing multiple sounds parallelly or simultaneously

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Antonio Fran├ža -- git.io -- github.com -- ahk4.net -- sites.google.com -- ahkscript.org

Member of the AHK community since 08/Apr/2009. Moderator since mid-2012.


Leef_me
  • Moderators
  • 8510 posts
  • Last active: Sep 10 2015 05:50 AM
  • Joined: 08 Apr 2009

- Playing multiple sounds parallelly or simultaneously

I looked at Bass but couldn't get it to work initially, so I quit trying.


I also seem to recall there was some restriction on usage, or on developing & marketing your own derived works.

Can you confirm the limitation on usage?

TLM
  • Administrators
  • 3864 posts
  • Last active:
  • Joined: 21 Aug 2006
I wrote this little playAudio() function based on Leef_me's info to play any audio file(s), any amount of times simultaneously.
; EXAMPLES
esc::Exitapp ; <- Press escape to exit.
F1::

playAudio("soundA.wav") ; <- audio file in script directory
sleep, 500
playAudio("soundA.wav")
; playAudio("C:\Documents and Settings\User\Desktop\sound.wav") ; <- Example of an audio file in a directory.

return

playAudio(aF){
   global
   fNm++
   fLoc := a_temp, cPF := fLoc "\pF_" fNm ".ahk"
      sbCmd =
      (
         #NoTrayIcon
         cSnd := "%aF%"
         soundPlay, `% cSnd, 1
      )
   fileAppend, % sbCmd, % cPF
   if fileExist(cPF)
      run % cPF
   sleep, 500 ; <- script hangs on exit if theres no delay.
      fileDelete, % a_temp "\pF_*.ahk"
   return
}
You can call the function with the name of the audio if its in the script directory, with the full directory location or with a static or dynamic variable.

The only thing is it seems to hang if theres no pause before removing the sub command (working on a fix).

Enjoy ;)

edit:
I have to add backward compatibility so for now it only works on 10.48+
I may also add the ability to stop current playing files on script exit as very long ones can become crazy. Let me know if you need this.

Posted Image

don't duplicate, iterate!


Leef_me
  • Moderators
  • 8510 posts
  • Last active: Sep 10 2015 05:50 AM
  • Joined: 08 Apr 2009

The only thing is it seems to hang if theres no pause before removing the sub command (working on a fix).

If by "subcommand" you mean the Ahkfile that is playing the sound, try this
msgbox %A_ScriptName%
ifexist %A_ScriptName%
FileDelete, %A_ScriptName%


Leef_me
  • Moderators
  • 8510 posts
  • Last active: Sep 10 2015 05:50 AM
  • Joined: 08 Apr 2009
Laerning from TLM's version. here is another method to play multiple sound files.
You could fileinstall one utility script. Here, I call it "playit"

; main script

a=welcomebm.wav
b=welcomeam.wav
c=welcomebf.wav


ifexist, playit.exe
{
  run, playit.exe %a%
  sleep, 200
  run, playit.exe %b%
  sleep, 200
  run, playit.exe %c%

}
else
{
  run, autohotkey.exe playit.ahk "%a%"
  sleep, 200
  run, autohotkey.exe playit.ahk "%b%"
  sleep, 200
  run, autohotkey.exe playit.ahk "%c%"
}

; playit.ahk

#NoTrayIcon
SoundPlay, %1%, wait

These are fun to play with, but I realized they have a flaw.
:arrow: There is some small amount of time required before the "subcommand" can play the audio file.

The alternate would be if the "main" script created/ran/whatever one or more copies of the player, first without sounds.
And then, "send a string of any length from one script to another" <!-- m -->http://www.autohotke...s/OnMessage.htm<!-- m -->

TLM
  • Administrators
  • 3864 posts
  • Last active:
  • Joined: 21 Aug 2006

..by "subcommand" you mean the Ahkfile..

I meant to say subscript. mb ;)

The only thing is it seems to hang if theres no pause before removing the sub command (working on a fix).

These are fun to play with, but I realized they have a flaw.
:arrow: There is some small amount of time required before the "subcommand" can play the audio file.

It looks like the audio has to be loaded (or buffered) into memory before any action can be taken on the underlying 'play file'.

I found this in the ahksc
ResultType Line::SoundPlay(char *aFilespec, bool aSleepUntilDone)
{
	char *cp = omit_leading_whitespace(aFilespec);
	if (*cp == '*')
		return g_ErrorLevel->Assign(MessageBeep(ATOU(cp + 1)) ? ERRORLEVEL_NONE : ERRORLEVEL_ERROR);
		// ATOU() returns 0xFFFFFFFF for -1, which is relied upon to support the -1 sound.
	// See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_play.asp
	// for some documentation mciSendString() and related.
	char buf[MAX_PATH * 2]; // Allow room for filename and commands.
	mciSendString("status " SOUNDPLAY_ALIAS " mode", buf, sizeof(buf), NULL);
	if (*buf) // "playing" or "stopped" (so close it before trying to re-open with a new aFilespec).
		mciSendString("close " SOUNDPLAY_ALIAS, NULL, 0, NULL);
	snprintf(buf, sizeof(buf), "open "%s" alias " SOUNDPLAY_ALIAS, aFilespec);
	if (mciSendString(buf, NULL, 0, NULL)) // Failure.
		return g_ErrorLevel->Assign(ERRORLEVEL_ERROR);  // Let ErrorLevel tell the story.
	g_SoundWasPlayed = true;  // For use by Script's destructor.
	if (mciSendString("play " SOUNDPLAY_ALIAS, NULL, 0, NULL)) // Failure.
		return g_ErrorLevel->Assign(ERRORLEVEL_ERROR);  // Let ErrorLevel tell the story.
	// Otherwise, the sound is now playing.
	g_ErrorLevel->Assign(ERRORLEVEL_NONE);
	if (!aSleepUntilDone)
		return OK;
	// Otherwise, caller wants us to wait until the file is done playing.  To allow our app to remain
	// responsive during this time, use a loop that checks our message queue:
	// Older method: "mciSendString("play " SOUNDPLAY_ALIAS " wait", NULL, 0, NULL)"
	for (;;)
	{
		mciSendString("status " SOUNDPLAY_ALIAS " mode", buf, sizeof(buf), NULL);
		if (!*buf) // Probably can't happen given the state we're in.
			break;
		if (!strcmp(buf, "stopped")) // The sound is done playing.
		{
			mciSendString("close " SOUNDPLAY_ALIAS, NULL, 0, NULL);
			break;
		}
		// Sleep a little longer than normal because I'm not sure how much overhead
		// and CPU utilization the above incurs:
		MsgSleep(20);
	}
	return OK;
}

Looks like this accesses C:\WINDOWS\system32\mciwave.dll
Not sure yet what messages are returned though.

As ref'd in the sc:
<!-- m -->http://msdn.microsof...ibrary/ms712842<!-- m -->
<!-- m -->http://msdn.microsof...ibrary/ms709492<!-- m -->

edit:

This function is great for playing audio!
<!-- m -->http://www.autohotke...pic.php?t=20666<!-- m -->

Posted Image

don't duplicate, iterate!


TLM
  • Administrators
  • 3864 posts
  • Last active:
  • Joined: 21 Aug 2006
The mciSendStringA function returns 2 messages that do not reflect start play.
; http://www.autohotkey.com/forum/viewtopic.php?p=132331#132331
OnMessage(MM_MCINOTIFY   := 0x03B9, "MM_MCINOTIFY") ; <- Play complete.
OnMessage(MM_MCISIGNAL   := 0x03CB, "MM_MCISIGNAL") ; <- Device has reached a position.
MM_MCINOTIFY is still pretty useful but the whole function would have to be rewritten.

I can simulate the same thing by using a secrect MCI window (ahk_class #43) that can be used in a condition. Not 100% sure, but it should be universal.
esc::Exitapp
F1::

playAudio("soundA.wav") ; <- audio file in script directory

return

playAudio(aF){
   global
   fNm++
   cPF := a_temp "\pF_" fNm ".ahk"
      sbCmd =
      (
         #NoTrayIcon
         cSnd := "%aF%"
         soundPlay, `% cSnd, 1
      )
   fileAppend, % sbCmd, % cPF
   if fileExist(cPF)
      run % cPF,,, pfPID
   detectHiddenWindows, On
   winWaitClose, % "ahk_id " winExist("ahk_class #43")
      fileDelete, % a_temp "\pF_*.ahk"
   return
}
Anyway, if all goes well this resolves the hung function. Let me know if there are any probs with it.

So the answer to op, because of the way MCI works, 2 files can not be played at the same time by calling its play function more than once simultaneously. These workarounds will play multiple files in a pseudo fashion ;).

hth

Posted Image

don't duplicate, iterate!


None
  • Members
  • 3199 posts
  • Last active: Nov 05 2015 09:55 PM
  • Joined: 28 Nov 2009
Another option is to have the script start another instance of itself with command line params.
Uncompiled
#SingleInstance off
input=%1%
if(input<>"")
 {
  SoundPlay, C:\WINDOWS\MEDIA\%input% ,1
  ExitApp
 }

Run %A_AhkPath% "%A_ScriptFullPath%" "flourish.mid"
Run %A_AhkPath% "%A_ScriptFullPath%" "town.mid"
Compiled
#SingleInstance off
input=%1%
if(input<>"")
 {
  SoundPlay, C:\WINDOWS\MEDIA\%input% ,1
  ExitApp
 }

Run %A_ScriptFullPath% "flourish.mid"
Run %A_ScriptFullPath% "town.mid"