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 "bladerunner/audio_cache.h"
24
25 #include "common/stream.h"
26
27 namespace BladeRunner {
28
AudioCache()29 AudioCache::AudioCache() :
30 _totalSize(0),
31 _maxSize(2457600),
32 _accessCounter(0) {}
33
~AudioCache()34 AudioCache::~AudioCache() {
35 for (uint i = 0; i != _cacheItems.size(); ++i) {
36 free(_cacheItems[i].data);
37 }
38 }
39
canAllocate(uint32 size) const40 bool AudioCache::canAllocate(uint32 size) const {
41 Common::StackLock lock(_mutex);
42
43 return _maxSize - _totalSize >= size;
44 }
45
dropOldest()46 bool AudioCache::dropOldest() {
47 Common::StackLock lock(_mutex);
48
49 if (_cacheItems.size() == 0)
50 return false;
51
52 int oldest = -1;
53 for (uint i = 1; i != _cacheItems.size(); ++i) {
54 if (_cacheItems[i].refs == 0) {
55 if (oldest == -1 || _cacheItems[i].lastAccess < _cacheItems[oldest].lastAccess) {
56 oldest = i;
57 }
58 }
59 }
60
61 if (oldest == -1) {
62 return false;
63 }
64
65 memset(_cacheItems[oldest].data, 0x00, _cacheItems[oldest].size);
66 free(_cacheItems[oldest].data);
67 _totalSize -= _cacheItems[oldest].size;
68 _cacheItems.remove_at(oldest);
69 return true;
70 }
71
findByHash(int32 hash)72 byte *AudioCache::findByHash(int32 hash) {
73 Common::StackLock lock(_mutex);
74
75 for (uint i = 0; i != _cacheItems.size(); ++i) {
76 if (_cacheItems[i].hash == hash) {
77 _cacheItems[i].lastAccess = _accessCounter++;
78 return _cacheItems[i].data;
79 }
80 }
81
82 return nullptr;
83 }
84
storeByHash(int32 hash,Common::SeekableReadStream * stream)85 void AudioCache::storeByHash(int32 hash, Common::SeekableReadStream *stream) {
86 Common::StackLock lock(_mutex);
87
88 uint32 size = stream->size();
89 byte *data = (byte *)malloc(size);
90 stream->read(data, size);
91
92 cacheItem item = {
93 hash,
94 0,
95 _accessCounter++,
96 data,
97 size
98 };
99
100 _cacheItems.push_back(item);
101 _totalSize += size;
102 }
103
incRef(int32 hash)104 void AudioCache::incRef(int32 hash) {
105 Common::StackLock lock(_mutex);
106
107 for (uint i = 0; i != _cacheItems.size(); ++i) {
108 if (_cacheItems[i].hash == hash) {
109 ++(_cacheItems[i].refs);
110 return;
111 }
112 }
113 assert(false && "AudioCache::incRef: hash not found");
114 }
115
decRef(int32 hash)116 void AudioCache::decRef(int32 hash) {
117 Common::StackLock lock(_mutex);
118
119 for (uint i = 0; i != _cacheItems.size(); ++i) {
120 if (_cacheItems[i].hash == hash) {
121 assert(_cacheItems[i].refs > 0);
122 --(_cacheItems[i].refs);
123 return;
124 }
125 }
126 assert(false && "AudioCache::decRef: hash not found");
127 }
128
129 } // End of namespace BladeRunner
130