Initial commit, very broken

This commit is contained in:
2023-01-09 19:04:04 +01:00
commit 5f82b549dc
8 changed files with 1575 additions and 0 deletions

16
src/main.rs Normal file
View File

@@ -0,0 +1,16 @@
mod note;
mod tracker;
mod sampler;
use std::fs::File;
use std::io::BufReader;
use std::time::Duration;
use rodio::{Decoder, OutputStream, Sink, Source};
use rodio::source::SineWave;
use crate::tracker::Tracker;
fn main() {
let mut tracker = Tracker::new(4, 64);
tracker.load_file("./3266CHIP.MOD");
tracker.play();
}

22
src/note.rs Normal file
View File

@@ -0,0 +1,22 @@
use std::fmt::{Display, Formatter};
#[derive(Debug, Clone)]
pub struct Note {
pub frequency: f32,
pub sample: u8,
pub effect: u16,
}
impl Display for Note {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "freq {}, sample: {}, effect: {}", self.frequency, self.sample, self.effect)
}
}
#[cfg(test)]
mod test {
#[test]
pub fn note_to_frequency() {
}
}

57
src/sampler.rs Normal file
View File

@@ -0,0 +1,57 @@
use std::time::Duration;
use modfile::ptmf::SampleInfo;
use rodio::Source;
#[derive(Clone, Debug)]
pub struct Sample {
num_sample: usize,
_sample_rate: u32,
sample: SampleInfo,
}
impl Sample {
pub fn new(sample_rate: u32, sample: SampleInfo) -> Self {
Self {
num_sample: 0,
_sample_rate: sample_rate,
sample,
}
}
pub fn set_sample_rate(&mut self, sample_rate: u32) {
self._sample_rate = sample_rate;
self.num_sample = 0;
}
}
impl Iterator for Sample {
type Item = f32;
fn next(&mut self) -> Option<Self::Item> {
if self.sample.data.len() == 0 {
return Some(0.0);
}
if self.num_sample >= self.sample.data.len() {
self.num_sample = 0;
}
let value = self.sample.data[self.num_sample];
self.num_sample = self.num_sample.wrapping_add(1);
Some((value as i8 as f32)/(i8::MAX as f32))
}
}
impl Source for Sample {
fn current_frame_len(&self) -> Option<usize> {
Some(self.sample.data.len()-self.num_sample)
}
fn channels(&self) -> u16 { 1 }
fn sample_rate(&self) -> u32 {
self._sample_rate
}
fn total_duration(&self) -> Option<Duration> {
Some(Duration::new(0, (self.sample.data.len() * 1_000_000_000 / self._sample_rate as usize) as u32))
}
}

131
src/tracker.rs Normal file
View File

@@ -0,0 +1,131 @@
use std::fs::File;
use std::io::BufReader;
use std::time::Duration;
use modfile::ptmf;
use rodio::{OutputStream, OutputStreamHandle, Sink, Source};
use rodio::source::SineWave;
use crate::note::Note;
use crate::sampler::Sample;
pub struct Tracker {
stream: OutputStream,
stream_handle: OutputStreamHandle,
sinks: Vec<Sink>,
patterns: Vec<Vec<Vec<Option<Note>>>>,
positions: Vec<u8>,
samples: Vec<Sample>,
}
impl Tracker {
pub fn new(tracks: u8, lines: u8) -> Self {
let (stream, stream_handle) = OutputStream::try_default().unwrap();
let mut _sinks = vec![];
let mut _tracks = vec![];
for _ in 0..tracks {
_sinks.push(Sink::try_new(&stream_handle).unwrap());
_tracks.push(vec![None; lines as usize])
}
Self {
stream, stream_handle,
sinks: _sinks, patterns: vec![_tracks.clone()],
positions: vec![],
samples: vec![]
}
}
pub fn play(&mut self) {
for sink in &self.sinks {
sink.pause();
}
let lines = self.patterns[0][0].len();
println!("Playing {} lines", lines);
for &position in &self.positions {
let pattern = &self.patterns[position as usize];
for line in 0..lines {
for (track, notes) in pattern.iter().enumerate() {
let note = notes[line].as_ref();
if note.is_some() {
//println!("Playing note: {}", note.as_ref().unwrap());
let note = note.unwrap();
let frequency = note.frequency;
let sample = note.sample;
self.samples[sample as usize].set_sample_rate(frequency as u32);
self.sinks[track].append(
self.samples[sample as usize].clone()
.take_duration(Duration::from_secs_f64(60.0/375.0))
.amplify(0.20)
)
} else {
//println!("Playing note: ---");
self.sinks[track].append(
SineWave::new(0.0)
.take_duration(Duration::from_secs_f64(60.0/375.0))
.amplify(0.20)
)
}
}
}
}
for sink in &self.sinks {
sink.play();
}
for sink in &self.sinks {
sink.sleep_until_end();
}
}
pub fn load_file(&mut self, file: &str) {
let mut reader = BufReader::new(File::open(file).unwrap());
let mut module = ptmf::read_mod(&mut reader, false).unwrap();
println!("Loading: {}", module.name);
println!("\tLength: {:?}", module.length);
//println!("\tPatterns: {:?}", module.patterns);
println!("\tPositions: {:?}", module.positions);
println!("\tSamples: {:?}", module.sample_info.len());
//println!("\tSamples: {:?}", module.sample_info);
for i in 0..module.length {
self.positions.push(module.positions.data[i as usize]);
}
for sample in module.sample_info {
self.samples.push(Sample::new(44100, sample.clone()));
}
let mut prev_freqs = vec![1.0; module.length as usize];
for _ in 0..(module.patterns.len()-1) {
self.patterns.push(self.patterns[0].clone());
}
for (patern_index, pattern) in module.patterns.iter().enumerate() {
for (line, row) in pattern.rows.iter().enumerate() {
for (track, channel) in row.channels.iter().enumerate() {
let frequency = if channel.period == 0 {
prev_freqs[track]
} else {
7093789.2/(2.0*channel.period as f32)
};
prev_freqs[track] = frequency;
println!("{patern_index}, {track}, {line}");
self.patterns[patern_index][track][line] = Some(Note {
frequency,
sample: channel.sample_number,
effect: channel.effect
});
}
}
}
}
}