Skip to content

Commit 71cfb28

Browse files
committed
Peg frame limit to audio playback
1 parent 211b909 commit 71cfb28

File tree

5 files changed

+76
-82
lines changed

5 files changed

+76
-82
lines changed

src/core/graphics/gpu.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ use crate::core::CpuType;
1111
use crate::core::CpuType::ARM9;
1212
use crate::logging::debug_println;
1313
use bilge::prelude::*;
14-
use std::intrinsics::{likely, unlikely};
14+
use std::intrinsics::unlikely;
1515
use std::ptr::NonNull;
1616
use std::sync::atomic::{AtomicU16, Ordering};
1717
use std::sync::Arc;
18-
use std::thread;
19-
use std::time::{Duration, Instant};
18+
use std::time::Instant;
2019

2120
pub const DISPLAY_WIDTH: usize = 256;
2221
pub const DISPLAY_HEIGHT: usize = 192;
@@ -38,17 +37,10 @@ impl FrameRateCounter {
3837
}
3938
}
4039

41-
fn on_frame_ready(&mut self, limit_frame: bool) {
40+
fn on_frame_ready(&mut self) {
4241
self.frame_counter += 1;
4342
let now = Instant::now();
44-
if likely(limit_frame) {
45-
let diff = now.duration_since(self.last_frame).as_millis();
46-
if unlikely(diff < 16) {
47-
thread::sleep(Duration::from_millis(16 - diff as u64));
48-
}
49-
self.last_frame = Instant::now();
50-
}
51-
if now.duration_since(self.last_update).as_millis() >= 1000 {
43+
if unlikely(now.duration_since(self.last_update).as_millis() >= 1000) {
5244
self.fps.store(self.frame_counter, Ordering::Relaxed);
5345
// #[cfg(target_os = "linux")]
5446
eprintln!("{}", self.frame_counter);
@@ -90,7 +82,6 @@ pub struct Gpu {
9082
pub pow_cnt1: u16,
9183
pub disp_cap_cnt: u32,
9284
frame_rate_counter: FrameRateCounter,
93-
pub frame_limit: bool,
9485
pub arm7_hle: bool,
9586
pub v_count: u16,
9687
pub gpu_2d_regs_a: Gpu2DRegisters<{ A }>,
@@ -106,7 +97,6 @@ impl Gpu {
10697
pow_cnt1: 0,
10798
disp_cap_cnt: 0,
10899
frame_rate_counter: FrameRateCounter::new(fps),
109-
frame_limit: false,
110100
arm7_hle: false,
111101
v_count: 0,
112102
gpu_2d_regs_a: Gpu2DRegisters::default(),
@@ -204,7 +194,7 @@ impl Gpu {
204194
for i in 0..2 {
205195
gpu.disp_stat[i].set_v_blank_flag(u1::new(0));
206196
}
207-
gpu.frame_rate_counter.on_frame_ready(gpu.frame_limit);
197+
gpu.frame_rate_counter.on_frame_ready();
208198
}
209199
263 => {
210200
gpu.v_count = 0;

src/core/spu.rs

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,36 @@ const SAMPLE_BUFFER_SIZE: usize = SAMPLE_RATE * PRESENTER_AUDIO_BUF_SIZE / PRESE
1818
pub struct SoundSampler {
1919
samples: Mutex<VecDeque<HeapMemU32<{ SAMPLE_BUFFER_SIZE }>>>,
2020
cond_var: Condvar,
21+
framelimit: bool,
2122
}
2223

2324
impl SoundSampler {
24-
pub fn new() -> SoundSampler {
25+
pub fn new(framelimit: bool) -> SoundSampler {
2526
SoundSampler {
2627
samples: Mutex::new(VecDeque::new()),
2728
cond_var: Condvar::new(),
29+
framelimit,
2830
}
2931
}
3032

3133
fn push(&self, samples: &[u32]) {
32-
let mut queue = self.samples.lock().unwrap();
33-
if queue.len() == 2 {
34-
queue.swap(0, 1);
35-
let s = queue.back_mut().unwrap();
36-
s.copy_from_slice(samples);
37-
} else {
34+
{
35+
let mut queue = self.samples.lock().unwrap();
36+
let mut queue = if queue.len() == 4 {
37+
if self.framelimit {
38+
self.cond_var.wait_while(queue, |queue| queue.len() == 4).unwrap()
39+
} else {
40+
queue.pop_front();
41+
queue
42+
}
43+
} else {
44+
queue
45+
};
3846
let mut s = HeapMemU32::new();
3947
s.copy_from_slice(samples);
4048
queue.push_back(s);
41-
self.cond_var.notify_one();
4249
}
50+
self.cond_var.notify_one();
4351
}
4452

4553
pub fn consume(&self, ret: &mut [u32; PRESENTER_AUDIO_BUF_SIZE]) {
@@ -48,6 +56,7 @@ impl SoundSampler {
4856
let mut samples = self.cond_var.wait_while(samples, |samples| samples.is_empty()).unwrap();
4957
samples.pop_front().unwrap()
5058
};
59+
self.cond_var.notify_one();
5160
for i in 0..PRESENTER_AUDIO_BUF_SIZE {
5261
ret[i] = samples[i * SAMPLE_BUFFER_SIZE / PRESENTER_AUDIO_BUF_SIZE];
5362
}
@@ -123,13 +132,14 @@ pub struct MainSoundCnt {
123132
#[derive(Copy, Clone, Default)]
124133
pub struct SpuChannel {
125134
cnt: SoundCnt,
135+
volume: u8,
126136
sad: u32,
127137
tmr: u16,
128138
pnt: u16,
129139
len: u32,
130140
snd_cap_cnt: u8,
131141
sad_current: u32,
132-
tmr_current: u16,
142+
tmr_current: u32,
133143
adpcm_value: i32,
134144
adpcm_loop_value: i32,
135145
adpcm_index: i32,
@@ -161,6 +171,7 @@ pub struct Spu {
161171
pub audio_enabled: bool,
162172
pub channels: [SpuChannel; CHANNEL_COUNT],
163173
main_sound_cnt: MainSoundCnt,
174+
master_volume: u8,
164175
sound_bias: u16,
165176
duty_cycles: [i32; 6],
166177
noise_values: [u16; 2],
@@ -174,6 +185,7 @@ impl Spu {
174185
audio_enabled: false,
175186
channels: [SpuChannel::default(); CHANNEL_COUNT],
176187
main_sound_cnt: MainSoundCnt::from(0),
188+
master_volume: 0,
177189
sound_bias: 0,
178190
duty_cycles: [0; 6],
179191
noise_values: [0; 2],
@@ -203,6 +215,11 @@ impl Spu {
203215

204216
mask &= 0xFF7F837F;
205217
self.channels[channel].cnt = ((u32::from(self.channels[channel].cnt) & !mask) | (value & mask)).into();
218+
let mut volume = u8::from(self.channels[channel].cnt.volume_mul());
219+
if volume == 127 {
220+
volume += 1;
221+
}
222+
self.channels[channel].volume = volume;
206223

207224
if was_disabled
208225
&& bool::from(self.channels[channel].cnt.start_status())
@@ -246,6 +263,11 @@ impl Spu {
246263

247264
mask &= 0xBF7F;
248265
self.main_sound_cnt = ((u16::from(self.main_sound_cnt) & !mask) | (value & mask)).into();
266+
let mut volume = u8::from(self.main_sound_cnt.master_volume());
267+
if volume == 127 {
268+
volume += 1;
269+
}
270+
self.master_volume = volume;
249271

250272
if was_disabled && bool::from(self.main_sound_cnt.master_enable()) {
251273
for i in 0..CHANNEL_COUNT {
@@ -280,7 +302,7 @@ impl Spu {
280302
fn start_channel(&mut self, channel_num: usize, emu: &mut Emu) {
281303
let channel = &mut self.channels[channel_num];
282304
channel.sad_current = channel.sad;
283-
channel.tmr_current = channel.tmr;
305+
channel.tmr_current = channel.tmr as u32;
284306

285307
match channel.cnt.get_format() {
286308
SoundChannelFormat::ImaAdpcm => {
@@ -381,7 +403,13 @@ impl Spu {
381403
for i in 0..CHANNEL_COUNT {
382404
get_channel_mut!(emu, i).cnt.set_start_status(u1::new(0));
383405
}
384-
get_cm_mut!(emu).schedule(512 * 10, EventType::SpuSample);
406+
let spu = get_spu_mut!(emu);
407+
spu.samples_buffer.push(0);
408+
if unlikely(spu.samples_buffer.len() == SAMPLE_BUFFER_SIZE) {
409+
spu.sound_sampler.push(spu.samples_buffer.as_slice());
410+
spu.samples_buffer.clear();
411+
}
412+
get_cm_mut!(emu).schedule(512 * 2, EventType::SpuSample);
385413
return;
386414
}
387415

@@ -416,25 +444,15 @@ impl Spu {
416444
}
417445
};
418446

419-
{
420-
let channel = get_channel_mut!(emu, i);
421-
channel.tmr_current = channel.tmr_current.wrapping_add(512);
422-
}
423-
424-
let mut overflow = get_channel!(emu, i).tmr_current < 512;
425-
while overflow {
426-
{
427-
let channel = get_channel_mut!(emu, i);
428-
channel.tmr_current = channel.tmr_current.wrapping_add(channel.tmr);
429-
}
430-
overflow = get_channel!(emu, i).tmr_current < get_channel!(emu, i).tmr;
447+
let mut tmr_current = get_channel!(emu, i).tmr_current.wrapping_add(512);
448+
let tmr = get_channel!(emu, i).tmr;
449+
while tmr_current >> 16 != 0 {
450+
tmr_current = tmr as u32 + (tmr_current - 0x10000);
431451

432452
match format {
433453
SoundChannelFormat::Pcm8 | SoundChannelFormat::Pcm16 => Self::next_sample_pcm(get_channel_mut!(emu, i)),
434454
SoundChannelFormat::ImaAdpcm => Self::next_sample_adpcm(get_channel_mut!(emu, i), emu),
435-
SoundChannelFormat::PsgNoise => {
436-
get_spu_mut!(emu).next_sample_psg(i);
437-
}
455+
SoundChannelFormat::PsgNoise => get_spu_mut!(emu).next_sample_psg(i),
438456
}
439457

440458
let channel = get_channel_mut!(emu, i);
@@ -454,19 +472,15 @@ impl Spu {
454472
}
455473
}
456474
}
475+
get_channel_mut!(emu, i).tmr_current = tmr_current;
457476

458477
let channel = get_channel!(emu, i);
459-
let mut volume_div = u8::from(channel.cnt.volume_div());
460-
if volume_div == 3 {
461-
volume_div += 1;
462-
}
463-
data <<= 4 - volume_div;
478+
let volume_div = u8::from(channel.cnt.volume_div());
479+
const VOLUME_DIVS: [u8; 4] = [4, 3, 2, 0];
480+
data <<= VOLUME_DIVS[volume_div as usize];
464481

465-
let mut volume_mul = u8::from(channel.cnt.volume_mul()) as i64;
466-
if volume_mul == 127 {
467-
volume_mul += 1;
468-
}
469-
data = (data << 7) * volume_mul / 128;
482+
let volume_mul = channel.volume as i64;
483+
data = ((data << 7) * volume_mul) >> 7;
470484

471485
let mut panning = u8::from(channel.cnt.panning()) as i64;
472486
if panning == 127 {
@@ -511,12 +525,9 @@ impl Spu {
511525
_ => unsafe { unreachable_unchecked() },
512526
};
513527

514-
let mut master_vol = u8::from(spu.main_sound_cnt.master_volume()) as i64;
515-
if master_vol == 127 {
516-
master_vol += 1;
517-
}
518-
let sample_left = (sample_left * master_vol / 128) >> 8;
519-
let sample_right = (sample_right * master_vol / 128) >> 8;
528+
let master_volume = spu.master_volume as i64;
529+
let sample_left = ((sample_left * master_volume) >> 7) >> 8;
530+
let sample_right = ((sample_right * master_volume) >> 7) >> 8;
520531

521532
let sample_left = (sample_left >> 6) + spu.sound_bias as i64;
522533
let sample_right = (sample_right >> 6) + spu.sound_bias as i64;

src/main.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ fn run_cpu(
149149
}
150150

151151
Gpu::initialize_schedule(get_cm_mut!(emu));
152-
common.gpu.frame_limit = emu.settings.framelimit();
153152
common.gpu.gpu_renderer = Some(gpu_renderer);
154153

155154
get_spu_mut!(emu).audio_enabled = emu.settings.audio();
@@ -295,27 +294,21 @@ pub fn actual_main() {
295294
let touch_points = Arc::new(AtomicU16::new(0));
296295
let touch_points_clone = touch_points.clone();
297296

298-
let sound_sampler = Arc::new(SoundSampler::new());
297+
let sound_sampler = Arc::new(SoundSampler::new(settings.framelimit()));
299298
let sound_sampler_clone = sound_sampler.clone();
300299

301300
let presenter_audio = presenter.get_presenter_audio();
302-
let audio_thread = if settings.audio() {
303-
Some(
304-
thread::Builder::new()
305-
.name("audio".to_owned())
306-
.spawn(move || {
307-
set_thread_prio_affinity(ThreadPriority::Default, ThreadAffinity::Core0);
308-
let mut audio_buffer = HeapMemU32::<{ PRESENTER_AUDIO_BUF_SIZE }>::new();
309-
loop {
310-
sound_sampler.consume(audio_buffer.deref_mut());
311-
presenter_audio.play(audio_buffer.deref());
312-
}
313-
})
314-
.unwrap(),
315-
)
316-
} else {
317-
None
318-
};
301+
let audio_thread = thread::Builder::new()
302+
.name("audio".to_owned())
303+
.spawn(move || {
304+
set_thread_prio_affinity(ThreadPriority::Default, ThreadAffinity::Core0);
305+
let mut audio_buffer = HeapMemU32::<{ PRESENTER_AUDIO_BUF_SIZE }>::new();
306+
loop {
307+
sound_sampler.consume(audio_buffer.deref_mut());
308+
presenter_audio.play(audio_buffer.deref());
309+
}
310+
})
311+
.unwrap();
319312

320313
let gpu_renderer = UnsafeCell::new(GpuRenderer::new());
321314
let gpu_renderer_ptr = gpu_renderer.get() as u32;
@@ -350,8 +343,6 @@ pub fn actual_main() {
350343
gpu_renderer.render_loop(&mut presenter, &fps, &last_save_time);
351344
}
352345

353-
if let Some(audio_thread) = audio_thread {
354-
audio_thread.join().unwrap();
355-
}
346+
audio_thread.join().unwrap();
356347
cpu_thread.join().unwrap();
357348
}

src/presenter/linux.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use sdl2::{keyboard, EventPump};
1414
use std::collections::HashMap;
1515
use std::path::PathBuf;
1616
use std::rc::Rc;
17-
use std::slice;
17+
use std::{slice, thread};
1818

1919
#[derive(Clone)]
2020
pub struct PresenterAudio {
@@ -29,9 +29,11 @@ impl PresenterAudio {
2929
}
3030

3131
pub fn play(&self, buffer: &[u32; PRESENTER_AUDIO_BUF_SIZE]) {
32-
self.audio_queue.clear();
3332
let raw = unsafe { slice::from_raw_parts(buffer.as_slice().as_ptr() as *const i16, PRESENTER_AUDIO_BUF_SIZE * 2) };
3433
self.audio_queue.queue_audio(raw).unwrap();
34+
while self.audio_queue.size() != 0 {
35+
thread::yield_now();
36+
}
3537
}
3638
}
3739

src/presenter/vita.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl PresenterAudio {
7676
fn new() -> Self {
7777
unsafe {
7878
PresenterAudio {
79-
audio_port: sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, PRESENTER_AUDIO_BUF_SIZE as _, PRESENTER_AUDIO_SAMPLE_RATE as _, SCE_AUDIO_OUT_MODE_STEREO),
79+
audio_port: sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_BGM, PRESENTER_AUDIO_BUF_SIZE as _, PRESENTER_AUDIO_SAMPLE_RATE as _, SCE_AUDIO_OUT_MODE_STEREO),
8080
}
8181
}
8282
}

0 commit comments

Comments
 (0)