pulseaudio-simple.cpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #include <pulse/simple.h>
  2. #include <pulse/error.h>
  3. struct AudioPulseAudioSimple : AudioDriver {
  4. AudioPulseAudioSimple& self = *this;
  5. AudioPulseAudioSimple(Audio& super) : AudioDriver(super) {}
  6. ~AudioPulseAudioSimple() { terminate(); }
  7. auto create() -> bool override {
  8. super.setBlocking(true);
  9. super.setChannels(2);
  10. super.setFrequency(48000);
  11. return initialize();
  12. }
  13. auto driver() -> string override { return "PulseAudio Simple"; }
  14. auto ready() -> bool override { return _ready; }
  15. auto hasFrequencies() -> vector<uint> override {
  16. return {44100, 48000, 96000};
  17. }
  18. auto setFrequency(uint frequency) -> bool override { return initialize(); }
  19. auto output(const double samples[]) -> void override {
  20. if(!ready()) return;
  21. _buffer[_offset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0;
  22. _buffer[_offset] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16;
  23. if(++_offset >= 64) {
  24. int error;
  25. pa_simple_write(_interface, (const void*)_buffer, _offset * sizeof(uint32_t), &error);
  26. _offset = 0;
  27. }
  28. }
  29. private:
  30. auto initialize() -> bool {
  31. terminate();
  32. pa_sample_spec specification;
  33. specification.format = PA_SAMPLE_S16LE;
  34. specification.channels = 2;
  35. specification.rate = self.frequency;
  36. int error = 0;
  37. _interface = pa_simple_new(
  38. 0, //default server
  39. "ruby::pulseAudioSimple", //application name
  40. PA_STREAM_PLAYBACK, //direction
  41. 0, //default device
  42. "audio", //stream description
  43. &specification, //sample format
  44. 0, //default channel map
  45. 0, //default buffering attributes
  46. &error //error code
  47. );
  48. if(!_interface) return false;
  49. _buffer = new uint32_t[64]();
  50. _offset = 0;
  51. return _ready = true;
  52. }
  53. auto terminate() -> void {
  54. _ready = false;
  55. if(_interface) {
  56. int error;
  57. pa_simple_flush(_interface, &error);
  58. pa_simple_free(_interface);
  59. _interface = nullptr;
  60. }
  61. if(_buffer) {
  62. delete[] _buffer;
  63. _buffer = nullptr;
  64. }
  65. }
  66. bool _ready = false;
  67. pa_simple* _interface = nullptr;
  68. uint32_t* _buffer = nullptr;
  69. uint _offset = 0;
  70. };