1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker // Do nothing on unix as win_audio is windows only.
6*bb4ee6a4SAndroid Build Coastguard Worker #![cfg(windows)]
7*bb4ee6a4SAndroid Build Coastguard Worker #![allow(non_upper_case_globals)]
8*bb4ee6a4SAndroid Build Coastguard Worker include!(concat!(
9*bb4ee6a4SAndroid Build Coastguard Worker env!("CARGO_MANIFEST_DIR"),
10*bb4ee6a4SAndroid Build Coastguard Worker "/src/r8brain_sys/bindings.rs"
11*bb4ee6a4SAndroid Build Coastguard Worker ));
12*bb4ee6a4SAndroid Build Coastguard Worker
13*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! check_hresult {
14*bb4ee6a4SAndroid Build Coastguard Worker ($hr: expr, $error: expr, $msg: expr) => {
15*bb4ee6a4SAndroid Build Coastguard Worker if winapi::shared::winerror::FAILED($hr) {
16*bb4ee6a4SAndroid Build Coastguard Worker base::warn!("{}: {}", $msg, $hr);
17*bb4ee6a4SAndroid Build Coastguard Worker Err($error)
18*bb4ee6a4SAndroid Build Coastguard Worker } else {
19*bb4ee6a4SAndroid Build Coastguard Worker Ok($hr)
20*bb4ee6a4SAndroid Build Coastguard Worker }
21*bb4ee6a4SAndroid Build Coastguard Worker };
22*bb4ee6a4SAndroid Build Coastguard Worker }
23*bb4ee6a4SAndroid Build Coastguard Worker
24*bb4ee6a4SAndroid Build Coastguard Worker pub mod intermediate_resampler_buffer;
25*bb4ee6a4SAndroid Build Coastguard Worker mod win_audio_impl;
26*bb4ee6a4SAndroid Build Coastguard Worker use std::error;
27*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
28*bb4ee6a4SAndroid Build Coastguard Worker
29*bb4ee6a4SAndroid Build Coastguard Worker use audio_streams::capture::AsyncCaptureBufferStream;
30*bb4ee6a4SAndroid Build Coastguard Worker use audio_streams::capture::NoopCaptureStream;
31*bb4ee6a4SAndroid Build Coastguard Worker use audio_streams::AsyncPlaybackBufferStream;
32*bb4ee6a4SAndroid Build Coastguard Worker use audio_streams::NoopStream;
33*bb4ee6a4SAndroid Build Coastguard Worker use audio_streams::NoopStreamSource;
34*bb4ee6a4SAndroid Build Coastguard Worker use audio_streams::NoopStreamSourceGenerator;
35*bb4ee6a4SAndroid Build Coastguard Worker use audio_streams::PlaybackBufferStream;
36*bb4ee6a4SAndroid Build Coastguard Worker use audio_streams::SampleFormat;
37*bb4ee6a4SAndroid Build Coastguard Worker use audio_streams::StreamSource;
38*bb4ee6a4SAndroid Build Coastguard Worker use audio_util::FileStreamSourceGenerator;
39*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
40*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
41*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
42*bb4ee6a4SAndroid Build Coastguard Worker pub use intermediate_resampler_buffer::ANDROID_CAPTURE_FRAME_SIZE_BYTES;
43*bb4ee6a4SAndroid Build Coastguard Worker pub use intermediate_resampler_buffer::BYTES_PER_32FLOAT;
44*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
45*bb4ee6a4SAndroid Build Coastguard Worker use win_audio_impl::async_stream::WinAudioStreamSourceGenerator;
46*bb4ee6a4SAndroid Build Coastguard Worker pub use win_audio_impl::*;
47*bb4ee6a4SAndroid Build Coastguard Worker
48*bb4ee6a4SAndroid Build Coastguard Worker pub type BoxError = Box<dyn error::Error + Send + Sync>;
49*bb4ee6a4SAndroid Build Coastguard Worker
50*bb4ee6a4SAndroid Build Coastguard Worker pub trait WinStreamSourceGenerator: Send + Sync {
generate(&self) -> Result<Box<dyn WinAudioServer>, BoxError>51*bb4ee6a4SAndroid Build Coastguard Worker fn generate(&self) -> Result<Box<dyn WinAudioServer>, BoxError>;
52*bb4ee6a4SAndroid Build Coastguard Worker }
53*bb4ee6a4SAndroid Build Coastguard Worker
54*bb4ee6a4SAndroid Build Coastguard Worker impl WinStreamSourceGenerator for WinAudioStreamSourceGenerator {
generate(&self) -> std::result::Result<Box<dyn WinAudioServer>, BoxError>55*bb4ee6a4SAndroid Build Coastguard Worker fn generate(&self) -> std::result::Result<Box<dyn WinAudioServer>, BoxError> {
56*bb4ee6a4SAndroid Build Coastguard Worker Ok(Box::new(WinAudio::new()?))
57*bb4ee6a4SAndroid Build Coastguard Worker }
58*bb4ee6a4SAndroid Build Coastguard Worker }
59*bb4ee6a4SAndroid Build Coastguard Worker
60*bb4ee6a4SAndroid Build Coastguard Worker impl WinStreamSourceGenerator for NoopStreamSourceGenerator {
generate(&self) -> Result<Box<dyn WinAudioServer>, BoxError>61*bb4ee6a4SAndroid Build Coastguard Worker fn generate(&self) -> Result<Box<dyn WinAudioServer>, BoxError> {
62*bb4ee6a4SAndroid Build Coastguard Worker Ok(Box::new(NoopStreamSource))
63*bb4ee6a4SAndroid Build Coastguard Worker }
64*bb4ee6a4SAndroid Build Coastguard Worker }
65*bb4ee6a4SAndroid Build Coastguard Worker
66*bb4ee6a4SAndroid Build Coastguard Worker impl WinStreamSourceGenerator for FileStreamSourceGenerator {
generate(&self) -> Result<Box<dyn WinAudioServer>, BoxError>67*bb4ee6a4SAndroid Build Coastguard Worker fn generate(&self) -> Result<Box<dyn WinAudioServer>, BoxError> {
68*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!();
69*bb4ee6a4SAndroid Build Coastguard Worker }
70*bb4ee6a4SAndroid Build Coastguard Worker }
71*bb4ee6a4SAndroid Build Coastguard Worker
72*bb4ee6a4SAndroid Build Coastguard Worker /// Contains information about the audio engine's properties, such as its audio sample format
73*bb4ee6a4SAndroid Build Coastguard Worker /// and its period in frames.
74*bb4ee6a4SAndroid Build Coastguard Worker ///
75*bb4ee6a4SAndroid Build Coastguard Worker /// This does exclude whether the bit depth is in the form of floats or ints. The bit depth form
76*bb4ee6a4SAndroid Build Coastguard Worker /// isn't used for sample rate conversion so it's excluded.
77*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy)]
78*bb4ee6a4SAndroid Build Coastguard Worker pub struct AudioSharedFormat {
79*bb4ee6a4SAndroid Build Coastguard Worker pub bit_depth: usize,
80*bb4ee6a4SAndroid Build Coastguard Worker pub frame_rate: usize,
81*bb4ee6a4SAndroid Build Coastguard Worker pub shared_audio_engine_period_in_frames: usize,
82*bb4ee6a4SAndroid Build Coastguard Worker pub channels: usize,
83*bb4ee6a4SAndroid Build Coastguard Worker // Only available for WAVEFORMATEXTENSIBLE
84*bb4ee6a4SAndroid Build Coastguard Worker pub channel_mask: Option<u32>,
85*bb4ee6a4SAndroid Build Coastguard Worker }
86*bb4ee6a4SAndroid Build Coastguard Worker
87*bb4ee6a4SAndroid Build Coastguard Worker impl AudioSharedFormat {
get_shared_audio_engine_period_in_bytes(&self) -> usize88*bb4ee6a4SAndroid Build Coastguard Worker fn get_shared_audio_engine_period_in_bytes(&self) -> usize {
89*bb4ee6a4SAndroid Build Coastguard Worker let frame_size_bytes = self.bit_depth * self.channels / 8;
90*bb4ee6a4SAndroid Build Coastguard Worker self.shared_audio_engine_period_in_frames * frame_size_bytes
91*bb4ee6a4SAndroid Build Coastguard Worker }
92*bb4ee6a4SAndroid Build Coastguard Worker }
93*bb4ee6a4SAndroid Build Coastguard Worker
94*bb4ee6a4SAndroid Build Coastguard Worker /// Implementation of StreamSource which will create the playback stream for the Windows
95*bb4ee6a4SAndroid Build Coastguard Worker /// audio engine.
96*bb4ee6a4SAndroid Build Coastguard Worker ///
97*bb4ee6a4SAndroid Build Coastguard Worker /// Extending the StreamSource trait will allow us to make necessary changes without modifying
98*bb4ee6a4SAndroid Build Coastguard Worker /// the third party audiostream library.
99*bb4ee6a4SAndroid Build Coastguard Worker pub trait WinAudioServer: StreamSource {
new_playback_stream_and_get_shared_format( &mut self, num_channels: usize, format: SampleFormat, frame_rate: usize, buffer_size: usize, ) -> Result<(Arc<Mutex<Box<dyn PlaybackBufferStream>>>, AudioSharedFormat), BoxError>100*bb4ee6a4SAndroid Build Coastguard Worker fn new_playback_stream_and_get_shared_format(
101*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
102*bb4ee6a4SAndroid Build Coastguard Worker num_channels: usize,
103*bb4ee6a4SAndroid Build Coastguard Worker format: SampleFormat,
104*bb4ee6a4SAndroid Build Coastguard Worker frame_rate: usize,
105*bb4ee6a4SAndroid Build Coastguard Worker buffer_size: usize,
106*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(Arc<Mutex<Box<dyn PlaybackBufferStream>>>, AudioSharedFormat), BoxError>;
107*bb4ee6a4SAndroid Build Coastguard Worker
new_async_playback_stream_and_get_shared_format( &mut self, _num_channels: usize, _format: SampleFormat, _frame_rate: usize, _buffer_size: usize, _ex: &dyn audio_streams::AudioStreamsExecutor, _audio_client_guid: Option<String>, ) -> Result<(Box<dyn AsyncPlaybackBufferStream>, AudioSharedFormat), BoxError>108*bb4ee6a4SAndroid Build Coastguard Worker fn new_async_playback_stream_and_get_shared_format(
109*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
110*bb4ee6a4SAndroid Build Coastguard Worker _num_channels: usize,
111*bb4ee6a4SAndroid Build Coastguard Worker _format: SampleFormat,
112*bb4ee6a4SAndroid Build Coastguard Worker _frame_rate: usize,
113*bb4ee6a4SAndroid Build Coastguard Worker _buffer_size: usize,
114*bb4ee6a4SAndroid Build Coastguard Worker _ex: &dyn audio_streams::AudioStreamsExecutor,
115*bb4ee6a4SAndroid Build Coastguard Worker _audio_client_guid: Option<String>,
116*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(Box<dyn AsyncPlaybackBufferStream>, AudioSharedFormat), BoxError> {
117*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!()
118*bb4ee6a4SAndroid Build Coastguard Worker }
119*bb4ee6a4SAndroid Build Coastguard Worker
new_async_capture_stream_and_get_shared_format( &mut self, _num_channels: usize, _format: SampleFormat, _frame_rate: u32, _buffer_size: usize, _ex: &dyn audio_streams::AudioStreamsExecutor, ) -> Result<(Box<dyn AsyncCaptureBufferStream>, AudioSharedFormat), BoxError>120*bb4ee6a4SAndroid Build Coastguard Worker fn new_async_capture_stream_and_get_shared_format(
121*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
122*bb4ee6a4SAndroid Build Coastguard Worker _num_channels: usize,
123*bb4ee6a4SAndroid Build Coastguard Worker _format: SampleFormat,
124*bb4ee6a4SAndroid Build Coastguard Worker _frame_rate: u32,
125*bb4ee6a4SAndroid Build Coastguard Worker _buffer_size: usize,
126*bb4ee6a4SAndroid Build Coastguard Worker _ex: &dyn audio_streams::AudioStreamsExecutor,
127*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(Box<dyn AsyncCaptureBufferStream>, AudioSharedFormat), BoxError> {
128*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!()
129*bb4ee6a4SAndroid Build Coastguard Worker }
130*bb4ee6a4SAndroid Build Coastguard Worker
131*bb4ee6a4SAndroid Build Coastguard Worker /// Evict the playback stream cache so that the audio device can be released, thus allowing
132*bb4ee6a4SAndroid Build Coastguard Worker /// for machines to go to sleep.
evict_playback_stream_cache(&mut self)133*bb4ee6a4SAndroid Build Coastguard Worker fn evict_playback_stream_cache(&mut self) {
134*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!()
135*bb4ee6a4SAndroid Build Coastguard Worker }
136*bb4ee6a4SAndroid Build Coastguard Worker
137*bb4ee6a4SAndroid Build Coastguard Worker /// Returns true if audio server is a noop stream. This determine if evicting a cache is worth
138*bb4ee6a4SAndroid Build Coastguard Worker /// doing
is_noop_stream(&self) -> bool139*bb4ee6a4SAndroid Build Coastguard Worker fn is_noop_stream(&self) -> bool;
140*bb4ee6a4SAndroid Build Coastguard Worker }
141*bb4ee6a4SAndroid Build Coastguard Worker
142*bb4ee6a4SAndroid Build Coastguard Worker impl WinAudioServer for WinAudio {
new_playback_stream_and_get_shared_format( &mut self, num_channels: usize, format: SampleFormat, frame_rate: usize, buffer_size: usize, ) -> Result<(Arc<Mutex<Box<dyn PlaybackBufferStream>>>, AudioSharedFormat), BoxError>143*bb4ee6a4SAndroid Build Coastguard Worker fn new_playback_stream_and_get_shared_format(
144*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
145*bb4ee6a4SAndroid Build Coastguard Worker num_channels: usize,
146*bb4ee6a4SAndroid Build Coastguard Worker format: SampleFormat,
147*bb4ee6a4SAndroid Build Coastguard Worker frame_rate: usize,
148*bb4ee6a4SAndroid Build Coastguard Worker buffer_size: usize,
149*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(Arc<Mutex<Box<dyn PlaybackBufferStream>>>, AudioSharedFormat), BoxError> {
150*bb4ee6a4SAndroid Build Coastguard Worker let hr = WinAudio::co_init_once_per_thread();
151*bb4ee6a4SAndroid Build Coastguard Worker let _ = check_hresult!(hr, WinAudioError::from(hr), "Co Initialized failed");
152*bb4ee6a4SAndroid Build Coastguard Worker
153*bb4ee6a4SAndroid Build Coastguard Worker // Return the existing stream if we have one.
154*bb4ee6a4SAndroid Build Coastguard Worker // This is mainly to reduce audio skips caused by a buffer underrun on the guest. An
155*bb4ee6a4SAndroid Build Coastguard Worker // underrun causes the guest to stop the audio stream, but then start it back up when the
156*bb4ee6a4SAndroid Build Coastguard Worker // guest buffer is filled again.
157*bb4ee6a4SAndroid Build Coastguard Worker if let Some((playback_buffer_stream, audio_format)) =
158*bb4ee6a4SAndroid Build Coastguard Worker self.cached_playback_buffer_stream.as_ref()
159*bb4ee6a4SAndroid Build Coastguard Worker {
160*bb4ee6a4SAndroid Build Coastguard Worker info!("Reusing playback_buffer_stream.");
161*bb4ee6a4SAndroid Build Coastguard Worker return Ok((playback_buffer_stream.clone(), *audio_format));
162*bb4ee6a4SAndroid Build Coastguard Worker }
163*bb4ee6a4SAndroid Build Coastguard Worker
164*bb4ee6a4SAndroid Build Coastguard Worker let (playback_buffer_stream, audio_shared_format): (
165*bb4ee6a4SAndroid Build Coastguard Worker Arc<Mutex<Box<dyn PlaybackBufferStream>>>,
166*bb4ee6a4SAndroid Build Coastguard Worker AudioSharedFormat,
167*bb4ee6a4SAndroid Build Coastguard Worker ) = match win_audio_impl::WinAudioRenderer::new(
168*bb4ee6a4SAndroid Build Coastguard Worker num_channels,
169*bb4ee6a4SAndroid Build Coastguard Worker format,
170*bb4ee6a4SAndroid Build Coastguard Worker frame_rate as u32,
171*bb4ee6a4SAndroid Build Coastguard Worker buffer_size,
172*bb4ee6a4SAndroid Build Coastguard Worker ) {
173*bb4ee6a4SAndroid Build Coastguard Worker Ok(renderer) => {
174*bb4ee6a4SAndroid Build Coastguard Worker let audio_shared_format = renderer.get_audio_shared_format();
175*bb4ee6a4SAndroid Build Coastguard Worker let renderer_arc = Arc::new(Mutex::new(
176*bb4ee6a4SAndroid Build Coastguard Worker Box::new(renderer) as Box<dyn PlaybackBufferStream>
177*bb4ee6a4SAndroid Build Coastguard Worker ));
178*bb4ee6a4SAndroid Build Coastguard Worker self.cached_playback_buffer_stream =
179*bb4ee6a4SAndroid Build Coastguard Worker Some((renderer_arc.clone(), audio_shared_format));
180*bb4ee6a4SAndroid Build Coastguard Worker (renderer_arc, audio_shared_format)
181*bb4ee6a4SAndroid Build Coastguard Worker }
182*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
183*bb4ee6a4SAndroid Build Coastguard Worker error!(
184*bb4ee6a4SAndroid Build Coastguard Worker "Failed to create WinAudioRenderer and in an unrecoverable state. Fallback to \
185*bb4ee6a4SAndroid Build Coastguard Worker NoopStream with error: {}",
186*bb4ee6a4SAndroid Build Coastguard Worker e
187*bb4ee6a4SAndroid Build Coastguard Worker );
188*bb4ee6a4SAndroid Build Coastguard Worker (
189*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(Box::new(NoopStream::new(
190*bb4ee6a4SAndroid Build Coastguard Worker num_channels,
191*bb4ee6a4SAndroid Build Coastguard Worker SampleFormat::S16LE,
192*bb4ee6a4SAndroid Build Coastguard Worker frame_rate as u32,
193*bb4ee6a4SAndroid Build Coastguard Worker buffer_size,
194*bb4ee6a4SAndroid Build Coastguard Worker )))),
195*bb4ee6a4SAndroid Build Coastguard Worker AudioSharedFormat {
196*bb4ee6a4SAndroid Build Coastguard Worker bit_depth: 16,
197*bb4ee6a4SAndroid Build Coastguard Worker frame_rate,
198*bb4ee6a4SAndroid Build Coastguard Worker channels: 2,
199*bb4ee6a4SAndroid Build Coastguard Worker shared_audio_engine_period_in_frames: frame_rate / 100,
200*bb4ee6a4SAndroid Build Coastguard Worker channel_mask: None,
201*bb4ee6a4SAndroid Build Coastguard Worker },
202*bb4ee6a4SAndroid Build Coastguard Worker )
203*bb4ee6a4SAndroid Build Coastguard Worker }
204*bb4ee6a4SAndroid Build Coastguard Worker };
205*bb4ee6a4SAndroid Build Coastguard Worker
206*bb4ee6a4SAndroid Build Coastguard Worker Ok((playback_buffer_stream, audio_shared_format))
207*bb4ee6a4SAndroid Build Coastguard Worker }
208*bb4ee6a4SAndroid Build Coastguard Worker
209*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/275406212): AudioSharedFormat not used outside of this crate anymore. Clean up before
210*bb4ee6a4SAndroid Build Coastguard Worker // upstreaming.
new_async_playback_stream_and_get_shared_format( &mut self, num_channels: usize, guest_bit_depth: SampleFormat, frame_rate: usize, buffer_size: usize, ex: &dyn audio_streams::AudioStreamsExecutor, audio_client_guid: Option<String>, ) -> Result<(Box<dyn AsyncPlaybackBufferStream>, AudioSharedFormat), BoxError>211*bb4ee6a4SAndroid Build Coastguard Worker fn new_async_playback_stream_and_get_shared_format(
212*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
213*bb4ee6a4SAndroid Build Coastguard Worker num_channels: usize,
214*bb4ee6a4SAndroid Build Coastguard Worker guest_bit_depth: SampleFormat,
215*bb4ee6a4SAndroid Build Coastguard Worker frame_rate: usize,
216*bb4ee6a4SAndroid Build Coastguard Worker buffer_size: usize,
217*bb4ee6a4SAndroid Build Coastguard Worker ex: &dyn audio_streams::AudioStreamsExecutor,
218*bb4ee6a4SAndroid Build Coastguard Worker audio_client_guid: Option<String>,
219*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(Box<dyn AsyncPlaybackBufferStream>, AudioSharedFormat), BoxError> {
220*bb4ee6a4SAndroid Build Coastguard Worker let hr = WinAudio::co_init_once_per_thread();
221*bb4ee6a4SAndroid Build Coastguard Worker let _ = check_hresult!(hr, WinAudioError::from(hr), "Co Initialized failed");
222*bb4ee6a4SAndroid Build Coastguard Worker
223*bb4ee6a4SAndroid Build Coastguard Worker let (async_playback_buffer_stream, audio_shared_format): (
224*bb4ee6a4SAndroid Build Coastguard Worker Box<dyn AsyncPlaybackBufferStream>,
225*bb4ee6a4SAndroid Build Coastguard Worker AudioSharedFormat,
226*bb4ee6a4SAndroid Build Coastguard Worker ) = match win_audio_impl::WinAudioRenderer::new_async(
227*bb4ee6a4SAndroid Build Coastguard Worker num_channels,
228*bb4ee6a4SAndroid Build Coastguard Worker guest_bit_depth,
229*bb4ee6a4SAndroid Build Coastguard Worker frame_rate as u32,
230*bb4ee6a4SAndroid Build Coastguard Worker buffer_size,
231*bb4ee6a4SAndroid Build Coastguard Worker ex,
232*bb4ee6a4SAndroid Build Coastguard Worker audio_client_guid,
233*bb4ee6a4SAndroid Build Coastguard Worker ) {
234*bb4ee6a4SAndroid Build Coastguard Worker Ok(renderer) => {
235*bb4ee6a4SAndroid Build Coastguard Worker let audio_shared_format = renderer.get_audio_shared_format();
236*bb4ee6a4SAndroid Build Coastguard Worker let renderer_box = Box::new(renderer) as Box<dyn AsyncPlaybackBufferStream>;
237*bb4ee6a4SAndroid Build Coastguard Worker (renderer_box, audio_shared_format)
238*bb4ee6a4SAndroid Build Coastguard Worker }
239*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
240*bb4ee6a4SAndroid Build Coastguard Worker error!(
241*bb4ee6a4SAndroid Build Coastguard Worker "Failed to create WinAudioRenderer and in an unrecoverable state. Fallback to \
242*bb4ee6a4SAndroid Build Coastguard Worker NoopStream with error: {}",
243*bb4ee6a4SAndroid Build Coastguard Worker e
244*bb4ee6a4SAndroid Build Coastguard Worker );
245*bb4ee6a4SAndroid Build Coastguard Worker (
246*bb4ee6a4SAndroid Build Coastguard Worker Box::new(NoopStream::new(
247*bb4ee6a4SAndroid Build Coastguard Worker num_channels,
248*bb4ee6a4SAndroid Build Coastguard Worker SampleFormat::S32LE,
249*bb4ee6a4SAndroid Build Coastguard Worker frame_rate as u32,
250*bb4ee6a4SAndroid Build Coastguard Worker buffer_size,
251*bb4ee6a4SAndroid Build Coastguard Worker )),
252*bb4ee6a4SAndroid Build Coastguard Worker AudioSharedFormat {
253*bb4ee6a4SAndroid Build Coastguard Worker bit_depth: 32,
254*bb4ee6a4SAndroid Build Coastguard Worker frame_rate,
255*bb4ee6a4SAndroid Build Coastguard Worker channels: 2,
256*bb4ee6a4SAndroid Build Coastguard Worker shared_audio_engine_period_in_frames: frame_rate / 100,
257*bb4ee6a4SAndroid Build Coastguard Worker channel_mask: None,
258*bb4ee6a4SAndroid Build Coastguard Worker },
259*bb4ee6a4SAndroid Build Coastguard Worker )
260*bb4ee6a4SAndroid Build Coastguard Worker }
261*bb4ee6a4SAndroid Build Coastguard Worker };
262*bb4ee6a4SAndroid Build Coastguard Worker
263*bb4ee6a4SAndroid Build Coastguard Worker Ok((async_playback_buffer_stream, audio_shared_format))
264*bb4ee6a4SAndroid Build Coastguard Worker }
265*bb4ee6a4SAndroid Build Coastguard Worker
266*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/275406212): AudioSharedFormat not used outside of this crate anymore. Clean up before
267*bb4ee6a4SAndroid Build Coastguard Worker // upstreaming.
new_async_capture_stream_and_get_shared_format( &mut self, num_channels: usize, guest_bit_depth: SampleFormat, frame_rate: u32, buffer_size: usize, ex: &dyn audio_streams::AudioStreamsExecutor, ) -> Result<(Box<dyn AsyncCaptureBufferStream>, AudioSharedFormat), BoxError>268*bb4ee6a4SAndroid Build Coastguard Worker fn new_async_capture_stream_and_get_shared_format(
269*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
270*bb4ee6a4SAndroid Build Coastguard Worker num_channels: usize,
271*bb4ee6a4SAndroid Build Coastguard Worker guest_bit_depth: SampleFormat,
272*bb4ee6a4SAndroid Build Coastguard Worker frame_rate: u32,
273*bb4ee6a4SAndroid Build Coastguard Worker buffer_size: usize,
274*bb4ee6a4SAndroid Build Coastguard Worker ex: &dyn audio_streams::AudioStreamsExecutor,
275*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(Box<dyn AsyncCaptureBufferStream>, AudioSharedFormat), BoxError> {
276*bb4ee6a4SAndroid Build Coastguard Worker let hr = WinAudio::co_init_once_per_thread();
277*bb4ee6a4SAndroid Build Coastguard Worker let _ = check_hresult!(hr, WinAudioError::from(hr), "Co Initialized failed");
278*bb4ee6a4SAndroid Build Coastguard Worker
279*bb4ee6a4SAndroid Build Coastguard Worker let (capturer, audio_shared_format): (
280*bb4ee6a4SAndroid Build Coastguard Worker Box<dyn AsyncCaptureBufferStream>,
281*bb4ee6a4SAndroid Build Coastguard Worker AudioSharedFormat,
282*bb4ee6a4SAndroid Build Coastguard Worker ) = match WinAudioCapturer::new_async(
283*bb4ee6a4SAndroid Build Coastguard Worker num_channels,
284*bb4ee6a4SAndroid Build Coastguard Worker guest_bit_depth,
285*bb4ee6a4SAndroid Build Coastguard Worker frame_rate,
286*bb4ee6a4SAndroid Build Coastguard Worker buffer_size,
287*bb4ee6a4SAndroid Build Coastguard Worker ex,
288*bb4ee6a4SAndroid Build Coastguard Worker ) {
289*bb4ee6a4SAndroid Build Coastguard Worker Ok(capturer) => {
290*bb4ee6a4SAndroid Build Coastguard Worker let audio_shared_format = capturer.get_audio_shared_format();
291*bb4ee6a4SAndroid Build Coastguard Worker (Box::new(capturer), audio_shared_format)
292*bb4ee6a4SAndroid Build Coastguard Worker }
293*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
294*bb4ee6a4SAndroid Build Coastguard Worker warn!("Failed to create WinAudioCapturer. Fallback to NoopCaptureStream with error: {}", e);
295*bb4ee6a4SAndroid Build Coastguard Worker (
296*bb4ee6a4SAndroid Build Coastguard Worker Box::new(NoopCaptureStream::new(
297*bb4ee6a4SAndroid Build Coastguard Worker num_channels,
298*bb4ee6a4SAndroid Build Coastguard Worker SampleFormat::S32LE,
299*bb4ee6a4SAndroid Build Coastguard Worker frame_rate,
300*bb4ee6a4SAndroid Build Coastguard Worker buffer_size,
301*bb4ee6a4SAndroid Build Coastguard Worker )),
302*bb4ee6a4SAndroid Build Coastguard Worker AudioSharedFormat {
303*bb4ee6a4SAndroid Build Coastguard Worker bit_depth: 32,
304*bb4ee6a4SAndroid Build Coastguard Worker frame_rate: frame_rate as usize,
305*bb4ee6a4SAndroid Build Coastguard Worker channels: 2,
306*bb4ee6a4SAndroid Build Coastguard Worker shared_audio_engine_period_in_frames: frame_rate as usize / 100,
307*bb4ee6a4SAndroid Build Coastguard Worker channel_mask: None,
308*bb4ee6a4SAndroid Build Coastguard Worker },
309*bb4ee6a4SAndroid Build Coastguard Worker )
310*bb4ee6a4SAndroid Build Coastguard Worker }
311*bb4ee6a4SAndroid Build Coastguard Worker };
312*bb4ee6a4SAndroid Build Coastguard Worker
313*bb4ee6a4SAndroid Build Coastguard Worker Ok((capturer, audio_shared_format))
314*bb4ee6a4SAndroid Build Coastguard Worker }
315*bb4ee6a4SAndroid Build Coastguard Worker
evict_playback_stream_cache(&mut self)316*bb4ee6a4SAndroid Build Coastguard Worker fn evict_playback_stream_cache(&mut self) {
317*bb4ee6a4SAndroid Build Coastguard Worker self.cached_playback_buffer_stream = None;
318*bb4ee6a4SAndroid Build Coastguard Worker }
319*bb4ee6a4SAndroid Build Coastguard Worker
is_noop_stream(&self) -> bool320*bb4ee6a4SAndroid Build Coastguard Worker fn is_noop_stream(&self) -> bool {
321*bb4ee6a4SAndroid Build Coastguard Worker false
322*bb4ee6a4SAndroid Build Coastguard Worker }
323*bb4ee6a4SAndroid Build Coastguard Worker }
324*bb4ee6a4SAndroid Build Coastguard Worker
325*bb4ee6a4SAndroid Build Coastguard Worker impl WinAudioServer for NoopStreamSource {
new_playback_stream_and_get_shared_format( &mut self, num_channels: usize, format: SampleFormat, frame_rate: usize, buffer_size: usize, ) -> Result<(Arc<Mutex<Box<dyn PlaybackBufferStream>>>, AudioSharedFormat), BoxError>326*bb4ee6a4SAndroid Build Coastguard Worker fn new_playback_stream_and_get_shared_format(
327*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
328*bb4ee6a4SAndroid Build Coastguard Worker num_channels: usize,
329*bb4ee6a4SAndroid Build Coastguard Worker format: SampleFormat,
330*bb4ee6a4SAndroid Build Coastguard Worker frame_rate: usize,
331*bb4ee6a4SAndroid Build Coastguard Worker buffer_size: usize,
332*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(Arc<Mutex<Box<dyn PlaybackBufferStream>>>, AudioSharedFormat), BoxError> {
333*bb4ee6a4SAndroid Build Coastguard Worker let (_, playback_buffer_stream) = self
334*bb4ee6a4SAndroid Build Coastguard Worker .new_playback_stream(num_channels, format, frame_rate as u32, buffer_size)
335*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
336*bb4ee6a4SAndroid Build Coastguard Worker Ok((
337*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(playback_buffer_stream)),
338*bb4ee6a4SAndroid Build Coastguard Worker AudioSharedFormat {
339*bb4ee6a4SAndroid Build Coastguard Worker bit_depth: 16,
340*bb4ee6a4SAndroid Build Coastguard Worker frame_rate,
341*bb4ee6a4SAndroid Build Coastguard Worker channels: 2,
342*bb4ee6a4SAndroid Build Coastguard Worker shared_audio_engine_period_in_frames: frame_rate / 100,
343*bb4ee6a4SAndroid Build Coastguard Worker channel_mask: None,
344*bb4ee6a4SAndroid Build Coastguard Worker },
345*bb4ee6a4SAndroid Build Coastguard Worker ))
346*bb4ee6a4SAndroid Build Coastguard Worker }
347*bb4ee6a4SAndroid Build Coastguard Worker
new_async_playback_stream_and_get_shared_format( &mut self, num_channels: usize, format: SampleFormat, frame_rate: usize, buffer_size: usize, ex: &dyn audio_streams::AudioStreamsExecutor, _audio_client_guid: Option<String>, ) -> Result<(Box<dyn AsyncPlaybackBufferStream>, AudioSharedFormat), BoxError>348*bb4ee6a4SAndroid Build Coastguard Worker fn new_async_playback_stream_and_get_shared_format(
349*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
350*bb4ee6a4SAndroid Build Coastguard Worker num_channels: usize,
351*bb4ee6a4SAndroid Build Coastguard Worker format: SampleFormat,
352*bb4ee6a4SAndroid Build Coastguard Worker frame_rate: usize,
353*bb4ee6a4SAndroid Build Coastguard Worker buffer_size: usize,
354*bb4ee6a4SAndroid Build Coastguard Worker ex: &dyn audio_streams::AudioStreamsExecutor,
355*bb4ee6a4SAndroid Build Coastguard Worker _audio_client_guid: Option<String>,
356*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(Box<dyn AsyncPlaybackBufferStream>, AudioSharedFormat), BoxError> {
357*bb4ee6a4SAndroid Build Coastguard Worker let (_, playback_stream) = self
358*bb4ee6a4SAndroid Build Coastguard Worker .new_async_playback_stream(num_channels, format, frame_rate as u32, buffer_size, ex)
359*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
360*bb4ee6a4SAndroid Build Coastguard Worker
361*bb4ee6a4SAndroid Build Coastguard Worker // Set shared format to be the same as the incoming audio format.
362*bb4ee6a4SAndroid Build Coastguard Worker let format = AudioSharedFormat {
363*bb4ee6a4SAndroid Build Coastguard Worker bit_depth: format.sample_bytes() * 8,
364*bb4ee6a4SAndroid Build Coastguard Worker frame_rate,
365*bb4ee6a4SAndroid Build Coastguard Worker channels: num_channels,
366*bb4ee6a4SAndroid Build Coastguard Worker shared_audio_engine_period_in_frames: buffer_size * format.sample_bytes(),
367*bb4ee6a4SAndroid Build Coastguard Worker channel_mask: None,
368*bb4ee6a4SAndroid Build Coastguard Worker };
369*bb4ee6a4SAndroid Build Coastguard Worker Ok((playback_stream, format))
370*bb4ee6a4SAndroid Build Coastguard Worker }
371*bb4ee6a4SAndroid Build Coastguard Worker
is_noop_stream(&self) -> bool372*bb4ee6a4SAndroid Build Coastguard Worker fn is_noop_stream(&self) -> bool {
373*bb4ee6a4SAndroid Build Coastguard Worker true
374*bb4ee6a4SAndroid Build Coastguard Worker }
375*bb4ee6a4SAndroid Build Coastguard Worker }
376*bb4ee6a4SAndroid Build Coastguard Worker
create_win_audio_device() -> Result<WinAudio, BoxError>377*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_win_audio_device() -> Result<WinAudio, BoxError> {
378*bb4ee6a4SAndroid Build Coastguard Worker WinAudio::new()
379*bb4ee6a4SAndroid Build Coastguard Worker }
380