Merge pull request #127 from gwilymk/make-it-easier-to-configure-sound-frequencies

Make it easier to configure sound frequencies
This commit is contained in:
Gwilym Kuiper 2021-10-29 16:23:37 +01:00 committed by GitHub
commit 225689b13d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 48 additions and 12 deletions

View file

@ -17,6 +17,9 @@ debug = true
[lib] [lib]
proc-macro = true proc-macro = true
[features]
freq18157 = []
[dependencies] [dependencies]
hound = "3.4.0" hound = "3.4.0"
syn = "1.0.73" syn = "1.0.73"

View file

@ -12,6 +12,11 @@ use std::{
}; };
use syn::parse_macro_input; use syn::parse_macro_input;
#[cfg(not(feature = "freq18157"))]
const FREQUENCY: u32 = 10512;
#[cfg(feature = "freq18157")]
const FREQUENCY: u32 = 18157;
#[proc_macro] #[proc_macro]
pub fn include_wav(input: TokenStream) -> TokenStream { pub fn include_wav(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as syn::LitStr); let input = parse_macro_input!(input as syn::LitStr);
@ -43,8 +48,9 @@ pub fn include_wav(input: TokenStream) -> TokenStream {
assert_eq!( assert_eq!(
wav_reader.spec().sample_rate, wav_reader.spec().sample_rate,
10512, FREQUENCY,
"agb currently only supports sample rate of 10512Hz" "agb currently only supports sample rate of {}Hz",
FREQUENCY
); );
let samples = samples_from_reader(wav_reader); let samples = samples_from_reader(wav_reader);

View file

@ -17,6 +17,7 @@ debug = true
[features] [features]
default = ["alloc"] default = ["alloc"]
alloc = [] alloc = []
freq18157 = ["agb_sound_converter/freq18157"]
[dependencies] [dependencies]
bitflags = "1.2" bitflags = "1.2"

View file

@ -64,5 +64,5 @@ b .Initialise_mb
b 1b b 1b
.pool .pool
.include "src/sound/mixer/mixer.s"
.include "interrupt_handler.s" .include "interrupt_handler.s"
.include "src/sound/mixer/mixer.s"

View file

@ -1,4 +1,8 @@
.equ SOUND_BUFFER_SIZE, 176 .section .iwram
.global agb_rs__buffer_size
.balign 4
agb_rs__buffer_size:
.word
agb_arm_func agb_rs__mixer_add agb_arm_func agb_rs__mixer_add
@ Arguments @ Arguments
@ -19,8 +23,8 @@ agb_arm_func agb_rs__mixer_add
modifications_fallback: modifications_fallback:
orr r7, r7, r3, lsl #16 @ r7 now is the left channel followed by the right channel modifications. orr r7, r7, r3, lsl #16 @ r7 now is the left channel followed by the right channel modifications.
mov r5, #0 @ current index we're reading from mov r5, #0 @ current index we're reading from
mov r8, #SOUND_BUFFER_SIZE @ the number of steps left ldr r8, agb_rs__buffer_size @ the number of steps left
1: 1:
@ -62,8 +66,8 @@ same_modification:
lsrs r7, r7, #1 lsrs r7, r7, #1
bne 1b bne 1b
mov r5, #0 @ current index we're reading from mov r5, #0 @ current index we're reading from
mov r8, #SOUND_BUFFER_SIZE @ the number of steps left ldr r8, agb_rs__buffer_size @ the number of steps left
.macro mixer_add_loop_simple .macro mixer_add_loop_simple
add r4, r0, r5, asr #8 @ calculate the address of the next read from the sound buffer add r4, r0, r5, asr #8 @ calculate the address of the next read from the sound buffer
@ -132,7 +136,7 @@ agb_arm_func agb_rs__mixer_add_stereo
str r4, [r1], #4 @ store the new value, and increment the pointer str r4, [r1], #4 @ store the new value, and increment the pointer
.endm .endm
mov r8, #SOUND_BUFFER_SIZE ldr r8, agb_rs__buffer_size
1: 1:
mixer_add_loop_simple_stereo mixer_add_loop_simple_stereo
mixer_add_loop_simple_stereo mixer_add_loop_simple_stereo
@ -159,8 +163,10 @@ agb_arm_func agb_rs__mixer_collapse
@ Arguments: @ Arguments:
@ r0 = target buffer (i8) @ r0 = target buffer (i8)
@ r1 = input buffer (i16) of fixnums with 4 bits of precision (read in sets of i16 in an i32) @ r1 = input buffer (i16) of fixnums with 4 bits of precision (read in sets of i16 in an i32)
push {r4}
mov r2, #SOUND_BUFFER_SIZE @ loop counter ldr r2, agb_rs__buffer_size @ loop counter
mov r4, r2
1: 1:
@ r12 = *r1; r1++ @ r12 = *r1; r1++
@ -173,11 +179,12 @@ agb_arm_func agb_rs__mixer_collapse
clamp_s8 r12 @ clamp the audio to 8 bit values clamp_s8 r12 @ clamp the audio to 8 bit values
clamp_s8 r3 clamp_s8 r3
strb r3, [r0, #SOUND_BUFFER_SIZE] @ *(r0 + SOUND_BUFFER_SIZE) = r3 strb r3, [r0, r4] @ *(r0 + r4 = SOUND_BUFFER_SIZE) = r3
strb r12, [r0], #1 @ *r0 = r12; r0++ strb r12, [r0], #1 @ *r0 = r12; r0++
subs r2, r2, #1 @ r2 -= 1 subs r2, r2, #1 @ r2 -= 1
bne 1b @ loop if not 0 bne 1b @ loop if not 0
pop {r4}
bx lr bx lr
agb_arm_end agb_rs__mixer_collapse agb_arm_end agb_rs__mixer_collapse

View file

@ -91,9 +91,26 @@ impl Mixer {
// I've picked one frequency that works nicely. But there are others that work nicely // I've picked one frequency that works nicely. But there are others that work nicely
// which we may want to consider in the future: http://deku.gbadev.org/program/sound1.html // which we may want to consider in the future: http://deku.gbadev.org/program/sound1.html
#[cfg(not(feature = "freq18157"))]
const SOUND_FREQUENCY: i32 = 10512; const SOUND_FREQUENCY: i32 = 10512;
#[cfg(not(feature = "freq18157"))]
const SOUND_BUFFER_SIZE: usize = 176; const SOUND_BUFFER_SIZE: usize = 176;
#[cfg(feature = "freq18157")]
const SOUND_FREQUENCY: i32 = 18157;
#[cfg(feature = "freq18157")]
const SOUND_BUFFER_SIZE: usize = 304;
fn set_asm_buffer_size() {
extern "C" {
static mut agb_rs__buffer_size: usize;
}
unsafe {
agb_rs__buffer_size = SOUND_BUFFER_SIZE;
}
}
#[repr(C, align(4))] #[repr(C, align(4))]
struct SoundBuffer([i8; SOUND_BUFFER_SIZE * 2]); struct SoundBuffer([i8; SOUND_BUFFER_SIZE * 2]);
@ -106,6 +123,8 @@ struct MixerBuffer {
impl MixerBuffer { impl MixerBuffer {
fn new() -> Self { fn new() -> Self {
set_asm_buffer_size();
MixerBuffer { MixerBuffer {
buffer1: SoundBuffer([0; SOUND_BUFFER_SIZE * 2]), buffer1: SoundBuffer([0; SOUND_BUFFER_SIZE * 2]),
buffer2: SoundBuffer([0; SOUND_BUFFER_SIZE * 2]), buffer2: SoundBuffer([0; SOUND_BUFFER_SIZE * 2]),