Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RustApp/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[env]
RUST_LOG = "warn,android_mic=info"
RUST_LOG = "error,android_mic=info"
ANDROID_MIC_COMMIT = "undefined"
# ANDROID_MIC_FORMAT = "flatpak"
# RUST_LOG = "info"
Expand Down
1 change: 1 addition & 0 deletions RustApp/i18n/en/android_mic.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ reset_denoise_settings = Reset Denoise Settings
title_app = App

start_at_login = Start at login
start_minimized = Start minimized
auto_connect = Auto connect
theme = Theme
amplify = Amplify
Expand Down
2 changes: 1 addition & 1 deletion RustApp/src/audio/denoise_rnnoise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub fn denoise_f32_stream(data: &[Vec<f32>]) -> anyhow::Result<Vec<Vec<f32>>> {
// Convert f32 to i16 range
let data_i16: Vec<Vec<f32>> = data
.iter()
.map(|channel| channel.iter().map(|&x| (x * i16::MAX as f32)).collect())
.map(|channel| channel.iter().map(|&x| x * i16::MAX as f32).collect())
.collect();

// Append new data into the cache
Expand Down
33 changes: 20 additions & 13 deletions RustApp/src/audio/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ impl AudioStream {
/// This function converts an audio stream from packet into producer
/// apply any necessary conversions based on the audio format
/// and returns mono channel f32 vector for audio wave display
pub fn process_audio_packet(&mut self, packet: AudioPacketMessage) -> anyhow::Result<Vec<f32>> {
pub fn process_audio_packet(
&mut self,
packet: AudioPacketMessage,
) -> anyhow::Result<Option<Vec<f32>>> {
match self.audio_params.target_format.audio_format {
AudioFormat::I16 => self.process_audio_packet_internal::<i16>(packet),
AudioFormat::I24 => self.process_audio_packet_internal::<f32>(packet),
Expand All @@ -32,7 +35,7 @@ impl AudioStream {
fn process_audio_packet_internal<F>(
&mut self,
packet: AudioPacketMessage,
) -> anyhow::Result<Vec<f32>>
) -> anyhow::Result<Option<Vec<f32>>>
where
F: cpal::SizedSample + AudioBytes + std::fmt::Debug + 'static,
{
Expand Down Expand Up @@ -130,18 +133,22 @@ impl AudioStream {
}
}

// prepare mono channel buffer to return
let buffer_mono = if config.target_format.channel_count.to_number() == 1 {
buffer[0].clone()
} else {
// if not mono, average the channels
let mut mono_buffer: Vec<f32> = Vec::with_capacity(buffer[0].len());
for i in 0..buffer[0].len() {
let sample: f32 = buffer.iter().map(|ch| ch[i]).sum::<f32>()
/ config.target_format.channel_count.to_number() as f32;
mono_buffer.push(sample);
let buffer_mono = if self.is_window_visible {
// prepare mono channel buffer to return
if config.target_format.channel_count.to_number() == 1 {
Some(buffer[0].clone())
} else {
// if not mono, average the channels
let mut mono_buffer: Vec<f32> = Vec::with_capacity(buffer[0].len());
for i in 0..buffer[0].len() {
let sample: f32 = buffer.iter().map(|ch| ch[i]).sum::<f32>()
/ config.target_format.channel_count.to_number() as f32;
mono_buffer.push(sample);
}
Some(mono_buffer)
}
mono_buffer
} else {
None
};

Ok(buffer_mono)
Expand Down
19 changes: 15 additions & 4 deletions RustApp/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{fmt::Display, net::IpAddr};

use clap::Parser;
use light_enum::Values;
use local_ip_address::local_ip;
use serde::{Deserialize, Serialize};

use crate::fl;
Expand All @@ -19,15 +20,20 @@ pub struct Config {
// device that could be disconnected sometime.
pub device_name: Option<String>,
pub start_at_login: bool,
pub start_minimized: bool,
pub auto_connect: bool,
pub denoise: bool,
pub denoise_kind: DenoiseKind,
/// range: [-100, 0]
pub speex_noise_suppress: i32,
pub speex_vad_enabled: bool,
/// range: [0, 100]
pub speex_vad_threshold: u32,
pub speex_agc_enabled: bool,
/// range: [8000, 65535]
pub speex_agc_target: u32,
pub speex_dereverb_enabled: bool,
/// range: [0.0, 1.0]
pub speex_dereverb_level: f32,
pub theme: AppTheme,
pub amplify: bool,
Expand Down Expand Up @@ -68,13 +74,14 @@ impl Default for Config {
theme: Default::default(),
amplify: false,
amplify_value: 2.0,
speex_noise_suppress: -30, // range: [-100, 0]
speex_noise_suppress: -30,
speex_vad_enabled: false,
speex_vad_threshold: 80, // range: [0, 100]
speex_vad_threshold: 80,
speex_agc_enabled: false,
speex_agc_target: 8000, // range: [8000, 65535]
speex_agc_target: 8000,
speex_dereverb_enabled: false,
speex_dereverb_level: 0.5, // range: [0.0, 1.0]
speex_dereverb_level: 0.5,
start_minimized: false,
}
}
}
Expand All @@ -89,6 +96,10 @@ impl Config {
self.speex_dereverb_enabled = false;
self.speex_dereverb_level = 0.5;
}

pub fn ip_or_default(&self) -> Option<IpAddr> {
self.ip.or(local_ip().ok())
}
}

#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Values)]
Expand Down
6 changes: 5 additions & 1 deletion RustApp/src/streamer/adb_streamer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use anyhow::Result;
use tokio::process::Command;

use crate::streamer::{StreamerMsg, tcp_streamer};
use crate::{
config::ConnectionMode,
streamer::{StreamerMsg, tcp_streamer},
};

use super::{
AudioStream, ConnectError, StreamerTrait,
Expand Down Expand Up @@ -108,6 +111,7 @@ impl StreamerTrait for AdbStreamer {
TcpStreamerState::Streaming { .. } => StreamerMsg::Connected {
ip: None,
port: None,
mode: ConnectionMode::Adb,
},
}
}
Expand Down
14 changes: 12 additions & 2 deletions RustApp/src/streamer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,28 @@ const MAX_PORT: u16 = 60000;
pub struct AudioStream {
pub buff: Producer<u8>,
pub audio_params: AudioProcessParams,
pub is_window_visible: bool,
}

impl AudioStream {
pub fn new(buff: Producer<u8>, audio_params: AudioProcessParams) -> Self {
Self { buff, audio_params }
pub fn new(
buff: Producer<u8>,
audio_params: AudioProcessParams,
is_window_visible: bool,
) -> Self {
Self {
buff,
audio_params,
is_window_visible,
}
}
}

impl Debug for AudioStream {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AudioStream")
.field("audio_params", &self.audio_params)
.field("is_window_visible", &self.is_window_visible)
.finish()
}
}
Expand Down
21 changes: 18 additions & 3 deletions RustApp/src/streamer/streamer_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::net::IpAddr;
use tokio::sync::mpsc::{self, Sender};

use crate::audio::AudioProcessParams;
use crate::config::ConnectionMode;
use crate::streamer::{StreamerTrait, WriteError};

use super::{AudioStream, ConnectError, DummyStreamer, Streamer, tcp_streamer, udp_streamer};
Expand All @@ -36,10 +37,12 @@ pub enum StreamerCommand {
connect_options: ConnectOption,
buff: Producer<u8>,
audio_params: AudioProcessParams,
is_window_visible: bool,
},
ReconfigureStream {
buff: Producer<u8>,
audio_params: AudioProcessParams,
is_window_visible: bool,
},
Stop,
}
Expand All @@ -51,17 +54,21 @@ impl Debug for StreamerCommand {
connect_options,
buff: _,
audio_params,
is_window_visible,
} => f
.debug_struct("Connect")
.field("connect_options", connect_options)
.field("audio_params", audio_params)
.field("is_window_visible", is_window_visible)
.finish(),
Self::ReconfigureStream {
buff: _,
audio_params,
is_window_visible,
} => f
.debug_struct("ReconfigureStream")
.field("audio_params", audio_params)
.field("is_window_visible", is_window_visible)
.finish(),
Self::Stop => write!(f, "Stop"),
}
Expand All @@ -82,6 +89,7 @@ pub enum StreamerMsg {
Connected {
ip: Option<IpAddr>,
port: Option<u16>,
mode: ConnectionMode,
},
Ready(Sender<StreamerCommand>),
}
Expand Down Expand Up @@ -128,8 +136,10 @@ pub fn sub() -> impl Stream<Item = StreamerMsg> {
connect_options,
buff,
audio_params,
is_window_visible,
} => {
let stream_config = AudioStream::new(buff, audio_params);
let stream_config =
AudioStream::new(buff, audio_params, is_window_visible);
let new_streamer: Result<Streamer, ConnectError> =
match connect_options {
ConnectOption::Tcp { ip } => {
Expand Down Expand Up @@ -167,8 +177,13 @@ pub fn sub() -> impl Stream<Item = StreamerMsg> {
}
}
}
StreamerCommand::ReconfigureStream { buff, audio_params } => {
let stream_config = AudioStream::new(buff, audio_params);
StreamerCommand::ReconfigureStream {
buff,
audio_params,
is_window_visible,
} => {
let stream_config =
AudioStream::new(buff, audio_params, is_window_visible);

streamer.reconfigure_stream(stream_config);
}
Expand Down
43 changes: 20 additions & 23 deletions RustApp/src/streamer/tcp_streamer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use prost::Message;
use tokio::net::{TcpListener, TcpStream};
use tokio_util::codec::{Framed, LengthDelimitedCodec};

use crate::streamer::{DEFAULT_PC_PORT, MAX_PORT, StreamerMsg, WriteError};
use crate::{
config::ConnectionMode,
streamer::{DEFAULT_PC_PORT, MAX_PORT, StreamerMsg, WriteError},
};

use super::{AudioPacketMessage, AudioStream, ConnectError, StreamerTrait};

Expand Down Expand Up @@ -76,6 +79,7 @@ impl StreamerTrait for TcpStreamer {
TcpStreamerState::Streaming { .. } => StreamerMsg::Connected {
ip: Some(self.ip),
port: Some(self.port),
mode: ConnectionMode::Tcp,
},
}
}
Expand All @@ -100,41 +104,34 @@ impl StreamerTrait for TcpStreamer {
Ok(Some(StreamerMsg::Connected {
ip: Some(self.ip),
port: Some(self.port),
mode: ConnectionMode::Tcp,
}))
}
TcpStreamerState::Streaming {
framed,
disconnect_loop_detecter: _,
} => {
match framed.next().await {
Some(Ok(frame)) => {
let mut res = None;

match AudioPacketMessage::decode(frame) {
Ok(packet) => {
let buffer_size = packet.buffer.len();
let sample_rate = packet.sample_rate;

if let Ok(buffer) = self.stream_config.process_audio_packet(packet)
{
// compute the audio wave from the buffer
res = Some(StreamerMsg::UpdateAudioWave {
Some(Ok(frame)) => match AudioPacketMessage::decode(frame) {
Ok(packet) => {
let buffer_size = packet.buffer.len();
let sample_rate = packet.sample_rate;

match self.stream_config.process_audio_packet(packet) {
Ok(Some(buffer)) => {
debug!("received {} bytes", buffer_size);
Ok(Some(StreamerMsg::UpdateAudioWave {
data: AudioPacketMessage::to_wave_data(
&buffer,
sample_rate,
),
});

debug!("received {} bytes", buffer_size);
};
}
Err(e) => {
return Err(ConnectError::WriteError(WriteError::Deserializer(e)));
}))
}
_ => Ok(None),
}
}

Ok(res)
}
Err(e) => Err(ConnectError::WriteError(WriteError::Deserializer(e))),
},

Some(Err(e)) => {
match e.kind() {
Expand Down
Loading