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 "cryo/sound.h"
24 #include "audio/audiostream.h"
25 #include "audio/mixer.h"
26 #include "audio/decoders/raw.h"
27
28 namespace Cryo {
29
CSoundChannel(Audio::Mixer * mixer,unsigned int sampleRate,bool stereo,bool is16bits)30 CSoundChannel::CSoundChannel(Audio::Mixer *mixer, unsigned int sampleRate, bool stereo, bool is16bits) : _mixer(mixer), _sampleRate(sampleRate), _stereo(stereo) {
31 _bufferFlags = is16bits ? (Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_16BITS) : Audio::FLAG_UNSIGNED;
32 if (stereo)
33 _bufferFlags |= Audio::FLAG_STEREO;
34 _audioStream = nullptr;
35 _volumeLeft = _volumeRight = Audio::Mixer::kMaxChannelVolume;
36 }
37
~CSoundChannel()38 CSoundChannel::~CSoundChannel() {
39 stop();
40 if (_audioStream)
41 delete _audioStream;
42 }
43
queueBuffer(byte * buffer,unsigned int size,bool playNow,bool playQueue,bool buffering)44 void CSoundChannel::queueBuffer(byte *buffer, unsigned int size, bool playNow, bool playQueue, bool buffering) {
45 if (playNow)
46 stop();
47
48 if (!buffer || !size)
49 return;
50
51 if (!_audioStream)
52 _audioStream = Audio::makeQueuingAudioStream(_sampleRate, _stereo);
53
54 if (buffering) {
55 byte *localBuffer = (byte*)malloc(size);
56 memcpy(localBuffer, buffer, size);
57 _audioStream->queueBuffer(localBuffer, size, DisposeAfterUse::YES, _bufferFlags);
58 } else
59 _audioStream->queueBuffer(buffer, size, DisposeAfterUse::NO, _bufferFlags);
60 if (playNow || playQueue)
61 play();
62 }
63
play()64 void CSoundChannel::play() {
65 if (!_audioStream)
66 return;
67 if (!_mixer->isSoundHandleActive(_soundHandle)) {
68 _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
69 applyVolumeChange();
70 }
71 }
72
stop()73 void CSoundChannel::stop() {
74 if (_mixer->isSoundHandleActive(_soundHandle))
75 _mixer->stopHandle(_soundHandle);
76
77 if (_audioStream) {
78 _audioStream->finish();
79 delete _audioStream;
80 _audioStream = nullptr;
81 }
82 }
83
numQueued()84 unsigned int CSoundChannel::numQueued() {
85 return _audioStream ? _audioStream->numQueuedStreams() : 0;
86 }
87
getVolume()88 unsigned int CSoundChannel::getVolume() {
89 return (_volumeRight + _volumeLeft) / 2;
90 }
91
setVolume(unsigned int volumeLeft,unsigned int volumeRight)92 void CSoundChannel::setVolume(unsigned int volumeLeft, unsigned int volumeRight) {
93 _volumeLeft = volumeLeft;
94 _volumeRight = volumeRight;
95 applyVolumeChange();
96 }
97
setVolumeLeft(unsigned int volume)98 void CSoundChannel::setVolumeLeft(unsigned int volume) {
99 setVolume(volume, _volumeRight);
100 }
101
setVolumeRight(unsigned int volume)102 void CSoundChannel::setVolumeRight(unsigned int volume) {
103 setVolume(_volumeLeft, volume);
104 }
105
applyVolumeChange()106 void CSoundChannel::applyVolumeChange() {
107 unsigned int volume = (_volumeRight + _volumeLeft) / 2;
108 int balance = (signed int)(_volumeRight - _volumeLeft) / 2;
109 _mixer->setChannelVolume(_soundHandle, volume);
110 _mixer->setChannelBalance(_soundHandle, balance);
111 }
112
113 }
114