Can't use 2 Playsound() statments ?

Questions about MultiCharts and user contributed studies.
User avatar
TJ
Posts: 7740
Joined: 29 Aug 2006
Location: Global Citizen
Has thanked: 1033 times
Been thanked: 2221 times

Can't use 2 Playsound() statments ?

Postby TJ » 25 Aug 2008

I have 2 Playsound() statements in an indicator, but MC is only playing the second sound.

Why?

Shouldn't MC play the first playsound statement, then the second one?

Code: Select all

if H > h[1] and c < c[1] then
begin
PlaySound("c:\sound\alarm.wav");
PlaySound("c:\sound\reverse.wav");
end;

fs

Postby fs » 25 Aug 2008

It probably does play both, but since there is no delay between the two lines of code, it probably starts the 2nd one a few milliseconds after the first and it sounds like only the 2nd one is played.

I doubt that there would be many trading platforms sophisticated enough to determine when a sound file is completed and wait for it to complete before going to the next line in the code.

User avatar
TJ
Posts: 7740
Joined: 29 Aug 2006
Location: Global Citizen
Has thanked: 1033 times
Been thanked: 2221 times

Postby TJ » 25 Aug 2008

FS:

Your explanation makes sense. I have forgotten the power of multi-tasking: the operating system would start the second playsound service as soon as a CPU resource is available.
(on a Quadcore machine, it is in milliseconds for sure.)

Unless I can get the second sound file into the playlist of the first mediaplayer instance, the operating system would simply start another instance of mediaplayer and happily play the sound immediately.

Thanks for your reply.
TJ

bowlesj3
Posts: 2180
Joined: 21 Jul 2007
Has thanked: 227 times
Been thanked: 429 times

Seconds bars.

Postby bowlesj3 » 25 Aug 2008

I think you could use SecondsFromDateTime to create the required delay. I think there may be some other ones in there if you check the powerlanguage help.

Curious. Why would you want two sounds right together?

User avatar
TJ
Posts: 7740
Joined: 29 Aug 2006
Location: Global Citizen
Has thanked: 1033 times
Been thanked: 2221 times

Re: Seconds bars.

Postby TJ » 25 Aug 2008

I think you could use SecondsFromDateTime to create the required delay. I think there may be some other ones in there if you check the powerlanguage help.

Curious. Why would you want two sounds right together?
thanks for your suggestion.

The 2 sounds are for my programming flexibility.

The first sound is an alarm to alert me of the signal.
The second sound is a voice description of the signal.

I can program different types of alarm to the indicator depending on the context. e.g. MA is up, or when the price is beyond BB 2sd, etc.

User avatar
TJ
Posts: 7740
Joined: 29 Aug 2006
Location: Global Citizen
Has thanked: 1033 times
Been thanked: 2221 times

Postby TJ » 05 Sep 2008

It would be great if MC can schedule the playsounds into a queue, so that all the sounds will be played, and played in the order of trigger.

nickG
Posts: 5
Joined: 05 Mar 2008

Can't use 2 Playsound() statments ?

Postby nickG » 22 Oct 2008

It would be great if MC can schedule the playsounds into a queue, so that all the sounds will be played, and played in the order of trigger.
This is an interesting subject. Two or more PlaySound may be called from different signals on different charts simultaneously. Only one sound will play.

Putting playsounds into a queue, so that all the sounds will be played, is very much desirable.

Any suggestions from TS Support please?

nickG
Posts: 5
Joined: 05 Mar 2008

Postby nickG » 30 Jul 2009

Any suggestions from TS Support please?

bowlesj3
Posts: 2180
Joined: 21 Jul 2007
Has thanked: 227 times
Been thanked: 429 times

Postby bowlesj3 » 02 Aug 2009

I don't think you will ever get TSS resolving this issue. Here is what you will likely have to do. This is the rough logic to two functions that will be used to create the delay you need. I think I have the rough logic pretty much correct. I don't have time or need to actually do it and test it in EL code (nor is it my job) but I think you will get the drift. Maybe when you get it done and tested you can donate the code to this thread.

John.

When you need to play a sound call functionStoreSound and submit the sound number to it and submit your estimate of the number of seconds of delay needed for this sound (could be a .wav file of your voice so it could be fairly long)

immediately Call functionPlaySound that does your play sounds. There are no parameters for this function.

Note: you may be able to combine these functions.




FunctionStoreSound(soundnumber, delayseconds)============================

When a sound is to be played update a rolling GV table of sounds that need to be played. (Rolling means when the pointer is off the end you set it back to the start and you do this in a common function. So you call the function submitting the sound number and the function does the roll for you). Here is some of the rough code you need (this is not EL coding).

Add 1 to GV_Sound_Count (if it is greater than your table size then alarm an error and figure out the solution - it may require a table size increase if thee is no bug)
Add 1 to the GV_table_pointer_added. (If it is greater than the table set it to the start of the table)
Store the sound number in the GV_table where GV_table_pointer_added is pointing.
Store the sound time estimate in a second GV table. Where GV_table_pointer_added is pointing.



FunctionPlaySound ============================

The function checks a GV_Sound_Count of the number of sounds it has pending to play.

If that number is zero then exit the function now.

note that if GV_table_pointer_played = GV_table_pointer_added then you have a bug since the above if test should have kicked you out. If this test is true create an alert.

Next the function checks GV_Sounds_Done which contains the estimated time_s in HHMMSS format when the last sound should have finished. The HHMMSS format allows a direct compare.

If the current time is less than that that estimated time then exit the function now.

Okay, now we know we have at least one sound to play and all prior sounds have been completed.

Use GV_table_pointer_played to know what the sound number is to be played.
First add 1 to GV_table_pointer_played. (If it is greater than the table set it to the start of the table)
Check to ensure that there is a sound number in the table where GV_table_pointer_played is pointing.
Play the sound and update the GV_Sounds_Done as currenttime_S + the estimate for this sound.
Remember that the seconds time estimate for this sound has been put in the second table (use the same pointer GV_table_pointer_played to get at this estimate). Also note that the function AddSubSeconds_s can be used to figure out how to do the add of the seconds. Do a search of the forum to find this function. Actually here is the thread
http://forum.tssupport.com/viewtopic.ph ... ght=addsub

Subtract 1 from GV_Sound_Count (check to ensure it is not less than 0)
Last edited by bowlesj3 on 02 Aug 2009, edited 2 times in total.

User avatar
TJ
Posts: 7740
Joined: 29 Aug 2006
Location: Global Citizen
Has thanked: 1033 times
Been thanked: 2221 times

Re: Can't use 2 Playsound() statments ?

Postby TJ » 02 Aug 2009

This is an interesting subject. Two or more PlaySound may be called from different signals on different charts simultaneously. Only one sound will play.

Putting playsounds into a queue, so that all the sounds will be played, is very much desirable.

Any suggestions from TS Support please?



I have explored this multiple playsound issue a bit.

I don't think the problem is in MultiCharts.

This is just the way multi-tasking operating system and software works.

When MC encounters a playsound statement, it sends the command to the operating system and the OS plays the sound. So far so good.

If MC encounters 2 playsound statement, one after another, it sends 2 command to the operating system, one after another. and the OS plays the sound.

With today's high speed computer and multi-tasking operating system, the computer is able to play ALL the sounds "simultaneously".

But the human ear can only hear the last one.

The issues are,
1/ MC does not know the length of your sound file
2/ MC does not check to see if the OS has finished playing the 1st sound file.
3/ the play queuing responsibility should be with OS, otherwise MC will have to stop everything, wait till the 1st sound has finished playing, then start to play the 2nd sound, before it can resume other MC operations. (unless MC has a queue... which brings us to point #4 below)
4/ I am not sure if queuing is a solution. because if you have too many sounds alerts, the computer might still be playing your sounds 5 minutes after it is triggered, instead of the most current alert.

My advice is: If the alert is important to you, use the pop up text message in addition to sound.


this rambling is just my thoughts...
Last edited by TJ on 02 Aug 2009, edited 3 times in total.

brodnicki steven
Posts: 407
Joined: 01 Jan 2008
Been thanked: 3 times

Postby brodnicki steven » 02 Aug 2009

Since you play one sound right after the other, another option would be to splice the 2 sounds together into one .wav file.

bowlesj3
Posts: 2180
Joined: 21 Jul 2007
Has thanked: 227 times
Been thanked: 429 times

Postby bowlesj3 » 02 Aug 2009

I use a software in my database program that reads text to me. It instructs me throughout the day in many ways and guides me with market notices picked up in the database program with the ultimate source being MC. It works by immediately playing anything that hits the clip board buffer. Often I get a first message being cut off by a second message (it is very noticable since my text could run for 30 seconds at times). I don't think the operating system is playing 2 sounds at the same time. I think it is just issuing a new sound to the speaker function before the second one completes. It has no way of knowing how long it will take. So I have to do stuff similar to what I mentioned above when I want to resolve this issue. Often I have messages that are critical (like the wall bounce has fired) and I actually want it to cut off any other text that is being read. So in this case only the low priority messages or sounds would go to the above routine or maybe the routine could recieve a priority code and play that sound first and be smart enough to know that a message was being played and it got cut off. It could say "Interupted message replay or something" (now that is a cool idea).

Anyway I agree TJ that the popups is better. Also the routine I put together above could announce that there are two alerts waiting by having .wav files with a human voice saying how many alerts are waiting. The thing is alerts could be coming from 5 studies and the above routine could be used to centralize the information for numerous purposes I suppose. Lots of things could be done with the rough coding structure above.

Steven's idea is cool. How do you append them together? I seem to remember doing something like this once a long time ago. I suppose if you have only 3 different sounds you could create your own .wav files with your own voice with all combinations. But the problem is what if one signal comes in 3 ticks later when the first one is 1/2 finished. That could get confusing.

For me I keep it simple. One trade at a time and like many small business owners who insist in signing all cheques I write the cheque (I hit the trigger button). MC is the manager of my employees (my studies) and I am the main owner manager who manages MC with a sub manager which is the database program. My employees never talk back but they do bug me sometimes but that is my fault :-)

brodnicki steven
Posts: 407
Joined: 01 Jan 2008
Been thanked: 3 times

Postby brodnicki steven » 02 Aug 2009

I think you could combine the .wav files with a free audio editor, like "Audacity".
http://audacity.sourceforge.net/

nickG
Posts: 5
Joined: 05 Mar 2008

Postby nickG » 03 Aug 2009

Thank you all for your effort to contribute to this subject.

A few words about its importance.

It can be used on signals or on indicators running on multiple charts with different time frames. While you are concentrated on a chart you can have the audible alerts coming from other charts without much distraction of attention. Visual alerts attract attention and text popup messages need time to read and action to cancel etc.

The audible alerts come randomly from different signals or indicators, sometime may coincide partly or totally. It is useful to hear them in the order they were issued. They can be made purposely very very short so that two or three of them played in sequence may not last more than 5 to 8 seconds and not 5 minutes!

Such set up with audible alerts is the final step before a fully automated system that would have to be very complicated in view of number of charts and time frames involved.

Yes I have also investigated the subject and the problem is not with MC but with OS.

I am not a programmer and can not use very technical language. As I understand it what is needed is a program subroutine working as a buffer that will be receiving the play calls from MC, queuing them and subsequently calling playsound statements for OS to execute in sequence one after the other.

Your comments would be much appreciated.

What would expect from TSsupport is to confirm if that could be possible and if a special function in EL would be required to call this buffer subroutine or not. Since TSsuport do not seem to give some significance to this subject the rest of the work should be ours ofcource.

Nicholas

bowlesj3
Posts: 2180
Joined: 21 Jul 2007
Has thanked: 227 times
Been thanked: 429 times

Postby bowlesj3 » 03 Aug 2009

Hi nickG,

It just occured to me that I can have text being read from the clipboard buffer and I will hear a beep or other sounds and the text will not be stopped. However if the clipboard buffer has a different set of text put in there immediately the first text read is stopped and it is replaced with the second text read (there is no overlay where I hear two sets of text). It is probably exactly the same with the various sounds (beep, buzz, alarm, whatever). One is stopped and replaced with the new one. How it manages to play two of these I am not sure. Maybe one is coming from the speaker inside the computer and the other one is going to the speakers attached out the back. That would make sense.

I agree from lots of experience that sound or having text read to you is a lot better than having to read it. My trading check list is read to me. Usually the first two words and I am off to the next one (very fast). One has to keep their eye on the market. Having said that one can miss the sound and need a way to go back and find what they missed so the popup isn't that bad an idea if it has enough delay.

As far as TS support creating something automatic I can't see that ever happening. IMO it is better for the trader to create their own approach. TSS is likely to agree and they likely don't have time. By having your own routine you have complete control over any priority changes you may want in the future. Once a routine is written like I suggested above it will be a piece of cake to change it to suit your future needs. Actually it isn't that hard to create it.

bowlesj3
Posts: 2180
Joined: 21 Jul 2007
Has thanked: 227 times
Been thanked: 429 times

Postby bowlesj3 » 03 Aug 2009

It occured to me that the logic I presented above could be improved such that the FunctionStoreSound(soundnumber, delayseconds) routine could at times avoid having to load the table of delayed sounds. It would do this by first detecting that the current time is greater than the GV_Sounds_Done which contains the estimated time_s in HHMMSS format when the last sound should have finished. If it was not greater only then would it store the sound in the table. Of course if this routine did play the sound it would have to update the GV_Sounds_Done field before it left the routine. The other routine could be renamed "FunctionPlayDelayedSounds" because it would serve the purpose of playing sounds from the delayed sounds table. It has occured to me that the "FunctionPlayDelayedSounds" routine is going to have to be positioned before every call to the FunctionStoreSound(soundnumber, delayseconds) routine. This is so that the FunctionPlayDelayedSounds can play any delayed sounds first and update the GV_Sounds_Done field properly so the FunctionStoreSound(soundnumber, delayseconds) routine knows if it should store the sound in the table or not.

Also FunctionPlayDelayedSounds" is probably going to have to be positioned somewhere so it will not get bypassed by any if tests so it can be checked for pending sounds on every tick. Maybe it needs to be the very first study on the very first chart you created on your workspace. I think that may ensure it is the very first thing to be done on each new tick.

Lots of fun.

nickG
Posts: 5
Joined: 05 Mar 2008

Postby nickG » 04 Aug 2009

Hi bowlesj3,

Your ideas are very useful. However the flexibility we have depends on the other end which is the PlaySound function itself in OS.

What can or cannot be done depends on that function.

If you have further interest you can have a look at this site:

msdn.microsoft.com/en-us/library/ms712879(VS.85).aspx

I will pursue this matter further with the help of a programmer and I hope that I will come with results.

Many thanks.

bowlesj3
Posts: 2180
Joined: 21 Jul 2007
Has thanked: 227 times
Been thanked: 429 times

Postby bowlesj3 » 04 Aug 2009

Hi nickG

There is one problem with creating a delay based upon waiting for a subsequent tick to test the end time for the last sound. That would be if the ticks are coming in very slow in which case the delay may be too great. There is a thread on this where a few of us are suggesting that studies can be set to execute a few ways including based upon a fixed interval. That would solve that problem.

Maybe these sounds could be submitted to a specialized DLL outside of MC that executes based upon a regular cycle rather than ticks.

John.

nickG
Posts: 5
Joined: 05 Mar 2008

Postby nickG » 04 Aug 2009

Maybe these sounds could be submitted to a specialized DLL outside of MC that executes based upon a regular cycle rather than ticks.

John.
Hi John,

Yes this is what I mean when I am talking about a subroutine that will be working as a buffer between MC and OS. I mean a specialized DLL outside MC.

I suppose what is needed from TSS part is a reserved function (statement) to call that DLL and pass necessary parameters to it, as it is presently done by PlaySound statement. Then the DLL will handle independently the instructions back and forth with Playsound function in OS until all sounds have been played.
There should be no delay and nothing to do with next tick.

At this moment my open question is how much flexibility there is from MC to call an independent DLL outside MC.

Nicholas

bowlesj3
Posts: 2180
Joined: 21 Jul 2007
Has thanked: 227 times
Been thanked: 429 times

Postby bowlesj3 » 04 Aug 2009

I have never called a DLL except the GV ones nor written one. You can get documentation on it. I think it is pretty much the same as TS.

The database program I run can pick up GV info at a cycle rate of every 1,000th of a second if I want. Normally I do it every second. For me I would do it all through that program since I use it anyway. I have tested the actual GV set and get and it is extremely fast..

John.

bowlesj3
Posts: 2180
Joined: 21 Jul 2007
Has thanked: 227 times
Been thanked: 429 times

Postby bowlesj3 » 06 Aug 2009

nickG,

Regarding my comment above about writting DLLs, the EL_Ref_Guide.pdf in appendix D has the "EasyLanguage Tool Kit Library". At the top it says

The EasyLanguage Tool Kit Library is implemented in the form of a dynamic-link library. It provides useful functions that can be called from any user DLL. It is commonly used to find the address of an offset of an EasyLanguage data object from within a user DLL.

So I think this is the direction you need to go to answer your question. No doubt there are C programmers on this list that have written DLLs to be called from MC. I gather you can write DLLs in power basic too. I am not sure about FreeBasic. If I ever find the time I would like to do this some day. At the moment it is not a priority with me. For now my database program is more than good enough and like I said it can set up a very fast cycle to check GVs and update them back to MC. I still think that TSS should set up a way to execute a study on a cycle basis rather than having to wait for the next tick. That would solve a lot of problems.

John.

brodnicki steven
Posts: 407
Joined: 01 Jan 2008
Been thanked: 3 times

Postby brodnicki steven » 06 Aug 2009

[quote]nickG,

"Regarding my comment above about writting DLLs, the EL_Ref_Guide.pdf in appendix D has the "EasyLanguage Tool Kit Library". At the top it says

The EasyLanguage Tool Kit Library is implemented in the form of a dynamic-link library. It provides useful functions that can be called from any user DLL. It is commonly used to find the address of an offset of an EasyLanguage data object from within a user DLL.

So I think this is the direction you need to go to answer your question. No doubt there are C programmers on this list that have written DLLs to be called from MC. I gather you can write DLLs in power basic too. I am not sure about FreeBasic. If I ever find the time I would like to do this some day. At the moment it is not a priority with me. For now my database program is more than good enough and like I said it can set up a very fast cycle to check GVs and update them back to MC. I still think that TSS should set up a way to execute a study on a cycle basis rather than having to wait for the next tick. That would solve a lot of problems.

John.["


" Power Basic" is great app for writing DLL's callable by MC or TS. Many of us are not "C" programmers, so power basic is for the rest of us, that can do a little "basic " programming and want the ability to call custom DLL's.

User avatar
TJ
Posts: 7740
Joined: 29 Aug 2006
Location: Global Citizen
Has thanked: 1033 times
Been thanked: 2221 times

Postby TJ » 06 Aug 2009

I thought Microsoft has a suite of BASIC stuff for free.
Can they be used?

janus
Posts: 835
Joined: 25 May 2009
Has thanked: 63 times
Been thanked: 104 times

Postby janus » 06 Aug 2009

I did a little test to see what I could to play multiple sounds at the same time. I complied two programs, one executed this command:

sndPlaySound( "C:\sounds\alarm1.wav", SND_SYNC )

and the other:

sndPlaySound( "C:\sounds\alarm2.wav", SND_SYNC )

Both sounds played at the same time. If I executed them from the same program, only the last one played. So, what I would do is have multiple programs, each with their own sound file command. The studies can then execute them when they need to and have the sounds playing simultaneously if need be. If the sounds have to be played one at a time then as mentioned earlier a queue system is required. All this can be done in various ways using external applications and/or DLLs.

bowlesj3
Posts: 2180
Joined: 21 Jul 2007
Has thanked: 227 times
Been thanked: 429 times

Postby bowlesj3 » 07 Aug 2009

Hi Janus,

So (if I understand your test correct) if one program plays your voice on a .wav file saying "Yes" on seconds 1 and 3 and 5 then the other program has your voice saying "No" on seconds 2 and 4 and 6 then on combined playback the user would hear "yes no yes no yes no" on seconds 1,2,3,4,5,6. Is this for sure through one speaker?

Also a question. Can freebasic create DLLs for MC?

Thanks,
John

janus
Posts: 835
Joined: 25 May 2009
Has thanked: 63 times
Been thanked: 104 times

Postby janus » 07 Aug 2009

John, both audio files will be played over the top of each other. Not sure if the sequence of the words would be as described, probably by chance it would be like you described. Yes, FB does do DLLs. However, I'm not sure about the addressing scheme when passing variables. I haven't yet tried it. It should work though. I've even seen wrappers written to handle C++ classes.

bowlesj3
Posts: 2180
Joined: 21 Jul 2007
Has thanked: 227 times
Been thanked: 429 times

Postby bowlesj3 » 07 Aug 2009

thanks Janus, I guess in that case when I find the time I will check into freebasic first.
John.

Kaos
Posts: 71
Joined: 01 Mar 2006
Location: Australia
Has thanked: 3 times
Been thanked: 6 times

Re: Can't use 2 Playsound() statments ?

Postby Kaos » 02 Jun 2020

Hi All,

I just encountered this problem and searched the forums and found this old thread.

I was just wondering has anyone found a solution?

I searched and found this.
https://stackoverflow.com/questions/150 ... s-in-queue
but don't know how I could implement this "queuing" in powerlanguage

Any ideas would be appreciated
Thanks all
+++++++++++++++++++++++++++++++++++++++
// From the above website
It's the classic captured-loop-variable-in-a-closure problem.

You need to take a copy of your loop variables i.e.

foreach (string f in files.ToList())
{
var copy = f;
Console.WriteLine("Queue file: " + f);
actionQueue.Add(() => PlaySound(copy));
}


Return to “MultiCharts”