ao.cpp 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #include <ao/ao.h>
  2. struct AudioAO : AudioDriver {
  3. AudioAO& self = *this;
  4. AudioAO(Audio& super) : AudioDriver(super) {}
  5. ~AudioAO() { terminate(); }
  6. auto create() -> bool override {
  7. super.setChannels(2);
  8. super.setFrequency(48000);
  9. return initialize();
  10. }
  11. auto driver() -> string override { return "libao"; }
  12. auto ready() -> bool override { return _ready; }
  13. auto hasChannels() -> vector<uint> override {
  14. return {2};
  15. }
  16. auto hasFrequencies() -> vector<uint> override {
  17. return {44100, 48000, 96000};
  18. }
  19. auto setFrequency(uint frequency) -> bool override { return initialize(); }
  20. auto output(const double samples[]) -> void override {
  21. uint32_t sample = 0;
  22. sample |= (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0;
  23. sample |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16;
  24. ao_play(_interface, (char*)&sample, 4);
  25. }
  26. private:
  27. auto initialize() -> bool {
  28. terminate();
  29. ao_initialize();
  30. int driverID = ao_default_driver_id();
  31. if(driverID < 0) return false;
  32. ao_sample_format format;
  33. format.bits = 16;
  34. format.channels = 2;
  35. format.rate = self.frequency;
  36. format.byte_format = AO_FMT_LITTLE;
  37. format.matrix = nullptr;
  38. ao_info* information = ao_driver_info(driverID);
  39. if(!information) return false;
  40. string device = information->short_name;
  41. ao_option* options = nullptr;
  42. if(device == "alsa") {
  43. ao_append_option(&options, "buffer_time", "100000"); //100ms latency (default was 500ms)
  44. }
  45. _interface = ao_open_live(driverID, &format, options);
  46. if(!_interface) return false;
  47. return _ready = true;
  48. }
  49. auto terminate() -> void {
  50. _ready = false;
  51. if(_interface) {
  52. ao_close(_interface);
  53. _interface = nullptr;
  54. }
  55. ao_shutdown();
  56. }
  57. bool _ready = false;
  58. ao_device* _interface = nullptr;
  59. };