listener/listener.rs
1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use fyrox_core::algebra::Point3;
22use fyrox_resource::io::FsResourceIo;
23use fyrox_sound::buffer::SoundBufferResourceExtension;
24use fyrox_sound::{
25 algebra::{UnitQuaternion, Vector3},
26 buffer::{DataSource, SoundBufferResource},
27 context::SoundContext,
28 engine::SoundEngine,
29 futures::executor::block_on,
30 source::{SoundSourceBuilder, Status},
31};
32use std::{
33 thread,
34 time::{self, Duration},
35};
36
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}