2 * An example showing how to load and apply a reverb effect to a source.
15 #include "efx-presets.h"
20 int ci_compare(alure::StringView lhs
, alure::StringView rhs
)
22 using traits
= alure::StringView::traits_type
;
24 auto left
= lhs
.begin();
25 auto right
= rhs
.begin();
26 for(;left
!= lhs
.end() && right
!= rhs
.end();++left
,++right
)
28 int diff
= std::tolower(traits::to_int_type(*left
)) -
29 std::tolower(traits::to_int_type(*right
));
30 if(diff
!= 0) return (diff
< 0) ? -1 : 1;
32 if(right
!= rhs
.end()) return -1;
33 if(left
!= lhs
.end()) return 1;
37 #define DECL(x) { #x, EFX_REVERB_PRESET_##x }
38 const struct ReverbEntry
{
40 EFXEAXREVERBPROPERTIES props
;
53 DECL(CARPETEDHALLWAY
),
69 DECL(CASTLE_SMALLROOM
),
70 DECL(CASTLE_SHORTPASSAGE
),
71 DECL(CASTLE_MEDIUMROOM
),
72 DECL(CASTLE_LARGEROOM
),
73 DECL(CASTLE_LONGPASSAGE
),
75 DECL(CASTLE_CUPBOARD
),
76 DECL(CASTLE_COURTYARD
),
79 DECL(FACTORY_SMALLROOM
),
80 DECL(FACTORY_SHORTPASSAGE
),
81 DECL(FACTORY_MEDIUMROOM
),
82 DECL(FACTORY_LARGEROOM
),
83 DECL(FACTORY_LONGPASSAGE
),
85 DECL(FACTORY_CUPBOARD
),
86 DECL(FACTORY_COURTYARD
),
89 DECL(ICEPALACE_SMALLROOM
),
90 DECL(ICEPALACE_SHORTPASSAGE
),
91 DECL(ICEPALACE_MEDIUMROOM
),
92 DECL(ICEPALACE_LARGEROOM
),
93 DECL(ICEPALACE_LONGPASSAGE
),
95 DECL(ICEPALACE_CUPBOARD
),
96 DECL(ICEPALACE_COURTYARD
),
97 DECL(ICEPALACE_ALCOVE
),
99 DECL(SPACESTATION_SMALLROOM
),
100 DECL(SPACESTATION_SHORTPASSAGE
),
101 DECL(SPACESTATION_MEDIUMROOM
),
102 DECL(SPACESTATION_LARGEROOM
),
103 DECL(SPACESTATION_LONGPASSAGE
),
104 DECL(SPACESTATION_HALL
),
105 DECL(SPACESTATION_CUPBOARD
),
106 DECL(SPACESTATION_ALCOVE
),
108 DECL(WOODEN_SMALLROOM
),
109 DECL(WOODEN_SHORTPASSAGE
),
110 DECL(WOODEN_MEDIUMROOM
),
111 DECL(WOODEN_LARGEROOM
),
112 DECL(WOODEN_LONGPASSAGE
),
114 DECL(WOODEN_CUPBOARD
),
115 DECL(WOODEN_COURTYARD
),
118 DECL(SPORT_EMPTYSTADIUM
),
119 DECL(SPORT_SQUASHCOURT
),
120 DECL(SPORT_SMALLSWIMMINGPOOL
),
121 DECL(SPORT_LARGESWIMMINGPOOL
),
122 DECL(SPORT_GYMNASIUM
),
123 DECL(SPORT_FULLSTADIUM
),
124 DECL(SPORT_STADIUMTANNOY
),
126 DECL(PREFAB_WORKSHOP
),
127 DECL(PREFAB_SCHOOLROOM
),
128 DECL(PREFAB_PRACTISEROOM
),
129 DECL(PREFAB_OUTHOUSE
),
130 DECL(PREFAB_CARAVAN
),
134 DECL(DOME_SAINTPAULS
),
139 DECL(OUTDOORS_BACKYARD
),
140 DECL(OUTDOORS_ROLLINGPLAINS
),
141 DECL(OUTDOORS_DEEPCANYON
),
142 DECL(OUTDOORS_CREEK
),
143 DECL(OUTDOORS_VALLEY
),
149 DECL(DRIVING_COMMENTATOR
),
150 DECL(DRIVING_PITGARAGE
),
151 DECL(DRIVING_INCAR_RACER
),
152 DECL(DRIVING_INCAR_SPORTS
),
153 DECL(DRIVING_INCAR_LUXURY
),
154 DECL(DRIVING_FULLGRANDSTAND
),
155 DECL(DRIVING_EMPTYGRANDSTAND
),
156 DECL(DRIVING_TUNNEL
),
162 DECL(CITY_UNDERPASS
),
163 DECL(CITY_ABANDONED
),
167 DECL(SMALLWATERROOM
),
172 // Helper class+method to print the time with human-readable formatting.
174 alure::Seconds mTime
;
176 inline std::ostream
&operator<<(std::ostream
&os
, const PrettyTime
&rhs
)
178 using hours
= std::chrono::hours
;
179 using minutes
= std::chrono::minutes
;
180 using seconds
= std::chrono::seconds
;
181 using centiseconds
= std::chrono::duration
<int64_t, std::ratio
<1, 100>>;
182 using std::chrono::duration_cast
;
184 centiseconds t
= duration_cast
<centiseconds
>(rhs
.mTime
);
191 // Only handle up to hour formatting
193 os
<< duration_cast
<hours
>(t
).count() << 'h' << std::setfill('0') << std::setw(2)
194 << duration_cast
<minutes
>(t
).count() << 'm';
196 os
<< duration_cast
<minutes
>(t
).count() << 'm' << std::setfill('0');
197 os
<< std::setw(2) << (duration_cast
<seconds
>(t
).count() % 60) << '.' << std::setw(2)
198 << (t
.count() % 100) << 's' << std::setw(0) << std::setfill(' ');
204 int main(int argc
, char *argv
[])
206 alure::ArrayView
<const char*> args(argv
, argc
);
210 std::cerr
<< "Usage: "<<args
.front()<<" [-device \"device name\"] [-preset \"reverb preset\"] files..." <<std::endl
;
213 args
= args
.slice(1);
215 alure::DeviceManager devMgr
= alure::DeviceManager::getInstance();
218 if(args
.size() > 2 && args
[0] == alure::StringView("-device"))
220 dev
= devMgr
.openPlayback(args
[1], std::nothrow
);
221 if(!dev
) std::cerr
<< "Failed to open \""<<args
[1]<<"\" - trying default" <<std::endl
;
222 args
= args
.slice(2);
224 if(!dev
) dev
= devMgr
.openPlayback();
225 std::cout
<< "Opened \""<<dev
.getName()<<"\"" <<std::endl
;
227 alure::Context ctx
= dev
.createContext();
228 alure::Context::MakeCurrent(ctx
);
230 alure::Effect effect
= ctx
.createEffect();
231 effect
.setReverbProperties(EFX_REVERB_PRESET_GENERIC
);
233 if(args
.size() > 1 && alure::StringView("-preset") == args
[0])
235 alure::StringView reverb_name
= args
[1];
236 args
= args
.slice(2);
238 auto iter
= std::find_if(std::begin(reverblist
), std::end(reverblist
),
239 [reverb_name
](const ReverbEntry
&entry
) -> bool
240 { return ci_compare(reverb_name
, entry
.name
) == 0; }
242 if(iter
!= std::end(reverblist
))
244 std::cout
<< "Loading preset "<<iter
->name
<<std::endl
;
245 effect
.setReverbProperties(iter
->props
);
248 std::cout
<< "Failed to find preset "<<reverb_name
<<std::endl
;
251 std::cout
<< "Using generic reverb preset" <<std::endl
;
253 alure::AuxiliaryEffectSlot auxslot
= ctx
.createAuxiliaryEffectSlot();
254 auxslot
.applyEffect(effect
);
256 for(;!args
.empty();args
= args
.slice(1))
258 alure::SharedPtr
<alure::Decoder
> decoder
= ctx
.createDecoder(args
.front());
259 alure::Source source
= ctx
.createSource();
261 source
.setAuxiliarySend(auxslot
, 0);
263 source
.play(decoder
, 12000, 4);
264 std::cout
<< "Playing "<<args
.front()<<" ("
265 << alure::GetSampleTypeName(decoder
->getSampleType())<<", "
266 << alure::GetChannelConfigName(decoder
->getChannelConfig())<<", "
267 << decoder
->getFrequency()<<"hz)" <<std::endl
;
269 double invfreq
= 1.0 / decoder
->getFrequency();
270 while(source
.isPlaying())
272 std::cout
<< "\r "<<PrettyTime
{source
.getSecOffset()}<<" / "<<
273 PrettyTime
{alure::Seconds(decoder
->getLength()*invfreq
)};
275 std::this_thread::sleep_for(std::chrono::milliseconds(25));
278 std::cout
<<std::endl
;
287 alure::Context::MakeCurrent(nullptr);