audio_capturer.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include "audio_capturer.h"
  2. #include "basic/basic.h"
  3. #define DEFAULT_SAMPLE_RATE 48000 // 默认采样率:48kHz
  4. #define DEFAULT_BITS_PER_SAMPLE 16 // 默认位深:16bit
  5. #define DEFAULT_CHANNELS 1 // 默认音频通道数:1
  6. #define DEFAULT_AUDIO_PACKET_INTERVAL 10 // 默认音频包发送间隔:10ms
  7. bool AudioCapturer::Init(Type deviceType, CallBack callback, void* userInfo)
  8. {
  9. Stop();
  10. _userInfo = userInfo;
  11. _callback = callback;
  12. _deviceType = deviceType;
  13. __CheckBool(_CreateDeviceEnumerator(&_pDeviceEnumerator));
  14. __CheckBool(_CreateDevice(_pDeviceEnumerator, &_pDevice));
  15. __CheckBool(_CreateAudioClient(_pDevice, &_pAudioClient));
  16. if (!_IsFormatSupported(_pAudioClient)) {
  17. __CheckBool(_GetPreferFormat(_pAudioClient, &_formatex));
  18. }
  19. __CheckBool(_InitAudioClient(_pAudioClient, &_formatex));
  20. __CheckBool(_CreateAudioCaptureClient(_pAudioClient, &_pAudioCaptureClient));
  21. _format.sampleRate = _formatex.Format.nSamplesPerSec;
  22. _format.channels = _formatex.Format.nChannels;
  23. _format.bitsPerSample = _formatex.Format.wBitsPerSample;
  24. _format.avgBytesPerSec = _formatex.Format.nAvgBytesPerSec;
  25. _format.blockAlign = _formatex.Format.nBlockAlign;
  26. _isInit = true;
  27. return true;
  28. }
  29. bool AudioCapturer::Start()
  30. {
  31. __CheckBool(_isInit);
  32. _loopFlag = true;
  33. // 用于强制打开扬声器
  34. PlaySoundA("./rc/mute.wav", nullptr, SND_FILENAME | SND_ASYNC | SND_LOOP);
  35. _captureThread = new std::thread(
  36. [this] { _ThreadRun(_pAudioClient, _pAudioCaptureClient); });
  37. return true;
  38. }
  39. void AudioCapturer::Stop()
  40. {
  41. // CoUninitialize();
  42. _isInit = false;
  43. _loopFlag = false;
  44. Free(_captureThread, [this] {
  45. _captureThread->join();
  46. delete _captureThread;
  47. });
  48. Free(_pAudioCaptureClient, [this] { _pAudioCaptureClient->Release(); });
  49. if (_pAudioClient != nullptr) {
  50. _pAudioClient->Stop();
  51. }
  52. PlaySoundA(nullptr, nullptr, SND_FILENAME | SND_ASYNC | SND_LOOP);
  53. Free(_pAudioClient, [this] { _pAudioClient->Release(); });
  54. Free(_pDevice, [this] { _pDevice->Release(); });
  55. Free(_pDeviceEnumerator, [this] { _pDeviceEnumerator->Release(); });
  56. }
  57. bool AudioCapturer::_CreateDeviceEnumerator(IMMDeviceEnumerator** enumerator)
  58. {
  59. // __CheckBool(SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)));
  60. // __CheckBool(SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)));
  61. __CheckBool(SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL,
  62. __uuidof(IMMDeviceEnumerator),
  63. reinterpret_cast<void**>(enumerator))));
  64. return true;
  65. }
  66. bool AudioCapturer::_CreateDevice(IMMDeviceEnumerator* enumerator, IMMDevice** device)
  67. {
  68. EDataFlow enDataFlow = _deviceType == Microphone ? eCapture : eRender;
  69. ERole enRole = eConsole;
  70. __CheckBool(SUCCEEDED(enumerator->GetDefaultAudioEndpoint(enDataFlow, enRole, device)));
  71. return true;
  72. }
  73. bool AudioCapturer::_CreateAudioClient(IMMDevice* device, IAudioClient** audioClient)
  74. {
  75. __CheckBool(SUCCEEDED(device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL,
  76. (void**)audioClient)));
  77. return true;
  78. }
  79. bool AudioCapturer::_IsFormatSupported(IAudioClient* audioClient)
  80. {
  81. memset(&_formatex, 0, sizeof(_formatex));
  82. WAVEFORMATEX* format = &_formatex.Format;
  83. format->nSamplesPerSec = DEFAULT_SAMPLE_RATE;
  84. format->wBitsPerSample = DEFAULT_BITS_PER_SAMPLE;
  85. format->nChannels = DEFAULT_CHANNELS;
  86. WAVEFORMATEX* closestMatch = nullptr;
  87. HRESULT hr = audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,
  88. format, &closestMatch);
  89. if (hr == AUDCLNT_E_UNSUPPORTED_FORMAT) // 0x88890008
  90. {
  91. if (closestMatch == nullptr) // 如果找不到最相近的格式,closestMatch可能为nullptr
  92. {
  93. return false;
  94. }
  95. format->nSamplesPerSec = closestMatch->nSamplesPerSec;
  96. format->wBitsPerSample = closestMatch->wBitsPerSample;
  97. format->nChannels = closestMatch->nChannels;
  98. return true;
  99. }
  100. return false;
  101. }
  102. bool AudioCapturer::_GetPreferFormat(IAudioClient* audioClient,
  103. WAVEFORMATEXTENSIBLE* formatex)
  104. {
  105. WAVEFORMATEX* format = nullptr;
  106. __CheckBool(SUCCEEDED(audioClient->GetMixFormat(&format)));
  107. formatex->Format.nSamplesPerSec = format->nSamplesPerSec;
  108. formatex->Format.wBitsPerSample = format->wBitsPerSample;
  109. formatex->Format.nChannels = format->nChannels;
  110. return true;
  111. }
  112. bool AudioCapturer::_InitAudioClient(IAudioClient* audioClient,
  113. WAVEFORMATEXTENSIBLE* formatex)
  114. {
  115. AUDCLNT_SHAREMODE shareMode = AUDCLNT_SHAREMODE_SHARED; // share Audio Engine with other applications
  116. DWORD streamFlags = _deviceType == Microphone ? 0 : AUDCLNT_STREAMFLAGS_LOOPBACK;
  117. streamFlags |= AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM; // A channel matrixer and a sample
  118. // rate converter are inserted
  119. streamFlags |= AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY; // a sample rate converter
  120. // with better quality than
  121. // the default conversion but
  122. // with a higher performance
  123. // cost is used
  124. REFERENCE_TIME hnsBufferDuration = 0;
  125. WAVEFORMATEX* format = &formatex->Format;
  126. format->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
  127. format->nBlockAlign = (format->wBitsPerSample >> 3) * format->nChannels;
  128. format->nAvgBytesPerSec = format->nBlockAlign * format->nSamplesPerSec;
  129. format->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
  130. formatex->Samples.wValidBitsPerSample = format->wBitsPerSample;
  131. formatex->dwChannelMask = format->nChannels == 1 ? KSAUDIO_SPEAKER_MONO : KSAUDIO_SPEAKER_STEREO;
  132. formatex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  133. __CheckBool(SUCCEEDED(audioClient->Initialize(shareMode, streamFlags, hnsBufferDuration, 0,
  134. format, nullptr)));
  135. return true;
  136. }
  137. bool AudioCapturer::_CreateAudioCaptureClient(IAudioClient* audioClient,
  138. IAudioCaptureClient** audioCaptureClient)
  139. {
  140. __CheckBool(SUCCEEDED(audioClient->GetService(IID_PPV_ARGS(audioCaptureClient))));
  141. return true;
  142. }
  143. bool AudioCapturer::_ThreadRun(IAudioClient* audio_client,
  144. IAudioCaptureClient* audio_capture_client)
  145. {
  146. UINT32 num_success = 0;
  147. BYTE* p_audio_data = nullptr;
  148. UINT32 num_frames_to_read = 0;
  149. DWORD dw_flag = 0;
  150. UINT32 num_frames_in_next_packet = 0;
  151. audio_client->Start();
  152. while (_loopFlag) {
  153. SleepMs(5);
  154. while (true) {
  155. __CheckBool(SUCCEEDED(audio_capture_client->GetNextPacketSize(&num_frames_in_next_packet)));
  156. if (num_frames_in_next_packet == 0) {
  157. break;
  158. }
  159. __CheckBool(SUCCEEDED(audio_capture_client->GetBuffer(&p_audio_data, &num_frames_to_read,
  160. &dw_flag, nullptr, nullptr)));
  161. size_t size = (_formatex.Format.wBitsPerSample >> 3) * _formatex.Format.nChannels * num_frames_to_read;
  162. _callback(p_audio_data, size, _userInfo);
  163. __CheckBool(SUCCEEDED(audio_capture_client->ReleaseBuffer(num_frames_to_read)));
  164. }
  165. }
  166. audio_client->Stop();
  167. return true;
  168. }