rewrite unsafe code in midi handling

This commit is contained in:
Skyler Lehmkuhl 2026-02-16 00:34:59 -05:00
parent 9db34daf85
commit ffe7799b6a
4 changed files with 8 additions and 32 deletions

View File

@ -317,15 +317,9 @@ impl Engine {
self.project.reset_read_ahead_targets();
// Render the entire project hierarchy into the mix buffer
// Note: We need to use a raw pointer to avoid borrow checker issues
// The midi_clip_pool is part of project, so we extract a reference before mutable borrow
let midi_pool_ptr = &self.project.midi_clip_pool as *const _;
// SAFETY: The midi_clip_pool is not mutated during render, only read
let midi_pool_ref = unsafe { &*midi_pool_ptr };
self.project.render(
&mut self.mix_buffer,
&self.audio_pool,
midi_pool_ref,
&mut self.buffer_pool,
playhead_seconds,
self.sample_rate,
@ -2149,15 +2143,11 @@ impl Engine {
Query::ExportAudio(settings, output_path) => {
// Perform export directly - this will block the audio thread but that's okay
// since we're exporting and not playing back anyway
// Use raw pointer to get midi_pool reference before mutable borrow of project
let midi_pool_ptr: *const _ = &self.project.midi_clip_pool;
let midi_pool_ref = unsafe { &*midi_pool_ptr };
// Pass event_tx directly - Rust allows borrowing different fields simultaneously
match crate::audio::export_audio(
&mut self.project,
&self.audio_pool,
midi_pool_ref,
&settings,
&output_path,
Some(&mut self.event_tx),

View File

@ -1,5 +1,4 @@
use super::buffer_pool::BufferPool;
use super::midi_pool::MidiClipPool;
use super::pool::AudioPool;
use super::project::Project;
use crate::command::AudioEvent;
@ -69,7 +68,6 @@ impl Default for ExportSettings {
pub fn export_audio<P: AsRef<Path>>(
project: &mut Project,
pool: &AudioPool,
midi_pool: &MidiClipPool,
settings: &ExportSettings,
output_path: P,
mut event_tx: Option<&mut rtrb::Producer<AudioEvent>>,
@ -87,7 +85,7 @@ pub fn export_audio<P: AsRef<Path>>(
// Ensure export mode is disabled even if an error occurs.
let result = match settings.format {
ExportFormat::Wav | ExportFormat::Flac => {
let samples = render_to_memory(project, pool, midi_pool, settings, event_tx.as_mut().map(|tx| &mut **tx))?;
let samples = render_to_memory(project, pool, settings, event_tx.as_mut().map(|tx| &mut **tx))?;
// Signal that rendering is done and we're now writing the file
if let Some(ref mut tx) = event_tx {
let _ = tx.push(AudioEvent::ExportFinalizing);
@ -99,10 +97,10 @@ pub fn export_audio<P: AsRef<Path>>(
}
}
ExportFormat::Mp3 => {
export_mp3(project, pool, midi_pool, settings, output_path, event_tx)
export_mp3(project, pool, settings, output_path, event_tx)
}
ExportFormat::Aac => {
export_aac(project, pool, midi_pool, settings, output_path, event_tx)
export_aac(project, pool, settings, output_path, event_tx)
}
};
@ -125,7 +123,6 @@ pub fn export_audio<P: AsRef<Path>>(
pub fn render_to_memory(
project: &mut Project,
pool: &AudioPool,
midi_pool: &MidiClipPool,
settings: &ExportSettings,
mut event_tx: Option<&mut rtrb::Producer<AudioEvent>>,
) -> Result<Vec<f32>, String>
@ -162,7 +159,6 @@ pub fn render_to_memory(
project.render(
&mut render_buffer,
pool,
midi_pool,
&mut buffer_pool,
playhead,
settings.sample_rate,
@ -302,7 +298,6 @@ fn write_flac<P: AsRef<Path>>(
fn export_mp3<P: AsRef<Path>>(
project: &mut Project,
pool: &AudioPool,
midi_pool: &MidiClipPool,
settings: &ExportSettings,
output_path: P,
mut event_tx: Option<&mut rtrb::Producer<AudioEvent>>,
@ -382,7 +377,6 @@ fn export_mp3<P: AsRef<Path>>(
project.render(
&mut render_buffer,
pool,
midi_pool,
&mut buffer_pool,
playhead,
settings.sample_rate,
@ -472,7 +466,6 @@ fn export_mp3<P: AsRef<Path>>(
fn export_aac<P: AsRef<Path>>(
project: &mut Project,
pool: &AudioPool,
midi_pool: &MidiClipPool,
settings: &ExportSettings,
output_path: P,
mut event_tx: Option<&mut rtrb::Producer<AudioEvent>>,
@ -552,7 +545,6 @@ fn export_aac<P: AsRef<Path>>(
project.render(
&mut render_buffer,
pool,
midi_pool,
&mut buffer_pool,
playhead,
settings.sample_rate,

View File

@ -349,7 +349,6 @@ impl Project {
&mut self,
output: &mut [f32],
audio_pool: &AudioClipPool,
midi_pool: &MidiClipPool,
buffer_pool: &mut BufferPool,
playhead_seconds: f64,
sample_rate: u32,
@ -374,7 +373,6 @@ impl Project {
track_id,
output,
audio_pool,
midi_pool,
buffer_pool,
ctx,
any_solo,
@ -389,7 +387,6 @@ impl Project {
track_id: TrackId,
output: &mut [f32],
audio_pool: &AudioClipPool,
midi_pool: &MidiClipPool,
buffer_pool: &mut BufferPool,
ctx: RenderContext,
any_solo: bool,
@ -437,7 +434,8 @@ impl Project {
}
Some(TrackNode::Midi(track)) => {
// Render MIDI track directly into output
track.render(output, midi_pool, ctx.playhead_seconds, ctx.sample_rate, ctx.channels);
// Access midi_clip_pool from self - safe because we only need immutable access
track.render(output, &self.midi_clip_pool, ctx.playhead_seconds, ctx.sample_rate, ctx.channels);
}
Some(TrackNode::Group(group)) => {
// Read group properties and transform context (index-based child iteration to avoid clone)
@ -462,7 +460,6 @@ impl Project {
child_id,
&mut group_buffer,
audio_pool,
midi_pool,
buffer_pool,
child_ctx,
any_solo,

View File

@ -54,7 +54,7 @@ pub fn export_audio<P: AsRef<Path>>(
fn export_audio_daw_backend<P: AsRef<Path>>(
project: &mut Project,
pool: &AudioPool,
midi_pool: &MidiClipPool,
_midi_pool: &MidiClipPool,
settings: &AudioExportSettings,
output_path: P,
) -> Result<(), String> {
@ -78,7 +78,6 @@ fn export_audio_daw_backend<P: AsRef<Path>>(
daw_backend::audio::export::export_audio(
project,
pool,
midi_pool,
&daw_settings,
output_path,
None,
@ -89,7 +88,7 @@ fn export_audio_daw_backend<P: AsRef<Path>>(
fn export_audio_ffmpeg_mp3<P: AsRef<Path>>(
project: &mut Project,
pool: &AudioPool,
midi_pool: &MidiClipPool,
_midi_pool: &MidiClipPool,
settings: &AudioExportSettings,
output_path: P,
cancel_flag: &Arc<AtomicBool>,
@ -114,7 +113,6 @@ fn export_audio_ffmpeg_mp3<P: AsRef<Path>>(
let pcm_samples = render_to_memory(
project,
pool,
midi_pool,
&daw_settings,
None, // No progress events for now
)?;
@ -292,7 +290,7 @@ fn receive_and_write_packets(
fn export_audio_ffmpeg_aac<P: AsRef<Path>>(
project: &mut Project,
pool: &AudioPool,
midi_pool: &MidiClipPool,
_midi_pool: &MidiClipPool,
settings: &AudioExportSettings,
output_path: P,
cancel_flag: &Arc<AtomicBool>,
@ -317,7 +315,6 @@ fn export_audio_ffmpeg_aac<P: AsRef<Path>>(
let pcm_samples = render_to_memory(
project,
pool,
midi_pool,
&daw_settings,
None, // No progress events for now
)?;