Add createContext methods that don't throw on error
[alure.git] / examples / alure-hrtf.cpp
blobe650ccc2d28aca6b6aa25a46e847086c5613c0cd
1 /*
2 * An example showing how to enable HRTF rendering, using the ALC_SOFT_HRTF
3 * extension.
4 */
6 #include <algorithm>
7 #include <iostream>
8 #include <sstream>
9 #include <iomanip>
10 #include <cstring>
11 #include <thread>
12 #include <chrono>
14 #include "alure2.h"
15 #include "alext.h"
17 int main(int argc, char *argv[])
19 alure::DeviceManager devMgr = alure::DeviceManager::get();
21 int fileidx = 1;
22 alure::Device dev;
23 if(argc > 3 && strcmp(argv[1], "-device") == 0)
25 fileidx = 3;
26 dev = devMgr.openPlayback(argv[2], std::nothrow);
27 if(!dev)
28 std::cerr<< "Failed to open \""<<argv[2]<<"\" - trying default" <<std::endl;
30 if(!dev)
31 dev = devMgr.openPlayback();
32 std::cout<< "Opened \""<<dev.getName()<<"\"" <<std::endl;
34 if(!dev.queryExtension("ALC_SOFT_HRTF"))
36 std::cerr<< "ALC_SOFT_HRTF not supported!" <<std::endl;
37 return 1;
40 // Enumerate (and display) the available HRTFs
41 std::cout<< "Available HRTFs:\n";
42 alure::Vector<alure::String> hrtf_names = dev.enumerateHRTFNames();
43 for(const alure::String &name : hrtf_names)
44 std::cout<< " "<<name <<'\n';
45 std::cout.flush();
47 alure::Vector<alure::AttributePair> attrs;
48 attrs.push_back({ALC_HRTF_SOFT, ALC_TRUE});
49 if(argc-fileidx > 1 && strcasecmp(argv[fileidx], "-hrtf") == 0)
51 // Find the given HRTF and add it to the attributes list
52 const char *hrtf_name = argv[fileidx+1];
53 fileidx += 2;
55 auto iter = std::find(hrtf_names.begin(), hrtf_names.end(), hrtf_name);
56 if(iter == hrtf_names.end())
57 std::cerr<< "HRTF \""<<hrtf_name<<"\" not found" <<std::endl;
58 else
59 attrs.push_back({ALC_HRTF_ID_SOFT, std::distance(hrtf_names.begin(), iter)});
61 attrs.push_back(alure::AttributesEnd);
62 alure::Context ctx = dev.createContext(attrs);
63 alure::Context::MakeCurrent(ctx);
65 std::cout<< "Using HRTF \""<<dev.getCurrentHRTF()<<"\"" <<std::endl;
67 for(int i = fileidx;i < argc;i++)
69 if(argc-i > 1 && strcasecmp(argv[i], "-hrtf") == 0)
71 // Find the given HRTF and reset the device using it
72 auto iter = std::find(hrtf_names.begin(), hrtf_names.end(), argv[i+1]);
73 if(iter == hrtf_names.end())
74 std::cerr<< "HRTF \""<<argv[i+1]<<"\" not found" <<std::endl;
75 else
77 alure::Array<alure::AttributePair,3> attrs{{
78 {ALC_HRTF_SOFT, ALC_TRUE},
79 {ALC_HRTF_ID_SOFT, std::distance(hrtf_names.begin(), iter)},
80 alure::AttributesEnd
81 }};
82 dev.reset(attrs);
83 std::cout<< "Using HRTF \""<<dev.getCurrentHRTF()<<"\"" <<std::endl;
86 ++i;
87 continue;
90 alure::SharedPtr<alure::Decoder> decoder(ctx.createDecoder(argv[i]));
91 alure::Source source = ctx.createSource();
93 source.play(decoder, 12000, 4);
94 std::cout<< "Playing "<<argv[i]<<" ("<<alure::GetSampleTypeName(decoder->getSampleType())<<", "
95 <<alure::GetChannelConfigName(decoder->getChannelConfig())<<", "
96 <<decoder->getFrequency()<<"hz)" <<std::endl;
98 float invfreq = 1.0f / decoder->getFrequency();
99 while(source.isPlaying())
101 std::cout<< "\r "<<std::setiosflags(std::ios::fixed)<<std::setprecision(2)<<
102 source.getSecOffset().count()<<" / "<<(decoder->getLength()*invfreq);
103 std::cout.flush();
104 std::this_thread::sleep_for(std::chrono::milliseconds(25));
105 ctx.update();
107 std::cout<<std::endl;
109 source.release();
112 alure::Context::MakeCurrent(nullptr);
113 ctx.destroy();
114 dev.close();
116 return 0;