Example generation#
Includes:
Generating with
n
random static and moving sourcesGenerating with sources in specified positions
Import dependencies#
[1]:
import os
from pathlib import Path
from scipy import stats
from audiblelight import utils
from audiblelight.core import Scene
Set default values#
All of these values can (and should!) be changed in order to experiment with the functionality of AudibleLight
.
[2]:
# OUTPUT DIRECTORY
OUTFOLDER = utils.get_project_root() / 'spatial_scenes'
if not os.path.isdir(OUTFOLDER):
os.makedirs(OUTFOLDER)
[3]:
# PATHS
FG_FOLDER = utils.get_project_root() / "tests/test_resources/soundevents"
MESH_PATH = utils.get_project_root() / "tests/test_resources/meshes/Oyens.glb"
AMBIENCE_PATH = utils.get_project_root() / "tests/test_resources/soundevents/waterTap/95709.wav"
AMBIENCE_NOISE = "white" # an alternative to specifying a filepath
[4]:
# SCENE SETTINGS
DURATION = 30.0 # seconds
MIC_ARRAY_NAME = 'ambeovr' # could also be "eigenmike32"...
MAX_OVERLAP = 3 # maximum number of temporally overlapping sound-events
MICROPHONE_POSITION = [2.5, -1.0, 1.0] # inside the living room
[5]:
# SCENE-WIDE DISTRIBUTIONS
MIN_VELOCITY, MAX_VELOCITY = 0.5, 1.5 # meters per second
MIN_SNR, MAX_SNR = 2, 8
MIN_RESOLUTION, MAX_RESOLUTION = 0.25, 2.0 # Hz/IRs per second
REF_DB = -50
[6]:
# This function simply returns a fresh `Scene` object with the parameters set in the cells above
def create_scene() -> Scene:
return Scene(
duration=DURATION,
mesh_path=Path(MESH_PATH),
scene_start_dist=stats.uniform(0.0, DURATION - 1),
event_start_dist=None,
event_duration_dist=None,
event_velocity_dist=stats.uniform(MIN_VELOCITY, MAX_VELOCITY),
event_resolution_dist=stats.uniform(MIN_RESOLUTION, MAX_RESOLUTION),
snr_dist=stats.uniform(MIN_SNR, MAX_SNR),
fg_path=Path(FG_FOLDER),
max_overlap=MAX_OVERLAP,
ref_db=REF_DB
)
[7]:
# These can be changed at will
N_STATIC_EVENTS = 4
N_MOVING_EVENTS = 1
[ ]:
# Create a fresh scene object
scene = create_scene()
[9]:
# Add the microphone type we want, at the desired position
scene.add_microphone(microphone_type=MIC_ARRAY_NAME, alias=MIC_ARRAY_NAME, position=MICROPHONE_POSITION)
[10]:
# Add the correct number of static and moving scenes
for _ in range(N_STATIC_EVENTS):
scene.add_event(event_type="static")
for _ in range(N_MOVING_EVENTS):
scene.add_event(event_type="moving")
2025-08-11 18:13:15.836 | INFO | audiblelight.core:add_event:493 - Event added successfully: Static 'Event' with alias 'event000', audio file '/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/maleSpeech/93899.wav' (unloaded), and 1 emitters.
2025-08-11 18:13:16.089 | INFO | audiblelight.core:add_event:493 - Event added successfully: Static 'Event' with alias 'event001', audio file '/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/maleSpeech/93856.wav' (unloaded), and 1 emitters.
2025-08-11 18:13:16.362 | INFO | audiblelight.core:add_event:493 - Event added successfully: Static 'Event' with alias 'event002', audio file '/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/femaleSpeech/236385.wav' (unloaded), and 1 emitters.
2025-08-11 18:13:16.698 | INFO | audiblelight.core:add_event:493 - Event added successfully: Static 'Event' with alias 'event003', audio file '/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/telephone/431669.wav' (unloaded), and 1 emitters.
2025-08-11 18:13:18.311 | INFO | audiblelight.core:add_event:493 - Event added successfully: Moving 'Event' with alias 'event004', audio file '/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/telephone/30085.wav' (unloaded), and 6 emitters.
[11]:
# Now add the ambience: this is a mono audio file that will be tiled correctly
scene.add_ambience(filepath=AMBIENCE_PATH)
[12]:
# Do the generation!
scene.generate(
audio_fname="audio_out_random.wav",
metadata_fname="metadata_out_random.json",
)
2025-08-11 18:13:18.431 | INFO | audiblelight.worldstate:simulate:1623 - Starting simulation with 10 emitters, 1 microphones
2025-08-11 18:14:11.335 | INFO | audiblelight.worldstate:simulate:1631 - Finished simulation! Overall indirect ray efficiency: 0.997
Rendering event audio...: 100%|██████████| 5/5 [00:11<00:00, 2.33s/it]
2025-08-11 18:14:24.205 | INFO | audiblelight.synthesize:render_audio_for_all_scene_events:520 - Rendered scene audio in 11.68 seconds.!
The audio file and metadata should now be accessible inside our output folder.
Add in events at specific positions#
Now, we can be a bit more granular, and specify the position for our audio events.
[7]:
# These dictionaries just contain kwargs passed to `add_event`
# We define them in a list here so we can pass them in in a loop
SOURCES = [
# First Event: static emitter
# Coordinates are cartesian, in absolute terms
{
"event_type": "static",
"alias": "speech",
"filepath": FG_FOLDER / "maleSpeech/93853.wav",
"polar": True,
"position": [90, 0.0, 0.5],
"scene_start": 0.0, # start at the beginning of the scene
"duration": None,
},
# Second Event: moving emitter with linear trajectory
# Coordinates are cartesian, in absolute terms
{
"event_type": "moving",
"alias": "music",
"filepath": FG_FOLDER / "music/000010.mp3",
"polar": False,
"position": [2.9, -2.5, 0.3],
"shape": "random",
"scene_start": 6.0, # overlaps with telephone event, below
"spatial_resolution": 1.0, # Hz
"spatial_velocity": 0.5,
"duration": 5,
},
# Third Event: moving emitter with random walk
# Coordinates are in polar terms WRT mic
{
"event_type": "moving",
"alias": "telephone",
"filepath": FG_FOLDER / "telephone/30085.wav",
"polar": True,
"position": [0.0, 90.0, 1.0],
"shape": "linear",
"scene_start": 5.0, # start five seconds in
"spatial_resolution": 1.5,
"spatial_velocity": 1.0,
"duration": 2,
}
# Add your own here...
]
[8]:
# Create a fresh scene object
scene = create_scene()
CreateContext: Context created
Material for category 'default' was not found. Using default material instead.
[9]:
# Add the microphone type we want, at the desired position
scene.clear_microphones()
scene.add_microphone(microphone_type=MIC_ARRAY_NAME, alias=MIC_ARRAY_NAME, position=MICROPHONE_POSITION)
[10]:
# Clean any events already added to the scene
scene.clear_events()
# Add the sound sources
for source in SOURCES:
scene.add_event(**source)
2025-08-12 15:52:27.566 | INFO | audiblelight.core:add_event:549 - Event added successfully: Static 'Event' with alias 'speech', audio file '/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/maleSpeech/93853.wav' (unloaded), and 1 emitters.
2025-08-12 15:52:27.768 | INFO | audiblelight.core:add_event:549 - Event added successfully: Moving 'Event' with alias 'music', audio file '/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/music/000010.mp3' (unloaded), and 6 emitters.
2025-08-12 15:52:33.013 | INFO | audiblelight.core:add_event:549 - Event added successfully: Moving 'Event' with alias 'telephone', audio file '/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/telephone/30085.wav' (unloaded), and 4 emitters.
[12]:
# Now add the ambience: this is a mono audio file that will be tiled correctly
scene.clear_ambience()
scene.add_ambience(noise=AMBIENCE_NOISE)
[ ]:
# Do the generation!
scene.generate(
audio_fname="audio_out_choice.wav",
metadata_fname="metadata_out_choice.json",
)
[11]:
# Pretty print the metadata JSON
print(repr(scene))
{
"audiblelight_version": "0.1.0",
"rlr_audio_propagation_version": "0.0.1",
"creation_time": "2025-08-12_15:52:36",
"duration": 30.0,
"ref_db": -50,
"max_overlap": 3,
"fg_path": "/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents",
"ambience": {},
"events": {
"speech": {
"alias": "speech",
"filename": "93853.wav",
"filepath": "/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/maleSpeech/93853.wav",
"class_id": null,
"class_label": null,
"is_moving": false,
"scene_start": 0.0,
"scene_end": 0.4876190476190476,
"event_start": 0.0,
"event_end": 0.4876190476190476,
"duration": 0.4876190476190476,
"snr": 2.084342568564807,
"sample_rate": 44100.0,
"spatial_resolution": null,
"spatial_velocity": null,
"num_emitters": 1,
"emitters": [
[
2.5,
-0.5,
1.0
]
],
"emitters_relative": {
"ambeovr": [
[
90.0,
0.0,
0.5
]
]
}
},
"music": {
"alias": "music",
"filename": "000010.mp3",
"filepath": "/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/music/000010.mp3",
"class_id": null,
"class_label": null,
"is_moving": true,
"scene_start": 6.0,
"scene_end": 11.0,
"event_start": 0.0,
"event_end": 5.0,
"duration": 5.0,
"snr": 4.810330462840957,
"sample_rate": 44100.0,
"spatial_resolution": 1.0,
"spatial_velocity": 0.5,
"num_emitters": 6,
"emitters": [
[
2.9,
-2.5,
0.3
],
[
2.899163232807978,
-2.513590454319441,
0.33436078168716565
],
[
2.9150129510701768,
-2.522839701771863,
0.3394386871688193
],
[
2.996728535936912,
-2.760346235793826,
0.3662909094885454
],
[
2.8975386710727236,
-2.9855524955924073,
0.5210420305566392
],
[
2.903862497813279,
-3.202793040557058,
0.3390289619201368
]
],
"emitters_relative": {
"ambeovr": [
[
284.9314171781375,
-24.271072303844804,
1.70293863659264
],
[
284.77364923519315,
-23.03696164125306,
1.7009888061914955
],
[
285.24436828856676,
-22.70962519969716,
1.7110282741257803
],
[
285.757825134524,
-19.109258851094992,
1.9357544574879262
],
[
281.32181224642505,
-13.30745305847426,
2.080830710135933
],
[
280.389288308529,
-16.443491142339546,
2.33501280721262
]
]
}
},
"telephone": {
"alias": "telephone",
"filename": "30085.wav",
"filepath": "/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/soundevents/telephone/30085.wav",
"class_id": null,
"class_label": null,
"is_moving": true,
"scene_start": 5.0,
"scene_end": 7.0,
"event_start": 0.0,
"event_end": 2.0,
"duration": 2.0,
"snr": 9.901234347874784,
"sample_rate": 44100.0,
"spatial_resolution": 1.5,
"spatial_velocity": 1.0,
"num_emitters": 4,
"emitters": [
[
2.5,
-1.0,
2.0
],
[
1.9978254333669292,
-0.9012029561309868,
1.7229742325609605
],
[
1.4956508667338582,
-0.8024059122619734,
1.445948465121921
],
[
0.9934763001007874,
-0.7036088683929602,
1.1689226976828813
]
],
"emitters_relative": {
"ambeovr": [
[
0.0,
90.0,
1.0
],
[
168.8698655535021,
54.704930608453004,
0.8857944977236413
],
[
168.8698655535021,
23.54111835511403,
1.1165261477216153
],
[
168.8698655535021,
6.278345748532462,
1.5446670317727949
]
]
}
}
},
"state": {
"emitters": {
"speech": [
[
2.5,
-0.5,
1.0
]
],
"music": [
[
2.9,
-2.5,
0.3
],
[
2.899163232807978,
-2.513590454319441,
0.33436078168716565
],
[
2.9150129510701768,
-2.522839701771863,
0.3394386871688193
],
[
2.996728535936912,
-2.760346235793826,
0.3662909094885454
],
[
2.8975386710727236,
-2.9855524955924073,
0.5210420305566392
],
[
2.903862497813279,
-3.202793040557058,
0.3390289619201368
]
],
"telephone": [
[
2.5,
-1.0,
2.0
],
[
1.9978254333669292,
-0.9012029561309868,
1.7229742325609605
],
[
1.4956508667338582,
-0.8024059122619734,
1.445948465121921
],
[
0.9934763001007874,
-0.7036088683929602,
1.1689226976828813
]
]
},
"microphones": {
"ambeovr": {
"name": "ambeovr",
"micarray_type": "AmbeoVR",
"is_spherical": true,
"n_capsules": 4,
"capsule_names": [
"FLU",
"FRD",
"BLD",
"BRU"
],
"coordinates_absolute": [
[
2.5057922796533956,
-0.9942077203466043,
1.0057357643635105
],
[
2.5057922796533956,
-1.0057922796533958,
0.9942642356364896
],
[
2.4942077203466044,
-0.9942077203466043,
0.9942642356364896
],
[
2.4942077203466044,
-1.0057922796533958,
1.0057357643635105
]
],
"coordinates_center": [
2.5,
-1.0,
1.0
]
}
},
"mesh": {
"fname": "Oyens",
"ftype": ".glb",
"fpath": "/home/huw-cheston/Documents/python_projects/AudibleLight/tests/test_resources/meshes/Oyens.glb",
"units": "meters",
"from_gltf_primitive": false,
"name": "defaultobject",
"node": "defaultobject",
"bounds": [
[
-3.0433080196380615,
-10.448445320129395,
-1.1850370168685913
],
[
5.973234176635742,
2.101027011871338,
2.4577369689941406
]
],
"centroid": [
1.527919030159762,
-4.550817438070386,
1.162934397641578
]
},
"rlr_config": {
"diffraction": 1,
"direct": 1,
"direct_ray_count": 500,
"direct_sh_order": 3,
"frequency_bands": 4,
"global_volume": 1.0,
"hrtf_back": [
0.0,
0.0,
1.0
],
"hrtf_right": [
1.0,
0.0,
0.0
],
"hrtf_up": [
0.0,
1.0,
0.0
],
"indirect": 1,
"indirect_ray_count": 5000,
"indirect_ray_depth": 200,
"indirect_sh_order": 1,
"max_diffraction_order": 10,
"max_ir_length": 4.0,
"mesh_simplification": 0,
"sample_rate": 44100.0,
"size": 146,
"source_ray_count": 200,
"source_ray_depth": 10,
"temporal_coherence": 0,
"thread_count": 1,
"transmission": 1,
"unit_scale": 1.0
},
"empty_space_around_mic": 0.1,
"empty_space_around_emitter": 0.2,
"empty_space_around_surface": 0.2,
"empty_space_around_capsule": 0.05,
"repair_threshold": null
}
}
Visualise the scene#
[14]:
out = scene.state.create_scene(emitter_radius=0.05)
out.show()
[14]: