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