Throw more appropriate exception types
[alure.git] / examples / alure-reverb.cpp
blobb6e80264421281e46ba45cfdb2ecbe1400765228
1 /*
2 * An example showing how to load and apply a reverb effect to a source.
3 */
5 #include <algorithm>
6 #include <iostream>
7 #include <iomanip>
8 #include <cstring>
9 #include <thread>
10 #include <chrono>
12 #include "alure2.h"
14 #include "efx-presets.h"
16 // Not UTF-8 aware!
17 int ci_compare(alure::StringView lhs, alure::StringView rhs)
19 using traits = alure::StringView::traits_type;
21 auto left = lhs.begin();
22 auto right = rhs.begin();
23 for(;left != lhs.end() && right != rhs.end();++left,++right)
25 int diff = std::tolower(traits::to_int_type(*left)) -
26 std::tolower(traits::to_int_type(*right));
27 if(diff != 0) return (diff < 0) ? -1 : 1;
29 if(right != rhs.end()) return -1;
30 if(left != lhs.end()) return 1;
31 return 0;
35 #define DECL(x) { #x, EFX_REVERB_PRESET_##x }
36 static const struct ReverbEntry {
37 const char name[32];
38 EFXEAXREVERBPROPERTIES props;
39 } reverblist[] = {
40 DECL(GENERIC),
41 DECL(PADDEDCELL),
42 DECL(ROOM),
43 DECL(BATHROOM),
44 DECL(LIVINGROOM),
45 DECL(STONEROOM),
46 DECL(AUDITORIUM),
47 DECL(CONCERTHALL),
48 DECL(CAVE),
49 DECL(ARENA),
50 DECL(HANGAR),
51 DECL(CARPETEDHALLWAY),
52 DECL(HALLWAY),
53 DECL(STONECORRIDOR),
54 DECL(ALLEY),
55 DECL(FOREST),
56 DECL(CITY),
57 DECL(MOUNTAINS),
58 DECL(QUARRY),
59 DECL(PLAIN),
60 DECL(PARKINGLOT),
61 DECL(SEWERPIPE),
62 DECL(UNDERWATER),
63 DECL(DRUGGED),
64 DECL(DIZZY),
65 DECL(PSYCHOTIC),
67 DECL(CASTLE_SMALLROOM),
68 DECL(CASTLE_SHORTPASSAGE),
69 DECL(CASTLE_MEDIUMROOM),
70 DECL(CASTLE_LARGEROOM),
71 DECL(CASTLE_LONGPASSAGE),
72 DECL(CASTLE_HALL),
73 DECL(CASTLE_CUPBOARD),
74 DECL(CASTLE_COURTYARD),
75 DECL(CASTLE_ALCOVE),
77 DECL(FACTORY_SMALLROOM),
78 DECL(FACTORY_SHORTPASSAGE),
79 DECL(FACTORY_MEDIUMROOM),
80 DECL(FACTORY_LARGEROOM),
81 DECL(FACTORY_LONGPASSAGE),
82 DECL(FACTORY_HALL),
83 DECL(FACTORY_CUPBOARD),
84 DECL(FACTORY_COURTYARD),
85 DECL(FACTORY_ALCOVE),
87 DECL(ICEPALACE_SMALLROOM),
88 DECL(ICEPALACE_SHORTPASSAGE),
89 DECL(ICEPALACE_MEDIUMROOM),
90 DECL(ICEPALACE_LARGEROOM),
91 DECL(ICEPALACE_LONGPASSAGE),
92 DECL(ICEPALACE_HALL),
93 DECL(ICEPALACE_CUPBOARD),
94 DECL(ICEPALACE_COURTYARD),
95 DECL(ICEPALACE_ALCOVE),
97 DECL(SPACESTATION_SMALLROOM),
98 DECL(SPACESTATION_SHORTPASSAGE),
99 DECL(SPACESTATION_MEDIUMROOM),
100 DECL(SPACESTATION_LARGEROOM),
101 DECL(SPACESTATION_LONGPASSAGE),
102 DECL(SPACESTATION_HALL),
103 DECL(SPACESTATION_CUPBOARD),
104 DECL(SPACESTATION_ALCOVE),
106 DECL(WOODEN_SMALLROOM),
107 DECL(WOODEN_SHORTPASSAGE),
108 DECL(WOODEN_MEDIUMROOM),
109 DECL(WOODEN_LARGEROOM),
110 DECL(WOODEN_LONGPASSAGE),
111 DECL(WOODEN_HALL),
112 DECL(WOODEN_CUPBOARD),
113 DECL(WOODEN_COURTYARD),
114 DECL(WOODEN_ALCOVE),
116 DECL(SPORT_EMPTYSTADIUM),
117 DECL(SPORT_SQUASHCOURT),
118 DECL(SPORT_SMALLSWIMMINGPOOL),
119 DECL(SPORT_LARGESWIMMINGPOOL),
120 DECL(SPORT_GYMNASIUM),
121 DECL(SPORT_FULLSTADIUM),
122 DECL(SPORT_STADIUMTANNOY),
124 DECL(PREFAB_WORKSHOP),
125 DECL(PREFAB_SCHOOLROOM),
126 DECL(PREFAB_PRACTISEROOM),
127 DECL(PREFAB_OUTHOUSE),
128 DECL(PREFAB_CARAVAN),
130 DECL(DOME_TOMB),
131 DECL(PIPE_SMALL),
132 DECL(DOME_SAINTPAULS),
133 DECL(PIPE_LONGTHIN),
134 DECL(PIPE_LARGE),
135 DECL(PIPE_RESONANT),
137 DECL(OUTDOORS_BACKYARD),
138 DECL(OUTDOORS_ROLLINGPLAINS),
139 DECL(OUTDOORS_DEEPCANYON),
140 DECL(OUTDOORS_CREEK),
141 DECL(OUTDOORS_VALLEY),
143 DECL(MOOD_HEAVEN),
144 DECL(MOOD_HELL),
145 DECL(MOOD_MEMORY),
147 DECL(DRIVING_COMMENTATOR),
148 DECL(DRIVING_PITGARAGE),
149 DECL(DRIVING_INCAR_RACER),
150 DECL(DRIVING_INCAR_SPORTS),
151 DECL(DRIVING_INCAR_LUXURY),
152 DECL(DRIVING_FULLGRANDSTAND),
153 DECL(DRIVING_EMPTYGRANDSTAND),
154 DECL(DRIVING_TUNNEL),
156 DECL(CITY_STREETS),
157 DECL(CITY_SUBWAY),
158 DECL(CITY_MUSEUM),
159 DECL(CITY_LIBRARY),
160 DECL(CITY_UNDERPASS),
161 DECL(CITY_ABANDONED),
163 DECL(DUSTYROOM),
164 DECL(CHAPEL),
165 DECL(SMALLWATERROOM),
167 #undef DECL
170 int main(int argc, char *argv[])
172 alure::DeviceManager devMgr = alure::DeviceManager::get();
174 int fileidx = 1;
175 alure::Device dev;
176 if(argc > 3 && strcmp(argv[1], "-device") == 0)
178 fileidx = 3;
179 dev = devMgr.openPlayback(argv[2], std::nothrow);
180 if(!dev)
181 std::cerr<< "Failed to open \""<<argv[2]<<"\" - trying default" <<std::endl;
183 if(!dev)
184 dev = devMgr.openPlayback();
185 std::cout<< "Opened \""<<dev.getName()<<"\"" <<std::endl;
187 alure::Context ctx = dev.createContext();
188 alure::Context::MakeCurrent(ctx);
190 bool gotreverb = false;
191 alure::Effect effect = ctx.createEffect();
193 if(argc-fileidx >= 2 && alure::StringView("-preset") == argv[fileidx])
195 const char *reverb_name = argv[fileidx+1];
196 fileidx += 2;
198 auto iter = std::find_if(std::begin(reverblist), std::end(reverblist),
199 [reverb_name](const ReverbEntry &entry) -> bool
200 { return ci_compare(reverb_name, entry.name) == 0; }
202 if(iter != std::end(reverblist))
204 std::cout<< "Loading preset "<<iter->name <<std::endl;
205 effect.setReverbProperties(iter->props);
206 gotreverb = true;
209 if(!gotreverb)
211 std::cout<< "Loading generic preset" <<std::endl;
212 effect.setReverbProperties(EFX_REVERB_PRESET_GENERIC);
215 alure::AuxiliaryEffectSlot auxslot = ctx.createAuxiliaryEffectSlot();
216 auxslot.applyEffect(effect);
218 for(int i = fileidx;i < argc;i++)
220 alure::SharedPtr<alure::Decoder> decoder(ctx.createDecoder(argv[i]));
221 alure::Source source = ctx.createSource();
223 source.setAuxiliarySend(auxslot, 0);
225 source.play(decoder, 12000, 4);
226 std::cout<< "Playing "<<argv[i]<<" ("<<alure::GetSampleTypeName(decoder->getSampleType())<<", "
227 <<alure::GetChannelConfigName(decoder->getChannelConfig())<<", "
228 <<decoder->getFrequency()<<"hz)" <<std::endl;
230 float invfreq = 1.0f / decoder->getFrequency();
231 while(source.isPlaying())
233 std::cout<< "\r "<<std::fixed<<std::setprecision(2)<<
234 source.getSecOffset().count()<<" / "<<(decoder->getLength()*invfreq);
235 std::cout.flush();
236 std::this_thread::sleep_for(std::chrono::milliseconds(25));
237 ctx.update();
239 std::cout<<std::endl;
241 source.release();
242 decoder.reset();
245 auxslot.release();
246 effect.destroy();
248 alure::Context::MakeCurrent(nullptr);
249 ctx.destroy();
250 dev.close();
252 return 0;