1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/textconsole.h"
24
25 #include "engines/grim/imuse/imuse.h"
26
27 #include "engines/grim/debug.h"
28
29 namespace Grim {
30
flushTrack(Track * track)31 void Imuse::flushTrack(Track *track) {
32 track->toBeRemoved = true;
33
34 if (track->stream) {
35 // Finalize the appendable stream, then remove our reference to it.
36 // Note that there might still be some data left in the buffers of the
37 // appendable stream. We play it nice and wait till all of it
38 // played. The audio mixer will take care of it afterwards (and dispose it).
39 track->stream->finish();
40 track->stream = nullptr;
41 if (track->soundDesc) {
42 _sound->closeSound(track->soundDesc);
43 track->soundDesc = nullptr;
44 }
45 }
46
47 if (!g_system->getMixer()->isSoundHandleActive(track->handle)) {
48 track->clear();
49 }
50 }
51
flushTracks()52 void Imuse::flushTracks() {
53 Common::StackLock lock(_mutex);
54 for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
55 Track *track = _track[l];
56 if (track->used && track->toBeRemoved && !g_system->getMixer()->isSoundHandleActive(track->handle)) {
57 track->clear();
58 }
59 }
60 }
61
refreshScripts()62 void Imuse::refreshScripts() {
63 Common::StackLock lock(_mutex);
64 bool found = false;
65
66 for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
67 Track *track = _track[l];
68 if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
69 found = true;
70 }
71 }
72
73 if (!found && _curMusicState) {
74 setMusicSequence(0);
75 }
76 }
77
startVoice(const char * soundName,int volume,int pan)78 bool Imuse::startVoice(const char *soundName, int volume, int pan) {
79 Debug::debug(Debug::Sound, "Imuse::startVoice(): SoundName %s, vol:%d, pan:%d", soundName, volume, pan);
80 return startSound(soundName, IMUSE_VOLGRP_VOICE, 0, volume, pan, 127, nullptr);
81 }
82
startMusic(const char * soundName,int hookId,int volume,int pan)83 void Imuse::startMusic(const char *soundName, int hookId, int volume, int pan) {
84 Debug::debug(Debug::Sound, "Imuse::startMusic(): SoundName %s, hookId:%d, vol:%d, pan:%d", soundName, hookId, volume, pan);
85 startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126, nullptr);
86 }
87
startMusicWithOtherPos(const char * soundName,int hookId,int volume,int pan,Track * otherTrack)88 void Imuse::startMusicWithOtherPos(const char *soundName, int hookId, int volume, int pan, Track *otherTrack) {
89 Debug::debug(Debug::Sound, "Imuse::startMusicWithOtherPos(): SoundName %s, hookId:%d, vol:%d, pan:%d", soundName, hookId, volume, pan);
90 startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126, otherTrack);
91 }
92
startSfx(const char * soundName,int priority)93 void Imuse::startSfx(const char *soundName, int priority) {
94 Debug::debug(Debug::Sound, "Imuse::startSfx(): SoundName %s, priority:%d", soundName, priority);
95 startSound(soundName, IMUSE_VOLGRP_SFX, 0, 127, 0, priority, nullptr);
96 }
97
getPosIn16msTicks(const char * soundName)98 int32 Imuse::getPosIn16msTicks(const char *soundName) {
99 Common::StackLock lock(_mutex);
100 Track *getTrack = nullptr;
101
102 getTrack = findTrack(soundName);
103 // Warn the user if the track was not found
104 if (getTrack == nullptr) {
105 Debug::warning(Debug::Sound, "Sound '%s' could not be found to get ticks", soundName);
106 return false;
107 }
108
109 int32 pos = (62.5 / 60.0) * (5 * (getTrack->dataOffset + getTrack->regionOffset)) / (getTrack->feedSize / 12); // 16ms is 62.5 Hz
110 return pos;
111 }
112
isVoicePlaying()113 bool Imuse::isVoicePlaying() {
114 Common::StackLock lock(_mutex);
115 for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
116 Track *track = _track[l];
117 if (track->used && track->volGroupId == IMUSE_VOLGRP_VOICE) {
118 if (g_system->getMixer()->isSoundHandleActive(track->handle))
119 return true;
120 }
121 }
122
123 return false;
124 }
125
getSoundStatus(const char * soundName)126 bool Imuse::getSoundStatus(const char *soundName) {
127 Common::StackLock lock(_mutex);
128 Track *track = nullptr;
129
130 // If there's no name then don't try to get the status!
131 if (strlen(soundName) == 0)
132 return false;
133
134 track = findTrack(soundName);
135 // Warn the user if the track was not found
136 if (track == nullptr || !g_system->getMixer()->isSoundHandleActive(track->handle)) {
137 // This debug warning should be "light" since this function gets called
138 // on occassion to see if a sound has stopped yet
139 Debug::debug(Debug::Sound, "Sound '%s' could not be found to get status, assume inactive.", soundName);
140 return false;
141 }
142 return true;
143 }
144
stopSound(const char * soundName)145 void Imuse::stopSound(const char *soundName) {
146 Common::StackLock lock(_mutex);
147 Debug::debug(Debug::Sound, "Imuse::stopSound(): SoundName %s", soundName);
148 Track *removeTrack = nullptr;
149
150 removeTrack = findTrack(soundName);
151 // Warn the user if the track was not found
152 if (removeTrack == nullptr) {
153 Debug::warning(Debug::Sound, "Sound track '%s' could not be found to stop", soundName);
154 return;
155 }
156 flushTrack(removeTrack);
157 }
158
stopAllSounds()159 void Imuse::stopAllSounds() {
160 Common::StackLock lock(_mutex);
161 Debug::debug(Debug::Sound, "Imuse::stopAllSounds()");
162
163 for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
164 Track *track = _track[l];
165 if (track->used) {
166 g_system->getMixer()->stopHandle(track->handle);
167 if (track->soundDesc) {
168 _sound->closeSound(track->soundDesc);
169 }
170 track->clear();
171 }
172 }
173 }
174
pause(bool p)175 void Imuse::pause(bool p) {
176 _pause = p;
177 }
178
179 } // end of namespace Grim
180