Does anyone have experience making audio alerts? (alert needs to play once)

 

My audio alert should trigger when a certain condition is met, it does trigger on this condition and plays the alert, but the issue I'm facing is that once the alert triggers it doesn't just play once...it sounds like someone starts suddenly playing the alert on a vinyl turntable.


I tried coding this logic with time to check if 500ms have elapsed after the alert played, then according to the documentation "PlaySound(NULL)" should stop playback. My audio file is placed in data_folder/MQL5/Files

https://www.mql5.com/en/docs/common/playsound


// global variables

input bool Audio_Alert_On_Signals = true;
input string Audio_Alert_Sound = "alert.wav";
bool audioAlertTrigger = false; 
bool alertPlayed = false;
datetime alertTime;
string audioFilePath = "\\Files\\" + Audio_Alert_Sound;
   if(Audio_Alert_On_Signals && audioAlertTrigger){
       PlaySound(audioFilePath); // Play alert sound 
       alertTime = TimeCurrent();  
       alertPlayed = true;
       audioAlertTrigger = false;
    }  
    
    // Check if 500ms have elapsed
   if (alertPlayed && int(TimeCurrent() - alertTime) >= 0.5){  
   
       // Stop playing alert
       PlaySound(NULL);
       alertPlayed = false;
   }

The alert plays at least 12 times, so this logic isn't necessarily working. Should I do something else like "if market price moves by 2 points....stop playback"? or what is the best way to go about this from your experience?

Documentation on MQL5: Common Functions / PlaySound
Documentation on MQL5: Common Functions / PlaySound
  • www.mql5.com
PlaySound - Common Functions - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
phade:

My audio alert should trigger when a certain condition is met, it does trigger on this condition and plays the alert, but the issue I'm facing is that once the alert triggers it doesn't just play once...it sounds like someone starts suddenly playing the alert on a vinyl turntable.


I tried coding this logic with time to check if 500ms have elapsed after the alert played, then according to the documentation "PlaySound(NULL)" should stop playback. My audio file is placed in data_folder/MQL5/Files

https://www.mql5.com/en/docs/common/playsound


The alert plays at least 12 times, so this logic isn't necessarily working. Should I do something else like "if market price moves by 2 points....stop playback"? or what is the best way to go about this from your experience?

maybe, depending on what you need, you could combine the playback condition with time or with new bar event.

But I would go with time, and I would use at least minute granularity, not seconds, and for sure not 500ms. I think that is to short.


 
Dominik Christian Egert #:
500ms. I think that is to short.


right, I was thinking that, I'll do some experimentation with it

 
phade:

My audio alert should trigger when a certain condition is met, it does trigger on this condition and plays the alert, but the issue I'm facing is that once the alert triggers it doesn't just play once...it sounds like someone starts suddenly playing the alert on a vinyl turntable.


I tried coding this logic with time to check if 500ms have elapsed after the alert played, then according to the documentation "PlaySound(NULL)" should stop playback. My audio file is placed in data_folder/MQL5/Files

https://www.mql5.com/en/docs/common/playsound


The alert plays at least 12 times, so this logic isn't necessarily working. Should I do something else like "if market price moves by 2 points....stop playback"? or what is the best way to go about this from your experience?

Hello 

the check for 500ms is not optimal as datetime is in seconds .

use this for checking ms

uint alertTime;

//in the trigger
alertTime=GetTickCount();

//for the check
uint now=GetTickCount();
long delta=now-alertTime;
if(now<alertTime){
delta=UINT_MAX-alertTime+now;  
}
if(delta>=500&&alertPlayed){
//stop
}
why the check if now<alertTime : i the ticks can ring around zero and start counting from there again , so what you do in this case is take the max possible ticks , subtract the start ticks , and add the current ticks (which are after 0) 
 
Lorentzos Roussos #:

Hello 

the check for 500ms is not optimal as datetime is in seconds .

use this for checking ms

Interesting logic but I'm confused about this line:

delta=UINT_MAX-alertTime+now;  

because wouldn't delta always be a huge number greater than 500 if you subtract it from UINT_MAX?

what if I just do

delta= alertTime+now;  

(but I get that it may be for optimization)

 

An alert came through and what I noticed is that it doesn't stop playback in OnCalculate until that bar is completed (the bar where the alert triggered). My idea now is to try a condition like this:

PlaySound(audioFilePath);

if(audioPlayed)
{
	if (i > startBar && low[i] != low[i-1])
	{
	    PlaySound(NULL); 
	}
} 
 
phade #:

Interesting logic but I'm confused about this line:

because wouldn't delta always be a huge number greater than 500 if you subtract it from UINT_MAX?

what if I just do


(but I get that it may be for optimization)

Yeah imagine a giant click counter of milliseconds that goes from 0 to UINT_MAX

if you add one more tick to UINT_MAX it will become 0 and will start a new cycle.

The check is for being ready for that rare event.

So to simplify let's imagine you have a clicker that goes up to 10 . 0 to 10

if your alert starts at 5 and ends at 9 , its 4 clicks elapsed . cool

But if your alert starts at 5 and ends at 2 you would do 10-5 + 2 

 
Lorentzos Roussos #:

Yeah imagine a giant click counter of milliseconds that goes from 0 to UINT_MAX

if you add one more tick to UINT_MAX it will become 0 and will start a new cycle.

The check is for being ready for that rare event.

So to simplify let's imagine you have a clicker that goes up to 10 . 0 to 10

if your alert starts at 5 and ends at 9 , its 4 clicks elapsed . cool

But if your alert starts at 5 and ends at 2 you would do 10-5 + 2 

I see, thanks for the help. I noticed that it is performing better as well. Although I forgot to account for the fact that OnCalculate still pushes the fact that the condition is found on that bar (when the condition is met) so what happens is the whole process repeats and the alert bangs out multiple times. so I may need to implement more flags for PlaySound(NULL)

 
phade #:

I see, thanks for the help. I noticed that it is performing better as well. Although I forgot to account for the fact that OnCalculate still pushes the fact that the condition is found on that bar (when the condition is met) so what happens is the whole process repeats and the alert bangs out multiple times. so I may need to implement more flags for PlaySound(NULL)

yeah .

You can establish a dual check with whether or not a new bar has formed or it has excaped a price range around the previous alert price ,or both, to fire a new alert. 

 
phade #:

An alert came through and what I noticed is that it doesn't stop playback in OnCalculate until that bar is completed (the bar where the alert triggered). My idea now is to try a condition like this:


Don't use low, use time.


static datetime last_playsound = LONG_MAX;
if(last_playsound < time[x])
{
// New bar event

/* Your Playsound Logic here*/
PlaySound();
}
last_playsound = time[x] - (time[x] % PeriodSeconds());

 
Dominik Christian Egert #:

Don't use low, use time.

I forgot about the timebuffer in OnCalculate. This gives me ideas.

Reason: