AudioGrabber.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #include <grabber/AudioGrabber.h>
  2. #include <math.h>
  3. #include <QImage>
  4. #include <QObject>
  5. #include <QJsonObject>
  6. #include <QJsonArray>
  7. #include <QJsonValue>
  8. // Constants
  9. namespace {
  10. const uint16_t RESOLUTION = 255;
  11. //Constants vuMeter
  12. const QJsonArray DEFAULT_HOTCOLOR { 255,0,0 };
  13. const QJsonArray DEFAULT_WARNCOLOR { 255,255,0 };
  14. const QJsonArray DEFAULT_SAFECOLOR { 0,255,0 };
  15. const int DEFAULT_WARNVALUE { 80 };
  16. const int DEFAULT_SAFEVALUE { 45 };
  17. const int DEFAULT_MULTIPLIER { 0 };
  18. const int DEFAULT_TOLERANCE { 20 };
  19. }
  20. #if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
  21. namespace QColorConstants
  22. {
  23. const QColor Black = QColor(0xFF, 0x00, 0x00);
  24. const QColor Red = QColor(0xFF, 0x00, 0x00);
  25. const QColor Green = QColor(0x00, 0xFF, 0x00);
  26. const QColor Blue = QColor(0x00, 0x00, 0xFF);
  27. const QColor Yellow = QColor(0xFF, 0xFF, 0x00);
  28. }
  29. #endif
  30. //End of constants
  31. AudioGrabber::AudioGrabber()
  32. : Grabber("AudioGrabber")
  33. , _deviceProperties()
  34. , _device("none")
  35. , _hotColor(QColorConstants::Red)
  36. , _warnValue(DEFAULT_WARNVALUE)
  37. , _warnColor(QColorConstants::Yellow)
  38. , _safeValue(DEFAULT_SAFEVALUE)
  39. , _safeColor(QColorConstants::Green)
  40. , _multiplier(DEFAULT_MULTIPLIER)
  41. , _tolerance(DEFAULT_TOLERANCE)
  42. , _dynamicMultiplier(INT16_MAX)
  43. , _started(false)
  44. {
  45. }
  46. AudioGrabber::~AudioGrabber()
  47. {
  48. freeResources();
  49. }
  50. void AudioGrabber::freeResources()
  51. {
  52. }
  53. void AudioGrabber::setDevice(const QString& device)
  54. {
  55. _device = device;
  56. if (_started)
  57. {
  58. this->stop();
  59. this->start();
  60. }
  61. }
  62. void AudioGrabber::setConfiguration(const QJsonObject& config)
  63. {
  64. QString audioEffect = config["audioEffect"].toString();
  65. QJsonObject audioEffectConfig = config[audioEffect].toObject();
  66. if (audioEffect == "vuMeter")
  67. {
  68. QJsonArray hotColorArray = audioEffectConfig.value("hotColor").toArray(DEFAULT_HOTCOLOR);
  69. QJsonArray warnColorArray = audioEffectConfig.value("warnColor").toArray(DEFAULT_WARNCOLOR);
  70. QJsonArray safeColorArray = audioEffectConfig.value("safeColor").toArray(DEFAULT_SAFECOLOR);
  71. _hotColor = QColor(hotColorArray.at(0).toInt(), hotColorArray.at(1).toInt(), hotColorArray.at(2).toInt());
  72. _warnColor = QColor(warnColorArray.at(0).toInt(), warnColorArray.at(1).toInt(), warnColorArray.at(2).toInt());
  73. _safeColor = QColor(safeColorArray.at(0).toInt(), safeColorArray.at(1).toInt(), safeColorArray.at(2).toInt());
  74. _warnValue = audioEffectConfig["warnValue"].toInt(DEFAULT_WARNVALUE);
  75. _safeValue = audioEffectConfig["safeValue"].toInt(DEFAULT_SAFEVALUE);
  76. _multiplier = audioEffectConfig["multiplier"].toDouble(DEFAULT_MULTIPLIER);
  77. _tolerance = audioEffectConfig["tolerance"].toInt(DEFAULT_MULTIPLIER);
  78. }
  79. else
  80. {
  81. Error(_log, "Unknow Audio-Effect: \"%s\" configured", QSTRING_CSTR(audioEffect));
  82. }
  83. }
  84. void AudioGrabber::resetMultiplier()
  85. {
  86. _dynamicMultiplier = INT16_MAX;
  87. }
  88. void AudioGrabber::processAudioFrame(int16_t* buffer, int length)
  89. {
  90. // Apply Visualizer and Construct Image
  91. // TODO: Pass Audio Frame to python and let the script calculate the image.
  92. // TODO: Support Stereo capture with different meters per side
  93. // Default VUMeter - Later Make this pluggable for different audio effects
  94. double averageAmplitude = 0;
  95. // Calculate the the average amplitude value in the buffer
  96. for (int i = 0; i < length; i++)
  97. {
  98. averageAmplitude += fabs(buffer[i]) / length;
  99. }
  100. double * currentMultiplier;
  101. if (_multiplier < std::numeric_limits<double>::epsilon())
  102. {
  103. // Dynamically calculate multiplier.
  104. const double pendingMultiplier = INT16_MAX / fmax(1.0, averageAmplitude + ((_tolerance / 100.0) * averageAmplitude));
  105. if (pendingMultiplier < _dynamicMultiplier)
  106. _dynamicMultiplier = pendingMultiplier;
  107. currentMultiplier = &_dynamicMultiplier;
  108. }
  109. else
  110. {
  111. // User defined multiplier
  112. currentMultiplier = &_multiplier;
  113. }
  114. // Apply multiplier to average amplitude
  115. const double result = averageAmplitude * (*currentMultiplier);
  116. // Calculate the average percentage
  117. const double percentage = fmin(result / INT16_MAX, 1);
  118. // Calculate the value
  119. const int value = static_cast<int>(ceil(percentage * RESOLUTION));
  120. // Draw Image
  121. QImage image(1, RESOLUTION, QImage::Format_RGB888);
  122. image.fill(QColorConstants::Black);
  123. int safePixelValue = static_cast<int>(round(( _safeValue / 100.0) * RESOLUTION));
  124. int warnPixelValue = static_cast<int>(round(( _warnValue / 100.0) * RESOLUTION));
  125. for (int i = 0; i < RESOLUTION; i++)
  126. {
  127. QColor color = QColorConstants::Black;
  128. int position = RESOLUTION - i;
  129. if (position < safePixelValue)
  130. {
  131. color = _safeColor;
  132. }
  133. else if (position < warnPixelValue)
  134. {
  135. color = _warnColor;
  136. }
  137. else
  138. {
  139. color = _hotColor;
  140. }
  141. if (position < value)
  142. {
  143. image.setPixelColor(0, i, color);
  144. }
  145. else
  146. {
  147. image.setPixelColor(0, i, QColorConstants::Black);
  148. }
  149. }
  150. // Convert to Image<ColorRGB>
  151. Image<ColorRgb> finalImage (static_cast<unsigned>(image.width()), static_cast<unsigned>(image.height()));
  152. for (int y = 0; y < image.height(); y++)
  153. {
  154. memcpy((unsigned char*)finalImage.memptr() + y * image.width() * 3, static_cast<unsigned char*>(image.scanLine(y)), image.width() * 3);
  155. }
  156. emit newFrame(finalImage);
  157. }
  158. Logger* AudioGrabber::getLog()
  159. {
  160. return _log;
  161. }
  162. bool AudioGrabber::start()
  163. {
  164. resetMultiplier();
  165. _started = true;
  166. return true;
  167. }
  168. void AudioGrabber::stop()
  169. {
  170. _started = false;
  171. }
  172. void AudioGrabber::restart()
  173. {
  174. stop();
  175. start();
  176. }
  177. QJsonArray AudioGrabber::discover(const QJsonObject& /*params*/)
  178. {
  179. QJsonArray result; // Return empty result
  180. return result;
  181. }