11diff --git a/modules/audio_device/win/audio_device_core_win.cc b/modules/audio_device/win/audio_device_core_win.cc
2- index f1cc0474fc..ffb0b159b1 100644
2+ index f1cc0474fc..f8e4f25bb9 100644
33--- a/modules/audio_device/win/audio_device_core_win.cc
44+++ b/modules/audio_device/win/audio_device_core_win.cc
5- @@ -1846,7 +1846,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
5+ @@ -1845,8 +1845,8 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
6+
67 HRESULT hr = S_OK;
78 WAVEFORMATEX* pWfxOut = NULL;
8- WAVEFORMATEX Wfx = WAVEFORMATEX();
9+ - WAVEFORMATEX Wfx = WAVEFORMATEX();
910- WAVEFORMATEX* pWfxClosestMatch = NULL;
10- + WAVEFORMATEX* pInitWfxClosestMatch = NULL;
11+ + WAVEFORMATEXTENSIBLE Wfx = WAVEFORMATEXTENSIBLE();
12+ + WAVEFORMATEXTENSIBLE* pInitWfxClosestMatch = NULL;
1113
1214 // Create COM object with IAudioClient interface.
1315 SAFE_RELEASE(_ptrClientOut);
14- @@ -1881,7 +1881,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
15- Wfx.wBitsPerSample = 16;
16- Wfx.cbSize = 0;
16+ @@ -1877,11 +1877,14 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
17+ }
18+
19+ // Set wave format
20+ - Wfx.wFormatTag = WAVE_FORMAT_PCM;
21+ - Wfx.wBitsPerSample = 16;
22+ - Wfx.cbSize = 0;
23+ + Wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
24+ + Wfx.Format.wBitsPerSample = 16;
25+ + Wfx.Format.cbSize = 22;
26+ + Wfx.dwChannelMask = 0;
27+ + Wfx.Samples.wValidBitsPerSample = Wfx.Format.wBitsPerSample;
28+ + Wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1729
1830- const int freqs[] = {48000, 44100, 16000, 96000, 32000, 8000};
1931+ const int freqs[] = {48000, 44100, 16000, 96000, 32000, 8000, 192000};
2032 hr = S_FALSE;
2133
2234 // Iterate over frequencies and channels, in order of priority
23- @@ -1896,6 +1896,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
35+ @@ -1889,30 +1892,38 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
36+ for (unsigned int chan = 0; chan < sizeof(_playChannelsPrioList) /
37+ sizeof(_playChannelsPrioList[0]);
38+ chan++) {
39+ - Wfx.nChannels = _playChannelsPrioList[chan];
40+ - Wfx.nSamplesPerSec = freqs[freq];
41+ - Wfx.nBlockAlign = Wfx.nChannels * Wfx.wBitsPerSample / 8;
42+ - Wfx.nAvgBytesPerSec = Wfx.nSamplesPerSec * Wfx.nBlockAlign;
43+ + Wfx.Format.nChannels = _playChannelsPrioList[chan];
44+ + Wfx.Format.nSamplesPerSec = freqs[freq];
45+ + Wfx.Format.nBlockAlign =
46+ + Wfx.Format.nChannels * Wfx.Format.wBitsPerSample / 8;
47+ + Wfx.Format.nAvgBytesPerSec =
48+ + Wfx.Format.nSamplesPerSec * Wfx.Format.nBlockAlign;
2449 // If the method succeeds and the audio endpoint device supports the
2550 // specified stream format, it returns S_OK. If the method succeeds and
2651 // provides a closest match to the specified format, it returns S_FALSE.
27- + WAVEFORMATEX* pWfxClosestMatch = NULL;
28- hr = _ptrClientOut->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &Wfx,
29- &pWfxClosestMatch);
52+ - hr = _ptrClientOut->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &Wfx,
53+ - &pWfxClosestMatch);
54+ + WAVEFORMATEXTENSIBLE* pWfxClosestMatch = NULL;
55+ + hr = _ptrClientOut->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,
56+ + (WAVEFORMATEX*)&Wfx,
57+ + (WAVEFORMATEX**)&pWfxClosestMatch);
3058 if (hr == S_OK) {
31- @@ -1908,8 +1909,12 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
59+ break;
60+ } else {
61+ if (pWfxClosestMatch) {
62+ - RTC_LOG(LS_INFO) << "nChannels=" << Wfx.nChannels
63+ - << ", nSamplesPerSec=" << Wfx.nSamplesPerSec
64+ + RTC_LOG(LS_INFO) << "nChannels=" << Wfx.Format.nChannels
65+ + << ", nSamplesPerSec=" << Wfx.Format.nSamplesPerSec
66+ << " is not supported. Closest match: "
3267 "nChannels="
33- << pWfxClosestMatch->nChannels << ", nSamplesPerSec="
34- << pWfxClosestMatch->nSamplesPerSec;
68+ - << pWfxClosestMatch->nChannels << ", nSamplesPerSec="
69+ - << pWfxClosestMatch->nSamplesPerSec;
3570- CoTaskMemFree(pWfxClosestMatch);
3671- pWfxClosestMatch = NULL;
72+ + << pWfxClosestMatch->Format.nChannels << ", nSamplesPerSec="
73+ + << pWfxClosestMatch->Format.nSamplesPerSec;
3774+
3875+ if (pInitWfxClosestMatch) {
3976+ CoTaskMemFree(pWfxClosestMatch);
4077+ } else {
4178+ pInitWfxClosestMatch = pWfxClosestMatch;
4279+ }
4380 } else {
44- RTC_LOG(LS_INFO) << "nChannels=" << Wfx.nChannels
45- << ", nSamplesPerSec=" << Wfx.nSamplesPerSec
46- @@ -1924,6 +1929,18 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
81+ - RTC_LOG(LS_INFO) << "nChannels=" << Wfx.nChannels
82+ - << ", nSamplesPerSec=" << Wfx.nSamplesPerSec
83+ + RTC_LOG(LS_INFO) << "nChannels=" << Wfx.Format.nChannels
84+ + << ", nSamplesPerSec=" << Wfx.Format.nSamplesPerSec
85+ << " is not supported. No closest match.";
86+ }
87+ }
88+ @@ -1924,26 +1935,42 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
4789 // TODO(andrew): what happens in the event of failure in the above loop?
4890 // Is _ptrClientOut->Initialize expected to fail?
4991 // Same in InitRecording().
5092+
5193+ if (pInitWfxClosestMatch) {
5294+ // Set up the closest match, and rely on the voice engine to resample. (roxanneskelly)
53- + Wfx.wFormatTag = WAVE_FORMAT_PCM;
54- + Wfx.wBitsPerSample = 16;
55- + Wfx.cbSize = 0;
56- + Wfx.nChannels = pInitWfxClosestMatch->nChannels;
57- + Wfx.nSamplesPerSec = pInitWfxClosestMatch->nSamplesPerSec;
58- + Wfx.nBlockAlign = pInitWfxClosestMatch->nBlockAlign;
59- + Wfx.nAvgBytesPerSec = pInitWfxClosestMatch->nAvgBytesPerSec;
95+ + CopyMemory(&Wfx, pInitWfxClosestMatch, sizeof(Wfx));
96+ + Wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
97+ + Wfx.Format.wBitsPerSample = 16; // force it to 16 bits per sample
98+ + Wfx.Samples.wValidBitsPerSample = Wfx.Format.wBitsPerSample;
99+ + Wfx.Format.nChannels = 2;
100+ + Wfx.Format.nBlockAlign =
101+ + Wfx.Format.nChannels * Wfx.Format.wBitsPerSample / 8;
102+ + Wfx.Format.nAvgBytesPerSec =
103+ + Wfx.Format.nSamplesPerSec * Wfx.Format.nBlockAlign;
60104+ hr = S_OK;
61105+ }
62106 if (hr == S_OK) {
63- _playAudioFrameSize = Wfx.nBlockAlign;
107+ - _playAudioFrameSize = Wfx.nBlockAlign;
108+ + _playAudioFrameSize = Wfx.Format.nBlockAlign;
64109 // Block size is the number of samples each channel in 10ms.
65- @@ -2031,7 +2048,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
110+ - _playBlockSize = Wfx.nSamplesPerSec / 100;
111+ - _playSampleRate = Wfx.nSamplesPerSec;
112+ + _playBlockSize = Wfx.Format.nSamplesPerSec / 100;
113+ + _playSampleRate = Wfx.Format.nSamplesPerSec;
114+ _devicePlaySampleRate =
115+ - Wfx.nSamplesPerSec; // The device itself continues to run at 44.1 kHz.
116+ - _devicePlayBlockSize = Wfx.nSamplesPerSec / 100;
117+ - _playChannels = Wfx.nChannels;
118+ + Wfx.Format
119+ + .nSamplesPerSec; // The device itself continues to run at 44.1 kHz.
120+ + _devicePlayBlockSize = Wfx.Format.nSamplesPerSec / 100;
121+ + _playChannels = Wfx.Format.nChannels;
122+
123+ RTC_LOG(LS_VERBOSE) << "VoE selected this rendering format:";
124+ RTC_LOG(LS_VERBOSE) << "wFormatTag : 0x"
125+ - << webrtc::ToHex(Wfx.wFormatTag) << " ("
126+ - << Wfx.wFormatTag << ")";
127+ - RTC_LOG(LS_VERBOSE) << "nChannels : " << Wfx.nChannels;
128+ - RTC_LOG(LS_VERBOSE) << "nSamplesPerSec : " << Wfx.nSamplesPerSec;
129+ - RTC_LOG(LS_VERBOSE) << "nAvgBytesPerSec : " << Wfx.nAvgBytesPerSec;
130+ - RTC_LOG(LS_VERBOSE) << "nBlockAlign : " << Wfx.nBlockAlign;
131+ - RTC_LOG(LS_VERBOSE) << "wBitsPerSample : " << Wfx.wBitsPerSample;
132+ - RTC_LOG(LS_VERBOSE) << "cbSize : " << Wfx.cbSize;
133+ + << webrtc::ToHex(Wfx.Format.wFormatTag) << " ("
134+ + << Wfx.Format.wFormatTag << ")";
135+ + RTC_LOG(LS_VERBOSE) << "nChannels : " << Wfx.Format.nChannels;
136+ + RTC_LOG(LS_VERBOSE) << "nSamplesPerSec : " << Wfx.Format.nSamplesPerSec;
137+ + RTC_LOG(LS_VERBOSE) << "nAvgBytesPerSec : "
138+ + << Wfx.Format.nAvgBytesPerSec;
139+ + RTC_LOG(LS_VERBOSE) << "nBlockAlign : " << Wfx.Format.nBlockAlign;
140+ + RTC_LOG(LS_VERBOSE) << "wBitsPerSample : " << Wfx.Format.wBitsPerSample;
141+ + RTC_LOG(LS_VERBOSE) << "cbSize : " << Wfx.Format.cbSize;
142+ RTC_LOG(LS_VERBOSE) << "Additional settings:";
143+ RTC_LOG(LS_VERBOSE) << "_playAudioFrameSize: " << _playAudioFrameSize;
144+ RTC_LOG(LS_VERBOSE) << "_playBlockSize : " << _playBlockSize;
145+ @@ -1980,12 +2007,14 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
146+ }
147+ hr = _ptrClientOut->Initialize(
148+ AUDCLNT_SHAREMODE_SHARED, // share Audio Engine with other applications
149+ - AUDCLNT_STREAMFLAGS_EVENTCALLBACK, // processing of the audio buffer by
150+ + AUDCLNT_STREAMFLAGS_EVENTCALLBACK | // processing of the audio buffer by
151+ // the client will be event driven
152+ + AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM |
153+ + AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY,
154+ hnsBufferDuration, // requested buffer capacity as a time value (in
155+ // 100-nanosecond units)
156+ 0, // periodicity
157+ - &Wfx, // selected wave format
158+ + (WAVEFORMATEX *)&Wfx, // selected wave format
159+ NULL); // session GUID
160+
161+ if (FAILED(hr)) {
162+ @@ -2031,7 +2060,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
66163 _playIsInitialized = true;
67164
68165 CoTaskMemFree(pWfxOut);
@@ -71,7 +168,7 @@ index f1cc0474fc..ffb0b159b1 100644
71168
72169 RTC_LOG(LS_VERBOSE) << "render side is now initialized";
73170 return 0;
74- @@ -2039,7 +2056 ,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
171+ @@ -2039,7 +2068 ,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
75172 Exit:
76173 _TraceCOMError(hr);
77174 CoTaskMemFree(pWfxOut);
@@ -80,16 +177,16 @@ index f1cc0474fc..ffb0b159b1 100644
80177 SAFE_RELEASE(_ptrClientOut);
81178 SAFE_RELEASE(_ptrRenderClient);
82179 return -1;
83- @@ -2163,7 +2180 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
180+ @@ -2163,7 +2192 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
84181 HRESULT hr = S_OK;
85182 WAVEFORMATEX* pWfxIn = NULL;
86183 WAVEFORMATEXTENSIBLE Wfx = WAVEFORMATEXTENSIBLE();
87184- WAVEFORMATEX* pWfxClosestMatch = NULL;
88- + WAVEFORMATEX * pInitWfxClosestMatch = NULL;
185+ + WAVEFORMATEXTENSIBLE * pInitWfxClosestMatch = NULL;
89186
90187 // Create COM object with IAudioClient interface.
91188 SAFE_RELEASE(_ptrClientIn);
92- @@ -2201,7 +2218 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
189+ @@ -2201,7 +2230 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
93190 Wfx.Samples.wValidBitsPerSample = Wfx.Format.wBitsPerSample;
94191 Wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
95192
@@ -98,20 +195,30 @@ index f1cc0474fc..ffb0b159b1 100644
98195 hr = S_FALSE;
99196
100197 // Iterate over frequencies and channels, in order of priority
101- @@ -2218,6 +2235,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
198+ @@ -2218,8 +2247,10 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
102199 // If the method succeeds and the audio endpoint device supports the
103200 // specified stream format, it returns S_OK. If the method succeeds and
104201 // provides a closest match to the specified format, it returns S_FALSE.
105- + WAVEFORMATEX* pWfxClosestMatch = NULL;
106- hr = _ptrClientIn->IsFormatSupported(
107- AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*)&Wfx, &pWfxClosestMatch);
202+ - hr = _ptrClientIn->IsFormatSupported(
203+ - AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*)&Wfx, &pWfxClosestMatch);
204+ + WAVEFORMATEXTENSIBLE* pWfxClosestMatch = NULL;
205+ + hr = _ptrClientIn->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,
206+ + (WAVEFORMATEX*)&Wfx,
207+ + (WAVEFORMATEX**)&pWfxClosestMatch);
108208 if (hr == S_OK) {
109- @@ -2230,8 +2248,11 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
209+ break;
210+ } else {
211+ @@ -2228,10 +2259,14 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
212+ << ", nSamplesPerSec=" << Wfx.Format.nSamplesPerSec
213+ << " is not supported. Closest match: "
110214 "nChannels="
111- << pWfxClosestMatch->nChannels << ", nSamplesPerSec="
112- << pWfxClosestMatch->nSamplesPerSec;
215+ - << pWfxClosestMatch->nChannels << ", nSamplesPerSec="
216+ - << pWfxClosestMatch->nSamplesPerSec;
113217- CoTaskMemFree(pWfxClosestMatch);
114218- pWfxClosestMatch = NULL;
219+ + << pWfxClosestMatch->Format.nChannels
220+ + << ", nSamplesPerSec="
221+ + << pWfxClosestMatch->Format.nSamplesPerSec;
115222+ if (pInitWfxClosestMatch) {
116223+ CoTaskMemFree(pWfxClosestMatch);
117224+ } else {
@@ -120,31 +227,38 @@ index f1cc0474fc..ffb0b159b1 100644
120227 } else {
121228 RTC_LOG(LS_INFO) << "nChannels=" << Wfx.Format.nChannels
122229 << ", nSamplesPerSec=" << Wfx.Format.nSamplesPerSec
123- @@ -2242,7 +2263,22 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
230+ @@ -2242,7 +2277,20 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
124231 if (hr == S_OK)
125232 break;
126233 }
127234-
128235+ if (pInitWfxClosestMatch) {
129236+ // Set up the closest match, and rely on the voice engine to resample.
130237+ // (roxanneskelly)
131- + Wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
132- + Wfx.Format.wBitsPerSample = 16;
133- + Wfx.Format.cbSize = 22;
134- + Wfx.dwChannelMask = 0;
135- + Wfx.Samples.wValidBitsPerSample = Wfx.Format.wBitsPerSample;
238+ + CopyMemory(&Wfx, pInitWfxClosestMatch, sizeof(Wfx));
136239+ Wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
137- +
138- + Wfx.Format.nChannels = pInitWfxClosestMatch->nChannels;
139- + Wfx.Format.nSamplesPerSec = pInitWfxClosestMatch->nSamplesPerSec;
140- + Wfx.Format.nBlockAlign = pInitWfxClosestMatch->nBlockAlign;
141- + Wfx.Format.nAvgBytesPerSec = pInitWfxClosestMatch->nAvgBytesPerSec;
240+ + Wfx.Format.wBitsPerSample = 16; // force it to 16 bits per sample
241+ + Wfx.Samples.wValidBitsPerSample = Wfx.Format.wBitsPerSample;
242+ + Wfx.Format.nChannels = 1;
243+ + Wfx.Format.nBlockAlign =
244+ + Wfx.Format.nChannels * Wfx.Format.wBitsPerSample / 8;
245+ + Wfx.Format.nAvgBytesPerSec =
246+ + Wfx.Format.nSamplesPerSec * Wfx.Format.nBlockAlign;
142247+ hr = S_OK;
143248+ }
144249 if (hr == S_OK) {
145250 _recAudioFrameSize = Wfx.Format.nBlockAlign;
146251 _recSampleRate = Wfx.Format.nSamplesPerSec;
147- @@ -2321,7 +2357,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
252+ @@ -2270,6 +2318,8 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
253+ AUDCLNT_SHAREMODE_SHARED, // share Audio Engine with other applications
254+ AUDCLNT_STREAMFLAGS_EVENTCALLBACK | // processing of the audio buffer by
255+ // the client will be event driven
256+ + AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM |
257+ + AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY |
258+ AUDCLNT_STREAMFLAGS_NOPERSIST, // volume and mute settings for an
259+ // audio session will not persist
260+ // across system restarts
261+ @@ -2321,7 +2371,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
148262 _recIsInitialized = true;
149263
150264 CoTaskMemFree(pWfxIn);
@@ -153,7 +267,7 @@ index f1cc0474fc..ffb0b159b1 100644
153267
154268 RTC_LOG(LS_VERBOSE) << "capture side is now initialized";
155269 return 0;
156- @@ -2329,7 +2365 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
270+ @@ -2329,7 +2379 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
157271 Exit:
158272 _TraceCOMError(hr);
159273 CoTaskMemFree(pWfxIn);
0 commit comments