ScummVM
sound.cpp
Go to the documentation of this file.
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM 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 "glk/sound.h"
24 #include "glk/glk.h"
25 #include "glk/events.h"
26 #include "common/file.h"
27 #include "audio/audiostream.h"
28 #include "audio/decoders/aiff.h"
29 #include "audio/decoders/mp3.h"
30 #include "audio/decoders/raw.h"
31 #include "audio/decoders/wave.h"
32 
33 namespace Glk {
34 
36  for (int idx = (int)_sounds.size() - 1; idx >= 0; --idx)
37  delete _sounds[idx];
38 }
39 
41  for (uint idx = 0; idx < _sounds.size(); ++idx) {
42  if (_sounds[idx] == snd) {
43  _sounds.remove_at(idx);
44  break;
45  }
46  }
47 }
48 
50  schanid_t snd = new SoundChannel(this, volume);
51  _sounds.push_back(snd);
52  return snd;
53 }
54 
56  for (int idx = 0; idx < (int)_sounds.size() - 1; ++idx) {
57  if (_sounds[idx] == chan) {
58  schanid_t next = _sounds[idx + 1];
59  if (*rockptr)
60  *rockptr = next->_rock;
61 
62  return next;
63  }
64  }
65 
66  return nullptr;
67 }
68 
69 void Sounds::poll() {
70  for (uint idx = 0; idx < _sounds.size(); ++idx)
71  _sounds[idx]->poll();
72 }
73 
74 /*--------------------------------------------------------------------------*/
75 
76 SoundChannel::SoundChannel(Sounds *owner, uint volume) : _owner(owner),
77  _soundNum(0), _rock(0), _notify(0) {
78  _defaultVolume = MIN(volume, (uint)GLK_MAXVOLUME);
79 
82 }
83 
85  stop();
86  _owner->removeSound(this);
87 
90 }
91 
92 uint SoundChannel::play(uint soundNum, uint repeats, uint notify) {
93  stop();
94  if (repeats == 0)
95  return 1;
96 
97  // Find a sound of the given name
98  Audio::AudioStream *stream;
100  Common::String nameSnd = Common::String::format("sound%u.snd", soundNum);
101  Common::String nameWav = Common::String::format("sound%u.wav", soundNum);
102  Common::String nameAiff = Common::String::format("sound%u.aiff", soundNum);
103 #ifdef USE_MAD
104  Common::String nameMp3 = Common::String::format("sound%u.mp3", soundNum);
105 #endif
106 
107  if (f.exists(nameSnd) && f.open(nameSnd)) {
108  if (f.readUint16BE() != (f.size() - 2))
109  error("Invalid sound filesize");
110  byte headerRepeats = f.readByte();
111  if (headerRepeats > 0)
112  repeats = headerRepeats;
113  f.skip(1);
114  uint freq = f.readUint16BE();
115  f.skip(2);
116  uint size = f.readUint16BE();
117 
118  Common::SeekableReadStream *s = f.readStream(size);
120 
121 #ifdef USE_MAD
122  } else if (f.exists(nameMp3) && f.open(nameMp3)) {
123  Common::SeekableReadStream *s = f.readStream(f.size());
125 #endif
126  } else if (f.exists(nameWav) && f.open(nameWav)) {
127  Common::SeekableReadStream *s = f.readStream(f.size());
129 
130  } else if (f.exists(nameAiff) && f.open(nameAiff)) {
131  Common::SeekableReadStream *s = f.readStream(f.size());
133 
134  } else {
135  warning("Could not find sound %u", soundNum);
136  return 1;
137  }
138 
139  _soundNum = soundNum;
140  _notify = notify;
141 
142  // Set up a repeat if multiple repeats are specified
143  if (repeats > 1) {
144  Audio::RewindableAudioStream *rwStream = dynamic_cast<Audio::RewindableAudioStream *>(stream);
145  assert(rwStream);
146  stream = new Audio::LoopingAudioStream(rwStream, repeats, DisposeAfterUse::YES);
147  }
148 
149  // Start playing the audio
151  _defaultVolume * 255 / GLK_MAXVOLUME);
152  return 0;
153 }
154 
157 }
158 
160  if (!g_vm->_mixer->isSoundHandleActive(_handle) && _notify != 0) {
161  uint notify = _notify;
162  _notify = 0;
163  g_vm->_events->store(evtype_SoundNotify, nullptr, _soundNum, notify);
164  }
165 }
166 
167 void SoundChannel::setVolume(uint volume, uint duration, uint notify) {
168  uint newVol = volume * 255 / GLK_MAXVOLUME;
169  g_vm->_mixer->setChannelVolume(_handle, newVol);
170 
171  if (notify) {
172  warning("TODO: Gradual volume change");
173  g_vm->_events->store(evtype_VolumeNotify, nullptr, 0, notify);
174  }
175 }
176 
178  g_vm->_mixer->pauseHandle(_handle, true);
179 }
180 
182  g_vm->_mixer->pauseHandle(_handle, false);
183 }
184 
185 } // End of namespace Glk
Glk::Events::store
void store(EvType type, Window *win, uint val1=0, uint val2=0)
Store an event for retrieval.
Definition: events.cpp:147
Common::SeekableReadStream
Interface for a seekable & readable data stream.
Definition: stream.h:569
Glk::SoundChannel::unpause
void unpause()
Unpause playback.
Definition: sound.cpp:181
Glk::SoundChannel::_handle
Audio::SoundHandle _handle
Definition: sound.h:45
MIN
T MIN(T a, T b)
Definition: util.h:49
Glk
Contains the necessary data structures andfunctions for adding to andreferring to the ID table(a very...
Definition: adrift.cpp:28
Glk::SoundChannel
Holds the data for a playing sound.
Definition: sound.h:40
Glk::Sounds::create
schanid_t create(uint rock=0, uint volume=GLK_MAXVOLUME)
Create a new channel.
Definition: sound.cpp:49
Glk::Level9::f
FILE * f
Definition: level9_main.cpp:155
Glk::SoundChannel::_rock
uint _rock
Definition: sound.h:48
Audio::Mixer::playStream
virtual void playStream(SoundType type, SoundHandle *handle, AudioStream *stream, int id=-1, byte volume=kMaxChannelVolume, int8 balance=0, DisposeAfterUse::Flag autofreeStream=DisposeAfterUse::YES, bool permanent=false, bool reverseStereo=false)=0
Start playing the given audio stream.
Glk::Sounds::iterate
schanid_t iterate(schanid_t chan, uint *rockptr=nullptr)
Used to iterate over the current list of sound channels.
Definition: sound.cpp:55
sound.h
Glk::SoundChannel::_owner
Sounds * _owner
Definition: sound.h:42
Audio::makeRawStream
SeekableAudioStream * makeRawStream(Common::SeekableReadStream *stream, int rate, byte flags, DisposeAfterUse::Flag disposeAfterUse)
Creates an audio stream, which plays from the given stream.
Definition: raw.cpp:201
Glk::Alan2::freq
Aword * freq
Definition: main.cpp:71
Common::String
Simple string class for ScummVM.
Definition: str.h:49
Glk::SoundChannel::_defaultVolume
uint _defaultVolume
Definition: sound.h:46
Glk::Sounds::removeSound
void removeSound(schanid_t snd)
Remove a sound from the sounds list.
Definition: sound.cpp:40
file.h
Glk::g_vm
GlkEngine * g_vm
Definition: glk.cpp:47
Glk::SoundChannel::~SoundChannel
~SoundChannel()
Destructor.
Definition: sound.cpp:84
Glk::SoundChannel::stop
void stop()
Stop playing sound.
Definition: sound.cpp:155
events.h
glk.h
error
void NORETURN_PRE error(const char *s,...)
Definition: textconsole.cpp:67
Audio::Mixer::setChannelVolume
virtual void setChannelVolume(SoundHandle handle, byte volume)=0
Set the channel volume for the given handle.
Audio::LoopingAudioStream
A looping audio stream.
Definition: audiostream.h:107
warning
void warning(const char *s,...)
Print a warning message to the text console (stderr).
Definition: textconsole.cpp:49
Audio::makeWAVStream
SeekableAudioStream * makeWAVStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse)
Try to load a WAVE from the given seekable stream and create an AudioStream from that data.
Definition: wave.cpp:190
Audio::makeMP3Stream
SeekableAudioStream * makeMP3Stream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse)
Create a new SeekableAudioStream from the MP3 data in the given stream.
Definition: mp3.cpp:530
Glk::gidisp_Class_Schannel
Definition: glk_types.h:203
aiff.h
Glk::Sounds::SoundChannel
friend class SoundChannel
Definition: sound.h:101
Audio::Mixer::stopHandle
virtual void stopHandle(SoundHandle handle)=0
Stop playing the sound corresponding to the given handle.
Audio::Mixer::pauseHandle
virtual void pauseHandle(SoundHandle handle, bool paused)=0
Pause/unpause the sound corresponding to the given handle.
Glk::SoundChannel::pause
void pause()
Pause playback.
Definition: sound.cpp:177
Glk::Sounds::poll
void poll()
Poll for whether any playing sounds are finished.
Definition: sound.cpp:69
Engine::_mixer
Audio::Mixer * _mixer
Definition: engine.h:63
OPL::DOSBox::DBOPL::volume
Bitu volume
Definition: dbopl.h:66
Glk::Sounds::_sounds
Common::Array< schanid_t > _sounds
Definition: sound.h:103
wave.h
Common::String::format
static String format(const char *fmt,...) GCC_PRINTF(1
Print formatted data into a String object.
Definition: str.cpp:641
Audio::makeAIFFStream
RewindableAudioStream * makeAIFFStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse)
Try to load an AIFF from the given seekable stream and create an AudioStream from that data.
Definition: aiff.cpp:75
Glk::Sounds::~Sounds
~Sounds()
Definition: sound.cpp:35
Glk::GlkEngine::_events
Events * _events
Definition: glk.h:110
uint
unsigned int uint
Definition: scummsys.h:440
Glk::SoundChannel::setVolume
void setVolume(uint volume, uint duration=0, uint notify=0)
Change the volume.
Definition: sound.cpp:167
Glk::SoundChannel::_dispRock
gidispatch_rock_t _dispRock
Definition: sound.h:49
Glk::Sounds
Sound manager.
Definition: sound.h:100
mp3.h
size
u32 size
Definition: cdaudio.cpp:39
raw.h
Glk::SoundChannel::poll
void poll()
Poll for whether a playing sound was finished.
Definition: sound.cpp:159
Audio::RewindableAudioStream
A rewindable audio stream.
Definition: audiostream.h:93
DisposeAfterUse::YES
Definition: types.h:29
Audio::AudioStream
Generic audio input stream.
Definition: audiostream.h:43
Glk::GlkEngine::gli_unregister_obj
void(* gli_unregister_obj)(void *obj, uint objclass, gidispatch_rock_t objrock)
Definition: glk.h:121
Audio::Mixer::kPlainSoundType
Definition: mixer.h:56
audiostream.h
Glk::SoundChannel::_soundNum
uint _soundNum
Definition: sound.h:43
Common::File
TODO: vital to document this core class properly!!! For both users and implementors.
Definition: file.h:39
Audio::Mixer::isSoundHandleActive
virtual bool isSoundHandleActive(SoundHandle handle)=0
Check if a sound with the given handle is active.
Glk::GlkEngine::gli_register_obj
gidispatch_rock_t(* gli_register_obj)(void *obj, uint objclass)
Definition: glk.h:120
Audio::FLAG_UNSIGNED
unsigned samples (default: signed)
Definition: raw.h:52
Glk::SoundChannel::_notify
uint _notify
Definition: sound.h:44
Glk::SoundChannel::SoundChannel
SoundChannel(Sounds *owner, uint volume)
Constructor.
Definition: sound.cpp:76
Glk::SoundChannel::play
uint play(uint soundNum, uint repeats=1, uint notify=0)
Play a sound.
Definition: sound.cpp:92
Glk::evtype_SoundNotify
Definition: events.h:48
Glk::evtype_VolumeNotify
Definition: events.h:50