old school music tracker audio backend
at main 83 lines 2.6 kB view raw
1use std::{ 2 num::{NonZero, NonZeroU16}, 3 time::Duration, 4}; 5 6use cpal::traits::{DeviceTrait, HostTrait}; 7use torque_tracker_engine::{ 8 file::impulse_format::sample::VibratoWave, 9 manager::{AudioManager, OutputConfig, ToWorkerMsg}, 10 project::{ 11 event_command::NoteCommand, 12 note_event::{Note, NoteEvent, VolumeEffect}, 13 song::{Song, SongOperation}, 14 }, 15 sample::{Sample, SampleMetaData}, 16}; 17 18fn main() { 19 let mut manager = AudioManager::new(Song::default()); 20 let mut reader = hound::WavReader::open("test-files/770_Hz_Tone.wav").unwrap(); 21 let spec = reader.spec(); 22 println!("sample specs: {spec:?}"); 23 assert!(spec.channels == 1); 24 let sample_data = reader 25 .samples::<i16>() 26 .map(|result| <f32 as dasp::Sample>::from_sample(result.unwrap())); 27 let sample = Sample::new_mono(sample_data); 28 let meta = SampleMetaData { 29 sample_rate: NonZero::new(spec.sample_rate).unwrap(), 30 default_volume: 150, 31 global_volume: 20, 32 default_pan: None, 33 vibrato_speed: 0, 34 vibrato_depth: 0, 35 vibrato_rate: 0, 36 vibrato_waveform: VibratoWave::default(), 37 base_note: Note::new(64).unwrap(), 38 }; 39 40 manager 41 .try_edit_song() 42 .unwrap() 43 .apply_operation(SongOperation::SetSample(1, meta, sample)) 44 .unwrap(); 45 46 let host = cpal::default_host(); 47 let default_device = host.default_output_device().unwrap(); 48 let default_config = default_device.default_output_config().unwrap(); 49 println!("default config {:?}", default_config); 50 println!("device: {:?}", default_device.name()); 51 let config = OutputConfig { 52 buffer_size: 2048, 53 channel_count: NonZeroU16::new(2).unwrap(), 54 sample_rate: NonZero::new(default_config.sample_rate().0).unwrap(), 55 }; 56 57 let mut audio_callback = manager.get_callback::<f32>(config); 58 let stream = default_device 59 .build_output_stream( 60 &default_config.config(), 61 move |data, _| audio_callback(data), 62 |e| eprintln!("{e:?}"), 63 None, 64 ) 65 .unwrap(); 66 67 let note_event = NoteEvent { 68 note: Note::new(70).unwrap(), 69 sample_instr: 1, 70 vol: VolumeEffect::None, 71 command: NoteCommand::None, 72 }; 73 manager 74 .try_msg_worker(ToWorkerMsg::PlayEvent(note_event)) 75 .unwrap(); 76 std::thread::sleep(Duration::from_secs(1)); 77 manager 78 .try_msg_worker(ToWorkerMsg::PlayEvent(note_event)) 79 .unwrap(); 80 std::thread::sleep(Duration::from_secs(3)); 81 drop(stream); 82 manager.stream_closed(); 83}