sl4f_lib/audio/
commands.rs1use crate::audio::types::AudioMethod;
6use crate::server::Facade;
7use anyhow::{Context, Error};
8use async_trait::async_trait;
9use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
10use base64::engine::Engine as _;
11use fidl_fuchsia_media::{AudioRenderUsage2, AudioSampleFormat, AudioStreamType};
12use fidl_fuchsia_media_sounds::{PlayerMarker, PlayerProxy};
13use fidl_fuchsia_test_audio::{CaptureMarker, CaptureProxy, InjectionMarker, InjectionProxy};
14use fuchsia_async as fasync;
15use fuchsia_component::client::connect_to_protocol;
16use futures::lock::Mutex;
17use futures::{AsyncReadExt, AsyncWriteExt};
18use log::{error, info};
19use serde_json::{to_value, Value};
20
21#[async_trait(?Send)]
22impl Facade for AudioFacade {
23 async fn handle_request(&self, method: String, args: Value) -> Result<Value, Error> {
24 match method.parse()? {
25 AudioMethod::PutInputAudio => self.put_input_audio(args).await,
26 AudioMethod::StartInputInjection => self.start_input_injection(args).await,
27 AudioMethod::StopInputInjection => self.stop_input_injection().await,
28 AudioMethod::StartOutputSave => self.start_output_save().await,
29 AudioMethod::StopOutputSave => self.stop_output_save().await,
30 AudioMethod::GetOutputAudio => self.get_output_audio().await,
31 AudioMethod::PlaySound => self.play_sine_wave().await,
32 }
33 }
34}
35
36#[derive(Debug)]
37pub struct AudioFacade {
38 injection_proxy: InjectionProxy,
39 capture_proxy: CaptureProxy,
40 player_proxy: PlayerProxy,
41 sound_buffer_id: Mutex<u32>,
42}
43
44impl AudioFacade {
45 pub fn new() -> Result<AudioFacade, Error> {
46 info!("Launching audio_recording component");
47 let injection_proxy = connect_to_protocol::<InjectionMarker>()?;
48 let recording_proxy = connect_to_protocol::<CaptureMarker>()?;
49 let player_proxy = connect_to_protocol::<PlayerMarker>()?;
50 let sound_buffer_id = Mutex::new(0u32);
51
52 Ok(AudioFacade {
53 injection_proxy,
54 capture_proxy: recording_proxy,
55 player_proxy,
56 sound_buffer_id,
57 })
58 }
59
60 pub async fn put_input_audio(&self, args: Value) -> Result<Value, Error> {
61 let data = args.get("data").ok_or_else(|| format_err!("PutInputAudio failed, no data"))?;
62 let data =
63 data.as_str().ok_or_else(|| format_err!("PutInputAudio failed, data not string"))?;
64
65 let wave_data_vec = BASE64_STANDARD.decode(data)?;
66
67 let sample_index =
68 args["index"].as_u64().ok_or_else(|| format_err!("index not a number"))?;
69 let sample_index = sample_index.try_into()?;
70
71 let _ = self
72 .injection_proxy
73 .clear_input_audio(sample_index)
74 .await
75 .context("Error calling clear_input_audio")?;
76
77 let (tx, rx) = zx::Socket::create_stream();
78 tx.half_close().expect("prevent writes on other side");
79 self.injection_proxy.write_input_audio(sample_index, rx)?;
80
81 let mut tx = fasync::Socket::from_socket(tx);
82 if let Err(e) = tx.write_all(&wave_data_vec).await {
83 error!("Failed to write audio data to socket: {:?}", e);
84 return Err(e.into());
85 }
86 std::mem::drop(tx); let byte_count = self
89 .injection_proxy
90 .get_input_audio_size(sample_index)
91 .await
92 .context("Error calling get_input_audio_size")?
93 .map_err(|e| anyhow!("get_input_audio_size failed: {:?}", e))?;
94 if byte_count != wave_data_vec.len() as u64 {
95 bail!("Expected to write {} bytes, found {} bytes", wave_data_vec.len(), byte_count);
96 }
97
98 Ok(to_value(byte_count)?)
99 }
100
101 pub async fn start_input_injection(&self, args: Value) -> Result<Value, Error> {
102 let sample_index =
103 args["index"].as_u64().ok_or_else(|| format_err!("index not a number"))?;
104 let sample_index = sample_index.try_into()?;
105 let status = self
106 .injection_proxy
107 .start_input_injection(sample_index)
108 .await
109 .context("Error calling start_input_injection")?;
110 match status {
111 Ok(_) => return Ok(to_value(true)?),
112 Err(_) => return Ok(to_value(false)?),
113 }
114 }
115
116 pub async fn stop_input_injection(&self) -> Result<Value, Error> {
117 let status = self
118 .injection_proxy
119 .stop_input_injection()
120 .await
121 .context("Error calling stop_input_injection")?;
122 match status {
123 Ok(_) => return Ok(to_value(true)?),
124 Err(_) => return Ok(to_value(false)?),
125 }
126 }
127
128 pub async fn start_output_save(&self) -> Result<Value, Error> {
129 let status = self
130 .capture_proxy
131 .start_output_capture()
132 .await
133 .context("Error calling start_output_save")?;
134 match status {
135 Ok(_) => return Ok(to_value(true)?),
136 Err(_) => return Ok(to_value(false)?),
137 }
138 }
139
140 pub async fn stop_output_save(&self) -> Result<Value, Error> {
141 let status = self
142 .capture_proxy
143 .stop_output_capture()
144 .await
145 .context("Error calling stop_output_save")?;
146 match status {
147 Ok(_) => return Ok(to_value(true)?),
148 Err(_) => return Ok(to_value(false)?),
149 }
150 }
151
152 pub async fn get_output_audio(&self) -> Result<Value, Error> {
153 let mut rx_socket = fasync::Socket::from_socket(
154 match self
155 .capture_proxy
156 .get_output_audio()
157 .await
158 .context("Error calling get_output_audio")?
159 {
160 Ok(socket) => socket,
161 Err(e) => {
162 bail!("Failure: {:?}", e);
163 }
164 },
165 );
166
167 let mut buffer = Vec::new();
168 rx_socket.read_to_end(&mut buffer).await?;
169 Ok(to_value(BASE64_STANDARD.encode(&buffer))?)
170 }
171
172 pub async fn play_sine_wave(&self) -> Result<Value, Error> {
175 let mut id = self.sound_buffer_id.lock().await;
176 *(id) += 1;
177 const FREQUENCY: f32 = 399.0;
178 const VOLUME: f32 = 0.1;
179 const DURATION: std::time::Duration = std::time::Duration::from_secs(1);
180 const FRAMES_PER_SECOND: u32 = 44100;
181
182 let (buffer, stream_type) =
183 self.sound_in_buffer(FREQUENCY, VOLUME, FRAMES_PER_SECOND, DURATION)?;
184
185 match self.player_proxy.add_sound_buffer(*id, buffer, &stream_type) {
186 Ok(()) => (),
187 Err(e) => return Err(format_err!("Cannot add sound to buffer: {}", e)),
188 };
189 self.player_proxy
190 .play_sound2(*id, AudioRenderUsage2::Media)
191 .await?
192 .map_err(|err| format_err!("PlaySound2 failed: {:?}", err))?;
193 Ok(to_value(true)?)
194 }
195
196 fn sound_in_buffer(
197 &self,
198 frequency: f32,
199 volume: f32,
200 frames_per_second: u32,
201 duration: std::time::Duration,
202 ) -> Result<(fidl_fuchsia_mem::Buffer, AudioStreamType), Error> {
203 let frame_count = (frames_per_second as f32 * duration.as_secs_f32()) as usize;
204
205 let amplitude = volume * (std::i16::MAX as f32);
206 let frames_per_period = (frames_per_second as f32) / (frequency as f32);
207 let mut samples = std::vec::Vec::with_capacity(frame_count);
208 for i in 0..frame_count {
209 let sample_f = f32::sin((i as f32) / frames_per_period * 2.0 * std::f32::consts::PI);
210 samples.push((sample_f * amplitude) as i16);
211 }
212
213 let bytes =
215 unsafe { std::slice::from_raw_parts(samples.as_ptr() as *const _, samples.len() * 2) };
216 let vmo = zx::Vmo::create((frame_count * 2) as u64).context("Creating VMO")?;
217 vmo.write(&bytes, 0).context("Writing to VMO")?;
218
219 Ok((
220 fidl_fuchsia_mem::Buffer { vmo: vmo, size: (frame_count * 2) as u64 },
221 AudioStreamType {
222 sample_format: AudioSampleFormat::Signed16,
223 channels: 1,
224 frames_per_second: frames_per_second,
225 },
226 ))
227 }
228}