ALSAAudioSink.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #pragma once
  2. #include <vector>
  3. #include <fstream>
  4. #include "AudioSink.h"
  5. #include <alsa/asoundlib.h>
  6. #include <stdio.h>
  7. #include <BellTask.h>
  8. #include <unistd.h>
  9. #include <memory>
  10. #include <mutex>
  11. #define PCM_DEVICE "default"
  12. template <typename T, int SIZE>
  13. class RingbufferPointer
  14. {
  15. typedef std::unique_ptr<T> TPointer;
  16. public:
  17. explicit RingbufferPointer()
  18. {
  19. // create objects
  20. for (int i = 0; i < SIZE; i++)
  21. {
  22. buf_[i] = std::make_unique<T>();
  23. }
  24. }
  25. bool push(TPointer &item)
  26. {
  27. std::lock_guard<std::mutex> lock(mutex_);
  28. if (full())
  29. return false;
  30. std::swap(buf_[head_], item);
  31. if (full_)
  32. tail_ = (tail_ + 1) % max_size_;
  33. head_ = (head_ + 1) % max_size_;
  34. full_ = head_ == tail_;
  35. return true;
  36. }
  37. bool pop(TPointer &item)
  38. {
  39. std::lock_guard<std::mutex> lock(mutex_);
  40. if (empty())
  41. return false;
  42. std::swap(buf_[tail_], item);
  43. full_ = false;
  44. tail_ = (tail_ + 1) % max_size_;
  45. return true;
  46. }
  47. void reset()
  48. {
  49. std::lock_guard<std::mutex> lock(mutex_);
  50. head_ = tail_;
  51. full_ = false;
  52. }
  53. bool empty() const
  54. {
  55. return (!full_ && (head_ == tail_));
  56. }
  57. bool full() const
  58. {
  59. return full_;
  60. }
  61. int capacity() const
  62. {
  63. return max_size_;
  64. }
  65. int size() const
  66. {
  67. int size = max_size_;
  68. if (!full_)
  69. {
  70. if (head_ >= tail_)
  71. size = head_ - tail_;
  72. else
  73. size = max_size_ + head_ - tail_;
  74. }
  75. return size;
  76. }
  77. private:
  78. TPointer buf_[SIZE];
  79. std::mutex mutex_;
  80. int head_ = 0;
  81. int tail_ = 0;
  82. const int max_size_ = SIZE;
  83. bool full_ = 0;
  84. };
  85. class ALSAAudioSink : public AudioSink, public bell::Task
  86. {
  87. public:
  88. ALSAAudioSink();
  89. ~ALSAAudioSink();
  90. void feedPCMFrames(const uint8_t *buffer, size_t bytes);
  91. void runTask();
  92. private:
  93. RingbufferPointer<std::vector<uint8_t>, 3> ringbuffer;
  94. unsigned int pcm;
  95. snd_pcm_t *pcm_handle;
  96. snd_pcm_hw_params_t *params;
  97. snd_pcm_uframes_t frames;
  98. int buff_size;
  99. std::vector<uint8_t> buff;
  100. };