1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
use std::collections::VecDeque;
use std::fs::File;
use std::io::Read;
use std::net::*;
use std::sync::*;
use std::{env, ffi, iter, thread};
use cpal::traits::{HostTrait, DeviceTrait, StreamTrait};
use synfone::client::*;
use synfone::lang::*;
use synfone::proto::*;
use synfone::synth::*;
use synfone::*;
fn main() -> Result<(), std::io::Error> {
let cmd = env::args_os().nth(1).expect("Please pass a command as the first argument; use `help` as a command for more information.");
let cmds = cmd.into_string().expect("Couldn't parse command");
let new_args: Vec<ffi::OsString> = env::args_os().skip(1).collect();
match &*cmds {
"help" => eprintln!("TODO! Commands are help, client."),
"client" => main_client(new_args)?,
_ => eprintln!("Unknown command; `help` for help."),
}
Ok(())
}
fn main_client(args: Vec<ffi::OsString>) -> Result<(), std::io::Error> {
let host = cpal::default_host();
let device = host.default_output_device().expect("no default host audio device!");
let mut conf_range = device.supported_output_configs().expect("could not query audio device capabilities -- audio device disconnected?");
let conf = conf_range.next().expect("audio device has no supported configs!").with_max_sample_rate().config();
println!("playing at sample rate {}", conf.sample_rate.0);
let env = Environment {
sample_rate: conf.sample_rate.0 as f32,
default_buffer_size: 64,
};
let mut genfile = File::open(
args.iter()
.nth(1)
.expect("Need first argument to be a file with a generator vector"),
)
.expect("Failed to open file");
let mut genstr = String::new();
genfile.read_to_string(&mut genstr)?;
let gens = Parser::new(Tokenizer::new(genstr.chars()), env.clone())
.expect("Failed to get first token")
.parse_gen_vec()
.expect("Failed to compile generators");
let sock = UdpSocket::bind("0.0.0.0:13676").expect("Failed to bind socket");
eprintln!("Parsed {} generator definitions", gens.len());
let client = Arc::new(Mutex::new(
Client::new(
sock.try_clone().expect("Failed to clone socket"),
gens,
env.clone(),
)
.expect("Failed to create client"),
));
let last_buffer = Arc::new(Mutex::new(<VecDeque<Sample>>::with_capacity(
env.default_buffer_size * 9,
)));
let last_buffer_lim = env.default_buffer_size * 8;
last_buffer
.lock()
.expect("Failed to init shared buffer")
.append(&mut iter::repeat(0.0f32).take(last_buffer_lim).collect());
let stream;
{
let client = client.clone();
let last_buffer = last_buffer.clone();
let mut ring: VecDeque<Sample> = VecDeque::new();
ring.reserve_exact(2 * env.default_buffer_size);
stream = device.build_output_stream(
&conf,
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
let frames = data.len();
while frames > ring.len() {
let mut cli = client.lock().unwrap();
cli.next_frames();
{
let mut buf = last_buffer
.lock()
.expect("Failed to acquire shared buffer in audio callback");
buf.append(&mut cli.buffer().samples.iter().map(|&x| x).collect());
let len = buf.len();
if len > last_buffer_lim {
buf.drain(..(len - last_buffer_lim));
}
}
ring.append(&mut cli.buffer().iter().map(|&x| x).collect());
}
let mut drain = ring.drain(..frames);
let mut min = 1.0;
let mut max = 0.0;
for i in 0..frames {
let frame = drain.next().unwrap();
min = f32::min(min, frame);
max = f32::max(min, frame);
data[i] = frame;
}
println!("played {} frames, min {}, max {}", frames, min, max);
},
move |err| {
println!("audio stream error: {}", err);
}
).expect("could not create audio stream!");
}
eprintln!("Starting.");
stream.play().expect("Failed to start stream");
eprintln!("Audio stream started.");
let net_thread = {
let client = client.clone();
let net_thread = thread::spawn(move || {
let mut buffer: [u8; Command::SIZE] = [0u8; Command::SIZE];
loop {
let (bytes, sender) = sock.recv_from(&mut buffer).unwrap();
if bytes < Command::SIZE {
continue;
}
let cmd = Command::from(&buffer);
{
let mut cli = client.lock().unwrap();
if !cli.handle_command(cmd, sender) {
break;
}
}
}
});
net_thread
};
eprintln!("Network thread started.");
net_thread.join().expect("Network thread panicked");
eprintln!("Exiting.");
Ok(())
}
|