audiomicspk2.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. #include "precompile.h"
  2. #include "audiomicspk.h"
  3. #include "audiomicspk2.h"
  4. #include "audiocontext.h"
  5. #include <assert.h>
  6. #include "audiolog.h"
  7. #include "./other/delaybuf.h"
  8. #include <dmo.h>
  9. #include <Mmsystem.h>
  10. #include <objbase.h>
  11. #include <mediaobj.h>
  12. #include <uuids.h>
  13. #include <propidl.h>
  14. #include <wmcodecdsp.h>
  15. #include <audioclient.h>
  16. #include <MMDeviceApi.h>
  17. #include <AudioEngineEndPoint.h>
  18. #include <DeviceTopology.h>
  19. #include <EndpointVolume.h>
  20. #include <functiondiscoverykeys.h>
  21. #include <portaudio.h>
  22. #include <speex/speex_resampler.h>
  23. #include <math.h>
  24. #define CLOCK_PERIOD 20
  25. #define MAX_STR_LEN 512
  26. #define AUDIO_CLOCK 8000
  27. #define CAPTURE_AUDIO_CLOCK 16000
  28. #define MAX_DELAY 100
  29. #define MS_REF_TICK 10000
  30. #define RESAMPLE_QUALITY 6
  31. #ifndef M_PI
  32. #define M_PI (3.14159265)
  33. #endif
  34. #define TWOPI (M_PI * 2.0)
  35. // play use portaudio
  36. typedef struct tagAUDIO_DEVICE_INFO
  37. {
  38. char szDeviceName[MAX_STR_LEN];
  39. char szDeviceID[MAX_STR_LEN];
  40. } AUDIO_DEVICE_INFO, *PAUDIO_DEVICE_INFO;
  41. static HRESULT GetDeviceNum(EDataFlow eDataFlow, UINT *uDevCount)
  42. {
  43. IMMDeviceEnumerator *pEnumerator = NULL;
  44. IMMDeviceCollection *pEndpoints = NULL;
  45. HRESULT hr;
  46. hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&pEnumerator);
  47. if (FAILED(hr))
  48. goto on_error;
  49. hr = pEnumerator->lpVtbl->EnumAudioEndpoints(pEnumerator, eDataFlow, DEVICE_STATE_ACTIVE, (void**)&pEndpoints);
  50. if (FAILED(hr))
  51. goto on_error;
  52. hr = pEndpoints->lpVtbl->GetCount(pEndpoints, uDevCount);
  53. if (FAILED(hr))
  54. goto on_error;
  55. on_error:
  56. if (pEndpoints)
  57. pEndpoints->lpVtbl->Release(pEndpoints);
  58. if (pEnumerator)
  59. pEnumerator->lpVtbl->Release(pEnumerator);
  60. return hr;
  61. }
  62. static HRESULT EnumDevice(EDataFlow eDataFlow, UINT uNumElements, AUDIO_DEVICE_INFO *pDevicInfo)
  63. {
  64. IMMDeviceEnumerator *pEnumerator = NULL;
  65. IMMDeviceCollection *pEndpoints = NULL;
  66. HRESULT hr;
  67. UINT uCount;
  68. UINT uIdx;
  69. hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&pEnumerator);
  70. if (FAILED(hr))
  71. goto on_error;
  72. hr = pEnumerator->lpVtbl->EnumAudioEndpoints(pEnumerator, eDataFlow, DEVICE_STATE_ACTIVE, (void**)&pEndpoints);
  73. if (FAILED(hr))
  74. goto on_error;
  75. hr = pEndpoints->lpVtbl->GetCount(pEndpoints, &uCount);
  76. if (FAILED(hr))
  77. goto on_error;
  78. ZeroMemory(pDevicInfo, sizeof(AUDIO_DEVICE_INFO)*uNumElements);
  79. for (uIdx = 0; uIdx < uCount && uIdx < uNumElements; ++uIdx) {
  80. IMMDevice *pDevice = NULL;
  81. IPropertyStore *pPS = NULL;
  82. WCHAR* pszDeviceId = NULL;
  83. PROPVARIANT value;
  84. PropVariantInit(&value);
  85. pEndpoints->lpVtbl->Item(pEndpoints, uIdx, &pDevice);
  86. pDevice->lpVtbl->GetId(pDevice, &pszDeviceId);
  87. pDevice->lpVtbl->OpenPropertyStore(pDevice, STGM_READ, &pPS);
  88. pPS->lpVtbl->GetValue(pPS, &PKEY_Device_FriendlyName, &value);
  89. WideCharToMultiByte(CP_ACP, 0, pszDeviceId, -1, pDevicInfo[uIdx].szDeviceID, MAX_STR_LEN-1, NULL, NULL);
  90. WideCharToMultiByte(CP_ACP, 0, value.pwszVal, -1, pDevicInfo[uIdx].szDeviceName, MAX_STR_LEN-1, NULL, NULL);
  91. PropVariantClear(&value);
  92. CoTaskMemFree(pszDeviceId);
  93. pPS->lpVtbl->Release(pPS);
  94. pDevice->lpVtbl->Release(pDevice);
  95. }
  96. on_error:
  97. if (pEndpoints)
  98. pEndpoints->lpVtbl->Release(pEndpoints);
  99. if (pEnumerator)
  100. pEnumerator->lpVtbl->Release(pEnumerator);
  101. return hr;
  102. }
  103. static HRESULT DeviceBindTo(
  104. EDataFlow eDataFlow, // eCapture/eRender
  105. INT iDevIdx, // Device Index. -1 - default device.
  106. IAudioClient **ppAudioClient, // pointer pointer to IAudioClient interface
  107. IAudioEndpointVolume **ppEndpointVolume
  108. )
  109. {
  110. IMMDeviceEnumerator *pEnumerator = NULL;
  111. IMMDeviceCollection *pEndpoints = NULL;
  112. IMMDevice *pDevice = NULL;
  113. HRESULT hr;
  114. hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&pEnumerator);
  115. if (FAILED(hr))
  116. goto on_error;
  117. if (iDevIdx < 0) {
  118. hr = pEnumerator->lpVtbl->GetDefaultAudioEndpoint(pEnumerator, eDataFlow, eConsole, &pDevice);
  119. if (FAILED(hr))
  120. goto on_error;
  121. } else {
  122. hr = pEnumerator->lpVtbl->EnumAudioEndpoints(pEnumerator, eDataFlow, DEVICE_STATE_ACTIVE, (void**)&pEndpoints);
  123. if (FAILED(hr))
  124. goto on_error;
  125. hr = pEndpoints->lpVtbl->Item(pEndpoints, iDevIdx, &pDevice);
  126. if (FAILED(hr))
  127. goto on_error;
  128. }
  129. hr = pDevice->lpVtbl->Activate(pDevice, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, (void**)ppAudioClient);
  130. if (FAILED(hr))
  131. goto on_error;
  132. if (ppEndpointVolume) {
  133. hr = pDevice->lpVtbl->Activate(pDevice, &IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, NULL, (void**)ppEndpointVolume);
  134. if (FAILED(hr)) {
  135. if (*ppAudioClient) {
  136. (*ppAudioClient)->lpVtbl->Release(*ppAudioClient);
  137. *ppAudioClient = NULL;
  138. }
  139. goto on_error;
  140. }
  141. }
  142. on_error:
  143. if (pDevice) {
  144. pDevice->lpVtbl->Release(pDevice);
  145. }
  146. if (pEndpoints) {
  147. pEndpoints->lpVtbl->Release(pEndpoints);
  148. }
  149. if (pEnumerator) {
  150. pEnumerator->lpVtbl->Release(pEnumerator);
  151. }
  152. return hr;
  153. }
  154. static int get_device_index(int indev, const char *key)
  155. {
  156. EDataFlow df = indev ? eCapture : eRender;
  157. UINT i;
  158. UINT n;
  159. AUDIO_DEVICE_INFO *pInfo = NULL;
  160. GetDeviceNum(df, &n);
  161. pInfo = malloc(sizeof(AUDIO_DEVICE_INFO) * n);
  162. EnumDevice(df, n, pInfo);
  163. for (i = 0; i < n; ++i) {
  164. if (strstr(pInfo[i].szDeviceName, key)) {
  165. free(pInfo);
  166. return i;
  167. }
  168. }
  169. free(pInfo);
  170. return -1;
  171. }
  172. static int get_device_index_poartaudio(int indev, const char *key)
  173. {
  174. int i;
  175. int n = Pa_GetDeviceCount();
  176. for (i = 0; i < n; ++i) {
  177. const PaDeviceInfo* pInfo = Pa_GetDeviceInfo(i);
  178. if (indev) {
  179. if (pInfo->maxInputChannels && strstr(pInfo->name, key))
  180. return i;
  181. } else {
  182. if (pInfo->maxOutputChannels && strstr(pInfo->name, key))
  183. return i;
  184. }
  185. }
  186. return -1;
  187. }
  188. static HRESULT CreateVoiceCaptureDMO(
  189. int spk_dev_id,
  190. int rec_dev_id,
  191. BOOL bNS,
  192. BOOL bAGC,
  193. IMediaObject *ppDMO)
  194. {
  195. HRESULT hr = S_OK;
  196. return hr;
  197. }
  198. typedef struct IMediaBufferImpl {
  199. struct IMediaBufferVtbl *lpVtbl;
  200. struct IMediaBufferVtbl vtbl;
  201. BYTE *m_pData;
  202. ULONG m_ulSize;
  203. ULONG m_ulData;
  204. ULONG m_cRef;
  205. }IMediaBufferImpl;
  206. static HRESULT STDMETHODCALLTYPE QueryInterface(IMediaBuffer * This, REFIID riid, void** ppvObject);
  207. static ULONG STDMETHODCALLTYPE AddRef(IMediaBuffer * This);
  208. static ULONG STDMETHODCALLTYPE Release(IMediaBuffer * This);
  209. static HRESULT STDMETHODCALLTYPE SetLength(IMediaBuffer * This, DWORD ulLength);
  210. static HRESULT STDMETHODCALLTYPE GetMaxLength(IMediaBuffer * This, DWORD *pcbMaxLength);
  211. static HRESULT STDMETHODCALLTYPE GetBufferAndLength(IMediaBuffer * This, BYTE **ppBuffer, DWORD *pcbLength);
  212. static void destroy_media_buffer(IMediaBufferImpl *pImpl)
  213. {
  214. free(pImpl->m_pData);
  215. free(pImpl);
  216. }
  217. static IMediaBuffer *create_media_buffer(ULONG len)
  218. {
  219. IMediaBufferImpl *pImpl = (IMediaBufferImpl*)malloc(sizeof(IMediaBufferImpl));
  220. if (pImpl) {
  221. pImpl->lpVtbl = &pImpl->vtbl;
  222. pImpl->lpVtbl->QueryInterface = &QueryInterface;
  223. pImpl->lpVtbl->AddRef = &AddRef;
  224. pImpl->lpVtbl->Release = &Release;
  225. pImpl->lpVtbl->SetLength = &SetLength;
  226. pImpl->lpVtbl->GetMaxLength = &GetMaxLength;
  227. pImpl->lpVtbl->GetBufferAndLength = &GetBufferAndLength;
  228. pImpl->m_pData = (BYTE*)malloc(len);
  229. pImpl->m_ulData = 0;
  230. pImpl->m_ulSize = len;
  231. pImpl->m_cRef = 1;
  232. }
  233. return (IMediaBuffer*)pImpl;
  234. }
  235. static HRESULT STDMETHODCALLTYPE QueryInterface(IMediaBuffer * This, REFIID riid, void** ppvObject)
  236. {
  237. if (This == NULL || riid == NULL || ppvObject == NULL || *ppvObject == NULL)
  238. return E_POINTER;
  239. if (IsEqualIID(riid, &IID_IUnknown)) {
  240. *ppvObject = (void*)This;
  241. return S_OK;
  242. } else if (IsEqualIID(riid, &IID_IMediaBuffer)) {
  243. *ppvObject = (void*)This;
  244. return S_OK;
  245. }
  246. return E_NOTIMPL;
  247. }
  248. static ULONG STDMETHODCALLTYPE AddRef(IMediaBuffer * This)
  249. {
  250. IMediaBufferImpl *pImpl = (IMediaBufferImpl *)This;
  251. return InterlockedIncrement(&pImpl->m_cRef);
  252. }
  253. static ULONG STDMETHODCALLTYPE Release(IMediaBuffer * This)
  254. {
  255. IMediaBufferImpl *pImpl = (IMediaBufferImpl *)This;
  256. ULONG lRet = InterlockedDecrement(&pImpl->m_cRef);
  257. if (lRet == 0) {
  258. destroy_media_buffer(pImpl);
  259. }
  260. return lRet;
  261. }
  262. static HRESULT STDMETHODCALLTYPE SetLength(IMediaBuffer * This, DWORD ulLength)
  263. {
  264. IMediaBufferImpl *pImpl = (IMediaBufferImpl *)This;
  265. pImpl->m_ulData = ulLength;
  266. return NOERROR;
  267. }
  268. static HRESULT STDMETHODCALLTYPE GetMaxLength(IMediaBuffer * This, DWORD *pcbMaxLength)
  269. {
  270. IMediaBufferImpl *pImpl = (IMediaBufferImpl *)This;
  271. *pcbMaxLength = pImpl->m_ulSize;
  272. return NOERROR;
  273. }
  274. static HRESULT STDMETHODCALLTYPE GetBufferAndLength(IMediaBuffer * This, BYTE **ppBuffer, DWORD *pcbLength)
  275. {
  276. IMediaBufferImpl *pImpl = (IMediaBufferImpl *)This;
  277. if (ppBuffer) *ppBuffer = pImpl->m_pData;
  278. if (pcbLength) *pcbLength = pImpl->m_ulData;
  279. return NOERROR;
  280. }
  281. static int load_data(audiomicspk2_t *micspk, BYTE *pData, UINT32 nCount, UINT32 *pReturnedCount)
  282. {
  283. UINT32 frame_samples = AUDIO_CLOCK * FRAME_TIME / 1000;
  284. UINT32 frame_offset = 0;
  285. while (nCount >= frame_samples) {
  286. delay_buf_get(micspk->ply_dbuf, (SHORT*)(pData+frame_offset*2));
  287. frame_offset += frame_samples;
  288. nCount -= frame_samples;
  289. }
  290. *pReturnedCount = frame_offset;
  291. return 0;
  292. }
  293. static int save_data(audiomicspk2_t *micspk, IMediaBuffer *pBuffer)
  294. {
  295. UINT32 frame_samples = AUDIO_CLOCK * FRAME_TIME / 1000;
  296. UINT32 capture_frame_samples = CAPTURE_AUDIO_CLOCK * FRAME_TIME / 1000;
  297. UINT32 frame_offset = 0;
  298. BYTE *pData;
  299. DWORD dwLength;
  300. pBuffer->lpVtbl->GetBufferAndLength(pBuffer, &pData, &dwLength);
  301. //AUDIO_LOG_INFO("micspk2 rec samples:%d", dwLength>>1);
  302. while (dwLength >= capture_frame_samples*2) {
  303. spx_uint32_t in_len = capture_frame_samples;
  304. spx_uint32_t out_len = frame_samples;
  305. SHORT *pFrameData = (SHORT*)(pData+frame_offset*2);
  306. SHORT outData[160];
  307. speex_resampler_process_int((SpeexResamplerState*)micspk->input_resample_state, 0,
  308. pFrameData, &in_len, outData, &out_len);
  309. delay_buf_put((delay_buf*)micspk->rec_dbuf, outData);
  310. frame_offset += capture_frame_samples;
  311. dwLength -= capture_frame_samples*2;
  312. }
  313. return 0;
  314. }
  315. typedef struct paTestData
  316. {
  317. int sleepFor;
  318. double phase;
  319. }
  320. paTestData;
  321. static int StreamCallback(const void *input,
  322. void *output,
  323. unsigned long frameCount,
  324. const PaStreamCallbackTimeInfo* timeInfo,
  325. PaStreamCallbackFlags statusFlags,
  326. void *userData)
  327. {
  328. audiomicspk2_t *micspk = (audiomicspk2_t*)userData;
  329. apr_status_t status;
  330. //double phase = 0;
  331. //int i=0;
  332. if (output) {
  333. unsigned nsamples_req = frameCount;
  334. if (micspk->ply_buf_cnt == 0 && nsamples_req == micspk->capture_frame_samples) {
  335. SHORT data[160];
  336. spx_uint32_t in_len = micspk->frame_samples;
  337. spx_uint32_t out_len = micspk->capture_frame_samples;
  338. delay_buf_get((delay_buf*)micspk->ply_dbuf, data);
  339. if (micspk->user_data/*&&strlen(data)*/)
  340. {
  341. micspk->on_rx_audio((char*)data,micspk->user_data);
  342. }
  343. speex_resampler_process_int((SpeexResamplerState*)micspk->output_resample_state, 0,
  344. data, &in_len, (spx_int16_t*)output, &out_len);
  345. }
  346. }
  347. //paTestData *data = (paTestData*)userData;
  348. //float *out = (float*)output;
  349. //unsigned long i;
  350. //int finished = 0;
  351. //double phaseInc = 0.02;
  352. //double phase = data->phase;
  353. //(void) input; /* Prevent unused argument warning. */
  354. //for( i=0; i<frameCount; i++ )
  355. //{
  356. // phase += phaseInc;
  357. // if( phase > TWOPI ) phase -= TWOPI;
  358. // /* This is not a very efficient way to calc sines. */
  359. // *out++ = (float) sin( phase )*2; /* mono */
  360. //}
  361. //write_log("output=%d",(spx_int16_t*)output);
  362. //if( data->sleepFor > 0 )
  363. //{
  364. // Pa_Sleep(1000 );
  365. //}
  366. //data->phase = phase;
  367. return paContinue;
  368. }
  369. static int initialize_spk(audiomicspk2_t *micspk)
  370. {
  371. UINT32 capture_frame_samples = CAPTURE_AUDIO_CLOCK * FRAME_TIME / 1000;
  372. UINT32 frame_samples = AUDIO_CLOCK * FRAME_TIME / 1000;
  373. const PaDeviceInfo *info;
  374. PaStreamParameters outParam;
  375. PaError paError;
  376. int ply_dev_id = micspk->ply_dev_id_portaudio;
  377. if (ply_dev_id == -1) {
  378. ply_dev_id = Pa_GetDefaultOutputDevice();
  379. if (ply_dev_id == paNoDevice) {
  380. AUDIO_LOG_ERROR("audiomicspk create error, cannot find output device");
  381. return APR_EGENERAL;
  382. }
  383. }
  384. info = Pa_GetDeviceInfo(ply_dev_id);
  385. outParam.device = ply_dev_id;
  386. outParam.channelCount = 1;
  387. outParam.sampleFormat = paInt16;
  388. outParam.suggestedLatency = info->defaultLowOutputLatency;
  389. outParam.hostApiSpecificStreamInfo = NULL;
  390. if (Pa_IsFormatSupported(NULL, &outParam, AUDIO_CLOCK) != paNoError) {
  391. AUDIO_LOG_ERROR("audiomicspk create error, cannot open audio output device");
  392. return APR_EGENERAL;
  393. }
  394. paError = Pa_OpenStream(&micspk->ply_stream, NULL, &outParam, CAPTURE_AUDIO_CLOCK, capture_frame_samples, paClipOff, &StreamCallback, micspk);
  395. if (paError != 0) {
  396. AUDIO_LOG_ERROR("audiomicspk create error, Pa_OpenStream function failed in dir! ");
  397. return APR_EGENERAL;
  398. }
  399. paError = Pa_StartStream(micspk->ply_stream);
  400. if (paError != 0) {
  401. AUDIO_LOG_ERROR("Pa_StartStream function failed in dir! ");
  402. Pa_CloseStream(micspk->ply_stream);
  403. micspk->ply_stream = NULL;
  404. return APR_EGENERAL;
  405. }
  406. return 0;
  407. }
  408. static int initialize_rec(audiomicspk2_t *micspk)
  409. {
  410. IMediaObject *pDMO = NULL;
  411. IPropertyStore *pPS = NULL;
  412. HRESULT hr;
  413. UINT32 capture_frame_samples = CAPTURE_AUDIO_CLOCK * FRAME_TIME / 1000;
  414. UINT32 frame_samples = AUDIO_CLOCK * FRAME_TIME / 1000;
  415. hr = CoCreateInstance(&CLSID_CWMAudioAEC, NULL, CLSCTX_INPROC_SERVER, &IID_IMediaObject, (void**)&pDMO);
  416. if (SUCCEEDED(hr)) {
  417. hr = pDMO->lpVtbl->QueryInterface(pDMO, &IID_IPropertyStore, (void**)&pPS);
  418. }
  419. if (FAILED(hr)) {
  420. if (pDMO) {
  421. pDMO->lpVtbl->Release(pDMO);
  422. }
  423. return -1;
  424. }
  425. // sys mode
  426. {
  427. PROPVARIANT pvSysMode;
  428. PropVariantInit(&pvSysMode);
  429. pvSysMode.vt = VT_I4;
  430. //pvSysMode.lVal = micspk->opt & AMS2_OPT_AEC ? SINGLE_CHANNEL_AEC : SINGLE_CHANNEL_NSAGC;
  431. pvSysMode.lVal = micspk->opt & AMS2_OPT_AEC ? OPTIBEAM_ARRAY_AND_AEC : SINGLE_CHANNEL_NSAGC;
  432. pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_SYSTEM_MODE, &pvSysMode);
  433. PropVariantClear(&pvSysMode);
  434. }
  435. #if 1
  436. // feature mode
  437. {
  438. PROPVARIANT pvFeatMode;
  439. PropVariantInit(&pvFeatMode);
  440. pvFeatMode.vt = VT_BOOL;
  441. pvFeatMode.boolVal = VARIANT_TRUE;
  442. pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_FEATURE_MODE, &pvFeatMode);
  443. PropVariantClear(&pvFeatMode);
  444. }
  445. #endif
  446. // set device index
  447. {
  448. PROPVARIANT pvDeviceId;
  449. PropVariantInit(&pvDeviceId);
  450. pvDeviceId.vt = VT_I4;
  451. pvDeviceId.lVal = (unsigned long)(micspk->ply_dev_id<<16) + (unsigned long)(0x0000ffff & micspk->rec_dev_id);
  452. pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_DEVICE_INDEXES, &pvDeviceId);
  453. PropVariantClear(&pvDeviceId);
  454. }
  455. // echo length
  456. #if 0
  457. if (micspk->opt & AMS2_OPT_AEC)
  458. {
  459. PROPVARIANT pvEchoLength;
  460. PropVariantInit(&pvEchoLength);
  461. pvEchoLength.vt = VT_I4;
  462. pvEchoLength.lVal = 128;
  463. pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_FEATR_ECHO_LENGTH, &pvEchoLength);
  464. PropVariantClear(&pvEchoLength);
  465. }
  466. #endif
  467. // echo supress times
  468. #if 1
  469. if (micspk->opt & AMS2_OPT_AEC)
  470. {
  471. PROPVARIANT pvAESTimes;
  472. PropVariantInit(&pvAESTimes);
  473. pvAESTimes.vt = VT_I4;
  474. pvAESTimes.lVal = 1; // 0, 1, 2
  475. pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_FEATR_AES, &pvAESTimes);
  476. PropVariantClear(&pvAESTimes);
  477. }
  478. #endif
  479. // center clip
  480. #if 0
  481. if (micspk->opt & AMS2_OPT_AEC)
  482. {
  483. PROPVARIANT pvCenterClip;
  484. PropVariantInit(&pvCenterClip);
  485. pvCenterClip.vt = VT_BOOL;
  486. pvCenterClip.boolVal = VARIANT_TRUE;
  487. pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_FEATR_CENTER_CLIP, &pvCenterClip);
  488. PropVariantClear(&pvCenterClip);
  489. }
  490. #endif
  491. #if 1
  492. // noise fill
  493. if (micspk->opt & AMS2_OPT_AEC)
  494. {
  495. PROPVARIANT pvNSFill;
  496. PropVariantInit(&pvNSFill);
  497. pvNSFill.vt = VT_BOOL;
  498. pvNSFill.boolVal = VARIANT_TRUE;
  499. pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_FEATR_NOISE_FILL, &pvNSFill);
  500. PropVariantClear(&pvNSFill);
  501. }
  502. // retreive TS
  503. if (micspk->opt & AMS2_OPT_AEC)
  504. {
  505. PROPVARIANT pvTS;
  506. PropVariantInit(&pvTS);
  507. pvTS.vt = VT_BOOL;
  508. pvTS.boolVal = VARIANT_TRUE;
  509. pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_RETRIEVE_TS_STATS, &pvTS);
  510. PropVariantClear(&pvTS);
  511. }
  512. #endif
  513. // noise suppression
  514. {
  515. PROPVARIANT pvNoiseSup;
  516. PropVariantInit(&pvNoiseSup);
  517. pvNoiseSup.vt = VT_I4;
  518. pvNoiseSup.lVal = micspk->opt & AMS2_OPT_NS;
  519. pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_FEATR_NS, &pvNoiseSup);
  520. PropVariantClear(&pvNoiseSup);
  521. }
  522. #if 1
  523. // Turn on/off AGC
  524. {
  525. PROPVARIANT pvAGC;
  526. PropVariantInit(&pvAGC);
  527. pvAGC.vt = VT_BOOL;
  528. pvAGC.boolVal = micspk->opt & AMS2_OPT_AGC ? VARIANT_TRUE : VARIANT_FALSE;
  529. pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_FEATR_AGC, &pvAGC);
  530. PropVariantClear(&pvAGC);
  531. }
  532. #endif
  533. // set output format
  534. {
  535. DMO_MEDIA_TYPE mt = {0};
  536. WAVEFORMATEX wfxOut = {WAVE_FORMAT_PCM, 1, CAPTURE_AUDIO_CLOCK, CAPTURE_AUDIO_CLOCK<<1, 2, 16, 0};
  537. MoInitMediaType(&mt, sizeof(WAVEFORMATEX));
  538. mt.majortype = MEDIATYPE_Audio;
  539. mt.subtype = MEDIASUBTYPE_PCM;
  540. mt.lSampleSize = 0;
  541. //mt.lSampleSize = 2;
  542. mt.bFixedSizeSamples = TRUE;
  543. mt.bTemporalCompression = FALSE;
  544. mt.formattype = FORMAT_WaveFormatEx;
  545. memcpy(mt.pbFormat, &wfxOut, sizeof(WAVEFORMATEX));
  546. pDMO->lpVtbl->SetOutputType(pDMO, 0, &mt, 0);
  547. micspk->rec_buf_size = wfxOut.nSamplesPerSec * wfxOut.wBitsPerSample / 8;
  548. MoFreeMediaType(&mt);
  549. }
  550. pDMO->lpVtbl->AllocateStreamingResources(pDMO);
  551. pPS->lpVtbl->Release(pPS);
  552. micspk->rec_dmo = pDMO;
  553. return 0;
  554. }
  555. static void dump_aec_config(audiomicspk2_t *micspk)
  556. {
  557. IMediaObject *pDMO = (IMediaObject*)micspk->rec_dmo;
  558. IPropertyStore *pPS = NULL;
  559. HRESULT hr;
  560. int echo_length = 0;
  561. int frame_size = 0;
  562. int aes_times = 0;
  563. hr = pDMO->lpVtbl->QueryInterface(pDMO, &IID_IPropertyStore, (void**)&pPS);
  564. //if (micspk->opt & AMS2_OPT_AEC)
  565. {
  566. PROPVARIANT pvEchoLength;
  567. PropVariantInit(&pvEchoLength);
  568. pvEchoLength.vt = VT_I4;
  569. //pvEchoLength.lVal = 128;
  570. pPS->lpVtbl->GetValue(pPS, &MFPKEY_WMAAECMA_FEATR_ECHO_LENGTH, &pvEchoLength);
  571. echo_length = pvEchoLength.lVal;
  572. PropVariantClear(&pvEchoLength);
  573. }
  574. //if (micspk->opt & AMS2_OPT_AEC)
  575. {
  576. PROPVARIANT pvFrameSize;
  577. PropVariantInit(&pvFrameSize);
  578. pvFrameSize.vt = VT_I4;
  579. //pvEchoLength.lVal = 128;
  580. pPS->lpVtbl->GetValue(pPS, &MFPKEY_WMAAECMA_FEATR_FRAME_SIZE, &pvFrameSize);
  581. frame_size = pvFrameSize.lVal;
  582. PropVariantClear(&pvFrameSize);
  583. }
  584. //if (micspk->opt & AMS2_OPT_AEC)
  585. {
  586. PROPVARIANT pvAESTimes;
  587. PropVariantInit(&pvAESTimes);
  588. pvAESTimes.vt = VT_I4;
  589. //pvAESTimes.lVal = 1; // 0, 1, 2
  590. pPS->lpVtbl->GetValue(pPS, &MFPKEY_WMAAECMA_FEATR_AES, &pvAESTimes);
  591. aes_times = pvAESTimes.lVal;
  592. PropVariantClear(&pvAESTimes);
  593. }
  594. if (0)
  595. {
  596. AecQualityMetrics_Struct *pAECQuality;
  597. PROPVARIANT pvAECQuality;
  598. PropVariantInit(&pvAECQuality);
  599. hr = pPS->lpVtbl->GetValue(pPS, &MFPKEY_WMAAECMA_QUALITY_METRICS, &pvAECQuality);
  600. if (SUCCEEDED(hr)) {
  601. pAECQuality = (AecQualityMetrics_Struct *)pvAECQuality.blob.pBlobData;
  602. AUDIO_LOG_INFO("i64Timestamp:%lld, ConvergenceFlag:%d, MicClippedFlag:%d, MicSilenceFlag:%d,"
  603. "PstvFeadbackFlag:%d, SpkClippedFlag:%d, SpkMuteFlag:%d, GlitchFlag:%d, DoubleTalkFlag:%d,"
  604. "uGlitchCount:%d,uMicClipCount:%d,fDuration:%f,fTSVariance:%f,fTSDriftRate:%f"
  605. "fVoiceLevel:%f,fNoiseLevel:%f,fERLE:%f,fAvgERLE:%f,dwReserved:%d",
  606. pAECQuality->i64Timestamp, pAECQuality->ConvergenceFlag, pAECQuality->MicClippedFlag,
  607. pAECQuality->MicSilenceFlag, pAECQuality->PstvFeadbackFlag, pAECQuality->SpkClippedFlag,
  608. pAECQuality->SpkMuteFlag, pAECQuality->GlitchFlag, pAECQuality->DoubleTalkFlag,
  609. pAECQuality->uGlitchCount, pAECQuality->uMicClipCount, pAECQuality->fDuration, pAECQuality->fTSVariance,
  610. pAECQuality->fTSDriftRate, pAECQuality->fVoiceLevel, pAECQuality->fNoiseLevel, pAECQuality->fERLE,
  611. pAECQuality->fAvgERLE, pAECQuality->dwReserved);
  612. if (!pAECQuality->ConvergenceFlag) {
  613. pAECQuality->ConvergenceFlag = 1;
  614. pAECQuality->uMicClipCount = 4;
  615. pAECQuality->fERLE = 0.009828;
  616. pAECQuality->fAvgERLE = 0.172231;
  617. hr = pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_QUALITY_METRICS, &pvAECQuality);
  618. if (SUCCEEDED(hr)) {
  619. AUDIO_LOG_INFO("set MFPKEY_WMAAECMA_QUALITY_METRICS ok!");
  620. } else {
  621. AUDIO_LOG_INFO("set MFPKEY_WMAAECMA_QUALITY_METRICS failed!");
  622. }
  623. }
  624. #if 0
  625. if (pAECQuality->ConvergenceFlag) {
  626. hr = pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_QUALITY_METRICS, &pvAECQuality);
  627. if (SUCCEEDED(hr)) {
  628. AUDIO_LOG_INFO("set MFPKEY_WMAAECMA_QUALITY_METRICS ok!");
  629. } else {
  630. AUDIO_LOG_INFO("set MFPKEY_WMAAECMA_QUALITY_METRICS failed!");
  631. }
  632. }
  633. #endif
  634. }
  635. PropVariantClear(&pvAECQuality);
  636. }
  637. AUDIO_LOG_INFO("echo_length:%d, frame_size:%d, aes_times:%d", echo_length, frame_size, aes_times);
  638. if (pPS) {
  639. pPS->lpVtbl->Release(pPS);
  640. }
  641. }
  642. static void set_aec_config(audiomicspk2_t *micspk)
  643. {
  644. IMediaObject *pDMO = (IMediaObject*)micspk->rec_dmo;
  645. IPropertyStore *pPS = NULL;
  646. HRESULT hr;
  647. int echo_length = 0;
  648. int frame_size = 0;
  649. hr = pDMO->lpVtbl->QueryInterface(pDMO, &IID_IPropertyStore, (void**)&pPS);
  650. // config AEC runtime state
  651. {
  652. AecQualityMetrics_Struct AECQuality = {0};
  653. PROPVARIANT pvAECQuality;
  654. PropVariantInit(&pvAECQuality);
  655. pvAECQuality.vt = VT_BLOB;
  656. pvAECQuality.blob.cbSize = sizeof(AECQuality);
  657. pvAECQuality.blob.pBlobData = &AECQuality;
  658. AECQuality.ConvergenceFlag = 1;
  659. AECQuality.uMicClipCount = 371;
  660. AECQuality.fDuration = 134.690002;
  661. AECQuality.fTSVariance = 0.167386;
  662. AECQuality.fTSDriftRate = 0.000002;
  663. AECQuality.fVoiceLevel =0.106498;
  664. AECQuality.fNoiseLevel = 0.004691;
  665. AECQuality.fERLE = 6.605908;
  666. AECQuality.fAvgERLE = 3.306793;
  667. hr = pPS->lpVtbl->SetValue(pPS, &MFPKEY_WMAAECMA_QUALITY_METRICS, &pvAECQuality);
  668. PropVariantClear(&pvAECQuality);
  669. if (SUCCEEDED(hr)) {
  670. AUDIO_LOG_INFO("set MFPKEY_WMAAECMA_QUALITY_METRICS ok!");
  671. }
  672. }
  673. if (pPS) {
  674. pPS->lpVtbl->Release(pPS);
  675. }
  676. }
  677. static void uninitialize_spk(audiomicspk2_t *micspk)
  678. {
  679. if (micspk->ply_stream) {
  680. Pa_AbortStream(micspk->ply_stream);
  681. Pa_CloseStream(micspk->ply_stream);
  682. }
  683. if (micspk->ply_dbuf) {
  684. delay_buf_destroy(micspk->ply_dbuf);
  685. micspk->ply_dbuf = NULL;
  686. }
  687. }
  688. static void uninitialize_rec(audiomicspk2_t *micspk)
  689. {
  690. IMediaObject *pDMO = (IMediaObject *)micspk->rec_dmo;
  691. if (pDMO) {
  692. pDMO->lpVtbl->Flush(pDMO);
  693. pDMO->lpVtbl->FreeStreamingResources(pDMO);
  694. pDMO->lpVtbl->Release(pDMO);
  695. }
  696. if (micspk->rec_dbuf) {
  697. delay_buf_destroy(micspk->rec_dbuf);
  698. micspk->rec_dbuf = NULL;
  699. }
  700. micspk->rec_dmo = NULL;
  701. }
  702. static void on_clock_rec(audiomicspk2_t *micspk)
  703. {
  704. IMediaObject *pDMO = (IMediaObject*)micspk->rec_dmo;
  705. DWORD dwStatus = 0;
  706. HRESULT hr;
  707. DWORD cOutputBufLen = micspk->rec_buf_size;
  708. DMO_OUTPUT_DATA_BUFFER bufferStruct = {0};
  709. do {
  710. bufferStruct.pBuffer = create_media_buffer(cOutputBufLen);
  711. bufferStruct.dwStatus = 0;
  712. hr = pDMO->lpVtbl->ProcessOutput(pDMO, 0, 1, &bufferStruct, &dwStatus);
  713. if (SUCCEEDED(hr)) {
  714. if (hr == S_FALSE) {
  715. //....
  716. } else {
  717. save_data(micspk, bufferStruct.pBuffer);
  718. #if 0
  719. if (micspk->opt & AMS2_OPT_AEC) {
  720. dump_aec_config(micspk);
  721. }
  722. #endif
  723. }
  724. bufferStruct.pBuffer->lpVtbl->Release(bufferStruct.pBuffer);
  725. } else {
  726. bufferStruct.pBuffer->lpVtbl->Release(bufferStruct.pBuffer);
  727. break;
  728. }
  729. } while (bufferStruct.dwStatus & DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE);
  730. }
  731. static unsigned int __stdcall work_proc(void *arg)
  732. {
  733. audiomicspk2_t *micspk = (audiomicspk2_t *)arg;
  734. int rc;
  735. // set a higher priority because of audio is very sensitive about timing
  736. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  737. CoInitialize(NULL);
  738. //
  739. // record need play because of AEC, so
  740. // record <---> record and play
  741. // play <---> play
  742. // record and play <---> record and play
  743. //
  744. if (micspk->opt & AMS_OPT_RECORD) {
  745. rc = initialize_spk(micspk);
  746. if (rc != 0){
  747. AUDIO_LOG_ERROR("record mode initialize speak louder param failed!");
  748. goto on_error;
  749. }
  750. Sleep(100); // play before record
  751. rc = initialize_rec(micspk);
  752. if (rc != 0){
  753. AUDIO_LOG_ERROR("initialize micro capture param failed!");
  754. goto on_error;
  755. }
  756. } else if (micspk->opt & AMS_OPT_PLAY) {
  757. rc = initialize_spk(micspk);
  758. if (rc != 0){
  759. AUDIO_LOG_ERROR("play mode initialize speak louder param failed!");
  760. goto on_error;
  761. }
  762. }
  763. micspk->evt_exit = CreateEventA(NULL, FALSE, FALSE, NULL);
  764. for (;;) {
  765. DWORD dwRet = WaitForSingleObject(micspk->evt_exit, CLOCK_PERIOD);
  766. if (dwRet == WAIT_OBJECT_0) { // exit
  767. break;
  768. } else { // timeout
  769. if (micspk->opt & AMS_OPT_RECORD) {
  770. on_clock_rec(micspk);
  771. } else if (micspk->opt & AMS_OPT_PLAY) {
  772. //on_clock_spk(micspk);
  773. }
  774. }
  775. }
  776. on_error:
  777. if (micspk->opt & AMS_OPT_RECORD) {
  778. uninitialize_rec(micspk);
  779. uninitialize_spk(micspk);
  780. } else if (micspk->opt & AMS_OPT_PLAY) {
  781. uninitialize_spk(micspk);
  782. }
  783. CoUninitialize();
  784. return 0;
  785. }
  786. static apr_status_t read_frame(void *self, audioframe_t *frame)
  787. {
  788. audiomicspk2_t *micspk = CONTAINING_RECORD(self, audiomicspk2_t, base);
  789. UINT32 frame_samples = AUDIO_CLOCK * FRAME_TIME / 1000;
  790. frame->size = 2*frame_samples;
  791. frame->dtmf = 0;
  792. delay_buf_get(micspk->rec_dbuf, (short*)frame->buffer);
  793. return APR_SUCCESS;
  794. }
  795. static apr_status_t write_frame(void *self, const audioframe_t *frame)
  796. {
  797. audiomicspk2_t *micspk = CONTAINING_RECORD(self, audiomicspk2_t, base);
  798. delay_buf_put(micspk->ply_dbuf, (short*)frame->buffer);
  799. return APR_SUCCESS;
  800. }
  801. static audiostream_vtbl_t g_stream_vtbl = {
  802. &read_frame,
  803. &write_frame,
  804. };
  805. apr_status_t audiomicspk2_create(apr_pool_t *pool,
  806. audioengine_t *engine,
  807. int opt,
  808. int clock,
  809. const char *rec_dev_key,
  810. const char *ply_dev_key,
  811. audiomicspk2_t **p_micspk)
  812. {
  813. int rec_dev_id = -1;
  814. int ply_dev_id = -1;
  815. int ply_dev_id_portaudio = -1;
  816. audiomicspk2_t *micspk;
  817. unsigned long frame_samples;
  818. unsigned long capture_frame_samples;
  819. ply_dev_id_portaudio = get_device_index_poartaudio(0, ply_dev_key);
  820. ply_dev_id = get_device_index(0, ply_dev_key);
  821. rec_dev_id = get_device_index(1, rec_dev_key);
  822. if (rec_dev_id < 0 || ply_dev_id < 0 || ply_dev_id_portaudio < 0)
  823. return APR_EGENERAL;
  824. //opt |= AMS2_OPT_AGC | AMS2_OPT_NS;
  825. micspk = apr_palloc(pool, sizeof(audiomicspk2_t));
  826. memset(micspk, 0, sizeof(audiomicspk2_t));
  827. frame_samples = FRAME_TIME * clock / 1000;
  828. capture_frame_samples = FRAME_TIME * CAPTURE_AUDIO_CLOCK/ 1000;
  829. micspk->rec_dev_id = rec_dev_id;
  830. micspk->ply_dev_id = ply_dev_id;
  831. micspk->ply_dev_id_portaudio = ply_dev_id_portaudio;
  832. micspk->opt = opt;
  833. micspk->frame_samples = frame_samples;
  834. micspk->capture_frame_samples = capture_frame_samples;
  835. audiostream_init(engine, &g_stream_vtbl, &micspk->base);
  836. micspk->base.direction = 0;
  837. if (opt & AMS_OPT_PLAY) {
  838. micspk->base.direction |= STREAM_DIR_WRITE;
  839. delay_buf_create(clock, frame_samples, 1, MAX_DELAY, 0, (delay_buf**)&micspk->ply_dbuf);
  840. micspk->ply_buf = (short*)apr_palloc(pool, frame_samples<<1);
  841. micspk->ply_buf_cnt = 0;
  842. micspk->output_resample_state = speex_resampler_init(1, AUDIO_CLOCK, CAPTURE_AUDIO_CLOCK, RESAMPLE_QUALITY, NULL);
  843. }
  844. if (opt & AMS_OPT_RECORD) {
  845. micspk->base.direction |= STREAM_DIR_READ;
  846. delay_buf_create(clock, frame_samples, 1, MAX_DELAY, 0, (delay_buf**)&micspk->rec_dbuf);
  847. micspk->input_resample_state = speex_resampler_init(1, CAPTURE_AUDIO_CLOCK, AUDIO_CLOCK, RESAMPLE_QUALITY, NULL);
  848. }
  849. micspk->worker_thread = (HANDLE)_beginthreadex(NULL, 0, &work_proc, micspk, 0, NULL);
  850. if (micspk->worker_thread) {
  851. BOOL bThreadExited = FALSE;
  852. do {
  853. DWORD dwRet = WaitForSingleObject(micspk->worker_thread, 10);
  854. if (dwRet == WAIT_TIMEOUT) {
  855. volatile HANDLE hExit = micspk->evt_exit;
  856. if (hExit)
  857. break;
  858. } else if (dwRet == WAIT_OBJECT_0) {
  859. bThreadExited = TRUE;
  860. }
  861. } while (!bThreadExited);
  862. if (bThreadExited) {
  863. audiomicspk2_destroy(micspk);
  864. return APR_EGENERAL;
  865. }
  866. } else {
  867. audiomicspk2_destroy(micspk);
  868. return APR_EGENERAL;
  869. }
  870. *p_micspk = micspk;
  871. return APR_SUCCESS;
  872. }
  873. void audiomicspk2_destroy(audiomicspk2_t *micspk)
  874. {
  875. if (micspk->evt_exit) {
  876. SetEvent(micspk->evt_exit);
  877. WaitForSingleObject(micspk->worker_thread, INFINITE);
  878. CloseHandle(micspk->worker_thread);
  879. CloseHandle(micspk->evt_exit);
  880. }
  881. if (micspk->input_resample_state) {
  882. speex_resampler_destroy((SpeexResamplerState*)micspk->input_resample_state);
  883. micspk->input_resample_state = NULL;
  884. }
  885. if (micspk->output_resample_state) {
  886. speex_resampler_destroy((SpeexResamplerState*)micspk->output_resample_state);
  887. micspk->output_resample_state = NULL;
  888. }
  889. }