Add volume control

This commit is contained in:
Jeremy Soller
2022-11-21 09:53:47 -07:00
parent b0d7fedc37
commit 8ff9a0bed6
+114 -42
View File
@@ -1,5 +1,6 @@
use std::collections::{BTreeMap, VecDeque};
use syscall::error::{EBADF, EWOULDBLOCK, Error, Result};
use std::str;
use syscall::error::{EBADF, EINVAL, ENOENT, EWOULDBLOCK, Error, Result};
use syscall::flag::O_NONBLOCK;
use syscall::scheme::SchemeBlockMut;
@@ -8,78 +9,149 @@ const HW_BUFFER_SIZE: usize = 512;
// The desired buffer size of each handle
const HANDLE_BUFFER_SIZE: usize = 4096;
struct Handle {
flags: usize,
buffer: VecDeque<(i16, i16)>,
enum Handle {
Audio {
flags: usize,
buffer: VecDeque<(i16, i16)>,
},
//TODO: move volume to audiohw:?
Volume {
flags: usize,
offset: usize,
}
}
pub struct AudioScheme {
next_id: usize,
handles: BTreeMap<usize, Handle>
handles: BTreeMap<usize, Handle>,
volume: i32,
}
impl AudioScheme {
pub fn new() -> Self {
AudioScheme {
next_id: 0,
handles: BTreeMap::new()
handles: BTreeMap::new(),
volume: 50,
}
}
pub fn buffer(&mut self) -> [(i16, i16); HW_BUFFER_SIZE] {
let mut buffer = [(0i16, 0i16); HW_BUFFER_SIZE];
let mut mix_buffer = [(0i16, 0i16); HW_BUFFER_SIZE];
for (_id, handle) in self.handles.iter_mut() {
let mut i = 0;
while i < buffer.len() {
if let Some(sample) = handle.buffer.pop_front() {
buffer[i].0 = buffer[i].0.saturating_add(sample.0);
buffer[i].1 = buffer[i].1.saturating_add(sample.1);
} else {
break;
}
i += 1;
match handle {
Handle::Audio { flags: _, ref mut buffer } => {
let mut i = 0;
while i < mix_buffer.len() {
if let Some(sample) = buffer.pop_front() {
let left = ((sample.0 as i32 * self.volume) / 100) as i16;
let right = ((sample.1 as i32 * self.volume) / 100) as i16;
mix_buffer[i].0 = mix_buffer[i].0.saturating_add(left);
mix_buffer[i].1 = mix_buffer[i].1.saturating_add(right);
} else {
break;
}
i += 1;
}
},
_ => (),
}
}
buffer
mix_buffer
}
}
impl SchemeBlockMut for AudioScheme {
fn open(&mut self, _path: &str, flags: usize, _uid: u32, _gid: u32) -> Result<Option<usize>> {
self.next_id += 1;
let id = self.next_id;
fn open(&mut self, path: &str, flags: usize, _uid: u32, _gid: u32) -> Result<Option<usize>> {
let handle = match path.trim_matches('/') {
"" => Handle::Audio {
flags,
buffer: VecDeque::new()
},
"volume" => Handle::Volume {
flags,
offset: 0,
},
_ => return Err(Error::new(ENOENT)),
};
self.handles.insert(id, Handle {
flags,
buffer: VecDeque::new()
});
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, handle);
Ok(Some(id))
}
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
//TODO: check flags for readable
match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::Audio { flags: _, buffer: _ } => {
//TODO: audio input?
Err(Error::new(EBADF))
},
Handle::Volume { flags: _, ref mut offset } => {
//TODO: should we allocate every time?
let string = format!("{}", self.volume);
let bytes = string.as_bytes();
let mut i = 0;
while i < buf.len() && *offset + i < bytes.len() {
buf[i] = bytes[*offset + i];
i += 1;
}
*offset += i;
Ok(Some(i))
}
}
}
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?;
//TODO: check flags for writable
match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::Audio { ref flags, ref mut buffer } => {
if buffer.len() >= HANDLE_BUFFER_SIZE {
if flags & O_NONBLOCK > 0 {
Err(Error::new(EWOULDBLOCK))
} else {
Ok(None)
}
} else {
let mut i = 0;
while i + 4 <= buf.len() {
buffer.push_back((
(buf[i] as i16) | ((buf[i + 1] as i16) << 8),
(buf[i + 2] as i16) | ((buf[i + 3] as i16) << 8)
));
if handle.buffer.len() >= HANDLE_BUFFER_SIZE {
if handle.flags & O_NONBLOCK > 0 {
Err(Error::new(EWOULDBLOCK))
} else {
Ok(None)
i += 4;
}
Ok(Some(i))
}
},
Handle::Volume { flags: _, ref mut offset } => {
//TODO: support other offsets?
if *offset == 0 {
let value = str::from_utf8(buf)
.map_err(|_| Error::new(EINVAL))?
.trim()
.parse::<i32>()
.map_err(|_| Error::new(EINVAL))?;
if value >= 0 && value <= 100 {
self.volume = value;
*offset += buf.len();
Ok(Some(buf.len()))
} else {
Err(Error::new(EINVAL))
}
} else {
// EOF
Ok(Some(0))
}
}
} else {
let mut i = 0;
while i + 4 <= buf.len() {
handle.buffer.push_back((
(buf[i] as i16) | ((buf[i + 1] as i16) << 8),
(buf[i + 2] as i16) | ((buf[i + 3] as i16) << 8)
));
i += 4;
}
Ok(Some(i))
}
}
}