fox32: Add support for audio playback

This commit is contained in:
Ry 2022-05-25 16:15:39 -07:00
parent a8d92c69b2
commit 5deb4fd8f8
5 changed files with 356 additions and 7 deletions

303
Cargo.lock generated
View File

@ -29,6 +29,28 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "alsa"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5915f52fe2cf65e83924d037b6c5290b7cee097c6b5c8700746e6168a343fd6b"
dependencies = [
"alsa-sys",
"bitflags",
"libc",
"nix 0.23.1",
]
[[package]]
name = "alsa-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527"
dependencies = [
"libc",
"pkg-config",
]
[[package]] [[package]]
name = "ansi_term" name = "ansi_term"
version = "0.12.1" version = "0.12.1"
@ -268,6 +290,12 @@ version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]] [[package]]
name = "cache-padded" name = "cache-padded"
version = "1.2.0" version = "1.2.0"
@ -303,6 +331,12 @@ dependencies = [
"jobserver", "jobserver",
] ]
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]] [[package]]
name = "cexpr" name = "cexpr"
version = "0.6.0" version = "0.6.0"
@ -378,6 +412,12 @@ dependencies = [
"vec_map", "vec_map",
] ]
[[package]]
name = "claxon"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688"
[[package]] [[package]]
name = "cocoa" name = "cocoa"
version = "0.24.0" version = "0.24.0"
@ -425,6 +465,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "combine"
version = "4.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948"
dependencies = [
"bytes",
"memchr",
]
[[package]] [[package]]
name = "concurrent-queue" name = "concurrent-queue"
version = "1.2.2" version = "1.2.2"
@ -522,6 +572,50 @@ dependencies = [
"objc", "objc",
] ]
[[package]]
name = "coreaudio-rs"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88"
dependencies = [
"bitflags",
"coreaudio-sys",
]
[[package]]
name = "coreaudio-sys"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dff444d80630d7073077d38d40b4501fd518bd2b922c2a55edcc8b0f7be57e6"
dependencies = [
"bindgen",
]
[[package]]
name = "cpal"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74117836a5124f3629e4b474eed03e479abaf98988b4bb317e29f08cfe0e4116"
dependencies = [
"alsa",
"core-foundation-sys 0.8.3",
"coreaudio-rs",
"jni",
"js-sys",
"lazy_static",
"libc",
"mach",
"ndk 0.6.0",
"ndk-glue 0.6.2",
"nix 0.23.1",
"oboe",
"parking_lot",
"stdweb",
"thiserror",
"web-sys",
"winapi",
]
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.3.2" version = "1.3.2"
@ -832,6 +926,7 @@ dependencies = [
"pixels", "pixels",
"rfd", "rfd",
"ringbuf", "ringbuf",
"rodio",
"vergen", "vergen",
"winit", "winit",
"winit_input_helper", "winit_input_helper",
@ -1197,6 +1292,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]]
name = "hound"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549"
[[package]] [[package]]
name = "humantime" name = "humantime"
version = "2.1.0" version = "2.1.0"
@ -1277,6 +1378,20 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "jni"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec"
dependencies = [
"cesu8",
"combine",
"jni-sys",
"log",
"thiserror",
"walkdir",
]
[[package]] [[package]]
name = "jni-sys" name = "jni-sys"
version = "0.3.0" version = "0.3.0"
@ -1344,6 +1459,17 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff" checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff"
[[package]]
name = "lewton"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030"
dependencies = [
"byteorder",
"ogg",
"tinyvec",
]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.125" version = "0.2.125"
@ -1402,6 +1528,15 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
] ]
[[package]]
name = "mach"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "malloc_buf" name = "malloc_buf"
version = "0.0.6" version = "0.0.6"
@ -1461,6 +1596,26 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c64630dcdd71f1a64c435f54885086a0de5d6a12d104d69b165fb7d5286d677" checksum = "9c64630dcdd71f1a64c435f54885086a0de5d6a12d104d69b165fb7d5286d677"
[[package]]
name = "minimp3"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372"
dependencies = [
"minimp3-sys",
"slice-deque",
"thiserror",
]
[[package]]
name = "minimp3-sys"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.4" version = "0.4.4"
@ -1537,11 +1692,30 @@ checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"jni-sys", "jni-sys",
"ndk-sys", "ndk-sys 0.2.2",
"num_enum", "num_enum",
"thiserror", "thiserror",
] ]
[[package]]
name = "ndk"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4"
dependencies = [
"bitflags",
"jni-sys",
"ndk-sys 0.3.0",
"num_enum",
"thiserror",
]
[[package]]
name = "ndk-context"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
[[package]] [[package]]
name = "ndk-glue" name = "ndk-glue"
version = "0.5.0" version = "0.5.0"
@ -1551,9 +1725,24 @@ dependencies = [
"lazy_static", "lazy_static",
"libc", "libc",
"log", "log",
"ndk", "ndk 0.5.0",
"ndk-macro", "ndk-macro",
"ndk-sys", "ndk-sys 0.2.2",
]
[[package]]
name = "ndk-glue"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f"
dependencies = [
"lazy_static",
"libc",
"log",
"ndk 0.6.0",
"ndk-context",
"ndk-macro",
"ndk-sys 0.3.0",
] ]
[[package]] [[package]]
@ -1575,6 +1764,15 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
[[package]]
name = "ndk-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97"
dependencies = [
"jni-sys",
]
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.22.0" version = "0.22.0"
@ -1621,6 +1819,17 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "num-derive"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.44" version = "0.1.44"
@ -1733,6 +1942,38 @@ dependencies = [
"objc", "objc",
] ]
[[package]]
name = "oboe"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1"
dependencies = [
"jni",
"ndk 0.6.0",
"ndk-context",
"num-derive",
"num-traits",
"oboe-sys",
]
[[package]]
name = "oboe-sys"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3370abb7372ed744232c12954d920d1a40f1c4686de9e79e800021ef492294bd"
dependencies = [
"cc",
]
[[package]]
name = "ogg"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e"
dependencies = [
"byteorder",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.8.0" version = "1.8.0"
@ -2098,6 +2339,19 @@ dependencies = [
"cache-padded", "cache-padded",
] ]
[[package]]
name = "rodio"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e"
dependencies = [
"claxon",
"cpal",
"hound",
"lewton",
"minimp3",
]
[[package]] [[package]]
name = "rustc-hash" name = "rustc-hash"
version = "1.1.0" version = "1.1.0"
@ -2119,6 +2373,15 @@ dependencies = [
"bytemuck", "bytemuck",
] ]
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "scoped-tls" name = "scoped-tls"
version = "1.0.0" version = "1.0.0"
@ -2195,6 +2458,17 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]]
name = "slice-deque"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25"
dependencies = [
"libc",
"mach",
"winapi",
]
[[package]] [[package]]
name = "slotmap" name = "slotmap"
version = "1.0.6" version = "1.0.6"
@ -2264,6 +2538,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "stdweb"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.8.0" version = "0.8.0"
@ -2493,6 +2773,17 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.0+wasi-snapshot-preview1" version = "0.10.0+wasi-snapshot-preview1"
@ -2866,9 +3157,9 @@ dependencies = [
"libc", "libc",
"log", "log",
"mio", "mio",
"ndk", "ndk 0.5.0",
"ndk-glue", "ndk-glue 0.5.0",
"ndk-sys", "ndk-sys 0.2.2",
"objc", "objc",
"parking_lot", "parking_lot",
"percent-encoding", "percent-encoding",

View File

@ -14,6 +14,7 @@ log = "0.4"
pixels = "0.9.0" pixels = "0.9.0"
rfd = "0.7.0" rfd = "0.7.0"
ringbuf = "0.2" ringbuf = "0.2"
rodio = "0.15.0"
winit = "0.26" winit = "0.26"
winit_input_helper = "0.11" winit_input_helper = "0.11"

15
src/audio.rs Normal file
View File

@ -0,0 +1,15 @@
// audio.rs
pub struct Audio {
pub current_buffer_is_0: bool,
pub playing: bool,
}
impl Audio {
pub fn new() -> Self {
Audio {
current_buffer_is_0: true,
playing: false,
}
}
}

View File

@ -1,6 +1,6 @@
// bus.rs // bus.rs
use crate::{Memory, DiskController, Keyboard, Mouse, Overlay}; use crate::{Memory, Audio, DiskController, Keyboard, Mouse, Overlay};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::io::{Write, stdout}; use std::io::{Write, stdout};
@ -10,6 +10,8 @@ pub struct Bus {
pub disk_controller: DiskController, pub disk_controller: DiskController,
pub audio: Arc<Mutex<Audio>>,
pub keyboard: Arc<Mutex<Keyboard>>, pub keyboard: Arc<Mutex<Keyboard>>,
pub mouse: Arc<Mutex<Mouse>>, pub mouse: Arc<Mutex<Mouse>>,
@ -165,6 +167,11 @@ impl Bus {
_ => panic!("invalid mouse control port"), _ => panic!("invalid mouse control port"),
} }
} }
0x80000600 => { // audio port
let mut audio_lock = self.audio.lock().unwrap();
audio_lock.playing = word != 0;
audio_lock.current_buffer_is_0 = true;
}
0x80001000..=0x80005003 => { // disk controller port 0x80001000..=0x80005003 => { // disk controller port
let id = port as u8; let id = port as u8;
let operation = (port & 0x0000F000) >> 8; let operation = (port & 0x0000F000) >> 8;

View File

@ -1,6 +1,7 @@
// main.rs // main.rs
pub mod memory; pub mod memory;
pub mod audio;
pub mod bus; pub mod bus;
pub mod cpu; pub mod cpu;
pub mod keyboard; pub mod keyboard;
@ -9,6 +10,7 @@ pub mod disk;
pub mod runtime; pub mod runtime;
pub mod wrapped; pub mod wrapped;
use audio::Audio;
use bus::Bus; use bus::Bus;
use cpu::{Cpu, Interrupt}; use cpu::{Cpu, Interrupt};
use keyboard::Keyboard; use keyboard::Keyboard;
@ -23,6 +25,7 @@ use std::mem;
use std::ops::Deref; use std::ops::Deref;
use std::sync::{Arc, mpsc, Mutex}; use std::sync::{Arc, mpsc, Mutex};
use std::thread; use std::thread;
use std::time;
use std::process::exit; use std::process::exit;
use std::env; use std::env;
use std::fs::{File, read}; use std::fs::{File, read};
@ -30,6 +33,7 @@ use std::fs::{File, read};
use image; use image;
use log::error; use log::error;
use pixels::{Pixels, SurfaceTexture}; use pixels::{Pixels, SurfaceTexture};
use rodio::{OutputStream, buffer::SamplesBuffer, Sink};
use winit::dpi::LogicalSize; use winit::dpi::LogicalSize;
use winit::event::{ElementState, Event, WindowEvent}; use winit::event::{ElementState, Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop}; use winit::event_loop::{ControlFlow, EventLoop};
@ -86,8 +90,11 @@ fn main() {
let keyboard = Arc::new(Mutex::new(Keyboard::new())); let keyboard = Arc::new(Mutex::new(Keyboard::new()));
let mouse = Arc::new(Mutex::new(Mouse::new())); let mouse = Arc::new(Mutex::new(Mouse::new()));
let audio = Arc::new(Mutex::new(Audio::new()));
let mut bus = Bus { let mut bus = Bus {
memory: Box::new(MemoryStub()), memory: Box::new(MemoryStub()),
audio: audio.clone(),
disk_controller: DiskController::new(), disk_controller: DiskController::new(),
keyboard: keyboard.clone(), keyboard: keyboard.clone(),
mouse: mouse.clone(), mouse: mouse.clone(),
@ -130,6 +137,7 @@ fn main() {
runtime.halted_set(false); runtime.halted_set(false);
let memory_audio = memory.clone();
let memory_cpu = memory.clone(); let memory_cpu = memory.clone();
let memory_eventloop = memory.clone(); let memory_eventloop = memory.clone();
@ -194,6 +202,33 @@ fn main() {
} }
}).unwrap(); }).unwrap();
let interrupt_sender_audio = interrupt_sender.clone();
let builder = thread::Builder::new().name("audio".to_string());
builder.spawn({
move || {
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
let sink = Sink::try_new(&stream_handle).unwrap();
loop {
// every 500 ms, play what is in the audio buffer and tell fox32 to swap them
let mut audio_lock = audio.lock().unwrap();
if audio_lock.playing {
let current_buffer: Vec<i16> = if audio_lock.current_buffer_is_0 {
audio_lock.current_buffer_is_0 = false;
memory_audio.ram()[0x0212C000..0x0212C000+32768].to_vec().chunks_exact(2).map(|x| ((x[1] as i16) << 8) | x[0] as i16).collect()
} else {
audio_lock.current_buffer_is_0 = true;
memory_audio.ram()[0x0212C000+32768..0x0212C000+65536].to_vec().chunks_exact(2).map(|x| ((x[1] as i16) << 8) | x[0] as i16).collect()
};
let buffer = SamplesBuffer::new(1, 22050, current_buffer);
sink.append(buffer);
drop(audio_lock);
interrupt_sender_audio.send(0xFE).unwrap(); // audio interrupt, swap audio buffers
thread::sleep(time::Duration::from_millis(500));
}
}
}
}).unwrap();
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll; *control_flow = ControlFlow::Poll;