mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 00:01:34 +11:00
Try composing my own theme (with some bug fixes)
This commit is contained in:
parent
70e763cc11
commit
4b145d3194
BIN
examples/the-dungeon-puzzlers-lament/sfx/gwilym-theme2.xm
Normal file
BIN
examples/the-dungeon-puzzlers-lament/sfx/gwilym-theme2.xm
Normal file
Binary file not shown.
|
@ -4,7 +4,7 @@ use agb::{
|
|||
};
|
||||
use agb_tracker::{include_xm, Track, Tracker};
|
||||
|
||||
const MUSIC: Track = include_xm!("sfx/theme.xm");
|
||||
const MUSIC: Track = include_xm!("sfx/gwilym-theme2.xm");
|
||||
|
||||
const BAD_SELECTION: &[u8] = include_wav!("sfx/bad.wav");
|
||||
const SELECT: &[u8] = include_wav!("sfx/select.wav");
|
||||
|
|
|
@ -12,6 +12,7 @@ pub struct Track<'a> {
|
|||
pub num_channels: usize,
|
||||
pub frames_per_tick: Num<u32, 8>,
|
||||
pub ticks_per_step: u32,
|
||||
pub repeat: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -50,9 +51,9 @@ pub enum PatternEffect {
|
|||
VolumeSlide(Num<i16, 8>),
|
||||
FineVolumeSlide(Num<i16, 8>),
|
||||
NoteCut(u32),
|
||||
Portamento(Num<u16, 8>),
|
||||
Portamento(Num<u16, 12>),
|
||||
/// Slide each tick the first amount to at most the second amount
|
||||
TonePortamento(Num<u16, 8>, Num<u16, 8>),
|
||||
TonePortamento(Num<u16, 12>, Num<u16, 12>),
|
||||
}
|
||||
|
||||
#[cfg(feature = "quote")]
|
||||
|
@ -68,6 +69,7 @@ impl<'a> quote::ToTokens for Track<'a> {
|
|||
num_channels,
|
||||
patterns_to_play,
|
||||
ticks_per_step,
|
||||
repeat,
|
||||
} = self;
|
||||
|
||||
let frames_per_tick = frames_per_tick.to_raw();
|
||||
|
@ -88,6 +90,7 @@ impl<'a> quote::ToTokens for Track<'a> {
|
|||
frames_per_tick: agb_tracker::__private::Num::from_raw(#frames_per_tick),
|
||||
num_channels: #num_channels,
|
||||
ticks_per_step: #ticks_per_step,
|
||||
repeat: #repeat,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -101,7 +101,7 @@ pub struct Tracker {
|
|||
|
||||
struct TrackerChannel {
|
||||
channel_id: Option<ChannelId>,
|
||||
base_speed: Num<u32, 8>,
|
||||
base_speed: Num<u32, 16>,
|
||||
volume: Num<i32, 8>,
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ impl Tracker {
|
|||
self.current_row = 0;
|
||||
|
||||
if self.current_pattern >= self.track.patterns_to_play.len() {
|
||||
self.current_pattern = 0;
|
||||
self.current_pattern = self.track.repeat;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,10 +229,10 @@ impl TrackerChannel {
|
|||
.and_then(|channel_id| mixer.channel(channel_id))
|
||||
{
|
||||
if speed != 0.into() {
|
||||
self.base_speed = speed;
|
||||
self.base_speed = speed.change_base();
|
||||
}
|
||||
|
||||
channel.playback(self.base_speed);
|
||||
channel.playback(self.base_speed.change_base());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,11 +245,11 @@ impl TrackerChannel {
|
|||
match effect {
|
||||
PatternEffect::None => {}
|
||||
PatternEffect::Stop => {
|
||||
channel.stop();
|
||||
channel.volume(0);
|
||||
}
|
||||
PatternEffect::Arpeggio(first, second) => {
|
||||
match tick % 3 {
|
||||
0 => channel.playback(self.base_speed),
|
||||
0 => channel.playback(self.base_speed.change_base()),
|
||||
1 => channel.playback(first.change_base()),
|
||||
2 => channel.playback(second.change_base()),
|
||||
_ => unreachable!(),
|
||||
|
@ -276,17 +276,18 @@ impl TrackerChannel {
|
|||
}
|
||||
PatternEffect::NoteCut(wait) => {
|
||||
if tick == *wait {
|
||||
channel.stop();
|
||||
self.volume = 0.into();
|
||||
channel.volume(0);
|
||||
}
|
||||
}
|
||||
PatternEffect::Portamento(amount) => {
|
||||
if tick != 0 {
|
||||
self.base_speed *= amount.change_base();
|
||||
channel.playback(self.base_speed);
|
||||
channel.playback(self.base_speed.change_base());
|
||||
}
|
||||
}
|
||||
PatternEffect::TonePortamento(amount, target) => {
|
||||
channel.volume(self.volume.try_change_base().unwrap());
|
||||
|
||||
if *amount < 1.into() {
|
||||
self.base_speed =
|
||||
(self.base_speed * amount.change_base()).max(target.change_base());
|
||||
|
@ -294,6 +295,8 @@ impl TrackerChannel {
|
|||
self.base_speed =
|
||||
(self.base_speed * amount.change_base()).min(target.change_base());
|
||||
}
|
||||
|
||||
channel.playback(self.base_speed.change_base());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ pub fn parse_module(module: &Module) -> TokenStream {
|
|||
for pattern in &module.pattern {
|
||||
let start_pos = pattern_data.len();
|
||||
let mut effect_parameters: [u8; 255] = [0; u8::MAX as usize];
|
||||
let mut tone_portamento_directions = vec![0.0; module.get_num_channels()];
|
||||
let mut tone_portamento_directions = vec![0; module.get_num_channels()];
|
||||
let mut note_and_sample = vec![None; module.get_num_channels()];
|
||||
|
||||
for row in pattern.iter() {
|
||||
|
@ -139,8 +139,8 @@ pub fn parse_module(module: &Module) -> TokenStream {
|
|||
let previous_note_and_sample = note_and_sample[channel_number];
|
||||
let maybe_note_and_sample = if matches!(slot.note, Note::KeyOff) {
|
||||
effect1 = PatternEffect::Stop;
|
||||
note_and_sample[channel_number] = None;
|
||||
&None
|
||||
// note_and_sample[channel_number] = None;
|
||||
¬e_and_sample[channel_number]
|
||||
} else if !matches!(slot.note, Note::None) {
|
||||
if sample != 0 {
|
||||
note_and_sample[channel_number] = Some((slot.note, &samples[sample - 1]));
|
||||
|
@ -221,13 +221,15 @@ pub fn parse_module(module: &Module) -> TokenStream {
|
|||
}
|
||||
}
|
||||
0x1 => {
|
||||
let c4_speed = note_to_speed(Note::C4, 0.0, 0, module.frequency_type);
|
||||
let speed = note_to_speed(
|
||||
let c4_speed: Num<u32, 12> =
|
||||
note_to_speed(Note::C4, 0.0, 0, module.frequency_type).change_base();
|
||||
let speed: Num<u32, 12> = note_to_speed(
|
||||
Note::C4,
|
||||
effect_parameter as f64,
|
||||
effect_parameter as f64 / 16.0,
|
||||
0,
|
||||
module.frequency_type,
|
||||
);
|
||||
)
|
||||
.change_base();
|
||||
|
||||
let portamento_amount = speed / c4_speed;
|
||||
|
||||
|
@ -237,12 +239,12 @@ pub fn parse_module(module: &Module) -> TokenStream {
|
|||
let c4_speed = note_to_speed(Note::C4, 0.0, 0, module.frequency_type);
|
||||
let speed = note_to_speed(
|
||||
Note::C4,
|
||||
-(effect_parameter as f64),
|
||||
effect_parameter as f64,
|
||||
0,
|
||||
module.frequency_type,
|
||||
);
|
||||
|
||||
let portamento_amount = speed / c4_speed;
|
||||
let portamento_amount = c4_speed / speed;
|
||||
|
||||
PatternEffect::Portamento(portamento_amount.try_change_base().unwrap())
|
||||
}
|
||||
|
@ -258,11 +260,11 @@ pub fn parse_module(module: &Module) -> TokenStream {
|
|||
);
|
||||
|
||||
let direction = match (prev_note as usize).cmp(&(*note as usize)) {
|
||||
std::cmp::Ordering::Less => 1.0,
|
||||
std::cmp::Ordering::Less => 1,
|
||||
std::cmp::Ordering::Equal => {
|
||||
tone_portamento_directions[channel_number]
|
||||
}
|
||||
std::cmp::Ordering::Greater => -1.0,
|
||||
std::cmp::Ordering::Greater => -1,
|
||||
};
|
||||
|
||||
tone_portamento_directions[channel_number] = direction;
|
||||
|
@ -270,12 +272,23 @@ pub fn parse_module(module: &Module) -> TokenStream {
|
|||
let c4_speed = note_to_speed(Note::C4, 0.0, 0, module.frequency_type);
|
||||
let speed = note_to_speed(
|
||||
Note::C4,
|
||||
effect_parameter as f64 * direction,
|
||||
effect_parameter as f64 * 8.0,
|
||||
0,
|
||||
module.frequency_type,
|
||||
);
|
||||
|
||||
let portamento_amount = speed / c4_speed;
|
||||
let portamento_amount = if direction > 0 {
|
||||
speed / c4_speed
|
||||
} else {
|
||||
c4_speed / speed
|
||||
};
|
||||
|
||||
dbg!(
|
||||
speed,
|
||||
c4_speed,
|
||||
portamento_amount,
|
||||
effect_parameter as f64 * 0.752941176470588
|
||||
);
|
||||
|
||||
PatternEffect::TonePortamento(
|
||||
portamento_amount.try_change_base().unwrap(),
|
||||
|
@ -320,7 +333,10 @@ pub fn parse_module(module: &Module) -> TokenStream {
|
|||
_ => PatternEffect::None,
|
||||
};
|
||||
|
||||
if sample == 0 {
|
||||
if sample == 0
|
||||
|| matches!(effect2, PatternEffect::TonePortamento(_, _))
|
||||
|| matches!(effect1, PatternEffect::Stop)
|
||||
{
|
||||
pattern_data.push(agb_tracker_interop::PatternSlot {
|
||||
speed: 0.into(),
|
||||
sample: 0,
|
||||
|
@ -382,6 +398,7 @@ pub fn parse_module(module: &Module) -> TokenStream {
|
|||
|
||||
frames_per_tick,
|
||||
ticks_per_step: ticks_per_step.into(),
|
||||
repeat: module.restart_position as usize,
|
||||
};
|
||||
|
||||
quote!(#interop)
|
||||
|
@ -392,7 +409,7 @@ fn note_to_speed(
|
|||
fine_tune: f64,
|
||||
relative_note: i8,
|
||||
frequency_type: FrequencyType,
|
||||
) -> Num<u32, 8> {
|
||||
) -> Num<u32, 12> {
|
||||
let frequency = match frequency_type {
|
||||
FrequencyType::LinearFrequencies => {
|
||||
note_to_frequency_linear(note, fine_tune, relative_note)
|
||||
|
@ -403,7 +420,7 @@ fn note_to_speed(
|
|||
let gba_audio_frequency = 18157f64;
|
||||
|
||||
let speed: f64 = frequency / gba_audio_frequency;
|
||||
Num::from_raw((speed * (1 << 8) as f64) as u32)
|
||||
Num::from_raw((speed * (1 << 12) as f64) as u32)
|
||||
}
|
||||
|
||||
fn note_to_frequency_linear(note: Note, fine_tune: f64, relative_note: i8) -> f64 {
|
||||
|
|
Loading…
Reference in a new issue