Skip to content

Commit 8fdfb05

Browse files
committed
use mnum to decide where to look for sound library sounds
1 parent 999ed45 commit 8fdfb05

File tree

5 files changed

+227
-16
lines changed

5 files changed

+227
-16
lines changed

common/circular_buffer.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ class CircularBuffer {
2525

2626
void push() { first_ += 1; }
2727
void push(size_t elements) { first_ += elements; }
28+
void unpush(size_t elements) { first_ -= elements; }
29+
30+
void push_back(T value) {
31+
*space() = value;
32+
push();
33+
}
34+
2835
T pop() {
2936
T ret = current();
3037
last_ += 1;
@@ -35,6 +42,10 @@ class CircularBuffer {
3542
void clear() { first_ = 0; last_=0; }
3643
size_t pos() { return last_.get(); }
3744

45+
T& operator[](size_t n) {
46+
return data_[(last_.get() + n) % SIZE];
47+
}
48+
3849
private:
3950
T data_[SIZE];
4051
POAtomic<size_t> first_;

sound/buffered_wav_player.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ class BufferedWavPlayer : public VolumeOverlay<BufferedAudioStream<AUDIO_BUFFER_
5151
return false;
5252
}
5353

54+
void PlayInSameDirAs(const char* name, Effect* effect) {
55+
Effect tmp(name);
56+
tmp.CopyDirectoryFrom(effect);
57+
char full_name[128];
58+
tmp.RandomFile().GetName(full_name);
59+
Play(full_name);
60+
}
61+
5462
void UpdateSaberBaseSoundInfo() {
5563
SaberBase::sound_length = length();
5664
SaberBase::sound_number = current_file_id().GetFileNum();

sound/effect.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,18 @@ class Effect {
159159
reset();
160160
}
161161

162+
void CopyDirectoryFrom(Effect* effect) {
163+
min_file_ = 0;
164+
max_file_ = 0;
165+
unnumbered_file_found_ = true;
166+
found_in_alt_dir_ = effect->found_in_alt_dir_;
167+
file_pattern_ = effect->file_pattern_;
168+
ext_ = Extension::WAV;
169+
num_files_ = 1;
170+
directory_ = effect->directory_;
171+
volume_ = effect->volume_;
172+
}
173+
162174
void reset() {
163175
min_file_ = 127;
164176
max_file_ = -1;

sound/sound_library.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,24 @@ class SoundLibrary {
166166
SayPercent();
167167
}
168168

169+
#ifdef SEARCH_FOR_SOUND_LIBRARY_FILES
170+
171+
// Search font path for sound.
169172
#define ADD_SL_SOUND(NAME, BASE) \
170173
void Say##NAME() { SOUNDQ->Play(BASE ".wav"); } \
171174
/* t for "trampoline" */ \
172175
struct t##NAME { static void say() { SOUNDQ->Play(BASE ".wav"); } }
173176

177+
#else
178+
179+
// Use mnum as template where to find sounds.
180+
#define ADD_SL_SOUND(NAME, BASE) \
181+
void Say##NAME() { SOUNDQ->Play(SoundToPlayInSameDirAs(BASE ".wav", &SFX_mnum)); } \
182+
/* t for "trampoline" */ \
183+
struct t##NAME { static void say() { SOUNDQ->Play(SoundToPlayInSameDirAs(BASE ".wav", &SFX_mnum)); } }
184+
185+
#endif
186+
174187
ADD_SL_SOUND(Red, "clrlst/clrlst01");
175188
ADD_SL_SOUND(OrangeRed, "clrlst/clrlst02");
176189
ADD_SL_SOUND(DarkOrange, "clrlst/clrlst03");

sound/sound_queue.h

Lines changed: 183 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,174 @@
11
#ifndef SOUND_SOUND_QUEUE_H
22
#define SOUND_SOUND_QUEUE_H
33

4+
class SoundToPlayBase {
5+
public:
6+
virtual bool Play(BufferedWavPlayer* player) = 0;
7+
virtual ~SoundToPlayBase() {}
8+
};
9+
10+
class SoundToPlayInSameDirAs : public SoundToPlayBase {
11+
public:
12+
SoundToPlayInSameDirAs(const char* filename, Effect* e) : filename_(filename), effect_(e) {}
13+
bool Play(BufferedWavPlayer* player) override {
14+
player->PlayInSameDirAs(filename_, effect_);
15+
return true;
16+
}
17+
18+
private:
19+
const char* filename_;
20+
Effect* effect_;
21+
};
22+
23+
class SoundToPlayInCurrentDir : public SoundToPlayBase {
24+
public:
25+
SoundToPlayInCurrentDir(const char* filename) : filename_(filename) {}
26+
bool Play(BufferedWavPlayer* player) override {
27+
return player->PlayInCurrentDir(filename_);
28+
}
29+
30+
private:
31+
const char* filename_;
32+
};
33+
34+
class SoundToPlayFileID : public SoundToPlayBase {
35+
public:
36+
SoundToPlayFileID(Effect::FileID id) : file_id_(id) {}
37+
bool Play(BufferedWavPlayer* player) override {
38+
player->PlayOnce(file_id_);
39+
return true;
40+
}
41+
42+
private:
43+
Effect::FileID file_id_;
44+
};
45+
46+
class SoundToPlayColor : public SoundToPlayBase {
47+
public:
48+
SoundToPlayColor(unsigned char r,
49+
unsigned char g,
50+
unsigned char b) : r_(r), g_(g), b_(b) {
51+
}
52+
bool Play(BufferedWavPlayer* player) override {
53+
// color
54+
char filename[32];
55+
strcpy(filename, "colors/");
56+
char* tmp = filename + strlen(filename);
57+
*(tmp++) = "0123456789abcdef"[r_ >> 4];
58+
*(tmp++) = "0123456789abcdef"[r_ & 15];
59+
*(tmp++) = "0123456789abcdef"[g_ >> 4];
60+
*(tmp++) = "0123456789abcdef"[g_ & 15];
61+
*(tmp++) = "0123456789abcdef"[b_ >> 4];
62+
*(tmp++) = "0123456789abcdef"[b_ & 15];
63+
strcpy(tmp, ".wav");
64+
return player->PlayInCurrentDir(filename);
65+
}
66+
unsigned char r_, g_, b_;
67+
};
68+
69+
// Fixed-size deque of objects with shared base class.
70+
// Similar to deque<shared_ptr<BASE>>, size is fixed and
71+
// all memory allocations are done from internal memory.
72+
// push_back/emplace_back will fail and return false/nullptr
73+
// if insufficient space is available.
74+
template<class BASE, size_t N = 8, size_t SIZE = N * 12>
75+
class VirtVec {
76+
public:
77+
size_t size() const { return elements_.size(); }
78+
BASE* operator[](size_t n) { return elements_[n]; }
79+
BASE* first() { return elements_[0]; }
80+
81+
template<class T, class... Args>
82+
T* emplace_back(Args&&... args) {
83+
char* ptr = allocate(sizeof(T), alignof(T));
84+
if (ptr == nullptr) return nullptr;
85+
return new(ptr) T(args...);
86+
}
87+
88+
template<class T> bool push_back(T value) {
89+
char* ptr = allocate(sizeof(T), alignof(T));
90+
if (ptr == nullptr) return false;
91+
return new(ptr) T(value);
92+
}
93+
94+
// Stack
95+
void pop_back() {
96+
if (elements_.empty()) return;
97+
int n = elements_.size() -1;
98+
(*this)[n]->~BASE();
99+
buffer_.unpush(element_size(n));
100+
elements_.unpush(-1);
101+
}
102+
103+
// Queue
104+
void pop_front() {
105+
if (elements_.empty()) return;
106+
(*this)[0]->~BASE();
107+
buffer_.pop(element_size(0));
108+
elements_.pop();
109+
}
110+
111+
void clear() {
112+
while (size()) pop_front();
113+
}
114+
115+
private:
116+
// May return a larger number, but not smaller.
117+
size_t element_size(size_t n) {
118+
char *a = reinterpret_cast<char *>(elements_[n]);
119+
char *b;
120+
if (n == size() - 1) {
121+
// Last element
122+
b = buffer_.space();
123+
} else {
124+
b = reinterpret_cast<char *>(elements_[n + 1]);
125+
}
126+
if (b < a) {
127+
b = buffer_.data() + buffer_.continuous_data();
128+
}
129+
return b - a;
130+
}
131+
132+
char* allocate(size_t size, size_t alignment) {
133+
if (elements_.space_available() == 0) return nullptr;
134+
while (true) {
135+
if (buffer_.space_available() < size) return nullptr;
136+
if (((size_t)buffer_.space()) % alignment) {
137+
// Fix alignment
138+
size_t misalignment = alignment - ((size_t)buffer_.space()) % alignment;
139+
if (buffer_.space_available() < misalignment) return nullptr;
140+
buffer_.push(misalignment);
141+
continue; // retry
142+
}
143+
if (buffer_.continuous_space() < size) {
144+
// Not enough space at end of buffer,
145+
// jump back to beginning of buffer.
146+
// (If there is enough space there.)
147+
if (buffer_.space_available() - buffer_.continuous_space() < size) return nullptr;
148+
buffer_.push(buffer_.continuous_space());
149+
continue; // retry
150+
}
151+
break;
152+
}
153+
char* ret = buffer_.space();
154+
buffer_.push(size);
155+
elements_.push_back(reinterpret_cast<BASE*>(ret));
156+
}
157+
158+
// Pointers to each of the elements in the VirtVec
159+
CircularBuffer<BASE*, N> elements_;
160+
161+
// Memory for storing the elements.
162+
CircularBuffer<char, SIZE> buffer_;
163+
};
164+
4165
struct SoundToPlay {
5166
const char* filename_;
6167
Effect::FileID file_id_;
7168

8169
SoundToPlay() :filename_(nullptr), file_id_(nullptr, 0xffff, 0, 0) {}
9170
explicit SoundToPlay(const char* file) : filename_(file) { }
171+
explicit SoundToPlay(const char* file, Effect* effect) : filename_(file), file_id_(effect, 0,0,0) { }
10172
SoundToPlay(Effect* effect) : filename_(nullptr), file_id_(effect->RandomFile()) {}
11173
SoundToPlay(Effect* effect, int selection) : filename_(nullptr), file_id_((effect->Select(selection),effect->RandomFile())) {}
12174
SoundToPlay(uint8_t R, uint8_t G, uint8_t B) :filename_(nullptr), file_id_(nullptr, R, G, B) {}
@@ -40,17 +202,24 @@ struct SoundToPlay {
40202
template<int QueueLength>
41203
class SoundQueue {
42204
public:
205+
template<class T>
206+
bool Play(T p) { queue_.push_back(p); }
207+
208+
// For backwards compatibility only.
43209
bool Play(SoundToPlay p) {
44-
if (sounds_ < QueueLength) {
45-
queue_[sounds_++] = p;
46-
return true;
210+
if (p.filename_) {
211+
return Play(SoundToPlayInCurrentDir(p.filename_));
47212
}
48-
return false;
49-
}
50-
bool Play(const char* p) {
51-
return Play(SoundToPlay(p));
213+
if (p.file_id_) {
214+
return Play(SoundToPlayFileID(p.file_id_));
215+
}
216+
return Play(SoundToPlayColor(p.file_id_.GetFileNum(),
217+
p.file_id_.GetSubId(),
218+
p.file_id_.GetAlt()));
52219
}
53220

221+
bool Play(const char* p) { return Play(SoundToPlayInCurrentDir(p)); }
222+
54223
// Called from Loop()
55224
void PollSoundQueue(RefPtr<BufferedWavPlayer>& player) {
56225
busy_ = player && player->isPlaying();
@@ -59,42 +228,40 @@ class SoundQueue {
59228
if (busy_) {
60229
// We really should add the time since the fadeout was scheduled here.
61230
// However, if polling is frequent, it would be a fraction of a milli
62-
// which basically dones't matter.
231+
// which basically doesn't matter.
63232
player->set_fade_time(fadeout_len_);
64233
player->FadeAndStop();
65234
}
66235
}
67236
if (!busy_) {
68-
if (sounds_) {
237+
if (queue_.size()) {
69238
busy_ = true;
70239
if (!player) {
71240
player = GetFreeWavPlayer();
72241
if (!player) return;
73242
}
74243
player->set_volume_now(1.0f);
75-
queue_[0].Play(player.get());
76-
sounds_--;
77-
for (int i = 0; i < sounds_; i++) queue_[i] = queue_[i+1];
244+
queue_[0]->Play(player.get());
245+
queue_.pop_front();
78246
} else {
79247
if (player) player.Free();
80248
}
81249
}
82250
}
83251
bool busy() const { return busy_; }
84252
void fadeout(float len) {
85-
sounds_ = 0;
253+
queue_.clear();
86254
fadeout_ = true;
87255
fadeout_len_ = len;
88256
}
89257
void clear_pending() {
90-
sounds_ = 0;
258+
queue_.clear();
91259
}
92260
private:
93-
int sounds_;
94261
bool busy_ = false;
95262
bool fadeout_;
96263
bool fadeout_len_;
97-
SoundToPlay queue_[QueueLength];
264+
VirtVec<SoundToPlayBase, QueueLength, QueueLength * 12> queue_;
98265
};
99266

100267
#endif // SOUND_SOUND_QUEUE_H

0 commit comments

Comments
 (0)