pub struct SoundEngine(/* private fields */);Expand description
Sound engine manages contexts, feeds output device with data. Sound engine instance can be cloned, however this is always a “shallow” clone, because actual sound engine data is wrapped in Arc.
Implementations§
Source§impl SoundEngine
impl SoundEngine
Sourcepub fn new() -> Result<Self, Box<dyn Error>>
pub fn new() -> Result<Self, Box<dyn Error>>
Creates new instance of the sound engine. It is possible to have multiple engines running at the same time, but you shouldn’t do this because you can create multiple contexts which should cover 99% of use cases.
Examples found in repository?
74fn main() {
75 // Initialize sound engine with default output device.
76 let engine = SoundEngine::new().unwrap();
77
78 // Initialize new sound context.
79 let context = SoundContext::new();
80
81 engine.state().add_context(context.clone());
82
83 // Create sine wave generator
84 let sine_wave = DataSource::RawStreaming(Box::new(SamplesGenerator::new()));
85
86 let sine_wave_buffer = SoundBufferResource::new_streaming(sine_wave).unwrap();
87
88 // Create generic source (without spatial effects) using that buffer.
89 let source = SoundSourceBuilder::new()
90 .with_buffer(sine_wave_buffer)
91 .with_status(Status::Playing)
92 .build()
93 .unwrap();
94
95 context.state().add_source(source);
96
97 // Play sound for some time.
98 thread::sleep(Duration::from_secs(10));
99}More examples
33fn main() {
34 // Initialize sound engine with default output device.
35 let engine = SoundEngine::new().unwrap();
36
37 // Initialize new sound context.
38 let context = SoundContext::new();
39
40 engine.state().add_context(context.clone());
41
42 // Load sound buffer.
43 let waterfall_buffer = SoundBufferResource::new_streaming(
44 block_on(DataSource::from_file(
45 "examples/data/waterfall.ogg",
46 // Load from the default resource io (File system)
47 &FsResourceIo,
48 ))
49 .unwrap(),
50 )
51 .unwrap();
52
53 // Create flat source (without spatial effects) using that buffer.
54 let source = SoundSourceBuilder::new()
55 .with_buffer(waterfall_buffer)
56 .with_status(Status::Playing)
57 .with_looping(true)
58 .build()
59 .unwrap();
60
61 // Each sound sound must be added to context, context takes ownership on source
62 // and returns pool handle to it by which it can be accessed later on if needed.
63 let _source_handle: Handle<SoundSource> = context.state().add_source(source);
64
65 thread::sleep(Duration::from_secs(30))
66}30fn main() {
31 // Initialize sound engine with default output device.
32 let engine = SoundEngine::new().unwrap();
33
34 // Initialize new sound context.
35 let context = SoundContext::new();
36
37 engine.state().add_context(context.clone());
38
39 // Create sine wave.
40 let sample_rate = 44100;
41 let sine_wave = DataSource::Raw {
42 sample_rate,
43 channel_count: 1,
44 samples: {
45 let frequency = 440.0;
46 let amplitude = 0.75;
47 (0..44100)
48 .map(|i| {
49 amplitude
50 * ((2.0 * std::f32::consts::PI * i as f32 * frequency) / sample_rate as f32)
51 .sin()
52 })
53 .collect()
54 },
55 };
56
57 let sine_wave_buffer = SoundBufferResource::new_generic(sine_wave).unwrap();
58
59 // Create generic source (without spatial effects) using that buffer.
60 let source = SoundSourceBuilder::new()
61 .with_buffer(sine_wave_buffer)
62 .with_status(Status::Playing)
63 .with_looping(true)
64 .build()
65 .unwrap();
66
67 context.state().add_source(source);
68
69 // Play sound for some time.
70 thread::sleep(Duration::from_secs(10));
71}32fn main() {
33 // Initialize sound engine with default output device.
34 let engine = SoundEngine::new().unwrap();
35
36 // Create new context.
37 let context = SoundContext::new();
38
39 // Register context in the engine.
40 engine.state().add_context(context.clone());
41
42 // Load sound buffer.
43 let door_open_buffer = SoundBufferResource::new_generic(
44 fyrox_sound::futures::executor::block_on(DataSource::from_file(
45 "examples/data/door_open.wav",
46 // Load from the default resource io (File system)
47 &FsResourceIo,
48 ))
49 .unwrap(),
50 )
51 .unwrap();
52
53 // Create generic source (without spatial effects) using that buffer.
54 let source = SoundSourceBuilder::new()
55 .with_buffer(door_open_buffer)
56 .with_status(Status::Playing)
57 // Ensure that no spatial effects will be applied.
58 .with_spatial_blend_factor(0.0)
59 .build()
60 .unwrap();
61
62 // Each sound sound must be added to context, context takes ownership on source
63 // and returns pool handle to it by which it can be accessed later on if needed.
64 let _source_handle: Handle<SoundSource> = context.state().add_source(source);
65
66 // Wait until sound will play completely.
67 thread::sleep(Duration::from_secs(3));
68}37fn main() {
38 // Initialize sound engine with default output device.
39 let engine = SoundEngine::new().unwrap();
40
41 // Initialize new sound context.
42 let context = SoundContext::new();
43
44 engine.state().add_context(context.clone());
45
46 // Load sound buffer.
47 let drop_buffer = SoundBufferResource::new_generic(
48 block_on(DataSource::from_file(
49 "examples/data/drop.wav",
50 // Load from the default resource io (File system)
51 &FsResourceIo,
52 ))
53 .unwrap(),
54 )
55 .unwrap();
56
57 // Create spatial source - spatial sources can be positioned in space.
58 let source = SoundSourceBuilder::new()
59 .with_buffer(drop_buffer)
60 .with_looping(true)
61 .with_status(Status::Playing)
62 .build()
63 .unwrap();
64
65 // Each sound sound must be added to context, context takes ownership on source
66 // and returns pool handle to it by which it can be accessed later on if needed.
67 let source_handle: Handle<SoundSource> = context.state().add_source(source);
68
69 // Move sound around listener for some time.
70 let start_time = time::Instant::now();
71 let mut angle = 0.0f32;
72 while (time::Instant::now() - start_time).as_secs() < 11 {
73 let axis = Vector3::y_axis();
74 let rotation_matrix =
75 UnitQuaternion::from_axis_angle(&axis, angle.to_radians()).to_homogeneous();
76 context.state().source_mut(source_handle).set_position(
77 rotation_matrix
78 .transform_point(&Point3::new(0.0, 0.0, 3.0))
79 .coords,
80 );
81
82 angle += 3.6;
83
84 // Limit rate of updates.
85 thread::sleep(Duration::from_millis(100));
86 }
87}37fn main() {
38 // Initialize sound engine with default output device.
39 let engine = SoundEngine::new().unwrap();
40
41 // Initialize new sound context.
42 let context = SoundContext::new();
43
44 engine.state().add_context(context.clone());
45
46 // Load sound buffer.
47 let drop_buffer = SoundBufferResource::new_generic(
48 block_on(DataSource::from_file(
49 "examples/data/drop.wav", // Load from the default resource io (File system)
50 &FsResourceIo,
51 ))
52 .unwrap(),
53 )
54 .unwrap();
55
56 // Create spatial source - spatial sources can be positioned in space.
57 let source = SoundSourceBuilder::new()
58 .with_buffer(drop_buffer)
59 .with_looping(true)
60 .with_status(Status::Playing)
61 .build()
62 .unwrap();
63
64 // Each sound sound must be added to context, context takes ownership on source
65 // and returns pool handle to it by which it can be accessed later on if needed.
66 context.state().add_source(source);
67
68 // Rotate listener for some time.
69 let start_time = time::Instant::now();
70 let mut angle = 0.0f32;
71 while (time::Instant::now() - start_time).as_secs() < 20 {
72 // Separate scope for update to make sure that mutex lock will be released before
73 // thread::sleep will be called so context can actually work in background thread.
74 {
75 let mut context = context.state();
76
77 let listener = context.listener_mut();
78
79 // Define up-axis of listener.
80 let up = Vector3::y_axis();
81
82 // And rotate look axis.
83 let rotation_matrix =
84 UnitQuaternion::from_axis_angle(&up, angle.to_radians()).to_homogeneous();
85 let look = rotation_matrix
86 .transform_point(&Point3::new(0.0, 0.0, 1.0))
87 .coords;
88
89 // Finally combine axes. _lh suffix here means that we using left-handed coordinate system.
90 // there is also _rh (right handed) version. Also basis can be set directly by using `set_basis`
91 listener.set_orientation_lh(look, *up);
92
93 // Move listener a bit back from sound source.
94 listener.set_position(Vector3::new(0.0, 0.0, -2.0));
95
96 // Continue rotation.
97 angle += 2.0;
98 }
99
100 // Limit rate of updates.
101 thread::sleep(Duration::from_millis(100));
102 }
103}Sourcepub fn without_device() -> Self
pub fn without_device() -> Self
Creates new instance of a sound engine without OS audio output device (so called headless mode).
The user should periodically run State::render if they want to implement their own sample sending
method to an output device (or a file, etc.).
Examples found in repository?
32fn main() {
33 // Initialize sound engine without output device.
34 let engine = SoundEngine::without_device();
35
36 // Create new context.
37 let context = SoundContext::new();
38
39 // Register context in the engine.
40 engine.state().add_context(context.clone());
41
42 // Load sound buffer.
43 let door_open_buffer = SoundBufferResource::new_generic(
44 fyrox_sound::futures::executor::block_on(DataSource::from_file(
45 "examples/data/door_open.wav",
46 // Load from the default resource io (File system)
47 &FsResourceIo,
48 ))
49 .unwrap(),
50 )
51 .unwrap();
52
53 // Create generic source (without spatial effects) using that buffer.
54 let source = SoundSourceBuilder::new()
55 .with_buffer(door_open_buffer)
56 .with_status(Status::Playing)
57 .build()
58 .unwrap();
59
60 // Each sound sound must be added to context, context takes ownership on source
61 // and returns pool handle to it by which it can be accessed later on if needed.
62 let _source_handle: Handle<SoundSource> = context.state().add_source(source);
63
64 // Create output wav file. The sample rate is currently fixed.
65 let wav_spec = hound::WavSpec {
66 channels: 2,
67 sample_rate: fyrox_sound::context::SAMPLE_RATE,
68 bits_per_sample: 32,
69 sample_format: hound::SampleFormat::Float,
70 };
71 let mut wav_writer = hound::WavWriter::create("output.wav", wav_spec).unwrap();
72
73 // Create an output buffer.
74 let buf_len = State::render_buffer_len();
75 let mut buf = vec![(0.0f32, 0.0f32); buf_len];
76 let mut samples_written = 0;
77
78 // Wait until sound will play completely.
79 while samples_written < 3 * fyrox_sound::context::SAMPLE_RATE {
80 engine.state().render(&mut buf);
81 for &(l, r) in buf.iter() {
82 wav_writer.write_sample(l).unwrap();
83 wav_writer.write_sample(r).unwrap();
84 }
85 samples_written += buf_len as u32;
86 }
87
88 wav_writer.finalize().unwrap();
89}Sourcepub fn initialize_audio_output_device(&self) -> Result<(), Box<dyn Error>>
pub fn initialize_audio_output_device(&self) -> Result<(), Box<dyn Error>>
Tries to initialize default audio output device.
Sourcepub fn destroy_audio_output_device(&self)
pub fn destroy_audio_output_device(&self)
Destroys current audio output device (if any).
Sourcepub fn state(&self) -> MutexGuard<'_, State>
pub fn state(&self) -> MutexGuard<'_, State>
Provides direct access to actual engine data.
Examples found in repository?
74fn main() {
75 // Initialize sound engine with default output device.
76 let engine = SoundEngine::new().unwrap();
77
78 // Initialize new sound context.
79 let context = SoundContext::new();
80
81 engine.state().add_context(context.clone());
82
83 // Create sine wave generator
84 let sine_wave = DataSource::RawStreaming(Box::new(SamplesGenerator::new()));
85
86 let sine_wave_buffer = SoundBufferResource::new_streaming(sine_wave).unwrap();
87
88 // Create generic source (without spatial effects) using that buffer.
89 let source = SoundSourceBuilder::new()
90 .with_buffer(sine_wave_buffer)
91 .with_status(Status::Playing)
92 .build()
93 .unwrap();
94
95 context.state().add_source(source);
96
97 // Play sound for some time.
98 thread::sleep(Duration::from_secs(10));
99}More examples
33fn main() {
34 // Initialize sound engine with default output device.
35 let engine = SoundEngine::new().unwrap();
36
37 // Initialize new sound context.
38 let context = SoundContext::new();
39
40 engine.state().add_context(context.clone());
41
42 // Load sound buffer.
43 let waterfall_buffer = SoundBufferResource::new_streaming(
44 block_on(DataSource::from_file(
45 "examples/data/waterfall.ogg",
46 // Load from the default resource io (File system)
47 &FsResourceIo,
48 ))
49 .unwrap(),
50 )
51 .unwrap();
52
53 // Create flat source (without spatial effects) using that buffer.
54 let source = SoundSourceBuilder::new()
55 .with_buffer(waterfall_buffer)
56 .with_status(Status::Playing)
57 .with_looping(true)
58 .build()
59 .unwrap();
60
61 // Each sound sound must be added to context, context takes ownership on source
62 // and returns pool handle to it by which it can be accessed later on if needed.
63 let _source_handle: Handle<SoundSource> = context.state().add_source(source);
64
65 thread::sleep(Duration::from_secs(30))
66}30fn main() {
31 // Initialize sound engine with default output device.
32 let engine = SoundEngine::new().unwrap();
33
34 // Initialize new sound context.
35 let context = SoundContext::new();
36
37 engine.state().add_context(context.clone());
38
39 // Create sine wave.
40 let sample_rate = 44100;
41 let sine_wave = DataSource::Raw {
42 sample_rate,
43 channel_count: 1,
44 samples: {
45 let frequency = 440.0;
46 let amplitude = 0.75;
47 (0..44100)
48 .map(|i| {
49 amplitude
50 * ((2.0 * std::f32::consts::PI * i as f32 * frequency) / sample_rate as f32)
51 .sin()
52 })
53 .collect()
54 },
55 };
56
57 let sine_wave_buffer = SoundBufferResource::new_generic(sine_wave).unwrap();
58
59 // Create generic source (without spatial effects) using that buffer.
60 let source = SoundSourceBuilder::new()
61 .with_buffer(sine_wave_buffer)
62 .with_status(Status::Playing)
63 .with_looping(true)
64 .build()
65 .unwrap();
66
67 context.state().add_source(source);
68
69 // Play sound for some time.
70 thread::sleep(Duration::from_secs(10));
71}32fn main() {
33 // Initialize sound engine with default output device.
34 let engine = SoundEngine::new().unwrap();
35
36 // Create new context.
37 let context = SoundContext::new();
38
39 // Register context in the engine.
40 engine.state().add_context(context.clone());
41
42 // Load sound buffer.
43 let door_open_buffer = SoundBufferResource::new_generic(
44 fyrox_sound::futures::executor::block_on(DataSource::from_file(
45 "examples/data/door_open.wav",
46 // Load from the default resource io (File system)
47 &FsResourceIo,
48 ))
49 .unwrap(),
50 )
51 .unwrap();
52
53 // Create generic source (without spatial effects) using that buffer.
54 let source = SoundSourceBuilder::new()
55 .with_buffer(door_open_buffer)
56 .with_status(Status::Playing)
57 // Ensure that no spatial effects will be applied.
58 .with_spatial_blend_factor(0.0)
59 .build()
60 .unwrap();
61
62 // Each sound sound must be added to context, context takes ownership on source
63 // and returns pool handle to it by which it can be accessed later on if needed.
64 let _source_handle: Handle<SoundSource> = context.state().add_source(source);
65
66 // Wait until sound will play completely.
67 thread::sleep(Duration::from_secs(3));
68}37fn main() {
38 // Initialize sound engine with default output device.
39 let engine = SoundEngine::new().unwrap();
40
41 // Initialize new sound context.
42 let context = SoundContext::new();
43
44 engine.state().add_context(context.clone());
45
46 // Load sound buffer.
47 let drop_buffer = SoundBufferResource::new_generic(
48 block_on(DataSource::from_file(
49 "examples/data/drop.wav",
50 // Load from the default resource io (File system)
51 &FsResourceIo,
52 ))
53 .unwrap(),
54 )
55 .unwrap();
56
57 // Create spatial source - spatial sources can be positioned in space.
58 let source = SoundSourceBuilder::new()
59 .with_buffer(drop_buffer)
60 .with_looping(true)
61 .with_status(Status::Playing)
62 .build()
63 .unwrap();
64
65 // Each sound sound must be added to context, context takes ownership on source
66 // and returns pool handle to it by which it can be accessed later on if needed.
67 let source_handle: Handle<SoundSource> = context.state().add_source(source);
68
69 // Move sound around listener for some time.
70 let start_time = time::Instant::now();
71 let mut angle = 0.0f32;
72 while (time::Instant::now() - start_time).as_secs() < 11 {
73 let axis = Vector3::y_axis();
74 let rotation_matrix =
75 UnitQuaternion::from_axis_angle(&axis, angle.to_radians()).to_homogeneous();
76 context.state().source_mut(source_handle).set_position(
77 rotation_matrix
78 .transform_point(&Point3::new(0.0, 0.0, 3.0))
79 .coords,
80 );
81
82 angle += 3.6;
83
84 // Limit rate of updates.
85 thread::sleep(Duration::from_millis(100));
86 }
87}32fn main() {
33 // Initialize sound engine without output device.
34 let engine = SoundEngine::without_device();
35
36 // Create new context.
37 let context = SoundContext::new();
38
39 // Register context in the engine.
40 engine.state().add_context(context.clone());
41
42 // Load sound buffer.
43 let door_open_buffer = SoundBufferResource::new_generic(
44 fyrox_sound::futures::executor::block_on(DataSource::from_file(
45 "examples/data/door_open.wav",
46 // Load from the default resource io (File system)
47 &FsResourceIo,
48 ))
49 .unwrap(),
50 )
51 .unwrap();
52
53 // Create generic source (without spatial effects) using that buffer.
54 let source = SoundSourceBuilder::new()
55 .with_buffer(door_open_buffer)
56 .with_status(Status::Playing)
57 .build()
58 .unwrap();
59
60 // Each sound sound must be added to context, context takes ownership on source
61 // and returns pool handle to it by which it can be accessed later on if needed.
62 let _source_handle: Handle<SoundSource> = context.state().add_source(source);
63
64 // Create output wav file. The sample rate is currently fixed.
65 let wav_spec = hound::WavSpec {
66 channels: 2,
67 sample_rate: fyrox_sound::context::SAMPLE_RATE,
68 bits_per_sample: 32,
69 sample_format: hound::SampleFormat::Float,
70 };
71 let mut wav_writer = hound::WavWriter::create("output.wav", wav_spec).unwrap();
72
73 // Create an output buffer.
74 let buf_len = State::render_buffer_len();
75 let mut buf = vec![(0.0f32, 0.0f32); buf_len];
76 let mut samples_written = 0;
77
78 // Wait until sound will play completely.
79 while samples_written < 3 * fyrox_sound::context::SAMPLE_RATE {
80 engine.state().render(&mut buf);
81 for &(l, r) in buf.iter() {
82 wav_writer.write_sample(l).unwrap();
83 wav_writer.write_sample(r).unwrap();
84 }
85 samples_written += buf_len as u32;
86 }
87
88 wav_writer.finalize().unwrap();
89}Trait Implementations§
Source§impl Clone for SoundEngine
impl Clone for SoundEngine
Source§fn clone(&self) -> SoundEngine
fn clone(&self) -> SoundEngine
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for SoundEngine
impl RefUnwindSafe for SoundEngine
impl Send for SoundEngine
impl Sync for SoundEngine
impl Unpin for SoundEngine
impl UnsafeUnpin for SoundEngine
impl UnwindSafe for SoundEngine
Blanket Implementations§
Source§impl<T> AsyncTaskResult for T
impl<T> AsyncTaskResult for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T, U> ObjectOrVariant<T> for Uwhere
PhantomData<U>: ObjectOrVariantHelper<T, U>,
impl<T, U> ObjectOrVariant<T> for Uwhere
PhantomData<U>: ObjectOrVariantHelper<T, U>,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.