1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2015-2018 Marcelo Fernandez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to
6 // deal in the Software without restriction, including without limitation the
7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 // sell copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 // IN THE SOFTWARE.
21 //-----------------------------------------------------------------------------
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "oamlCommon.h"
28
29
oamlMusicTrack(bool _verbose)30 oamlMusicTrack::oamlMusicTrack(bool _verbose) {
31 verbose = _verbose;
32 name = "Track";
33 playing = false;
34 filesSamples = 0;
35
36 playCondSamples = 0;
37 playCondAudio = -1;
38
39 fadeIn = 0;
40 fadeOut = 0;
41 xfadeIn = 0;
42 xfadeOut = 0;
43 playingOrder = 0;
44 maxPlayOrder = 0;
45
46 tailPos = 0;
47
48 curAudio = -1;
49 tailAudio = -1;
50 fadeAudio = -1;
51 }
52
~oamlMusicTrack()53 oamlMusicTrack::~oamlMusicTrack() {
54 ClearAudios(&introAudios);
55 ClearAudios(&loopAudios);
56 ClearAudios(&randAudios);
57 ClearAudios(&condAudios);
58 }
59
GetAudioByTypeId(int type,int id)60 oamlAudio *oamlMusicTrack::GetAudioByTypeId(int type, int id) {
61 switch (type) {
62 case 0:
63 if (id >= 0 && (size_t)id < introAudios.size()) {
64 return introAudios[id];
65 }
66 break;
67 case 1:
68 if (id >= 0 && (size_t)id < loopAudios.size()) {
69 return loopAudios[id];
70 }
71 break;
72 case 2:
73 if (id >= 0 && (size_t)id < randAudios.size()) {
74 return randAudios[id];
75 }
76 break;
77 case 3:
78 if (id >= 0 && (size_t)id < condAudios.size()) {
79 return condAudios[id];
80 }
81 break;
82 }
83
84 return NULL;
85 }
86
GetCurAudio()87 oamlAudio *oamlMusicTrack::GetCurAudio() {
88 return GetAudioByTypeId(curAudio >> 24, curAudio & 0xFFFFFF);
89 }
90
GetFadeAudio()91 oamlAudio *oamlMusicTrack::GetFadeAudio() {
92 return GetAudioByTypeId(fadeAudio >> 24, fadeAudio & 0xFFFFFF);
93 }
94
GetTailAudio()95 oamlAudio *oamlMusicTrack::GetTailAudio() {
96 return GetAudioByTypeId(tailAudio >> 24, tailAudio & 0xFFFFFF);
97 }
98
SetCurAudio(int type,int id)99 void oamlMusicTrack::SetCurAudio(int type, int id) {
100 curAudio = (type << 24) | (id & 0xFFFFFF);
101 }
102
AddAudio(oamlAudio * audio)103 void oamlMusicTrack::AddAudio(oamlAudio *audio) {
104 ASSERT(audio != NULL);
105
106 if (GetAudio(audio->GetName())) {
107 fprintf(stderr, "oaml: Warning, duplicated audio name: %s\n", audio->GetName().c_str());
108 }
109
110 if (audio->GetType() == 1) {
111 introAudios.push_back(audio);
112 } else if (audio->GetType() == 4) {
113 condAudios.push_back(audio);
114 } else if (audio->GetRandomChance() > 0) {
115 randAudios.push_back(audio);
116 } else {
117 loopAudios.push_back(audio);
118 }
119 }
120
GetAudio(std::string filename)121 oamlAudio* oamlMusicTrack::GetAudio(std::string filename) {
122 oamlAudio *audio;
123
124 audio = FindAudio(&introAudios, filename);
125 if (audio) return audio;
126 audio = FindAudio(&loopAudios, filename);
127 if (audio) return audio;
128 audio = FindAudio(&randAudios, filename);
129 if (audio) return audio;
130 audio = FindAudio(&condAudios, filename);
131 if (audio) return audio;
132
133 return NULL;
134 }
135
RemoveAudio(std::string filename)136 oamlRC oamlMusicTrack::RemoveAudio(std::string filename) {
137 if (FindAudioAndRemove(&introAudios, filename) == OAML_OK)
138 return OAML_OK;
139 if (FindAudioAndRemove(&loopAudios, filename) == OAML_OK)
140 return OAML_OK;
141 if (FindAudioAndRemove(&randAudios, filename) == OAML_OK)
142 return OAML_OK;
143 if (FindAudioAndRemove(&condAudios, filename) == OAML_OK)
144 return OAML_OK;
145 return OAML_NOT_FOUND;
146 }
147
SetCondition(int id,int value)148 void oamlMusicTrack::SetCondition(int id, int value) {
149 bool stopCond = false;
150 bool playCond = false;
151
152 if (playCondSamples > 0)
153 return;
154
155 if (id == OAML_CONDID_MAIN_LOOP) {
156 for (size_t i=0; i<loopAudios.size(); i++) {
157 oamlAudio *audio = loopAudios[i];
158 if (audio->HasCondition(id)) {
159 audio->SetPickable(audio->TestCondition(id, value));
160 }
161 }
162
163 if (playing == true && curAudio == -1) {
164 // If track is currently playing but no audio is actually playing this to play one
165 PlayNext();
166 }
167 return;
168 }
169
170 oamlAudio *pcurAudio = GetCurAudio();
171 for (size_t i=0; i<condAudios.size(); i++) {
172 oamlAudio *audio = condAudios[i];
173 if (audio->GetCondId() != id)
174 continue;
175
176 if (pcurAudio != audio) {
177 // Audio isn't being played right now
178 if (audio->TestCondition(id, value) == true) {
179 // Condition is true, so let's play the audio
180 if (pcurAudio == NULL || pcurAudio->GetMinMovementBars() == 0) {
181 PlayCond((3 << 24) | i);
182 } else {
183 PlayCondWithMovement((3 << 24) | i);
184 }
185
186 playCond = true;
187 }
188 } else {
189 // Audio is being played right now
190 if (audio->TestCondition(id, value) == false) {
191 stopCond = true;
192 }
193 }
194 }
195
196 if (stopCond == true && playCond == false) {
197 // No condition is being played now, let's go back to the main loop
198 if (pcurAudio == NULL || pcurAudio->GetMinMovementBars() == 0) {
199 PlayCond(-1);
200 } else {
201 PlayCondWithMovement(-1);
202 }
203 }
204 }
205
PlayCondWithMovement(int audio)206 void oamlMusicTrack::PlayCondWithMovement(int audio) {
207 oamlAudio *pcurAudio = GetCurAudio();
208 if (pcurAudio == NULL)
209 return;
210
211 playCondAudio = audio;
212 playCondSamples = pcurAudio->GetBarsSamples(pcurAudio->GetMinMovementBars());
213 if (playCondSamples == 0)
214 return;
215
216 playCondSamples = (playCondSamples + pcurAudio->GetBarsSamples(pcurAudio->GetSamplesCount() / playCondSamples) * pcurAudio->GetMinMovementBars()) - pcurAudio->GetSamplesCount();
217 // printf("%s %d\n", __FUNCTION__, playCondSamples);
218 }
219
PlayCond(int audio)220 void oamlMusicTrack::PlayCond(int audio) {
221 fadeAudio = curAudio;
222 curAudio = audio;
223
224 oamlAudio *pcurAudio = GetCurAudio();
225 if (pcurAudio == NULL) {
226 PlayNext();
227 } else {
228 pcurAudio->Open();
229 XFadePlay();
230 }
231 }
232
Play(int mainCondValue)233 oamlRC oamlMusicTrack::Play(int mainCondValue) {
234 int doFade = 0;
235
236 if (lock > 0) {
237 return OAML_ERROR;
238 }
239
240 if (verbose) __oamlLog("%s %s\n", __FUNCTION__, GetNameStr());
241 fadeAudio = -1;
242
243 if (curAudio == -1) {
244 doFade = 1;
245 }
246
247 printf("mainCondValue=%d\n", mainCondValue);
248 SetCondition(OAML_CONDID_MAIN_LOOP, mainCondValue);
249
250 playingOrder = 0;
251 maxPlayOrder = 0;
252
253 // Check if we need to use the playOrder audio property
254 size_t count = 0;
255 for (std::vector<oamlAudio*>::iterator it=loopAudios.begin(); it<loopAudios.end(); ++it) {
256 oamlAudio *audio = *it;
257 int playOrder = audio->GetPlayOrder();
258 if (playOrder != 0) {
259 if (playOrder > maxPlayOrder) {
260 maxPlayOrder = playOrder;
261 }
262 count++;
263 }
264 }
265
266 if (count == loopAudios.size()) {
267 // All of our loop audios have the playOrder property assigned, enable its use
268 playingOrder = 1;
269 }
270
271 if (introAudios.size() >= 1) {
272 if (introAudios.size() == 1) {
273 SetCurAudio(0, 0);
274 } else {
275 int i = Random(0, introAudios.size()-1);
276 SetCurAudio(0, i);
277 }
278
279 oamlAudio *audio = GetCurAudio();
280 if (audio) {
281 audio->Open();
282 }
283 } else {
284 PlayNext();
285 }
286
287 oamlAudio *pcurAudio = GetCurAudio();
288 if (doFade && pcurAudio != NULL) {
289 // First check the fade in property for the audio and then the track fade in property
290 if (pcurAudio->GetFadeIn()) {
291 pcurAudio->DoFadeIn(pcurAudio->GetFadeIn());
292 } else if (fadeIn) {
293 pcurAudio->DoFadeIn(fadeIn);
294 }
295 }
296
297 playing = true;
298
299 return OAML_OK;
300 }
301
PickNextAudio()302 int oamlMusicTrack::PickNextAudio() {
303 if (verbose) __oamlLog("%s %s\n", __FUNCTION__, GetNameStr());
304
305 oamlAudio *pcurAudio = GetCurAudio();
306 if (randAudios.size() > 0 && (pcurAudio == NULL || pcurAudio->GetRandomChance() == 0)) {
307 for (size_t i=0; i<randAudios.size(); i++) {
308 int chance = randAudios[i]->GetRandomChance();
309 if (Random(0, 100) > chance) {
310 continue;
311 } else {
312 return (3 << 24) | (i & 0xFFFFFF);
313 }
314 }
315 }
316
317 if (loopAudios.size() == 1) {
318 return (1 << 24) | (0 & 0xFFFFFF);
319 } else if (loopAudios.size() >= 2) {
320 std::vector<int> list;
321
322 for (size_t i=0; i<loopAudios.size(); i++) {
323 oamlAudio *audio = loopAudios[i];
324 if (audio->IsPickable()) {
325 if (playingOrder != 0 && audio->GetPlayOrder() != playingOrder) {
326 continue;
327 }
328 list.push_back((1 << 24) | (i & 0xFFFFFF));
329 }
330 }
331
332 if (playingOrder != 0) {
333 playingOrder++;
334 if (playingOrder > maxPlayOrder) {
335 playingOrder = 1;
336 }
337 }
338
339 if (list.size() == 0) {
340 return -1;
341 } else if (list.size() == 1) {
342 return list[0];
343 } else {
344 int r = Random(0, list.size()-1);
345 while (curAudio == list[r]) {
346 r = Random(0, list.size()-1);
347 }
348
349 return list[r];
350 }
351 }
352
353 return -1;
354 }
355
PlayNext()356 void oamlMusicTrack::PlayNext() {
357 if (verbose) __oamlLog("%s %s\n", __FUNCTION__, GetNameStr());
358
359 oamlAudio *pcurAudio = GetCurAudio();
360 if (pcurAudio) {
361 if (pcurAudio->GetType() == 4) {
362 tailAudio = curAudio;
363 tailPos = pcurAudio->GetSamplesCount();
364
365 pcurAudio->Open();
366 return;
367 }
368 }
369
370 if (fadeAudio == -1)
371 fadeAudio = curAudio;
372
373 curAudio = PickNextAudio();
374 pcurAudio = GetCurAudio();
375 if (pcurAudio)
376 pcurAudio->Open();
377
378 if (fadeAudio != curAudio) {
379 XFadePlay();
380 } else {
381 fadeAudio = -1;
382 }
383 }
384
XFadePlay()385 void oamlMusicTrack::XFadePlay() {
386 oamlAudio *pcurAudio = GetCurAudio();
387 oamlAudio *pfadeAudio = GetFadeAudio();
388 if (pcurAudio) {
389 // First check the fade in property for the audio and then the track fade in property
390 if (pcurAudio->GetXFadeIn()) {
391 pcurAudio->DoFadeIn(pcurAudio->GetXFadeIn());
392 } else if (pfadeAudio && pfadeAudio->GetXFadeIn()) {
393 pcurAudio->DoFadeIn(pfadeAudio->GetXFadeIn());
394 } else if (xfadeIn) {
395 pcurAudio->DoFadeIn(xfadeIn);
396 }
397 }
398
399 if (pfadeAudio) {
400 if (pcurAudio && pcurAudio->GetXFadeOut()) {
401 pfadeAudio->DoFadeOut(pcurAudio->GetXFadeOut());
402 } else if (pfadeAudio && pfadeAudio->GetXFadeOut()) {
403 pfadeAudio->DoFadeOut(pfadeAudio->GetXFadeOut());
404 } else if (xfadeOut) {
405 pfadeAudio->DoFadeOut(xfadeOut);
406 } else {
407 fadeAudio = -1;
408 }
409 }
410 }
411
Mix(float * samples,int channels,bool debugClipping)412 void oamlMusicTrack::Mix(float *samples, int channels, bool debugClipping) {
413 if (curAudio == -1 && tailAudio == -1 && fadeAudio == -1)
414 return;
415
416 lock++;
417
418 oamlAudio *pcurAudio = GetCurAudio();
419 if (pcurAudio) {
420 MixAudio(pcurAudio, samples, channels, debugClipping);
421 }
422
423 oamlAudio *ptailAudio = GetTailAudio();
424 if (ptailAudio) {
425 tailPos = MixAudio(ptailAudio, samples, channels, debugClipping, tailPos);
426 if (ptailAudio->HasFinishedTail(tailPos))
427 tailAudio = -1;
428 }
429
430 oamlAudio *pfadeAudio = GetFadeAudio();
431 if (pfadeAudio) {
432 MixAudio(pfadeAudio, samples, channels, debugClipping);
433 }
434
435 if (pcurAudio && pcurAudio->HasFinished()) {
436 tailAudio = curAudio;
437 tailPos = pcurAudio->GetSamplesCount();
438
439 PlayNext();
440 }
441
442 if (pfadeAudio && pfadeAudio->HasFinished()) {
443 fadeAudio = -1;
444 }
445
446 if (playCondSamples > 0) {
447 playCondSamples--;
448 if (playCondSamples == 0) {
449 PlayCond(playCondAudio);
450 }
451 }
452
453 if (curAudio == -1 && tailAudio == -1 && fadeAudio == -1) {
454 FreeMemory();
455 }
456
457 lock--;
458 }
459
IsPlaying()460 bool oamlMusicTrack::IsPlaying() {
461 return playing;
462 }
463
GetPlayingInfo()464 std::string oamlMusicTrack::GetPlayingInfo() {
465 char str[1024];
466 std::string info = "";
467
468 if (curAudio == -1 && tailAudio == -1 && fadeAudio == -1) {
469 if (playing == true) {
470 return "Playing track but no available audio, missing condition?";
471 }
472
473 return info;
474 }
475
476 info+= GetName() + ":";
477
478 oamlAudio *audio = GetCurAudio();
479 if (audio) {
480 snprintf(str, 1024, " curAudio = %s (pos=%d)", audio->GetName().c_str(), audio->GetSamplesCount());
481 info+= str;
482 }
483
484 audio = GetTailAudio();
485 if (audio) {
486 snprintf(str, 1024, " tailAudio = %s (pos=%d)", audio->GetName().c_str(), audio->GetSamplesCount());
487 info+= str;
488 }
489
490 audio = GetFadeAudio();
491 if (audio) {
492 snprintf(str, 1024, " fadeAudio = %s (pos=%d)", audio->GetName().c_str(), audio->GetSamplesCount());
493 info+= str;
494 }
495
496 return info;
497 }
498
Stop()499 void oamlMusicTrack::Stop() {
500 if (curAudio != -1) {
501 if (fadeOut) {
502 fadeAudio = curAudio;
503 oamlAudio *audio = GetFadeAudio();
504 if (audio) {
505 audio->DoFadeOut(fadeOut);
506 }
507 }
508 curAudio = -1;
509 }
510
511 tailAudio = -1;
512 playing = false;
513
514 if (curAudio == -1 && tailAudio == -1 && fadeAudio == -1) {
515 FreeMemory();
516 }
517 }
518
Load()519 oamlRC oamlMusicTrack::Load() {
520 for (std::vector<oamlAudio*>::iterator it=loopAudios.begin(); it<loopAudios.end(); ++it) {
521 oamlAudio *audio = *it;
522 oamlRC ret = audio->Load();
523 if (ret != OAML_OK) return ret;
524 }
525
526 return OAML_OK;
527 }
528
LoadProgress()529 float oamlMusicTrack::LoadProgress() {
530 int samples;
531
532 if (filesSamples == 0) {
533 // Calculate the total size of the audio loops to read
534
535 samples = GetFilesSamplesFor(&introAudios);
536 if (samples == -1)
537 return -1.f;
538 filesSamples+= samples;
539
540 samples = GetFilesSamplesFor(&loopAudios);
541 if (samples == -1)
542 return -1.f;
543 filesSamples+= samples;
544
545 samples = GetFilesSamplesFor(&randAudios);
546 if (samples == -1)
547 return -1.f;
548 filesSamples+= samples;
549
550 samples = GetFilesSamplesFor(&condAudios);
551 if (samples == -1)
552 return -1.f;
553 filesSamples+= samples;
554 }
555
556 if (filesSamples == 0) {
557 return -1.f;
558 }
559
560 int totalSamplesRead = 0;
561
562 samples = LoadProgressFor(&introAudios);
563 if (samples == -1) {
564 return -1.f;
565 }
566 totalSamplesRead+= samples;
567
568 samples = LoadProgressFor(&loopAudios);
569 if (samples == -1) {
570 return -1.f;
571 }
572 totalSamplesRead+= samples;
573
574 samples = LoadProgressFor(&randAudios);
575 if (samples == -1) {
576 return -1.f;
577 }
578 totalSamplesRead+= samples;
579
580 samples = LoadProgressFor(&condAudios);
581 if (samples == -1) {
582 return -1.f;
583 }
584 totalSamplesRead+= samples;
585
586 return float(double(totalSamplesRead) / double(filesSamples));
587 }
588
ReadInfo(oamlTrackInfo * info)589 void oamlMusicTrack::ReadInfo(oamlTrackInfo *info) {
590 oamlTrack::ReadInfo(info);
591
592 ReadAudiosInfo(&introAudios, info);
593 ReadAudiosInfo(&loopAudios, info);
594 ReadAudiosInfo(&randAudios, info);
595 ReadAudiosInfo(&condAudios, info);
596 }
597
SaveAudioState(tinyxml2::XMLDocument & doc,tinyxml2::XMLElement * node,const char * nodeName,std::vector<oamlAudio * > * audios)598 void oamlMusicTrack::SaveAudioState(tinyxml2::XMLDocument &doc, tinyxml2::XMLElement *node, const char *nodeName, std::vector<oamlAudio*> *audios) {
599 for (std::vector<oamlAudio*>::iterator it=audios->begin(); it<audios->end(); ++it) {
600 oamlAudio *audio = *it;
601
602 tinyxml2::XMLElement *elem = doc.NewElement(nodeName);
603 audio->SaveState(elem);
604 node->InsertEndChild(elem);
605 }
606 }
607
SaveState(tinyxml2::XMLDocument & doc,tinyxml2::XMLElement * node)608 void oamlMusicTrack::SaveState(tinyxml2::XMLDocument &doc, tinyxml2::XMLElement *node) {
609 node->SetAttribute("name", GetNameStr());
610 node->SetAttribute("playing", playing);
611 node->SetAttribute("playingOrder", playingOrder);
612 node->SetAttribute("tailPos", tailPos);
613 node->SetAttribute("curAudio", curAudio);
614 node->SetAttribute("fadeAudio", fadeAudio);
615 node->SetAttribute("tailAudio", tailAudio);
616 node->SetAttribute("playCondAudio", playCondAudio);
617 node->SetAttribute("playCondSamples", playCondSamples);
618
619 if (introAudios.size() > 0) {
620 SaveAudioState(doc, node, "introAudio", &introAudios);
621 }
622 if (loopAudios.size() > 0) {
623 SaveAudioState(doc, node, "loopAudio", &loopAudios);
624 }
625 if (randAudios.size() > 0) {
626 SaveAudioState(doc, node, "randAudio", &randAudios);
627 }
628 if (condAudios.size() > 0) {
629 SaveAudioState(doc, node, "condAudio", &condAudios);
630 }
631 }
632
LoadAudioState(tinyxml2::XMLElement * node,std::vector<oamlAudio * > * audios)633 void oamlMusicTrack::LoadAudioState(tinyxml2::XMLElement *node, std::vector<oamlAudio*> *audios) {
634 for (std::vector<oamlAudio*>::iterator it=audios->begin(); it<audios->end(); ++it) {
635 oamlAudio *audio = *it;
636 if (strcmp(node->Attribute("name"), audio->GetName().c_str()) == 0) {
637 audio->LoadState(node);
638 break;
639 }
640 }
641 }
642
LoadState(tinyxml2::XMLElement * node)643 void oamlMusicTrack::LoadState(tinyxml2::XMLElement *node) {
644 const char *attr = node->Attribute("playing");
645 if (attr && strcmp(attr, "true") == 0) {
646 playing = true;
647 } else {
648 playing = false;
649 }
650
651 playingOrder = node->IntAttribute("playingOrder");
652 tailPos = node->IntAttribute("tailPos");
653 curAudio = node->IntAttribute("curAudio");
654 fadeAudio = node->IntAttribute("fadeAudio");
655 tailAudio = node->IntAttribute("tailAudio");
656 playCondAudio = node->IntAttribute("playCondAudio");
657 playCondSamples = node->IntAttribute("playCondSamples");
658
659 tinyxml2::XMLElement *el = node->FirstChildElement();
660 while (el != NULL) {
661 if (strcmp(el->Name(), "introAudio") == 0) {
662 LoadAudioState(el, &introAudios);
663 } else if (strcmp(el->Name(), "loopAudio") == 0) {
664 LoadAudioState(el, &loopAudios);
665 } else if (strcmp(el->Name(), "randAudio") == 0) {
666 LoadAudioState(el, &randAudios);
667 } else if (strcmp(el->Name(), "condAudio") == 0) {
668 LoadAudioState(el, &condAudios);
669 }
670
671 el = el->NextSiblingElement();
672 }
673 }
674
FreeMemory()675 void oamlMusicTrack::FreeMemory() {
676 FreeAudiosMemory(&introAudios);
677 FreeAudiosMemory(&loopAudios);
678 FreeAudiosMemory(&randAudios);
679 FreeAudiosMemory(&condAudios);
680
681 filesSamples = 0;
682 }
683
GetAudioList(std::vector<std::string> & list)684 void oamlMusicTrack::GetAudioList(std::vector<std::string>& list) {
685 FillAudiosList(&introAudios, list);
686 FillAudiosList(&loopAudios, list);
687 FillAudiosList(&randAudios, list);
688 FillAudiosList(&condAudios, list);
689 }
690
_SetLayerGain(std::vector<oamlAudio * > * audios,std::string layer,float gain)691 void oamlMusicTrack::_SetLayerGain(std::vector<oamlAudio*> *audios, std::string layer, float gain) {
692 for (std::vector<oamlAudio*>::iterator it=audios->begin(); it<audios->end(); ++it) {
693 oamlAudio *audio = *it;
694 audio->SetLayerGain(layer, gain);
695 }
696 }
697
SetLayerGain(std::string layer,float gain)698 void oamlMusicTrack::SetLayerGain(std::string layer, float gain) {
699 _SetLayerGain(&introAudios, layer, gain);
700 _SetLayerGain(&loopAudios, layer, gain);
701 _SetLayerGain(&randAudios, layer, gain);
702 _SetLayerGain(&condAudios, layer, gain);
703 }
704