1extern crate easyjack as jack;
3
4extern crate nix;
7
8use nix::sys::signal;
9use std::f32::consts;
10use std::f32;
11use std::sync::atomic;
12use std::sync::mpsc::{SyncSender, Receiver};
13use std::sync::mpsc;
14use std::thread;
15use std::time::Duration;
16
17static RUNNING: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;
18
19type IPort = jack::InputPortHandle<jack::MidiEvent>;
20type OPort = jack::OutputPortHandle<jack::DefaultAudioSample>;
21
22struct MetadataHandler {
24 outgoing: SyncSender<[jack::DefaultAudioSample; 128]>,
25}
26
27impl MetadataHandler {
28 pub fn new(outgoing: SyncSender<[jack::DefaultAudioSample; 128]>) -> Self {
29 MetadataHandler { outgoing: outgoing }
30 }
31}
32
33impl jack::MetadataHandler for MetadataHandler {
34 fn sample_rate_changed(&mut self, srate: jack::NumFrames) -> i32 {
35 println!("updating sample rate: {}", srate);
36
37 let f = AudioHandler::calc_note_freqs(srate);
38 match self.outgoing.send(f) {
39 Ok(_) => 0,
40 Err(_) => 0
41 }
42 }
43
44 fn callbacks_of_interest(&self) -> Vec<jack::MetadataHandlers> {
45 vec![jack::MetadataHandlers::SampleRate]
46 }
47}
48
49struct AudioHandler {
51 input: jack::InputPortHandle<jack::MidiEvent>,
52 output: jack::OutputPortHandle<jack::DefaultAudioSample>,
53
54 ramp: jack::DefaultAudioSample,
56 note_on: jack::DefaultAudioSample,
57 note: u8,
58 note_freqs: [jack::DefaultAudioSample; 128],
59
60 incoming: Receiver<[jack::DefaultAudioSample; 128]>,
61}
62
63impl AudioHandler {
64 pub fn new(input: IPort, output: OPort, incoming: Receiver<[jack::DefaultAudioSample; 128]>)
65 -> AudioHandler
66 {
67 let freqs = [0.0; 128];
68 AudioHandler {
69 input: input,
70 output: output,
71 ramp: 0.0,
72 note_on: 0.0,
73 note: 0,
74 note_freqs: freqs,
75 incoming: incoming,
76 }
77 }
78
79 pub fn calc_note_freqs(srate: jack::NumFrames) -> [jack::DefaultAudioSample; 128] {
80 println!("recalculating note frequencies");
81 let mut freqs = [0.0; 128];
82 print!("new_freqs: ");
83 for i in 0..128 {
84 let a = 2.0 * (440.0 / 32.0);
85 let b = 2.0_f32.powf( (i as f32 - 9.0) / 12.0 );
86 freqs[i] = a * b / srate as f32;
87
88 print!("{},", freqs[i]);
89 }
90 println!("");
91
92
93 freqs
94 }
95}
96
97impl jack::ProcessHandler for AudioHandler {
98 fn process(&mut self, ctx: &jack::CallbackContext, nframes: jack::NumFrames) -> i32 {
99 let output_buffer = self.output.get_write_buffer(nframes, &ctx);
100 let input_buffer = self.input.get_read_buffer(nframes, &ctx);
101
102 let mut event_index = 0;
103 let event_count = input_buffer.len();
104
105 for i in 0..(nframes as usize) {
106 if event_index < event_count {
107 let event = input_buffer.get(event_index);
108
109 println!("evi={} evt={}, i={}", event_index, event.get_jack_time(), i);
110 if event.get_jack_time() == i as jack::NumFrames {
111 let buf = event.raw_midi_bytes();
112
113 if buf[0] & 0x90 == 0x90 {
114 println!("note on!");
115 self.note = buf[1];
116 self.note_on = 1.0;
117 } else if buf[0] & 0x90 == 0x80 {
118 println!("note off!");
119 self.note = buf[1];
120 self.note_on = 0.0;
121 }
122 event_index += 1;
123 if event_index < event_count {
124 event_index += 1;
125 }
126 }
127 }
128
129 self.ramp += self.note_freqs[self.note as usize];
130 self.ramp = if self.ramp > 1.0 { self.ramp - 2.0 } else { self.ramp };
131
132 let s = (2.0 * (consts::PI) * self.ramp).sin();
133 output_buffer[i] = self.note_on*s;
134 }
136
137 match self.incoming.try_recv() {
138 Ok(freqs) => self.note_freqs = freqs,
139 Err(_) => (),
140 };
141
142 0
143 }
144}
145
146extern "C" fn handle_sigint(_: i32) {
147 RUNNING.store(false, atomic::Ordering::SeqCst);
148}
149
150fn main() {
151 let action = signal::SigAction::new(
153 signal::SigHandler::Handler(handle_sigint),
154 signal::SaFlags::empty(),
155 signal::SigSet::empty());
156
157 unsafe { signal::sigaction(signal::Signal::SIGINT, &action) }.unwrap();
158
159 RUNNING.store(true, atomic::Ordering::SeqCst);
161
162
163 let mut c = jack::Client::open("midi_sine", jack::options::NO_START_SERVER).unwrap().0;
164 let i = c.register_input_midi_port("midi_in").unwrap();
165 let o = c.register_output_audio_port("audio_out").unwrap();
166
167 let (tx, rx) = mpsc::sync_channel(1);
168
169 let handler = AudioHandler::new(i, o, rx);
170 c.set_process_handler(handler).unwrap();
171
172 let handler = MetadataHandler::new(tx);
173 c.set_metadata_handler(handler).unwrap();
174
175 c.activate().unwrap();
176
177 while RUNNING.load(atomic::Ordering::SeqCst) {
178 thread::sleep(Duration::from_millis(1000));
179 }
180 println!("tearing down");
181 c.close().unwrap();
182}