pub(crate) mod audio_sample;
pub(crate) mod effects;
pub(crate) mod headphone;
pub(crate) mod headphone_state;
pub(crate) mod loop_sound_span;
pub(crate) mod midi;
pub(crate) mod signals;
pub(crate) mod sound_channel;
pub(crate) mod sound_format;
pub(crate) mod sources;
pub(crate) mod volume;
pub use audio_sample::AudioSample;
pub use effects::bit_crusher::BitCrusher;
pub use effects::delay_line::DelayLine;
pub use effects::one_pole_filter::OnePoleFilter;
pub use effects::overdrive::Overdrive;
pub use effects::ring_modulator::RingModulator;
pub use effects::sound_effect::SoundEffect;
pub use effects::two_pole_filter::TwoPoleFilter;
pub use headphone::{ActiveMicrophoneCallback, MicrophoneCallbackOutput};
pub use headphone_state::HeadphoneState;
pub use loop_sound_span::LoopTimeSpan;
pub use midi::midi_note_range::MidiNoteRange;
pub use midi::sequence::Sequence;
pub use midi::sequence_track::SequenceTrack;
pub use midi::track_note::TrackNote;
pub use signals::control::Control;
pub use signals::envelope::Envelope;
pub use signals::lfo::Lfo;
pub use signals::synth_signal::{AsSynthSignal, SynthSignal};
pub use sound_channel::SoundChannel;
pub use sound_format::*;
pub use sources::callback_source::CallbackSource;
pub use sources::delay_line_tap::DelayLineTap;
pub use sources::file_player::FilePlayer;
pub use sources::instrument::{Instrument, VoiceId};
pub use sources::sample_player::SamplePlayer;
pub use sources::sound_source::{AsSoundSource, SoundSource};
pub use sources::synth::{Synth, SynthGenerator, SynthGeneratorVTable, SynthRender};
pub use volume::{StereoVolume, Volume};
use crate::callback_builder::{AllowNull, CallbackBuilder, CallbackBuilderWithArg, Constructed};
use crate::capi_state::CApiState;
use crate::time::TimeTicks;
pub(crate) const SAMPLE_FRAMES_PER_SEC: i32 = 44_100;
pub type SoundCompletionCallback<'a, T, F, S> = CallbackBuilder<'a, T, F, AllowNull, S>;
pub type HeadphoneChangeCallback<'a, T, F, S> =
CallbackBuilderWithArg<'a, HeadphoneState, T, (), F, AllowNull, S>;
#[derive(Debug)]
pub struct Sound {
default_channel: SoundChannel,
}
impl Sound {
pub(crate) fn new() -> Self {
Sound {
default_channel: SoundChannel::new_system_channel(unsafe {
Self::fns().getDefaultChannel.unwrap()()
}),
}
}
pub fn default_channel(&self) -> &SoundChannel {
&self.default_channel
}
pub fn default_channel_mut(&mut self) -> &mut SoundChannel {
&mut self.default_channel
}
pub fn add_channel(&mut self, channel: &mut SoundChannel) {
if !channel.is_system_channel() {
channel.set_added(true);
unsafe { Self::fns().addChannel.unwrap()(channel.cptr_mut()) };
}
}
pub fn remove_channel(&mut self, channel: &mut SoundChannel) {
if !channel.is_system_channel() {
channel.set_added(false);
unsafe { Self::fns().removeChannel.unwrap()(channel.cptr_mut()) }
}
}
pub fn current_sound_time(&self) -> TimeTicks {
TimeTicks::from_sample_frames(unsafe { Self::fns().getCurrentTime.unwrap()() })
}
pub fn set_active_outputs(&mut self, headphone: bool, speaker: bool) {
unsafe { Self::fns().setOutputsActive.unwrap()(headphone as i32, speaker as i32) };
}
pub fn set_microphone_callback<F: Fn(&[i16]) -> MicrophoneCallbackOutput + Sync + 'static>(
&mut self,
maybe_closure: Option<F>,
force_device_microphone: bool,
) -> Option<ActiveMicrophoneCallback> {
match maybe_closure {
Some(closure) => Some(ActiveMicrophoneCallback::set_active_callback(
closure,
force_device_microphone,
)),
None => {
unsafe { Self::fns().setMicCallback.unwrap()(None, core::ptr::null_mut(), false as i32) }
None
}
}
}
pub fn set_headphone_change_callback<'a, T, F: Fn(HeadphoneState, T) + 'static>(
&mut self,
change_callback: HeadphoneChangeCallback<'a, T, F, Constructed>,
) {
let mut headphone_callback = CApiState::get().headphone_change_callback.borrow_mut();
*headphone_callback = None;
let func = change_callback.into_inner().and_then(|(callbacks, cb)| {
let (func, reg) = callbacks.add_headphone_change(cb);
*headphone_callback = Some(reg);
Some(func)
});
let mut headphone = 0;
let mut mic = 0;
unsafe { Self::fns().getHeadphoneState.unwrap()(&mut headphone, &mut mic, func) }
*CApiState::get().headphone_change_func.borrow_mut() = func;
}
pub fn headphone_state(&self) -> HeadphoneState {
let func = CApiState::get().headphone_change_func.borrow().clone();
let mut headphone = 0;
let mut mic = 0;
unsafe { Self::fns().getHeadphoneState.unwrap()(&mut headphone, &mut mic, func) };
HeadphoneState::new(headphone != 0, mic != 0)
}
pub(crate) fn fns() -> &'static craydate_sys::playdate_sound {
CApiState::get().csound
}
}