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
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use fixed_resample::{audioadapter_buffers::direct::InterleavedSlice, PushStatus, ReadStatus};
fn main() {
let host = cpal::default_host();
let input_device = host.default_input_device().unwrap();
let output_device = host.default_output_device().unwrap();
let output_config: cpal::StreamConfig = output_device.default_output_config().unwrap().into();
// Try selecting an input config that matches the output sample rate to
// avoid resampling.
let mut input_config = None;
for config in input_device.supported_input_configs().unwrap() {
if let Some(config) = config.try_with_sample_rate(output_config.sample_rate) {
input_config = Some(config);
break;
}
}
let input_config: cpal::StreamConfig = input_config
.unwrap_or_else(|| input_device.default_input_config().unwrap())
.into();
let input_channels = input_config.channels as usize;
let output_channels = output_config.channels as usize;
dbg!(&input_config);
dbg!(&output_config);
let (mut prod, mut cons) = fixed_resample::resampling_channel::<f32>(
input_channels, // number of channels
input_config.sample_rate,
output_config.sample_rate,
true, // push_interleave_only
Default::default(), // configuration
);
let input_data_fn = move |data: &[f32], _: &cpal::InputCallbackInfo| {
let status = prod.push_interleaved(data);
match status {
// All samples were successfully pushed to the channel.
PushStatus::Ok => {}
// The output stream is not yet ready to read samples from the channel. No
// samples have been pushed to the channel.
PushStatus::OutputNotReady => {}
// An overflow occured due to the input stream running faster than the output
// stream.
PushStatus::OverflowOccurred {
num_frames_pushed: _,
} => {
eprintln!("output stream fell behind: try increasing channel capacity");
}
// An underflow occured due to the output stream running faster than the
// input stream.
//
// All of the samples were successfully pushed to the channel, however extra
// zero samples were also pushed to the channel to correct for the jitter.
PushStatus::UnderflowCorrected {
num_zero_frames_pushed: _,
} => {
eprintln!("input stream fell behind: try increasing channel latency");
}
}
};
let output_data_fn = move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
let frames = data.len() / output_channels;
let status = cons.read(
&mut InterleavedSlice::new_mut(data, output_channels, frames).unwrap(),
None, // output_range
None, // active_channels_mask
false, // output_is_already_cleared
);
match status {
// The output buffer was fully filled with samples from the channel.
ReadStatus::Ok => {}
// The input stream is not yet ready to push samples to the channel.
// The output buffer was filled with zeros.
ReadStatus::InputNotReady => {}
// An underflow occured due to the output stream running faster than the input
// stream.
ReadStatus::UnderflowOccurred { num_frames_read: _ } => {
eprintln!("input stream fell behind: try increasing channel latency");
}
// An overflow occured due to the input stream running faster than the output
// stream
//
// All of the samples in the output buffer were successfully filled with samples,
// however a number of frames have also been discarded to correct for the jitter.
ReadStatus::OverflowCorrected {
num_frames_discarded: _,
} => {
eprintln!("output stream fell behind: try increasing channel capacity");
}
}
};
let input_stream = input_device
.build_input_stream(&input_config, input_data_fn, err_fn, None)
.unwrap();
let output_stream = output_device
.build_output_stream(&output_config, output_data_fn, err_fn, None)
.unwrap();
// Play the streams.
input_stream.play().unwrap();
output_stream.play().unwrap();
// Run for 10 seconds before closing.
std::thread::sleep(std::time::Duration::from_secs(10));
}
fn err_fn(err: cpal::StreamError) {
eprintln!("an error occurred on stream: {}", err);
}