This sample demonstrates the usage of the Web Audio notifications that Coherent UI provides through the Coherent::UI::ViewListener class and its derivates.
The sample solution is already configured and you only have to compile and run it.
It uses a sample mini game framework that provides very basic functionality.
The output will be in the Coherent/Samples/UI/bin directory.
Create
notification will contain information about the audio stream format. More details about each one follow in the sample walkthrough.Play
notification, you should start consuming data using the Coherent::UI::View::GetAudioData
API.Pause
notification is received since this API call informs the Coherent UI Host that the stream playback has progressed.Close
notification you can release all related resources.Coherent::UI::View::GetAudioData
might stop before a stream Pause
notification is received, causing possible deadlocks.The sample utilizes a very basic audio system framework. It consists of the following interfaces:
IAudioSystem
- manages audio device creation and update, sound creation and destructionISound
- provides an API for sound manipulationIMoreDataProvider
- and interface that can be passed to an ISound
, which will then be used as a callback when more audio data needs to be buffered.The sample provides two implementations - using OpenAL and FMOD.
inc
and lib
directories located in the FMOD_SDK/api/lowlevel
folder into Coherent/Samples/UI/C++/Sample_ClientAudio/external/FMOD
.The first important thing to do when you want to play web audio yourself is to use the EnableClientAudioPlayback
property in the ContextSettings
structure before initializing the View Context:
The sample view listener handles the web audio stream notifications. Those are:
The view listener keeps a collection of the streams and information about them. When the OnAudioStreamCreated
event is received, a new entry in the collection is added with information about the stream with the received ID. This information also contains a pointer to an ISound
instance, which is null initially. The information is contained in this structure:
When the OnAudioStreamPlay
event is received, a new ISound
is created that will be responsible for playing the data from the stream. The entry in the collection for the corresponding stream ID is updated so we can identify the ISound
by stream ID. A reverse map is also maintained so we can identify the stream ID by an ISound
instance. Next, a very important call is made. The newly created ISound
instance is assigned an IMoreDataProvider
- in the case of this sample, this is the view listener, which implements the interface.
Now that the ISound
is ready for playing, we have to provide the actual audio data. The ISound
uses the IMoreDataProvider
that was set to get it. In our case, as we already saw, the IMoreDataProvider
is the view listener. The view listener is a convenient audio data provider since it already has access to the Coherent::UI::View instance. The Coherent::UI::View instance is used to obtain more data using the Coherent::UI::View::GetAudioData API. The GetAudioData
method provides the ISound
instance which requested the data. Using the reverse map in the view listener, we can obtain the stream ID for the corresponding ISound
and use it in the API call.
Here's the whole method:
OnAudioStreamPlay
until a OnAudioStreamPause
event is received. Failure to do so can result in program exceptions and deadlocks.Coherent::UI::ViewContext::Update
. Usually, GetAudioData will be called from the audio dedicated thread, in which case it's recommended that you use the same thread for managing you Audio and UI calls.When the OnAudioStreamPause
event is received, we can release the ISound
instance or pause it. In this sample we're just releasing it and creating new ones on each 'Play'.
When the OnAudioStreamClose
event is received we just clear the information about the corresponding stream ID.
As a very brief summary, when we receive a Create
notification we save the information about the stream; when we receive a Play
notification we create a new sound and continuously request data until we receive Pause
. The requested data is played by the audio system. Upon Close
we delete the saved information.
We encourage you to play with the sample for a more hands-on experience.