Example generation#

Includes:

  1. Generating with n random static and moving sources

  2. Generating 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]: