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 "ultima/nuvie/sound/decoder/random_collection_audio_stream.h"
24 #include "ultima/nuvie/core/game.h"
25 #include "audio/audiostream.h"
26 #include "common/mutex.h"
27 #include "audio/mixer.h"
28
29 namespace Ultima {
30 namespace Nuvie {
31 namespace U6Audio {
32
33 #pragma mark -
34 #pragma mark --- random collection audio stream ---
35 #pragma mark -
36
37 class RandomCollectionAudioStreamImpl : public RandomCollectionAudioStream {
38 private:
39 /**
40 * The sampling rate of this audio stream.
41 */
42 const int _rate;
43
44 /**
45 * Whether this audio stream is mono (=false) or stereo (=true).
46 */
47 const int _stereo;
48
49 /**
50 * This flag is set by the finish() method only. See there for more details.
51 */
52 bool _finished;
53
54 /**
55 * An array of audio streams.
56 */
57 Std::vector<Audio::RewindableAudioStream *> _streams;
58
59 DisposeAfterUse::Flag _disposeAfterUse;
60
61 Audio::RewindableAudioStream *_currentStream;
62 public:
RandomCollectionAudioStreamImpl(int rate,bool stereo,Std::vector<Audio::RewindableAudioStream * > streams,DisposeAfterUse::Flag disposeAfterUse)63 RandomCollectionAudioStreamImpl(int rate, bool stereo, Std::vector<Audio::RewindableAudioStream *> streams, DisposeAfterUse::Flag disposeAfterUse)
64 : _rate(rate), _stereo(stereo), _finished(false), _streams(streams), _disposeAfterUse(disposeAfterUse) {
65 if (_streams.size() > 0)
66 _currentStream = _streams[NUVIE_RAND() % _streams.size()];
67 else
68 _currentStream = NULL;
69 }
70
71 ~RandomCollectionAudioStreamImpl() override;
72
73 // Implement the AudioStream API
74 int readBuffer(int16 *buffer, const int numSamples) override;
isStereo() const75 bool isStereo() const override {
76 return _stereo;
77 }
getRate() const78 int getRate() const override {
79 return _rate;
80 }
endOfData() const81 bool endOfData() const override {
82 return false;
83 }
endOfStream() const84 bool endOfStream() const override {
85 return _finished;
86 }
87
finish()88 void finish() override {
89 _finished = true;
90 }
91 };
92
~RandomCollectionAudioStreamImpl()93 RandomCollectionAudioStreamImpl::~RandomCollectionAudioStreamImpl() {
94 if (_disposeAfterUse == DisposeAfterUse::YES) {
95 while (!_streams.empty()) {
96 delete _streams.back();
97 _streams.pop_back();
98 }
99 }
100 }
101
readBuffer(int16 * buffer,const int numSamples)102 int RandomCollectionAudioStreamImpl::readBuffer(int16 *buffer, const int numSamples) {
103 int samplesDecoded = 0;
104
105 if (_currentStream) {
106 while (samplesDecoded < numSamples) {
107 samplesDecoded += _currentStream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded);
108
109 if (_currentStream->endOfData()) {
110 _currentStream->rewind();
111
112 //pseudo random we don't want to play the same stream twice in a row.
113 int32 idx = NUVIE_RAND() % _streams.size();
114 Audio::RewindableAudioStream *tmp = _streams[idx];
115 if (_currentStream == tmp) {
116 idx = (idx + (NUVIE_RAND() % 1 == 1 ? 1 : _streams.size() - 1)) % _streams.size();
117 _currentStream = _streams[idx];
118 } else
119 _currentStream = tmp;
120
121 //DEBUG(0, LEVEL_INFORMATIONAL, "new sample_num = %d\n", idx);
122 }
123 }
124 }
125 return samplesDecoded;
126 }
127
makeRandomCollectionAudioStream(int rate,bool stereo,Std::vector<Audio::RewindableAudioStream * > streams,DisposeAfterUse::Flag disposeAfterUse)128 RandomCollectionAudioStream *makeRandomCollectionAudioStream(int rate, bool stereo,
129 Std::vector<Audio::RewindableAudioStream *> streams, DisposeAfterUse::Flag disposeAfterUse) {
130 return new RandomCollectionAudioStreamImpl(rate, stereo, streams, disposeAfterUse);
131 }
132
133 } // End of namespace U6Audio
134 } // End of namespace Nuvie
135 } // End of namespace Ultima
136