webrtc_audio_input_tester.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #include "webrtc/webrtc_audio_input_tester.h"
  8. #include "webrtc/webrtc_device_common.h"
  9. #include "webrtc/webrtc_create_adm.h"
  10. #include "crl/crl_object_on_thread.h"
  11. #include "crl/crl_async.h"
  12. #include <api/task_queue/default_task_queue_factory.h>
  13. #include <modules/audio_device/include/audio_device_defines.h>
  14. #include <modules/audio_device/include/audio_device.h>
  15. namespace Webrtc {
  16. class AudioInputTester::Impl : public webrtc::AudioTransport {
  17. public:
  18. explicit Impl(const std::shared_ptr<std::atomic<int>> &maxSample);
  19. ~Impl();
  20. void setDeviceId(const DeviceResolvedId &deviceId);
  21. private:
  22. void init();
  23. void restart();
  24. int32_t RecordedDataIsAvailable(
  25. const void* audioSamples,
  26. const size_t nSamples,
  27. const size_t nBytesPerSample,
  28. const size_t nChannels,
  29. const uint32_t samplesPerSec,
  30. const uint32_t totalDelayMS,
  31. const int32_t clockDrift,
  32. const uint32_t currentMicLevel,
  33. const bool keyPressed,
  34. uint32_t& newMicLevel) override;
  35. // Implementation has to setup safe values for all specified out parameters.
  36. int32_t NeedMorePlayData(
  37. const size_t nSamples,
  38. const size_t nBytesPerSample,
  39. const size_t nChannels,
  40. const uint32_t samplesPerSec,
  41. void* audioSamples,
  42. size_t& nSamplesOut, // NOLINT
  43. int64_t* elapsed_time_ms,
  44. int64_t* ntp_time_ms) override;
  45. // Method to pull mixed render audio data from all active VoE channels.
  46. // The data will not be passed as reference for audio processing internally.
  47. void PullRenderData(
  48. int bits_per_sample,
  49. int sample_rate,
  50. size_t number_of_channels,
  51. size_t number_of_frames,
  52. void* audio_data,
  53. int64_t* elapsed_time_ms,
  54. int64_t* ntp_time_ms) override;
  55. std::shared_ptr<std::atomic<int>> _maxSample;
  56. std::unique_ptr<webrtc::TaskQueueFactory> _taskQueueFactory;
  57. rtc::scoped_refptr<webrtc::AudioDeviceModule> _adm;
  58. Fn<void(DeviceResolvedId)> _setDeviceIdCallback;
  59. DeviceResolvedId _deviceId;
  60. };
  61. AudioInputTester::Impl::Impl(
  62. const std::shared_ptr<std::atomic<int>> &maxSample)
  63. : _maxSample(std::move(maxSample))
  64. , _taskQueueFactory(webrtc::CreateDefaultTaskQueueFactory())
  65. , _deviceId{ .type = DeviceType::Capture } {
  66. const auto saveSetDeviceIdCallback = [=](
  67. Fn<void(DeviceResolvedId)> setDeviceIdCallback) {
  68. _setDeviceIdCallback = std::move(setDeviceIdCallback);
  69. if (!_deviceId.isDefault()) {
  70. _setDeviceIdCallback(_deviceId);
  71. restart();
  72. }
  73. };
  74. _adm = CreateAudioDeviceModule(
  75. _taskQueueFactory.get(),
  76. saveSetDeviceIdCallback);
  77. init();
  78. }
  79. AudioInputTester::Impl::~Impl() {
  80. if (_adm) {
  81. _adm->StopRecording();
  82. _adm->RegisterAudioCallback(nullptr);
  83. _adm->Terminate();
  84. }
  85. }
  86. void AudioInputTester::Impl::init() {
  87. if (!_adm) {
  88. return;
  89. }
  90. _adm->Init();
  91. _adm->RegisterAudioCallback(this);
  92. }
  93. void AudioInputTester::Impl::setDeviceId(const DeviceResolvedId &deviceId) {
  94. _deviceId = deviceId;
  95. if (_setDeviceIdCallback) {
  96. _setDeviceIdCallback(_deviceId);
  97. restart();
  98. }
  99. }
  100. void AudioInputTester::Impl::restart() {
  101. if (!_adm) {
  102. return;
  103. }
  104. _adm->StopRecording();
  105. _adm->SetRecordingDevice(0);
  106. if (_adm->InitRecording() == 0) {
  107. _adm->StartRecording();
  108. }
  109. }
  110. int32_t AudioInputTester::Impl::RecordedDataIsAvailable(
  111. const void* audioSamples,
  112. const size_t nSamples,
  113. const size_t nBytesPerSample,
  114. const size_t nChannels,
  115. const uint32_t samplesPerSec,
  116. const uint32_t totalDelayMS,
  117. const int32_t clockDrift,
  118. const uint32_t currentMicLevel,
  119. const bool keyPressed,
  120. uint32_t& newMicLevel) {
  121. const auto channels = nBytesPerSample / sizeof(int16_t);
  122. if (channels > 0 && !(nBytesPerSample % sizeof(int16_t))) {
  123. auto max = 0;
  124. auto values = static_cast<const int16_t*>(audioSamples);
  125. for (auto i = size_t(); i != nSamples * channels; ++i) {
  126. if (max < values[i]) {
  127. max = values[i];
  128. }
  129. }
  130. const auto now = _maxSample->load();
  131. if (max > now) {
  132. _maxSample->store(max);
  133. }
  134. }
  135. newMicLevel = currentMicLevel;
  136. return 0;
  137. }
  138. int32_t AudioInputTester::Impl::NeedMorePlayData(const size_t nSamples,
  139. const size_t nBytesPerSample,
  140. const size_t nChannels,
  141. const uint32_t samplesPerSec,
  142. void* audioSamples,
  143. size_t& nSamplesOut,
  144. int64_t* elapsed_time_ms,
  145. int64_t* ntp_time_ms) {
  146. nSamplesOut = 0;
  147. return 0;
  148. }
  149. void AudioInputTester::Impl::PullRenderData(int bits_per_sample,
  150. int sample_rate,
  151. size_t number_of_channels,
  152. size_t number_of_frames,
  153. void* audio_data,
  154. int64_t* elapsed_time_ms,
  155. int64_t* ntp_time_ms) {
  156. }
  157. AudioInputTester::AudioInputTester(rpl::producer<DeviceResolvedId> deviceId)
  158. : _maxSample(std::make_shared<std::atomic<int>>(0))
  159. , _impl(std::as_const(_maxSample)) {
  160. std::move(
  161. deviceId
  162. ) | rpl::start_with_next([=](const DeviceResolvedId &id) {
  163. _impl.with([=](Impl &impl) {
  164. impl.setDeviceId(id);
  165. });
  166. }, _lifetime);
  167. }
  168. AudioInputTester::~AudioInputTester() = default;
  169. float AudioInputTester::getAndResetLevel() {
  170. return _maxSample->exchange(0) / float(INT16_MAX);
  171. }
  172. } // namespace Webrtc