use std::f32::consts::PI;
use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
use std::sync::Arc;
use crate::context::{AudioContextRegistration, ConcreteBaseAudioContext};
use crate::events::EventType;
use crate::media::MediaStream;
use crate::render::{AudioParamValues, AudioProcessor, AudioRenderQuantum, RenderScope};
use lazy_static::lazy_static;
mod analyser;
pub use analyser::*;
mod audio_buffer_source;
pub use audio_buffer_source::*;
mod biquad_filter;
pub use biquad_filter::*;
mod channel_merger;
pub use channel_merger::*;
mod channel_splitter;
pub use channel_splitter::*;
mod constant_source;
pub use constant_source::*;
mod convolver;
pub use convolver::*;
mod delay;
pub use delay::*;
mod destination;
pub use destination::*;
mod dynamics_compressor;
pub use dynamics_compressor::*;
mod gain;
pub use gain::*;
mod iir_filter;
pub use iir_filter::*;
mod media_element_source;
pub use media_element_source::*;
mod media_stream_destination;
pub use media_stream_destination::*;
mod media_stream_source;
pub use media_stream_source::*;
mod oscillator;
pub use oscillator::*;
mod panner;
pub use panner::*;
mod stereo_panner;
pub use stereo_panner::*;
mod waveshaper;
use crate::events::EventHandler;
use crate::Event;
pub use waveshaper::*;
pub(crate) const TABLE_LENGTH_USIZE: usize = 8192;
pub(crate) const TABLE_LENGTH_BY_4_USIZE: usize = TABLE_LENGTH_USIZE / 4;
pub(crate) const TABLE_LENGTH_F32: f32 = TABLE_LENGTH_USIZE as f32;
pub(crate) const TABLE_LENGTH_BY_4_F32: f32 = TABLE_LENGTH_BY_4_USIZE as f32;
lazy_static! {
pub(crate) static ref SINETABLE: Vec<f32> = {
let table: Vec<f32> = (0..TABLE_LENGTH_USIZE)
.map(|x| ((x as f32) * 2.0 * PI * (1. / (TABLE_LENGTH_F32))).sin())
.collect();
table
};
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ChannelCountMode {
Max,
ClampedMax,
Explicit,
}
impl From<u32> for ChannelCountMode {
fn from(i: u32) -> Self {
use ChannelCountMode::*;
match i {
0 => Max,
1 => ClampedMax,
2 => Explicit,
_ => unreachable!(),
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ChannelInterpretation {
Speakers,
Discrete,
}
impl From<u32> for ChannelInterpretation {
fn from(i: u32) -> Self {
use ChannelInterpretation::*;
match i {
0 => Speakers,
1 => Discrete,
_ => unreachable!(),
}
}
}
#[derive(Clone, Debug)]
pub struct ChannelConfigOptions {
pub count: usize,
pub count_mode: ChannelCountMode,
pub interpretation: ChannelInterpretation,
}
impl Default for ChannelConfigOptions {
fn default() -> Self {
Self {
count: 2,
count_mode: ChannelCountMode::Max,
interpretation: ChannelInterpretation::Speakers,
}
}
}
#[derive(Clone, Debug)]
pub struct ChannelConfig {
count: Arc<AtomicUsize>,
count_mode: Arc<AtomicU32>,
interpretation: Arc<AtomicU32>,
}
impl Default for ChannelConfig {
fn default() -> Self {
ChannelConfigOptions::default().into()
}
}
impl ChannelConfig {
pub(crate) fn count_mode(&self) -> ChannelCountMode {
self.count_mode.load(Ordering::SeqCst).into()
}
fn set_count_mode(&self, v: ChannelCountMode) {
self.count_mode.store(v as u32, Ordering::SeqCst)
}
pub(crate) fn interpretation(&self) -> ChannelInterpretation {
self.interpretation.load(Ordering::SeqCst).into()
}
fn set_interpretation(&self, v: ChannelInterpretation) {
self.interpretation.store(v as u32, Ordering::SeqCst)
}
pub(crate) fn count(&self) -> usize {
self.count.load(Ordering::SeqCst)
}
fn set_count(&self, v: usize) {
crate::assert_valid_number_of_channels(v);
self.count.store(v, Ordering::SeqCst)
}
}
impl From<ChannelConfigOptions> for ChannelConfig {
fn from(opts: ChannelConfigOptions) -> Self {
Self {
count: Arc::new(AtomicUsize::from(opts.count)),
count_mode: Arc::new(AtomicU32::from(opts.count_mode as u32)),
interpretation: Arc::new(AtomicU32::from(opts.interpretation as u32)),
}
}
}
pub trait AudioNode {
fn registration(&self) -> &AudioContextRegistration;
fn channel_config(&self) -> &ChannelConfig;
fn context(&self) -> &ConcreteBaseAudioContext {
self.registration().context()
}
fn connect<'a>(&self, dest: &'a dyn AudioNode) -> &'a dyn AudioNode {
self.connect_at(dest, 0, 0)
}
fn connect_at<'a>(
&self,
dest: &'a dyn AudioNode,
output: usize,
input: usize,
) -> &'a dyn AudioNode {
if self.context() != dest.context() {
panic!("InvalidAccessError: Attempting to connect nodes from different contexts");
}
if self.number_of_outputs() <= output {
panic!("IndexSizeError: output port {} is out of bounds", output);
}
if dest.number_of_inputs() <= input {
panic!("IndexSizeError: input port {} is out of bounds", input);
}
self.context().connect(
self.registration().id(),
dest.registration().id(),
output,
input,
);
dest
}
fn disconnect_from<'a>(&self, dest: &'a dyn AudioNode) -> &'a dyn AudioNode {
if self.context() != dest.context() {
panic!("attempting to disconnect nodes from different contexts");
}
self.context()
.disconnect_from(self.registration().id(), dest.registration().id());
dest
}
fn disconnect(&self) {
self.context().disconnect(self.registration().id());
}
fn number_of_inputs(&self) -> usize;
fn number_of_outputs(&self) -> usize;
fn channel_count_mode(&self) -> ChannelCountMode {
self.channel_config().count_mode()
}
fn set_channel_count_mode(&self, v: ChannelCountMode) {
self.channel_config().set_count_mode(v)
}
fn channel_interpretation(&self) -> ChannelInterpretation {
self.channel_config().interpretation()
}
fn set_channel_interpretation(&self, v: ChannelInterpretation) {
self.channel_config().set_interpretation(v)
}
fn channel_count(&self) -> usize {
self.channel_config().count()
}
fn set_channel_count(&self, v: usize) {
self.channel_config().set_count(v)
}
}
pub trait AudioScheduledSourceNode: AudioNode {
fn start(&self);
fn start_at(&self, when: f64);
fn stop(&self);
fn stop_at(&self, when: f64);
fn set_onended<F: FnOnce(Event) + Send + 'static>(&self, callback: F) {
let callback = move |_| callback(Event { type_: "ended" });
self.context().set_event_handler(
EventType::Ended(self.registration().id()),
EventHandler::Once(Box::new(callback)),
);
}
fn clear_onended(&self) {
self.context()
.clear_event_handler(EventType::Ended(self.registration().id()));
}
}
struct MediaStreamRenderer<R> {
stream: R,
finished: bool,
}
impl<R> MediaStreamRenderer<R> {
fn new(stream: R) -> Self {
Self {
stream,
finished: false,
}
}
}
impl<R: MediaStream> AudioProcessor for MediaStreamRenderer<R> {
fn process(
&mut self,
_inputs: &[AudioRenderQuantum],
outputs: &mut [AudioRenderQuantum],
_params: AudioParamValues,
_scope: &RenderScope,
) -> bool {
let output = &mut outputs[0];
match self.stream.next() {
Some(Ok(buffer)) => {
let channels = buffer.number_of_channels();
output.set_number_of_channels(channels);
output
.channels_mut()
.iter_mut()
.zip(buffer.channels())
.for_each(|(o, i)| o.copy_from_slice(i.as_slice()));
}
Some(Err(e)) => {
log::warn!("Error playing audio stream: {}", e);
self.finished = true; output.make_silent()
}
None => {
if !self.finished {
log::debug!("Stream finished");
self.finished = true;
}
output.make_silent()
}
}
!self.finished
}
}