[aud] Add audio subsystem
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
.idea
|
||||
/target
|
||||
/roms
|
||||
|
@@ -14,10 +14,10 @@ Screenshot program author: [Javamannen](https://esolangs.org/wiki/User:Javamanne
|
||||
- [X] Outer loop - 60fps display loop
|
||||
- [X] Display adapter
|
||||
- [X] SDL2 adapter
|
||||
- [ ] Keyboard
|
||||
- [ ] Audio
|
||||
- [X] Keyboard
|
||||
- [X] Audio
|
||||
- [ ] Load/Save memory
|
||||
- [ ] Load a ROM
|
||||
- [X] Load a ROM
|
||||
|
||||
## Usage instructions
|
||||
|
||||
|
@@ -0,0 +1,48 @@
|
||||
use sdl2::audio::AudioQueue;
|
||||
|
||||
use crate::emu::memory::RamMemory;
|
||||
use crate::misc::endian::read_big_endian_u16;
|
||||
use crate::misc::error::DeviceType::AUDIO;
|
||||
use crate::misc::error::EmulatorError;
|
||||
use crate::misc::result::EmulatorResult;
|
||||
|
||||
pub const AUDIO_BUFFER_SIZE: usize = 256;
|
||||
|
||||
|
||||
pub struct AudioProcessor<'a> {
|
||||
ram: &'a RamMemory,
|
||||
frame_buffer: Box<[u8; AUDIO_BUFFER_SIZE]>,
|
||||
audio_queue: &'a AudioQueue<u8>,
|
||||
}
|
||||
|
||||
impl<'a> AudioProcessor<'a> {
|
||||
pub fn try_new(ram: &'a RamMemory, audio_queue: &'a AudioQueue<u8>) -> EmulatorResult<AudioProcessor<'a>> {
|
||||
let frame_buffer = vec![0u8; AUDIO_BUFFER_SIZE].into_boxed_slice()
|
||||
.try_into()
|
||||
.map_err(|_| {
|
||||
EmulatorError::AllocationFailure(AUDIO, "Failed to allocate graphics")
|
||||
})?;
|
||||
Ok(AudioProcessor {
|
||||
ram,
|
||||
audio_queue,
|
||||
frame_buffer,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AudioProcessor<'a> {
|
||||
pub fn queue(&mut self) -> EmulatorResult<()> {
|
||||
let audio_base_reg = (self.get_audio_base_reg() as u32) << 8;
|
||||
let fb = self.frame_buffer.as_mut();
|
||||
if self.audio_queue.size() == 0 {
|
||||
log::warn!("Detected Queue empty!");
|
||||
}
|
||||
self.ram.try_copy_block(audio_base_reg, fb)?;
|
||||
self.audio_queue.queue_audio(fb).map_err(|s| { EmulatorError::OtherError(Some(AUDIO), s) })
|
||||
}
|
||||
fn get_audio_base_reg(&self) -> u16 {
|
||||
let data = self.ram.get_data_ref();
|
||||
let audio_base_reg = data.get(6..8).unwrap();
|
||||
read_big_endian_u16(audio_base_reg.try_into().unwrap())
|
||||
}
|
||||
}
|
20
src/main.rs
20
src/main.rs
@@ -2,6 +2,7 @@ use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::time::Duration;
|
||||
use clap::Parser;
|
||||
use sdl2::audio::{AudioQueue, AudioSpecDesired};
|
||||
use sdl2::event::Event;
|
||||
use sdl2::EventPump;
|
||||
use sdl2::keyboard::Keycode;
|
||||
@@ -9,6 +10,7 @@ use sdl2::pixels::Color;
|
||||
use sdl2::render::{BlendMode, WindowCanvas};
|
||||
use simple_logger::SimpleLogger;
|
||||
use crate::args::BytePusherArgs;
|
||||
use crate::emu::audio::AudioProcessor;
|
||||
use crate::emu::cpu::Cpu;
|
||||
use crate::emu::graphics::GraphicsProcessor;
|
||||
use crate::emu::keyboard::Keyboard;
|
||||
@@ -30,11 +32,12 @@ fn main() -> EmulatorResult<()> {
|
||||
let (file_bytes, x) = try_load_rom(&file_name)?;
|
||||
assert!(x < MEM_LENGTH);
|
||||
|
||||
let (mut canvas, mut event_pump) = initiate_sdl();
|
||||
let (mut canvas, mut event_pump, mut audio_queue) = initiate_sdl();
|
||||
|
||||
|
||||
let ram = RamMemory::try_from(file_bytes.as_slice())?;
|
||||
let graphics_processor = GraphicsProcessor::try_new(&ram)?;
|
||||
let mut audio_processor = AudioProcessor::try_new(&ram,&audio_queue)?;
|
||||
let mut keyboard = Keyboard::new(&ram);
|
||||
let cpu = Cpu::new(&ram, &graphics_processor);
|
||||
|
||||
@@ -70,6 +73,7 @@ fn main() -> EmulatorResult<()> {
|
||||
// draw graphics
|
||||
sdl2_graphics_adapter.draw(&mut canvas)?;
|
||||
// TODO render audio
|
||||
audio_processor.queue()?;
|
||||
|
||||
canvas.present();
|
||||
|
||||
@@ -115,12 +119,22 @@ fn try_load_rom(file_name_option: &Option<String>) -> EmulatorResult<(Vec<u8>, u
|
||||
Ok((file_bytes, bytes_read))
|
||||
}
|
||||
|
||||
fn initiate_sdl() -> (WindowCanvas, EventPump) {
|
||||
fn initiate_sdl() -> (WindowCanvas, EventPump, AudioQueue<u8>) {
|
||||
const BASE_RESOLUTION: u32 = 256;
|
||||
const DRAW_FACTOR: u32 = 4;
|
||||
const WINDOW_RESOLUTION: u32 = BASE_RESOLUTION * DRAW_FACTOR;
|
||||
let sdl_context = sdl2::init().unwrap();
|
||||
let video_subsystem = sdl_context.video().unwrap();
|
||||
// TODO audio subsystem
|
||||
let audio_subsystem = sdl_context.audio().unwrap();
|
||||
let wanted_spec = AudioSpecDesired{
|
||||
channels: Some(1),
|
||||
samples: Some(256),
|
||||
freq: Some(15360),
|
||||
};
|
||||
let audio_queue = audio_subsystem.open_queue::<u8,_>(None, &wanted_spec).unwrap();
|
||||
audio_queue.resume();
|
||||
|
||||
|
||||
let window = video_subsystem.window("byte-pusher-emu", WINDOW_RESOLUTION, WINDOW_RESOLUTION)
|
||||
.position_centered()
|
||||
@@ -136,5 +150,5 @@ fn initiate_sdl() -> (WindowCanvas, EventPump) {
|
||||
canvas.set_blend_mode(BlendMode::None);
|
||||
canvas.present();
|
||||
let event_pump = sdl_context.event_pump().unwrap();
|
||||
(canvas, event_pump)
|
||||
(canvas, event_pump, audio_queue)
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ pub enum EmulatorError {
|
||||
AllocationFailure(DeviceType, &'static str),
|
||||
UnreachableMemory(DeviceType, u32),
|
||||
EmulatorIOError(Error),
|
||||
OtherError(Option<DeviceType>,String)
|
||||
}
|
||||
|
||||
impl From<TryFromSliceError> for EmulatorError {
|
||||
|
Reference in New Issue
Block a user