2 * An example showing how to enable HRTF rendering, using the ALC_SOFT_HRTF
18 // Helper class+method to print the time with human-readable formatting.
22 inline std::ostream
&operator<<(std::ostream
&os
, const PrettyTime
&rhs
)
24 using hours
= std::chrono::hours
;
25 using minutes
= std::chrono::minutes
;
26 using seconds
= std::chrono::seconds
;
27 using centiseconds
= std::chrono::duration
<int64_t, std::ratio
<1, 100>>;
28 using std::chrono::duration_cast
;
30 centiseconds t
= duration_cast
<centiseconds
>(rhs
.mTime
);
37 // Only handle up to hour formatting
39 os
<< duration_cast
<hours
>(t
).count() << 'h' << std::setfill('0') << std::setw(2)
40 << duration_cast
<minutes
>(t
).count() << 'm';
42 os
<< duration_cast
<minutes
>(t
).count() << 'm' << std::setfill('0');
43 os
<< std::setw(2) << (duration_cast
<seconds
>(t
).count() % 60) << '.' << std::setw(2)
44 << (t
.count() % 100) << 's' << std::setw(0) << std::setfill(' ');
50 int main(int argc
, char *argv
[])
52 alure::ArrayView
<const char*> args(argv
, argc
);
56 std::cerr
<< "Usage: "<<args
.front()<<" [-device \"device name\"] [-hrtf \"HRTF name\"] files..." <<std::endl
;
61 alure::DeviceManager devMgr
= alure::DeviceManager::getInstance();
64 if(args
.size() > 2 && args
[0] == alure::StringView("-device"))
66 dev
= devMgr
.openPlayback(args
[1], std::nothrow
);
67 if(!dev
) std::cerr
<< "Failed to open \""<<args
[1]<<"\" - trying default" <<std::endl
;
70 if(!dev
) dev
= devMgr
.openPlayback();
71 std::cout
<< "Opened \""<<dev
.getName()<<"\"" <<std::endl
;
73 // Enumerate (and display) the available HRTFs
74 alure::Vector
<alure::String
> hrtf_names
= dev
.enumerateHRTFNames();
75 if(hrtf_names
.empty())
76 std::cout
<< "No HRTFs found!\n";
79 std::cout
<< "Available HRTFs:\n";
80 for(const alure::String
&name
: hrtf_names
)
81 std::cout
<< " "<<name
<<'\n';
85 alure::Vector
<alure::AttributePair
> attrs
;
86 attrs
.push_back({ALC_HRTF_SOFT
, ALC_TRUE
});
87 if(args
.size() > 1 && alure::StringView("-hrtf") == args
[0])
89 // Find the given HRTF and add it to the attributes list
90 alure::StringView hrtf_name
= args
[1];
93 size_t idx
= std::distance(
94 hrtf_names
.begin(), std::find(hrtf_names
.begin(), hrtf_names
.end(), hrtf_name
)
96 if(idx
== hrtf_names
.size())
97 std::cerr
<< "HRTF \""<<hrtf_name
<<"\" not found" <<std::endl
;
99 attrs
.push_back({ALC_HRTF_ID_SOFT
, static_cast<ALint
>(idx
)});
101 attrs
.push_back(alure::AttributesEnd());
102 alure::Context ctx
= dev
.createContext(attrs
);
103 alure::Context::MakeCurrent(ctx
);
105 if(dev
.isHRTFEnabled())
106 std::cout
<< "Using HRTF \""<<dev
.getCurrentHRTF()<<"\"" <<std::endl
;
108 std::cout
<< "HRTF not enabled!" <<std::endl
;
110 for(;!args
.empty();args
= args
.slice(1))
112 if(args
.size() > 1 && alure::StringView("-hrtf") == args
[0])
114 // Find the given HRTF and reset the device using it
115 alure::StringView hrtf_name
= args
[1];
116 size_t idx
= std::distance(
117 hrtf_names
.begin(), std::find(hrtf_names
.begin(), hrtf_names
.end(), hrtf_name
)
119 if(idx
== hrtf_names
.size())
120 std::cerr
<< "HRTF \""<<hrtf_name
<<"\" not found" <<std::endl
;
123 alure::Array
<alure::AttributePair
,3> attrs
{{
124 {ALC_HRTF_SOFT
, ALC_TRUE
},
125 {ALC_HRTF_ID_SOFT
, static_cast<ALint
>(idx
)},
126 alure::AttributesEnd()
129 if(dev
.isHRTFEnabled())
130 std::cout
<< "Using HRTF \""<<dev
.getCurrentHRTF()<<"\"" <<std::endl
;
132 std::cout
<< "HRTF not enabled!" <<std::endl
;
135 args
= args
.slice(1);
139 alure::SharedPtr
<alure::Decoder
> decoder
= ctx
.createDecoder(args
.front());
140 alure::Source source
= ctx
.createSource();
142 source
.play(decoder
, 12000, 4);
143 std::cout
<< "Playing "<<args
.front()<<" ("
144 << alure::GetSampleTypeName(decoder
->getSampleType())<<", "
145 << alure::GetChannelConfigName(decoder
->getChannelConfig())<<", "
146 << decoder
->getFrequency()<<"hz)" <<std::endl
;
148 double invfreq
= 1.0 / decoder
->getFrequency();
149 while(source
.isPlaying())
151 std::cout
<< "\r "<<PrettyTime
{source
.getSecOffset()}<<" / "<<
152 PrettyTime
{alure::Seconds(decoder
->getLength()*invfreq
)};
154 std::this_thread::sleep_for(std::chrono::milliseconds(25));
157 std::cout
<<std::endl
;
162 alure::Context::MakeCurrent(nullptr);