ALSAAudioSink.h 2.0 KB

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