Expand description
Kira-compatible generated synthesis sound sources.
This crate follows the WebAudio graph shape where it maps cleanly to Rust
and Kira. Browser-only integration points are intentionally unsupported:
DOM media elements, MediaStream, sink/device selection,
decodeAudioData, deprecated ScriptProcessorNode, AudioRenderCapacity
events, JavaScript module loading, MessagePort, promises, and EventTarget. Use
AudioContext::create_sound_data_source for Kira SoundData media/source
integration, and use Rust Result values plus source state handles for
errors and ended status. HRTF panning is also unsupported; panner nodes use
equal-power spatialization.
Use AudioContext::create_audio_worklet_node with an
AudioWorkletProcessor implementation for custom render-quantum
processing.
struct Passthrough;
impl AudioWorkletProcessor for Passthrough {
fn process(
&mut self,
inputs: &[Vec<Vec<f32>>],
outputs: &mut [Vec<Vec<f32>>],
_context: AudioWorkletProcessContext,
) -> bool {
if let (Some(input), Some(output)) = (inputs.first(), outputs.first_mut()) {
for (output_channel, input_channel) in output.iter_mut().zip(input) {
output_channel.copy_from_slice(input_channel);
}
}
true
}
}
let mut context = AudioContext::new();
let _node = context.create_audio_worklet_node(Passthrough);let _channel = melody_bay::Channel::main(melody_bay::AudioContext::new());Author new musical material with IndexedSequence when events should sit
on a tempo-mapped grid, or TimedSequence when events already have exact
timestamps. Indexed sequences resolve into timed sequences before playback.
Automation targets use WebAudio-style parameter names such as "gain" or
"playback_rate". Use AudioContext::label_node and "label.param" to
target a specific graph node, for example "output.gain". Add #n to
target the nth matching parameter in graph node order, for example
"gain#1". Infallible render/playback helpers follow Kira’s ergonomic
SoundData style and ignore invalid sequencer automation. Use
TimedSequence::validate or TimedSequence::try_sound_data when
automation should be checked before rendering.
let mut graph = AudioContext::new();
let source = graph.create_constant_source();
let gain = graph.create_gain();
graph.connect(source, &gain).unwrap();
graph.connect(&gain, graph.destination()).unwrap();
let mut sequence = IndexedSequence::new(4);
sequence.tempo_at(0, 120.0);
sequence.add_track(
TrackId::named("lead"),
IndexedTrack::new(Instrument::graph(graph))
.note_with_velocity(0, Note::from_midi(60), 4, Velocity::new(0.8))
.linear_ramp_to_value_at_index(4, "gain", 0.25),
);
let timed = sequence.resolve();
let _sound_data = timed.try_sound_data().unwrap().sample_rate(44_100);let _id = melody_bay::EventId(1);let _time = melody_bay::SequenceTime::seconds(0.0);let _stem = melody_bay::StemId::named("lead");let _envelope = melody_bay::Envelope::Adsr(melody_bay::Adsr::default());let _curve = melody_bay::AutomationCurve::constant(1.0);let _param = melody_bay::AudioParam::new(0.5);let _filter = melody_bay::BiquadFilterNode::new(melody_bay::BiquadFilterType::Lowpass);let _delay = melody_bay::DelayNode::new(0.25);let _instrument = melody_bay::InstrumentGraph::constant(1.0);let _oscillator = melody_bay::Oscillator::new(melody_bay::Waveform::Sine, 440.0);let _gain = melody_bay::Gain { amount: 1.0 };let _pan = melody_bay::Pan { amount: 0.0 };let mut context = melody_bay::AudioContext::new();
let _compressor = context.dynamics_compressor();let _graph = melody_bay::Graph::new();let _data: Option<melody_bay::GraphSoundData> = None;let _handle: Option<melody_bay::GraphSoundHandle> = None;let live = melody_bay::AudioContext::new();
let mut offline = melody_bay::OfflineAudioContext::try_new(2, 128, 48_000).unwrap();
let _buffer = offline.render_graph(&live);let mut context = melody_bay::AudioContext::new();
let _gain = context.create_gain().set_gain(0.5);let context = melody_bay::AudioContext::new();
let _listener = context.listener().position(1.0, 2.0, 3.0);let context = melody_bay::AudioContext::new();
let _listener = context.listener().forward(0.0, 0.0, -1.0);let context = melody_bay::AudioContext::new();
let _listener = context.listener().up(0.0, 1.0, 0.0);let mut context = melody_bay::AudioContext::new();
let _gain = context
.create_gain()
.gain_param(melody_bay::AudioParam::new(0.5));let mut context = melody_bay::AudioContext::new();
let _param = context.create_gain().gain_param_id();Use GainNode::gain to access the live node-owned
AudioParamHandle instead of raw parameter ids.
let mut context = melody_bay::AudioContext::new();
let _id = context.create_gain().gain().id();let _id: Option<melody_bay::ParamId> = None;let _id: Option<melody_bay::NodeId> = None;let mut context = melody_bay::AudioContext::new();
let _id = melody_bay::NodeId::from(context.create_gain());let mut context = melody_bay::AudioContext::new();
context.set_sample_rate(48_000);let _context = melody_bay::AudioContext::new_with_sample_rate(48_000);let mut context = melody_bay::AudioContext::new();
let _source = context.create_constant_source().set_offset(1.0);let mut context = melody_bay::AudioContext::new();
let _pan = context.create_stereo_panner().set_pan(0.5);let mut context = melody_bay::AudioContext::new();
let _source = context
.create_buffer_source()
.set_playback_rate(2.0);let mut context = melody_bay::AudioContext::new();
let _delay = context.create_delay().set_delay_time(0.25);let mut context = melody_bay::AudioContext::new();
let _osc = context.create_oscillator().set_detune(1200.0);let mut context = melody_bay::AudioContext::new();
let _source = context.create_buffer_source().set_detune(1200.0);let mut context = melody_bay::AudioContext::new();
let _filter = context.create_biquad_filter().set_detune(1200.0);let mut context = melody_bay::AudioContext::new();
let _compressor = context.create_dynamics_compressor().set_threshold(-24.0);let mut context = melody_bay::AudioContext::new();
let _compressor = context.create_dynamics_compressor().set_knee(0.0);let mut context = melody_bay::AudioContext::new();
let _compressor = context.create_dynamics_compressor().set_ratio(12.0);let mut context = melody_bay::AudioContext::new();
let _compressor = context.create_dynamics_compressor().set_attack(0.003);let mut context = melody_bay::AudioContext::new();
let _compressor = context.create_dynamics_compressor().set_release(0.25);let mut context = melody_bay::AudioContext::new();
let _filter = context.create_biquad_filter().set_frequency(1_000.0);let mut context = melody_bay::AudioContext::new();
let _filter = context.create_biquad_filter().set_q(0.707);let mut context = melody_bay::AudioContext::new();
let _filter = context.create_biquad_filter().set_gain(3.0);let mut context = melody_bay::AudioContext::new();
let _osc = context.create_oscillator().set_frequency(440.0);let mut context = melody_bay::AudioContext::new();
let _panner = context.create_panner().position(1.0, 2.0, 3.0);let mut context = melody_bay::AudioContext::new();
let _panner = context.create_panner().orientation(0.0, 0.0, -1.0);let mut context = melody_bay::AudioContext::new();
let _analyser = context.create_analyser().fft_size(2048);let mut context = melody_bay::AudioContext::new();
let _analyser = context.create_analyser().min_decibels(-100.0);let mut context = melody_bay::AudioContext::new();
let _analyser = context.create_analyser().max_decibels(-30.0);let mut context = melody_bay::AudioContext::new();
let _analyser = context.create_analyser().smoothing_time_constant(0.5);let context = melody_bay::AudioContext::new();
let _buffer = context.create_buffer(2, 128, 44_100).unwrap();let context = melody_bay::OfflineAudioContext::try_new(2, 128, 44_100).unwrap();
let _buffer = context.create_buffer(2, 128, 44_100).unwrap();let context = melody_bay::AudioContext::new();
let _wave = context
.create_periodic_wave([0.0, 1.0], [0.0, 0.5])
.unwrap();let context = melody_bay::OfflineAudioContext::try_new(2, 128, 44_100).unwrap();
let _wave = context
.create_periodic_wave([0.0, 1.0], [0.0, 0.5])
.unwrap();let mut context = melody_bay::AudioContext::new();
let _filter = context.create_iir_filter([1.0], [1.0]).unwrap();let _wave = melody_bay::PeriodicWave::new([0.0, 1.0], [0.0, 0.5]);let mut context = melody_bay::OfflineAudioContext::try_new(2, 128, 44_100).unwrap();
let _filter = context.create_iir_filter([1.0], [1.0]).unwrap();let _context = melody_bay::OfflineAudioContext::new(2, 128, 44_100);let context = melody_bay::AudioContext::new();
let _rendered = context.render_offline(44_100, 128);let context = melody_bay::AudioContext::new();
let _rendered = context.render_offline_channels(44_100, 128, 2);let context = melody_bay::AudioContext::new();
let _rendered = context.render_offline_seconds(44_100, 1.0);let mut context = melody_bay::AudioContext::new();
let _splitter = context.create_channel_splitter(2);let mut context = melody_bay::AudioContext::new();
let _merger = context.create_channel_merger(2);let mut context = melody_bay::OfflineAudioContext::try_new(2, 128, 44_100).unwrap();
let _splitter = context.create_channel_splitter(2);let mut context = melody_bay::OfflineAudioContext::try_new(2, 128, 44_100).unwrap();
let _merger = context.create_channel_merger(2);let mut context = melody_bay::AudioContext::new();
let _shaper = context.create_wave_shaper().curve([-1.0, 0.0, 1.0]);let mut context = melody_bay::AudioContext::new();
let buffer = melody_bay::AudioBuffer::from_mono(44_100, 1, [1.0]);
let _source = context.create_buffer_source().buffer(buffer);let _buffer = melody_bay::AudioBuffer::from_frames(44_100, &[]);let _buffer = melody_bay::AudioBuffer::from_mono(44_100, 1, [1.0]);let _buffer = melody_bay::AudioBuffer::from_stereo(44_100, 1, [1.0], [1.0]);let _buffer = melody_bay::AudioBuffer::from_channels(44_100, 1, [[1.0]]);let mut context = melody_bay::AudioContext::new();
let _delay = context.create_delay().max_delay_time(0.5);let mut context = melody_bay::AudioContext::new();
let _panner = context.create_panner().cone_inner_angle(30.0);let mut context = melody_bay::AudioContext::new();
let _panner = context.create_panner().cone_outer_angle(60.0);let mut context = melody_bay::AudioContext::new();
let _panner = context.create_panner().cone_outer_gain(0.25);let mut context = melody_bay::AudioContext::new();
let _panner = context.create_panner().ref_distance(1.0);let mut context = melody_bay::AudioContext::new();
let _panner = context.create_panner().max_distance(10.0);let mut context = melody_bay::AudioContext::new();
let _panner = context.create_panner().rolloff_factor(1.0);let mut context = melody_bay::AudioContext::new();
let _source = context.create_buffer_source().loop_range(0.0, 1.0);let mut context = melody_bay::AudioContext::new();
let _osc = context.create_oscillator().start(0.0);let mut context = melody_bay::AudioContext::new();
let _osc = context.create_oscillator().stop(1.0);let mut context = melody_bay::AudioContext::new();
let _source = context.create_constant_source().start(0.0);let mut context = melody_bay::AudioContext::new();
let _source = context.create_constant_source().stop(1.0);let mut context = melody_bay::AudioContext::new();
let _source = context.create_buffer_source().start(0.0);let mut context = melody_bay::AudioContext::new();
let _source = context.create_buffer_source().start_with_offset(0.0, 0.25);let mut context = melody_bay::AudioContext::new();
let _source = context
.create_buffer_source()
.start_with_offset_and_duration(0.0, 0.25, 1.0);let mut context = melody_bay::AudioContext::new();
let _source = context.create_buffer_source().stop(1.0);Structs§
- Analyser
Node - Analyser
Options - Audio
Buffer - Audio
Buffer Options - Audio
Buffer Source Node - Audio
Buffer Source Options - Audio
Context - Audio
Context Options - Audio
Context Sound Data - Audio
Context Sound Handle - Audio
Destination Node - Audio
Listener - Audio
Node Info - Audio
Param Handle - Audio
Timestamp - Audio
Worklet Node - Audio
Worklet Node Options - Audio
Worklet Parameter Descriptor - Audio
Worklet Process Context - Biquad
Filter Handle - Biquad
Filter Options - Channel
Merger Node - Channel
Merger Options - Channel
Splitter Node - Channel
Splitter Options - Constant
Source Node - Constant
Source Options - Convolver
Node - Convolver
Options - Delay
Node Handle - Delay
Options - Dynamics
Compressor Node - Dynamics
Compressor Options - Gain
Node - Gain
Options - IirFilter
Node - IirFilter
Options - Import
Warning - Imported
Sequence - Indexed
Automation Event - Indexed
Note Event - Indexed
Sequence - Indexed
Track - Instrument
Id - Midi
Import - ModImport
- Note
- Offline
Audio Context - Offline
Audio Context Options - Oscillator
Node - Oscillator
Options - Panner
Node - Panner
Options - Param
Timeline - Periodic
Wave - Periodic
Wave Options - Sample
Envelope - Sample
Instrument - Sample
Loop - Sequence
Metadata - Sequencer
Sound Data - Sequencer
Sound Error - Sequencer
Sound Handle - Sound
Data Source Node - Stereo
Panner Node - Stereo
Panner Options - Tempo
Map - Timed
Automation Event - Timed
Note Event - Timed
Sequence - Timed
Track - TrackId
- Velocity
- Wave
Shaper Node - Wave
Shaper Options - XmImport
Enums§
- Audio
Context Latency Hint - Automation
Rate - Automation
Shape - Biquad
Filter Type - Channel
Count Mode - Channel
Interpretation - Distance
Model - Graph
Error - Import
Error - Import
Warning Kind - Imported
Format - Indexed
Automation Shape - Instrument
- Offline
Audio Context State - Oscillator
Type - Oscillator
Type Value - Oversample
- Panning
Model - Sequencer
Validation Error - Waveform