#[repr(C)]pub struct Sound(pub NonNull<_SoundT>);
Expand description
This class represents a sound effect! Excellent for blips and bloops and little clips that you might play around your scene. Right now, this supports .wav, .mp3, and procedurally generated noises!
On HoloLens 2, sounds are automatically processed on the HPU, freeing up the CPU for more of your app’s code. To simulate this same effect on your development PC, you need to enable spatial sound on your audio endpoint. To do this, right click the speaker icon in your system tray, navigate to “Spatial sound”, and choose “Windows Sonic for Headphones.” For more information, visit https://docs.microsoft.com/en-us/windows/win32/coreaudio/spatial-sound https://stereokit.net/Pages/StereoKit/Sound.html
§Examples
use stereokit_rust::{maths::{Vec3, Quat, Matrix}, mesh::Mesh, material::Material,
sound::Sound, util::named_colors};
let mesh = Mesh::generate_cube(Vec3::ONE * 1.6, None);
let material = Material::unlit().tex_file_copy("textures/sound.jpeg", true, None)
.expect("sound.jpeg should be there");
let mut position = Vec3::new(-0.5, 0.0, 0.5);
let rotation = Quat::from_angles(45.0, 45.0, 45.0);
let mut transform = Matrix::IDENTITY;
let mut plane_sound = Sound::from_file("sounds/plane_engine.mp3")
.expect("plane_engine.mp3 should be there");
plane_sound.id("sound_plane").decibels(70.0);
let mut plane_sound_inst = plane_sound.play(position, Some(1.0));
number_of_steps = 4000;
filename_scr = "screenshots/sound.jpeg";
test_screenshot!( // !!!! Get a proper main loop !!!!
transform.update_t_r(&position, &rotation);
mesh.draw(token, &material, transform, Some(named_colors::CYAN.into()), None);
if iter == 0 {
assert!(plane_sound_inst.is_playing());
position = Vec3::new(0.0, 0.0, -1.0);
plane_sound_inst
.position(position)
.volume(0.5);
} else if iter == 2999 {
assert!(plane_sound_inst.is_playing());
assert_eq!(plane_sound_inst.get_position(), Vec3::new(0.0, 0.0, -1.0));
assert_eq!(plane_sound_inst.get_volume(), 0.5);
plane_sound_inst.stop();
assert!(!plane_sound_inst.is_playing());
}
);

Tuple Fields§
§0: NonNull<_SoundT>
Implementations§
Source§impl Sound
impl Sound
Sourcepub fn create_stream(
stream_buffer_duration: f32,
) -> Result<Sound, StereoKitError>
pub fn create_stream( stream_buffer_duration: f32, ) -> Result<Sound, StereoKitError>
Create a sound used for streaming audio in or out! This is useful for things like reading from a microphone stream, or playing audio from a source streaming over the network, or even procedural sounds that are generated on the fly! Use stream sounds with the WriteSamples and ReadSamples functions. https://stereokit.net/Pages/StereoKit/Sound/CreateStream.html
stream_buffer_duration
- How much audio time should this stream be able to hold without writing back over itself?
see also sound_create_stream
Sound::from_samples
§Examples
use stereokit_rust::sound::Sound;
let mut stream_sound = Sound::create_stream(0.5).
expect("A sound stream should be created");
assert!(stream_sound.get_id().starts_with("auto/sound_"));
stream_sound.id("sound_stream");
let mut samples: Vec<f32> = vec![0.0; 48000];
for i in 0..48000 {
samples[i] = (i as f32 / 48000.0).sin();
}
stream_sound.write_samples(samples.as_slice(), Some(48000));
assert_eq!(stream_sound.get_duration(), 0.5);
let mut stream_sound_inst = stream_sound.play([0.0, 0.0, -0.5], Some(0.5));
filename_scr = "screenshots/sound_stream.jpeg";
number_of_steps = 100000;
test_steps!( // !!!! Get a proper main loop !!!!
if iter == 0 {
assert!(stream_sound_inst.is_playing());
} else if iter == 100000 - 2 {
assert!(stream_sound_inst.is_playing());
stream_sound_inst.stop();
assert!(!stream_sound_inst.is_playing());
}
);
Sourcepub fn from_file(file_utf8: impl AsRef<Path>) -> Result<Sound, StereoKitError>
pub fn from_file(file_utf8: impl AsRef<Path>) -> Result<Sound, StereoKitError>
Loads a sound effect from file! Currently, StereoKit supports .wav and .mp3 files. Audio is converted to mono. https://stereokit.net/Pages/StereoKit/Sound/FromFile.html
file_utf8
- Name of the audio file! Supports .wav and .mp3 files.
see also sound_create
§Examples
use stereokit_rust::{maths::Vec3, sound::Sound};
let mut position = Vec3::new(-0.5, 0.0, 0.5);
let mut plane_sound = Sound::from_file("sounds/no.wav")
.expect("no.wav should be in the sounds folder");
assert_eq!(plane_sound.get_id(), "sounds/no.wav");
plane_sound.id("sound_plane").decibels(90.0);
let mut plane_sound_inst = plane_sound.play(position, Some(1.0));
number_of_steps = 100000;
test_steps!( // !!!! Get a proper main loop !!!!
if iter < 10000 {
assert!(plane_sound_inst.is_playing());
}
);
Sourcepub fn from_samples(
in_arr_samples_at_48000s: &[f32],
) -> Result<Sound, StereoKitError>
pub fn from_samples( in_arr_samples_at_48000s: &[f32], ) -> Result<Sound, StereoKitError>
This function will create a sound from an array of samples. Values should range from -1 to +1, and there should be 48,000 values per second of audio. https://stereokit.net/Pages/StereoKit/Sound/FromSamples.html
in_arr_samples_at_48000s
- Values should range from -1 to +1, and there should be 48,000 per second of audio.
see also sound_create_samples
Sound::write_samples
§Examples
use stereokit_rust::sound::Sound;
let mut samples: Vec<f32> = vec![0.0; 48000];
for i in 0..48000 {
samples[i] = (i as f32 / 48000.0).sin();
}
let mut sound = Sound::from_samples(&samples)
.expect("Sound should be created from samples");
assert!(sound.get_id().starts_with("auto/sound_"));
sound.id("sound_samples");
let mut sound_inst = sound.play([0.0, 0.0, -0.5], Some(0.5));
test_steps!( // !!!! Get a proper main loop !!!!
assert!(sound_inst.is_playing());
);
Sourcepub fn generate(
generator: unsafe extern "C" fn(f32) -> f32,
duration: f32,
) -> Result<Sound, StereoKitError>
pub fn generate( generator: unsafe extern "C" fn(f32) -> f32, duration: f32, ) -> Result<Sound, StereoKitError>
This function will generate a sound from a function you provide! The function is called once for each sample in the duration. As an example, it may be called 48,000 times for each second of duration. https://stereokit.net/Pages/StereoKit/Sound/Generate.html
generator
- This function takes a time value as an argument, which will range from 0-duration, and should return a value from -1 - +1 representing the audio wave at that point in time.duration
- The duration of the sound in seconds.
see also sound_generate
§Examples
use stereokit_rust::sound::Sound;
unsafe extern "C" fn generator(sample_time: f32) -> f32 {
(sample_time * 440.0 * 2.0 * std::f32::consts::PI).sin()
}
let mut sound = Sound::generate(generator, 1.0)
.expect("Sound should be created from generator");
assert!(sound.get_id().starts_with("auto/sound_"));
sound.id("sound_generator");
let mut sound_inst = sound.play([0.0, 0.0, -0.5], Some(0.5));
number_of_steps = 100000;
test_steps!( // !!!! Get a proper main loop !!!!
if iter < 10000 {
assert!(sound_inst.is_playing());
}
);
Sourcepub fn find<S: AsRef<str>>(id: S) -> Result<Sound, StereoKitError>
pub fn find<S: AsRef<str>>(id: S) -> Result<Sound, StereoKitError>
ooks for a Sound asset that’s already loaded, matching the given id! https://stereokit.net/Pages/StereoKit/Sound/Find.html
id
- Which Sound are you looking for?
see also sound_find
Sound::clone_ref
§Examples
use stereokit_rust::sound::Sound;
let mut plane_sound = Sound::from_file("sounds/plane_engine.mp3")
.expect("plane_engine.mp3 should be in the sounds folder");
plane_sound.id("sound_plane").decibels(70.0);
let same_sound = Sound::find("sound_plane")
.expect("sound_plane should be found");
assert_eq!(plane_sound.get_id(), same_sound.get_id());
assert_eq!(plane_sound, same_sound);
Sourcepub fn clone_ref(&self) -> Sound
pub fn clone_ref(&self) -> Sound
Creates a clone of the same reference. Basically, the new variable is the same asset. This is what you get by calling find() method. https://stereokit.net/Pages/StereoKit/Sound/Find.html
see also sound_find
Sound::find
§Examples
use stereokit_rust::sound::Sound;
let mut plane_sound = Sound::from_file("sounds/plane_engine.mp3")
.expect("plane_engine.mp3 should be in the sounds folder");
let same_sound = plane_sound.clone_ref();
assert_eq!(plane_sound.get_id(), same_sound.get_id());
assert_eq!(plane_sound, same_sound);
Sourcepub fn id<S: AsRef<str>>(&mut self, id: S) -> &mut Self
pub fn id<S: AsRef<str>>(&mut self, id: S) -> &mut Self
Sets the unique identifier of this asset resource! This can be helpful for debugging, managing your assets, or finding them later on! https://stereokit.net/Pages/StereoKit/Sound/Id.html
see also sound_set_id
§Examples
use stereokit_rust::sound::Sound;
// A sound from a file will have its file path as its id
let mut plane_sound = Sound::from_file("sounds/plane_engine.mp3")
.expect("plane_engine.mp3 should be in the sounds folder");
assert_eq!(plane_sound.get_id(), "sounds/plane_engine.mp3");
plane_sound.id("plane_sound");
assert_eq!(plane_sound.get_id(), "plane_sound");
// A sound other than from a file will have an auto id
let mut stream_sound = Sound::create_stream(0.5).
expect("A sound stream should be created");
assert!(stream_sound.get_id().starts_with("auto/sound_"));
stream_sound.id("sound_stream");
Sourcepub fn play(&self, at: impl Into<Vec3>, volume: Option<f32>) -> SoundInst
pub fn play(&self, at: impl Into<Vec3>, volume: Option<f32>) -> SoundInst
Plays the sound at the 3D location specified, using the volume parameter as an additional volume control option! Sound volume falls off from 3D location, and can also indicate direction and location through spatial audio cues. So make sure the position is where you want people to think it’s from! Currently, if this sound is playing somewhere else, it’ll be canceled, and moved to this location. https://stereokit.net/Pages/StereoKit/Sound/Play.html
at
- World space location for the audio to play at.volume
- Volume modifier for the effect! 1 means full volume, and 0 means completely silent. If None will have default value of 1.0
see also sound_play
SoundInst::position
§Examples
use stereokit_rust::{maths::Vec3, sound::Sound};
let mut position = Vec3::new(-0.5, 0.0, 0.5);
let mut plane_sound = Sound::from_file("sounds/plane_engine.mp3").
expect("A sound should be created");
plane_sound.id("sound_plane").decibels(70.0);
let mut plane_sound_inst = plane_sound.play(position, Some(1.0));
test_steps!( // !!!! Get a proper main loop !!!!
assert!(plane_sound_inst.is_playing());
if iter == 2 {
// Move the sound to the other side
plane_sound_inst.position(Vec3::new(0.5, 0.0, 0.5));
}
);
Sourcepub fn decibels(&self, decibels: f32)
pub fn decibels(&self, decibels: f32)
https://stereokit.net/Pages/StereoKit/Sound/Decibels.html
see also sound_set_decibels
§Examples
use stereokit_rust::{maths::Vec3, sound::Sound};
let mut position = Vec3::new(-0.5, 0.0, 0.5);
let mut plane_sound = Sound::from_file("sounds/plane_engine.mp3").
expect("A sound should be created");
plane_sound.id("sound_plane").decibels(70.0);
let mut plane_sound_inst = plane_sound.play(position, Some(1.0));
test_steps!( // !!!! Get a proper main loop !!!!
assert!(plane_sound_inst.is_playing());
if iter == 1 {
// Change decibel for all instances
assert_eq!(plane_sound.get_decibels(), 70.0);
plane_sound.decibels(10.0);
} else if iter == 2 {
assert_eq!(plane_sound.get_decibels(), 10.0);
}
);
Sourcepub fn read_samples(
&self,
out_arr_samples: &mut [f32],
sample_count: Option<u64>,
) -> u64
pub fn read_samples( &self, out_arr_samples: &mut [f32], sample_count: Option<u64>, ) -> u64
This will read samples from the sound stream, starting from the first unread sample. Check UnreadSamples for how many samples are available to read. https://stereokit.net/Pages/StereoKit/Sound/ReadSamples.html
out_arr_samples
- A pre-allocated buffer to read the samples into! This function will stop reading when this buffer is full, or when the sound runs out of unread samples.sample_count
- The maximum number of samples to read, this should be less than or equal to the number of samples the sampleBuffer can contain.
see also sound_read_samples
§Examples
use stereokit_rust::sound::Sound;
// Half of the samples won't be kept in the buffer (0.5 instead of 1.0)
let mut stream_sound = Sound::create_stream(0.5).
expect("A sound stream should be created");
let mut samples: Vec<f32> = vec![0.0; 48000];
for i in 0..48000 {
samples[i] = (i as f32 / 48000.0).sin();
}
stream_sound.write_samples(samples.as_slice(), Some(48000));
assert_eq!(stream_sound.get_unread_samples(), 24000);
let mut read_samples: Vec<f32> = vec![0.0; 48000];
let read_count = stream_sound.read_samples(read_samples.as_mut_slice(), Some(48000));
assert_eq!(read_count, 24000);
for i in 0..24000 {
assert_eq!(samples[i], read_samples[i]);
}
let read_count = stream_sound.read_samples(read_samples.as_mut_slice(), Some(48000));
assert_eq!(read_count, 0);
Sourcepub fn write_samples(&self, in_arr_samples: &[f32], sample_count: Option<u64>)
pub fn write_samples(&self, in_arr_samples: &[f32], sample_count: Option<u64>)
Only works if this Sound is a stream type! This writes a number of audio samples to the sample buffer, and samples should be between -1 and +1. Streams are stored as ring buffers of a fixed size, so writing beyond the capacity of the ring buffer will overwrite the oldest samples.
StereoKit uses 48,000 samples per second of audio.
This variation of the method bypasses marshalling memory into C#, so it is the most optimal way to copy sound data if your source is already in native memory! https://stereokit.net/Pages/StereoKit/Sound/WriteSamples.html
in_arr_samples
- An array of audio samples, where each sample is between -1 and +1.sample_count
- You can use this to write only a subset of the samples in the array, rather than the entire array!
see also sound_write_samples
§Examples
use stereokit_rust::sound::Sound;
// Half of the samples won't be kept in the buffer (0.5 instead of 1.0)
let mut stream_sound = Sound::create_stream(1.0).
expect("A sound stream should be created");
let mut samples: Vec<f32> = vec![0.0; 48000];
for i in 0..48000 {
samples[i] = (i as f32 / 48000.0).sin();
}
stream_sound.write_samples(samples.as_slice(), Some(48000));
assert_eq!(stream_sound.get_unread_samples(), 48000);
Sourcepub fn get_id(&self) -> &str
pub fn get_id(&self) -> &str
The id of this sound https://stereokit.net/Pages/StereoKit/Sound/Id.html
see also sound_get_id
see example in Sound::id
Sourcepub fn get_cursor_samples(&self) -> u64
pub fn get_cursor_samples(&self) -> u64
This is the current position of the playback cursor, measured in samples from the start of the audio data. https://stereokit.net/Pages/StereoKit/Sound/CursorSamples.html
see also sound_cursor_samples
§Examples
use stereokit_rust::sound::Sound;
let mut samples: Vec<f32> = vec![0.0; 48000];
for i in 0..48000 {
samples[i] = (i as f32 / 48000.0).sin();
}
let mut sound = Sound::from_samples(&samples)
.expect("Sound should be created from samples");
assert_eq!(sound.get_cursor_samples(), 0);
let mut sound_inst = sound.play([0.0, 0.0, -0.5], Some(0.5));
sound_inst.stop();
test_steps!( // !!!! Get a proper main loop !!!!
if iter == 1 {
assert_eq!(sound.get_total_samples(), 48000);
assert_eq!(sound.get_cursor_samples(), 0);
sound.write_samples(&samples, None);
} else if iter == 2 {
assert_eq!(sound.get_cursor_samples(), 0);
}
);
Sourcepub fn get_duration(&self) -> f32
pub fn get_duration(&self) -> f32
This will return the total length of the sound in seconds. https://stereokit.net/Pages/StereoKit/Sound/Duration.html
see also sound_duration
§Examples
use stereokit_rust::sound::Sound;
let mut samples: Vec<f32> = vec![0.0; 48000];
for i in 0..48000 {
samples[i] = (i as f32 / 48000.0).sin();
}
let mut sound = Sound::from_samples(&samples)
.expect("Sound should be created from samples");
assert_eq!(sound.get_duration(), 1.0);
let mut sound_file = Sound::from_file("sounds/no.wav")
.expect("Sound should be created from file");
assert_eq!(sound_file.get_duration(), 1.4830834);
Sourcepub fn get_decibels(&self) -> f32
pub fn get_decibels(&self) -> f32
https://stereokit.net/Pages/StereoKit/Sound/Decibels.html
see also sound_get_decibels
see example in Sound::decibels
Sourcepub fn get_total_samples(&self) -> u64
pub fn get_total_samples(&self) -> u64
This will return the total number of audio samples used by the sound! StereoKit currently uses 48,000 samples per second for all audio. https://stereokit.net/Pages/StereoKit/Sound/TotalSamples.html
see also sound_total_samples
§Examples
use stereokit_rust::sound::Sound;
let mut samples: Vec<f32> = vec![0.0; 48000];
for i in 0..48000 {
samples[i] = (i as f32 / 48000.0).sin();
}
let mut sound = Sound::from_samples(&samples)
.expect("Sound should be created from samples");
assert_eq!(sound.get_total_samples(), 48000);
let mut sound_file = Sound::from_file("sounds/no.wav")
.expect("Sound should be created from file");
assert_eq!(sound_file.get_duration(), 1.4830834);
// 1.4830834 * 48000 = 71188
assert_eq!(sound_file.get_total_samples(), 71188);
Sourcepub fn get_unread_samples(&self) -> u64
pub fn get_unread_samples(&self) -> u64
This is the maximum number of samples in the sound that are currently available for reading via ReadSamples! ReadSamples will reduce this number by the amount of samples read. This is only really valid for Stream sounds, all other sound types will just return 0. https://stereokit.net/Pages/StereoKit/Sound/UnreadSamples.html
see also sound_unread_samples
§Examples
use stereokit_rust::sound::Sound;
// Half of the samples won't be kept in the buffer (0.5 instead of 1.0)
let mut stream_sound = Sound::create_stream(1.0).
expect("A sound stream should be created");
let mut samples: Vec<f32> = vec![0.0; 48000];
for i in 0..48000 {
samples[i] = (i as f32 / 48000.0).sin();
}
stream_sound.write_samples(samples.as_slice(), Some(48000));
assert_eq!(stream_sound.get_unread_samples(), 48000);
let mut read_samples: Vec<f32> = vec![0.0; 48000];
let read_count = stream_sound.read_samples(read_samples.as_mut_slice(), Some(48000));
assert_eq!(read_count, 48000);
assert_eq!(stream_sound.get_unread_samples(), 0);
Sourcepub fn click() -> Self
pub fn click() -> Self
A default click sound that lasts for 300ms. It’s a procedurally generated sound based on a mouse press, with extra low frequencies in it. https://stereokit.net/Pages/StereoKit/Sound/Click.html
§Examples
use stereokit_rust::{maths::Vec3, sound::Sound};
let mut click_sound = Sound::click();
assert_eq!(click_sound.get_id(), "default/sound_click");
let mut click_sound_inst = click_sound.play([0.0, 0.0, -0.5], Some(0.5));
number_of_steps = 100;
test_steps!( // !!!! Get a proper main loop !!!!
assert!(click_sound_inst.is_playing());
);
Sourcepub fn unclick() -> Self
pub fn unclick() -> Self
A default unclick sound that lasts for 300ms. It’s a procedurally generated sound based on a mouse press, with extra low frequencies in it. https://stereokit.net/Pages/StereoKit/Sound/Unclick.html
§Examples
use stereokit_rust::{maths::Vec3, sound::Sound};
let mut unclick_sound = Sound::unclick();
assert_eq!(unclick_sound.get_id(), "default/sound_unclick");
let mut unclick_sound_inst = unclick_sound.play([0.0, 0.0, -0.5], Some(0.5));
number_of_steps = 100;
test_steps!( // !!!! Get a proper main loop !!!!
assert!(unclick_sound_inst.is_playing());
);
Sourcepub fn grab() -> Self
pub fn grab() -> Self
A default grab sound https://stereokit.net/Pages/StereoKit/Sound.html
§Examples
use stereokit_rust::{maths::Vec3, sound::Sound};
let mut grab_sound = Sound::grab();
assert_eq!(grab_sound.get_id(), "default/sound_grab");
let mut grab_sound_inst = grab_sound.play([0.0, 0.0, -0.5], Some(0.5));
number_of_steps = 100;
test_steps!( // !!!! Get a proper main loop !!!!
assert!(grab_sound_inst.is_playing());
);
Sourcepub fn ungrab() -> Self
pub fn ungrab() -> Self
A default ungrab sound https://stereokit.net/Pages/StereoKit/Sound.html
§Examples
use stereokit_rust::{maths::Vec3, sound::Sound};
let mut ungrab_sound = Sound::ungrab();
assert_eq!(ungrab_sound.get_id(), "default/sound_ungrab");
let mut ungrab_sound_inst = ungrab_sound.play([0.0, 0.0, -0.5], Some(0.5));
number_of_steps = 100;
test_steps!( // !!!! Get a proper main loop !!!!
assert!(ungrab_sound_inst.is_playing());
);
Trait Implementations§
Source§impl IAsset for Sound
impl IAsset for Sound
Source§fn get_id(&self) -> &str
fn get_id(&self) -> &str
impl Send for Sound
impl StructuralPartialEq for Sound
impl Sync for Sound
Auto Trait Implementations§
Blanket Implementations§
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> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.