Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » is a SAMPLE playing?

Credits go to Billybob and Thomas Fjellstrom for helping out!
This thread is locked; no one can reply to it. rss feed Print
is a SAMPLE playing?
Mark Oates
Member #1,146
March 2001
avatar

I like having self-contained code, so I'm trying to figure out a way to prevent a sample from playing if it's already playing.

The way the code works, if the player is inside a "hint zone" then the sample plays looped. I want to avoid triggering the sample once, instead using a function like this:

int play_sound(SAMPLE *s, bool looped=false)
{
     if (!s) return 0;
     else if (****SAMPLE_IS_NOT_PLAYING****)
     {
         play_sample(s, 255, 128, 1000, looped);
     }
     return 1;
}

I searched the forums and found info about voice allocation. it seemed complicated and required external variables. Is there a simple way to do this?

Billybob
Member #3,136
January 2003

There's a way to do it, but from my research you're going to need that external variable.
It might be best to wrap SAMPLE into a class CSample or something.

Anyway you need to store the voice returned by play_sample. Then run voice_check on that value and see if it == the SAMPLE. If it does, the sample is playing.

EDIT: I can't find a place where SAMPLE::param is used. Does Allegro ever use it? If not you can store the voice in there, that way you won't have to make a CSample or something to contain it.
sample->param = (void *)the_voice;

will only work if sizeof(void *) == sizeof(int)

Thomas Fjellstrom
Member #476
June 2000
avatar

or instead of wrapping SAMPLE, just wrap a voice.. thats all play_sample does. This way you get greater controll over your sounds.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Mark Oates
Member #1,146
March 2001
avatar

It works, but it's ghetto:

1class sample_wrap_class
2{
3private:
4 vector<SAMPLE *> sample;
5 vector<int> voice;
6 
7public:
8 
9 void add_pair(SAMPLE *s, int v)
10 {
11 sample.push_back(s);
12 voice.push_back(v);
13 }
14
15 bool is_playing(SAMPLE *s)
16 {
17 for (int i=0; i<voice.size(); i++)
18 {
19 if (sample<i> == s) return voice_check(voice<i>);
20 }
21 return false;
22 }
23
24 void remove_reference(SAMPLE *s)
25 {
26 for (int i=0; i<voice.size(); i++)
27 {
28 if (sample<i> == s)
29 {
30 sample.erase(sample.begin() + i);
31 voice.erase(voice.begin() + i);
32 }
33 }
34 }
35
36 void update()
37 {
38 for (int i=0; i<voice.size(); i++)
39 {
40 if (!voice_check(voice<i>))
41 {
42 sample.erase(sample.begin() + i);
43 voice.erase(voice.begin() + i);
44 }
45 }
46 }
47 
48};
49 
50sample_wrap_class sample_wrap;
51 
52 
53int play_sound(SAMPLE *s, bool looped=false)
54{
55 if (!s)
56 {
57 //allegro_message("error");
58 return 0;
59 }
60 else
61 {
62 if (!sample_wrap.is_playing(s))
63 {
64 int v = play_sample(s, 255, 128, 1000, looped);
65 sample_wrap.add_pair(s, v);
66 }
67 }
68}
69 
70int stop_sound(SAMPLE *s)
71{
72 if (!s) return 0;
73 else stop_sample(s);
74}

[edit]reply for cookies

Billybob
Member #3,136
January 2003

Better than nothin'.

Neil Walker
Member #210
April 2000
avatar

[edit]Ignore this, I spewed out a whole set of code for using the voice functions and managing them via timers, etc without realising that wasn't the question. So I've deleted it.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Mark Oates
Member #1,146
March 2001
avatar

Neil: What was the code all about? I'm interested. :)

Neil Walker
Member #210
April 2000
avatar

You'll have to fill in the gaps yourself and ignore the class prefix, but...
you'll need these and set your own nice values
#define TIMER_DIGIPURGETIME 5000
#define MAXSOUNDS 32
int VoiceArray[MAXSOUNDS]; //maximum allowed voices

and maybe this somewhere:

install_int(TimerDigiPurgeNow,TIMER_DIGIPURGETIME);
void TimerDigiPurgeNow()
{
  //music handler for purging stuff
  //automatically deallocates sounds that have stopped playing
  //called every 5 seconds, which seems reasonable to me
  TimerDigiPurge=true;
}
END_OF_FUNCTION(TimerDigiPurgeNow);

Then in your timer looper say,
if(TimerDigiPurge) { SoundPurgeDigi(false); TimerDigiPurge=false;}

1int Framework::SoundPlayDigi(DATAFILE* df, int samplenum,int loopflag,int vol)
2{
3 if(vol==0) return -1;
4 else
5 {
6 return SoundPlayDigi((SAMPLE*)df[samplenum].dat,vol,loopflag);
7 }
8}
9 
10int Framework::SoundPlayDigi(SAMPLE* samp, int vol, int loopflag)
11{
12 int ret=-1; //default which is could not play
13 
14 if(vol==-1) vol=GameConfiguration->CapsSound.SampleVolume;
15 if(vol>255 || vol<0) vol=255;
16
17 if(GameConfiguration->CapsActualSystem.UseSound && vol!=0)
18 {
19 
20 //allocate a voice if possible
21 ret=allocate_voice(samp);
22 if(ret!=-1)
23 {
24 //if available add to list and play - see purgedigi/stopdigi
25 //may fail to add if system removes a lower priority voice
26 //until the purgedigi is called
27 //hopefully
28 //set sample priority
29 voice_set_playmode(ret,loopflag);
30 voice_set_volume(ret, vol);
31 voice_start(ret);
32 
33 //go through the voice array and deallocate voice if being stored
34 for(int i=0;i<GameConfiguration->CapsSound.MaxSounds;i++)
35 {
36 if(VoiceArray<i>==-1)
37 {
38 VoiceArray<i>=ret;
39 break;
40 }
41 }
42 }
43 }
44 return ret;
45}
46 
47void Framework::SoundStopDigi(int voice,bool force)
48{
49 //stop a digi playing, for example if in a loop
50 if(voice<0 && GameConfiguration->CapsActualSystem.UseSound)
51 {
52 if(force==true) deallocate_voice(voice);
53 else release_voice(voice); //allow it to finish first
54 
55 //go through the voice array and deallocate voice if being stored
56 for(int i=0;i<GameConfiguration->CapsSound.MaxSounds;i++)
57 {
58 if(VoiceArray<i>==voice)
59 {
60 VoiceArray<i>=-1;
61 break;
62 }
63 }
64 }
65}
66 
67void Framework::SoundPurgeDigi(bool killit)
68{
69 //go through the voice array and deallocate voices
70 //this is used to stop the user from having to do stopdigi
71 // to speed up call it on a timer rather than, say, every frame
72 // the game loop will do this for us automatically
73 int pos;
74 assert(GameConfiguration->CapsSound.MaxSounds<255);
75 
76 if(GameConfiguration->CapsActualSystem.UseSound)
77 {
78 //loop through array
79 for(int i=0;i<GameConfiguration->CapsSound.MaxSounds;i++)
80 {
81 //if it contains a voice get its position
82 if(VoiceArray<i>!=-1) pos=voice_get_position(VoiceArray<i>); else pos=-2;
83 
84 //if it is at the end then release it
85 if(pos==-1 || (killit==true && pos!=-2))
86 {
87 deallocate_voice(VoiceArray<i>);
88 VoiceArray<i>=-1;
89 }
90 }
91 }
92}
93 
94void Framework::SoundKillDigi()
95{
96 //stop all samples in their tracks and clear the play buffer
97 if(GameConfiguration->CapsActualSystem.UseSound)
98 {
99 //loop through array
100 for(int i=0;i<GameConfiguration->CapsSound.MaxSounds;i++)
101 {
102 //if it contains a voice get its position
103 if(VoiceArray<i>!=-1) deallocate_voice(VoiceArray<i>);
104 VoiceArray<i>=-1;
105 }
106 }
107}
108 
109int Framework::SoundDigiPos(int voice)
110{
111 if(GameConfiguration->CapsActualSystem.UseSound && voice>=0) return voice_get_position(voice);
112 else return -1;
113}

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Go to: