1mod audio;
2pub mod audio_codec;
3#[cfg(target_os = "freebsd")]
4pub mod audio_devices {
5 pub use crate::hw::freebsd::{AudioDeviceDescriptor, discover_freebsd_audio_devices};
6}
7pub mod client;
8pub mod connectable;
9mod engine;
10pub use engine::Engine;
11pub mod executor;
12pub mod history;
13mod hw;
14pub mod kind;
15pub mod loudness;
16pub use loudness::LoudnessValues;
17pub mod message;
18pub mod meter;
19pub mod midi;
20pub mod modulator;
21mod osc;
22#[cfg(unix)]
23mod pitch_shift;
24mod plan_builder;
25pub mod plugins;
26pub mod render_plan;
27mod routing;
28pub mod simd;
29pub mod state;
30mod track;
31pub mod triple_buffer;
32pub mod workers;
33pub use workers::worker;
34
35pub use plugins::clap_proc;
36#[cfg(unix)]
37pub use plugins::lv2_proc;
38pub use plugins::vst3_proc;
39
40pub mod clap {
41 pub use crate::plugins::types::is_supported_clap_binary;
42 pub use crate::plugins::types::{
43 ClapMidiOutputEvent, ClapParameterInfo, ClapPluginInfo, ClapPluginState,
44 };
45}
46pub mod vst3 {
47 pub use crate::plugins::types::{Vst3PluginInfo, Vst3PluginState};
48 pub mod interfaces {
49 pub use crate::plugins::types::Vst3GuiInfo;
50 }
51 pub mod port {
52 pub use crate::plugins::types::ParameterInfo;
53 }
54 pub mod state {
55 pub use crate::plugins::types::Vst3PluginState;
56 }
57}
58#[cfg(unix)]
59pub mod lv2 {
60 pub use crate::plugins::types::Lv2PluginInfo;
61}
62
63use tokio::sync::mpsc::{Sender, channel};
64use tokio::task::JoinHandle;
65
66pub fn enable_flush_denormals_to_zero() {
67 #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
68 unsafe {
69 let mut mxcsr: u32 = 0;
70 std::arch::asm!("stmxcsr [{}]", in(reg) &mut mxcsr);
71 mxcsr |= 0x8040;
72 std::arch::asm!("ldmxcsr [{}]", in(reg) &mxcsr);
73 }
74
75 #[cfg(target_arch = "aarch64")]
76 unsafe {
77 let mut fpcr: u64;
78 std::arch::asm!("mrs {0}, fpcr", out(reg) fpcr);
79 fpcr |= 1 << 24;
80 std::arch::asm!("msr fpcr, {0}", in(reg) fpcr);
81 }
82}
83
84#[cfg(target_os = "windows")]
86pub struct WindowsTimerResolutionGuard;
87
88#[cfg(target_os = "windows")]
89impl Drop for WindowsTimerResolutionGuard {
90 fn drop(&mut self) {
91 #[link(name = "winmm")]
92 unsafe extern "system" {
93 fn timeEndPeriod(period: u32) -> u32;
94 }
95 unsafe {
96 timeEndPeriod(1);
97 }
98 }
99}
100
101#[cfg(target_os = "windows")]
106pub fn enable_windows_high_resolution_timer() -> Option<WindowsTimerResolutionGuard> {
107 #[link(name = "winmm")]
108 unsafe extern "system" {
109 fn timeBeginPeriod(period: u32) -> u32;
110 }
111 unsafe {
112 if timeBeginPeriod(1) == 0 {
113 tracing::info!("Windows timer resolution set to 1 ms");
114 Some(WindowsTimerResolutionGuard)
115 } else {
116 tracing::warn!("Failed to set Windows timer resolution to 1 ms");
117 None
118 }
119 }
120}
121
122pub type EngineInit = (
123 Sender<message::Message>,
124 JoinHandle<()>,
125 triple_buffer::TripleBufferConsumer<meter::MeterSnapshot>,
126 triple_buffer::TripleBufferConsumer<meter::TransportSnapshot>,
127 triple_buffer::TripleBufferConsumer<meter::SessionRuntimeSnapshot>,
128);
129
130pub fn init() -> EngineInit {
131 let command_queue_capacity = num_cpus::get().saturating_mul(4).max(128);
132 let (tx, rx) = channel::<message::Message>(command_queue_capacity);
133 let (meter_producer, meter_consumer) =
134 triple_buffer::triple_buffer(meter::MeterSnapshot::default());
135 let (transport_producer, transport_consumer) =
136 triple_buffer::triple_buffer(meter::TransportSnapshot::default());
137 let (session_runtime_producer, session_runtime_consumer) =
138 triple_buffer::triple_buffer(meter::SessionRuntimeSnapshot::default());
139 let mut engine = engine::Engine::new_with_snapshots(
140 rx,
141 tx.clone(),
142 meter_producer,
143 transport_producer,
144 session_runtime_producer,
145 );
146 let handle = tokio::spawn(async move {
147 engine.init().await;
148 engine.work().await;
149 });
150 (
151 tx.clone(),
152 handle,
153 meter_consumer,
154 transport_consumer,
155 session_runtime_consumer,
156 )
157}