Examples#

The most basic operation this extension can provide is to load a sound from disk and play it. More detailed usages can also wait for the sound to finish playing by periodically polling it, or query the length of a sound asset. The example below will demonstrate all usages:

Python#

import omni.kit.uiaudio
import time


def play_one_shot_ui_sound(filename: str, count: int = 1, delay_ms: int = 0, wait: bool = False) -> bool:
    uiaudio = omni.kit.uiaudio.get_ui_audio_interface()
    snd = uiaudio.create_sound(filename)

    if count <= 0:
        count = 1

    if snd == None:
        return False

    length = uiaudio.get_sound_length(snd)
    print(f"The sound asset is {length}s long.")

    for i in range(count - 1):
        uiaudio.play_sound(snd)
        # wait a bit before starting the next sound.  Note that a sleep like this shouldn't be used
        # in production code since it will lock up the UI or other threads.  An `asyncio.sleep()`
        # call should be used instead on async functions.
        time.sleep(delay_ms / 1000.0)

    uiaudio.play_sound(snd)

    if wait:
        while uiaudio.is_sound_playing(snd):
            time.sleep(0.250)

    snd = None
    print("done!")


play_one_shot_ui_sound("soundToPlay.mp3")
play_one_shot_ui_sound("soundToPlay.mp3", 2, 500, True)
play_one_shot_ui_sound("soundToPlay.mp3", 1, 5000, True)
play_one_shot_ui_sound("soundToPlay.mp3", 2, 500)

C++#

First, include the header files necessary for the example:

#include <omni/audio/IUiAudio.h>

#include <carb/InterfaceUtils.h>
#include <carb/logging/Log.h>

#include <chrono>
#include <thread>

Then create a helper function that can play a sound by a requested filename:

/** Loads a sound asset, plays it twice, and optionally waits for it to finish playing.
 *
 *  @param[in] filename The name and path to the local file asset to be loaded.  This must be
 *                      either an WAV, MP3, FLAC, Ogg/Vorbis, or Opus formatted file.  This
 *                      may not be an empty string or `nullptr`.
 *  @param[in] count    The total number of times to play the sound.  Note that setting this
 *                      to a value larger than 1 will cause this call to block for `(count - 1) *
 *                      delayMs` milliseconds.
 *  @param[in] delayMs  The delay in milliseconds between playing the sound the first and
 *                      second times.  Set this to 0 to have both instances of the sound play
 *                      only once.
 *  @param[in] wait     Set to `true` to block this function from returning until the last
 *                      instance of the requested sound is finished playing.  Set to `false` to
 *                      simply fire-and-forget the sound.
 *  @returns `true` if the sounds were successfully queued.  Returns `false` if the asset could
 *           not be loaded or coud not be played.
 */
bool playOneShotUiSound(const char* filename, size_t count = 1, size_t delayMs = 0, bool wait = false)
{
    auto uiAudio = carb::getCachedInterface<omni::audio::IUiAudio>();
    std::unique_ptr<omni::audio::UiSound> snd;
    double length;

    if (count == 0)
        count = 1;

    if (uiAudio == nullptr)
    {
        CARB_LOG_WARN("failed to acquire the `omni::audio::IUiAudio` interface.");
        return false;
    }


    snd.reset(uiAudio->createSound(filename));

    if (snd == nullptr)
    {
        CARB_LOG_WARN("failed to load the sound asset '%s' from disk.", filename);
        return false;
    }


    length = uiAudio->getSoundLength(snd.get());
    CARB_LOG_VERBOSE("The sound asset is %gs long.", length);

    for (size_t i = 0; i < count - 1; i++)
    {
        uiAudio->playSound(snd.get());
        carb::cpp::this_thread::sleep_for(std::chrono::milliseconds(delayMs));
    }

    uiAudio->playSound(snd.get());

    if (wait)
    {
        while (uiAudio->isSoundPlaying(snd.get()))
            carb::cpp::this_thread::sleep_for(std::chrono::milliseconds(250));
    }

    snd.reset();
    CARB_LOG_VERBOSE("done!");

    return true;
}