CRI ADX  Last Updated: 2024-07-17 10:48 p
Cue Playback (Stream)


This tutorial shows how to play a cue in streaming mode by CRI Atom.

Files Needef for Playback

The files required for playing cues are ACF file (*.acf), ACB file (*.acb), AWB file (*.awb) and header files (*.h).
Those files are output of the Atom tool. For this tutorial, you can use the same data as the sample program and they are located:

Files related to this tutorial
  * CRIWARE

  \ * SDK

    \ * common

      \ * smpdata

        \ * criatomex

          o * TutorialProject.acf

          o * tutorial_streaming.acb

          o * tutorial_streaming.h

          \ * tutorial_streaming_streamfiles.awb

 

 

 

: Sample data for tutorial

 

: ACF file

: ACB file

: ACB header file

: AWB file

 

Project File and Source Code

The project file and source codes are located at following folders.

Location of Tutorial source code
  * CRIWARE

  \ * SDK

    \ * pc

      \ * tutorials

        \ * criatomex

          \ * playback_cue_streaming

            o * pcvc

            | o * playback_cue_streaming.sln

            | o * playback_cue_streaming.vcxproj

            | \ * playback_cue_streaming.vcxproj.filters

            |  

            \ * playback_cue_streaming.c

 

 

[Platform specific]

: Tutorial program

 

: Streaming playback tutorial

: Project file folder

: Visual Studio solution file

: Visual Studio project file

: Visual Studio filter file

 

: Source code of Streaming playback

 

Program Flow

Program flow is as follows.
The different points from Cue Playback (Memory) are;
"3. Create D-BAS", "5. Allocate voice pool" and "7. Start playback".

  1. Include header files
  2. CRI Atom library initialization
  3. Create D-BAS
  4. Load necessary files
  5. Allocate voice pool
  6. Create AtomEx player
  7. Start playback
  8. Wait for playend and update internal state
  9. Finalization
  10. Verify playback
/* CRI SDK Header */
#include <cri_xpt.h>
/* CRI ADX Headers */
#include <cri_atom_ex.h>
#include <cri_atom_pc.h>
/* Header file for ACB file used in this tutorial */
#include "../../../../common/smpdata/criatomex/tutorial_streaming.h"
/* Path string for data directory */
#define PATH "..\\..\\..\\..\\..\\common\\smpdata\\criatomex\\"
/* File names for the sample */
#define ACF_FILE "TutorialProject.acf"
#define ACB_FILE "tutorial_streaming.acb"
#define AWB_FILE "tutorial_streaming_streamfiles.awb"
/* main function */
CriSint32 main(CriSint32 argc, CriChar8 *argv[])
{
CriAtomDbasId dbas_id;
UNUSED(argc);
UNUSED(argv);
/* Initialization (minimum) */
tutorial_initialize();
/* Registration of error callback function */
criErr_SetCallback(tutorial_error_callback_func);
/* Registration of memory allocator */
criAtomEx_SetUserAllocator(tutorial_alloc, tutorial_free, NULL);
/* Library initialization */
criAtomEx_Initialize_PC(NULL, NULL, 0);
/* D-BAS creation */
dbas_id = criAtomDbas_Create(NULL, NULL, 0);
/* Read and register ACF file */
criAtomEx_RegisterAcfFile(NULL, PATH ACF_FILE, NULL, 0);
/* Read ACB file and create ACB handle */
NULL, PATH ACB_FILE, NULL, PATH AWB_FILE, NULL, 0);
/* Allocate voice pool */
voice_pool_config.player_config.streaming_flag = CRI_TRUE;
voice_pool = criAtomExVoicePool_AllocateStandardVoicePool(&voice_pool_config, NULL, 0);
/* Create player */
player = criAtomExPlayer_Create(NULL, NULL, 0);
/* Specify Cue ID */
criAtomExPlayer_SetCueId(player, acb_hn, CRI_TUTORIAL_STREAMING_MUSIC_TR);
/* Start playback */
for(;;) {
CriAtomExPlayerStatus explayer_status;
tutorial_sleep(10);
/* Execute server process */
/* check the player status */
explayer_status = criAtomExPlayer_GetStatus(player);
/* Exit playback loop if the status is PLAYEND */
if (explayer_status == CRIATOMEXPLAYER_STATUS_PLAYEND) {
break;
}
}
/* Destroy player handle */
/* Free voice pool */
/* Release ACB handle */
/* Unregister ACF */
/* Destroy D-BAS */
/* Library Finalization */
/* Finalization (minimum) */
tutorial_finalize();
return 0;
}
void criAtomExPlayer_Destroy(CriAtomExPlayerHn player)
Destroy an AtomEx player
CriAtomExAcbObj * CriAtomExAcbHn
ACB handle
Definition: cri_le_atom_ex.h:3033
CriAtomExAcbHn criAtomExAcb_LoadAcbFile(CriFsBinderHn acb_binder, const CriChar8 *acb_path, CriFsBinderHn awb_binder, const CriChar8 *awb_path, void *work, CriSint32 work_size)
Load an ACB file
void criAtomExAcb_Release(CriAtomExAcbHn acb_hn)
Release an ACB handle
void criAtomEx_UnregisterAcf(void)
Unregister an ACF file
void criAtomEx_ExecuteMain(void)
Execute the server processing
CriBool criAtomEx_RegisterAcfFile(CriFsBinderHn binder, const CriChar8 *path, void *work, CriSint32 work_size)
Register an ACF file
#define criAtomEx_SetUserAllocator(p_malloc_func, p_free_func, p_obj)
Register a custom memory allocator
Definition: cri_le_atom_ex.h:309
CriAtomExPlayerStatus criAtomExPlayer_GetStatus(CriAtomExPlayerHn player)
Get the player status
CriAtomExPlaybackId criAtomExPlayer_Start(CriAtomExPlayerHn player)
Start the playback
CriAtomExPlayerObj * CriAtomExPlayerHn
Player handle
Definition: cri_le_atom_ex.h:3622
CriAtomExPlayerHn criAtomExPlayer_Create(const CriAtomExPlayerConfig *config, void *work, CriSint32 work_size)
Create an AtomEx player
void criAtomExPlayer_SetCueId(CriAtomExPlayerHn player, CriAtomExAcbHn acb_hn, CriAtomExCueId id)
Set the sound data to play (specifying a Cue ID)
enum CriAtomExPlayerStatusTag CriAtomExPlayerStatus
Player status
@ CRIATOMEXPLAYER_STATUS_PLAYEND
Definition: cri_le_atom_ex.h:3670
#define criAtomExVoicePool_SetDefaultConfigForStandardVoicePool(p_config)
Assign the default values to the configuration structure used to create a standard Voice Pool
Definition: cri_le_atom_ex.h:564
CriAtomExVoicePoolHn criAtomExVoicePool_AllocateStandardVoicePool(const CriAtomExStandardVoicePoolConfig *config, void *work, CriSint32 work_size)
Create a standard Voice Pool
struct CriAtomExVoicePoolTag * CriAtomExVoicePoolHn
Voice Pool handle
Definition: cri_le_atom_ex.h:3220
void criAtomExVoicePool_Free(CriAtomExVoicePoolHn pool)
Destroy a Voice Pool
CriSint32 CriAtomDbasId
Atom D-BAS ID
Definition: cri_le_atom.h:2513
void criAtomDbas_Destroy(CriAtomDbasId atom_dbas_id)
Destroy D-BAS
CriAtomDbasId criAtomDbas_Create(const CriAtomDbasConfig *config, void *work, CriSint32 work_size)
Create D-BAS
void criAtomEx_Finalize_PC(void)
Finalize the library
void criAtomEx_Initialize_PC(const CriAtomExConfig_PC *config, void *work, CriSint32 work_size)
Initialize the library
void criErr_SetCallback(CriErrCbFunc cbf)
Register error callback function
Configuration structure used when creating a standard Voice Pool
Definition: cri_le_atom_ex.h:3255
CriAtomStandardPlayerConfig player_config
Definition: cri_le_atom_ex.h:3258
CriBool streaming_flag
Whether to perform streaming playback
Definition: cri_le_atom.h:1484


Description of Program

Detail explanation for each step.

1. Include header files
/* CRI SDK Header */
#include <cri_xpt.h>
/* CRI ADX Headers */
#include <cri_atom_ex.h>
#include <cri_atom_pc.h>
/* Header file for ACB file used in this tutorial */
#include "../../../../common/smpdata/criatomex/tutorial_streaming.h"



Include cri_xpt.h first, as it contains CRI specific type definitions.
Other header files have no restriction for their order.

cri_atom_ex.h contains API declaration of functions for CRI Atom.
It must be included.

tutorial_streaming.h contains cue information for ACB file and AWB file. Cue IDs for playback are defined in this header file.

2. CRI Atom library initialization
/* Registration of error callback function */
criErr_SetCallback(tutorial_error_callback_func);
/* Registration of memory allocator */
criAtomEx_SetUserAllocator(tutorial_alloc, tutorial_free, NULL);
/* Library initialization */
criAtomEx_Initialize_PC(NULL, NULL, 0);



Initialize CRI Atom Library.
In this tutorial, parameters for criAtomEx_Initialize_PC function are simplified.
The first argument of criAtomEx_Initialize_PC function is initialization parameter, but when it is NULL, the default setting is selected.
Second and third parameters are for specification of work area.
criAtomEx_Initialize_PC allocates work memory dynamically and internally when memory allocator function is set by criAtomEx_SetUserAllocator and NULL is passed as work area point and work memory size is 0 (zero).

3. Create D-BAS
/* D-BAS creation */
dbas_id = criAtomDbas_Create(NULL, NULL, 0);



For streaming playback, it is necessary to create D-BAS by calling criAtomDbas_Create.
In this tutorial, parameters for criAtomDbas_Create function are simplified.
The first argument of criAtomDbas_Create function is initialization parameter, but when it is NULL, the default setting is selected.
Second and third parameters are for specification of work area.
criAtomDbas_Create allocates work memory dynamically and internally when memory allocator function is set by criAtomEx_SetUserAllocator and NULL is passed as work area point and work memory size is 0 (zero).

The role of D-BAS is to manage streaming buffer for players.
Streaming buffer is divided into blocks and dynamically D-BAS assigns blocks needed to each player based on bitrate of each player.

Error handling is eliminated in this tutorial but return value verification should be recommended as criAtomDbas_Create may fail to allocate huge work memory.
[Note]
For current version, only one D-BAS can be created.
In the future, we are expecting more flexible feature such that application can assign different D-BAS for different player by creating multiple D-BASs.

4. Loading necessary files
/* Read and register ACF file */
criAtomEx_RegisterAcfFile(NULL, PATH ACF_FILE, NULL, 0);
/* Read ACB file and create ACB handle */
NULL, PATH ACB_FILE, NULL, PATH AWB_FILE, NULL, 0);



Read ACF file by calling criAtomEx_RegisterAcfFile function. This file is used for configuration of environment.
Then read ACB file by criAtomExAcb_LoadAcbFile. This function returns a ACB handle which is passed to player.
Both functions require work size as their arguments, but those are NULL and 0(zero) for simplification and work memory are allocated internally.

Both criAtomEx_RegisterAcfFile and criAtomExAcb_LoadAcbFile are synchronous functions.
After criAtomExAcb_LoadAcbFile successfully executed, ACB file loading should be completed and a valid ACB handle ( CriAtomExAcbHn ) should be returned.

Error handling is eliminated in this tutorial but return value verification should be recommended as both criAtomEx_RegisterAcfFile and criAtomExAcb_LoadAcbFile may fail with some reasons such as "file not found".

5. Allocate voice pool
/* Allocate voice pool */
voice_pool_config.player_config.streaming_flag = CRI_TRUE;
voice_pool = criAtomExVoicePool_AllocateStandardVoicePool(&voice_pool_config, NULL, 0);



Here Standard voice pool is allocated.

To play cue in streaming mode, it is necessary to set streaming_flag in voice pool configuration parameter, otherwise streaming buffer is not allocated to voice pool.

So in this tutorial, it is necessary to specify configuration parameter explicitly.

Initialize a variable with CriAtomExStandardVoicePoolConfig type by a macro, criAtomExVoicePool_SetDefaultConfigForStandardVoicePool.

Then modify parameters necessary. That is, player_config.streaming_flag in CriAtomExStandardVoicePoolConfig member is set to ::CRI_TRUE for streaming playback.
And pass this structure to criAtomExVoicePool_AllocateStandardVoicePool.

In the source code above, only configuration parameter is set explicitly.
Handling work memory is independent, so work memory parameters can be default, NULL and 0(zero) again.

6. Create AtomEx player
/* Create player */
player = criAtomExPlayer_Create(NULL, NULL, 0);



This code creates AtomEx player (in short we call it "player" simply here).

Again arguments are NULLs and 0 to specify default setting and the function returns a player handle (CriAtomExPlayerHn).
You can control AtomEx player through this handle.

For work memory, NULL and 0(zero) are specified in this tutorial to allocate work memory dynamically.

7. Start playback
/* Specify Cue ID */
criAtomExPlayer_SetCueId(player, acb_hn, CRI_TUTORIAL_STREAMING_MUSIC_TR);
/* Start playback */



Specifying Cue ID with criAtomExPlayer_SetCueId function, call criAtomExPlayer_Start start playback.
The second argument criAtomExPlayer_SetCueId is ACB handle that should have loaded and the third one is Cue ID (number) to be played.

The player start playback according to ACB handle and cue ID.
The sample cue ID, CRI_TUTORIAL_STREAMING_MUSIC_TR, is defined in tutorial_streaming.h.
CRI_TUTORIAL_STREAMING_MUSIC_TR is a streaming cue though it is not obvious in the cuesheet header file.

criAtomExPlayer_Start function starts playback with Atom player handle which is created by criAtomExPlayer_Create.

8. Waiting for play-end and updating internal state
/* Playback loop */
for(;;) {
CriAtomExPlayerStatus explayer_status;
tutorial_sleep(10);
/* Execute server process */
/* check Ex player status */
explayer_status = criAtomExPlayer_GetStatus(player);
/* Exit playback loop if play-end */
if (explayer_status == CRIATOMEXPLAYER_STATUS_PLAYEND) {
break;
}
}


criAtomExPlayer_GetStatus returns the player status and if it is play-end(CRIATOMEXPLAYER_STATUS_PLAYEND) then exit the loop.
In the playback loop, criAtomEx_ExecuteMain, the server process of CRI Atom, should be called for every V-sync, otherwise reading sound data may be delayed and it may result audio playback stuttering.

Also the status of player is updated by CRI Atom server process, so criAtomEx_ExecuteMain should be called for keep updating the status.

9. Finalization
/* Destroy Atom handle */
/* Free voice pool */
/* Release ACB handle */
/* Unregister ACF */
/* Destroy D-BAS */
/* Finalize library */



At the termination of the application, each handles should be discarded through appropriate function, then all work area allocated dynamically are released in those functions.
Then lastly terminate the library by criAtomEx_Finalize_PC function.

10. Veryfy playback
Can you play the streaming sound of cue, can't you ?
You should hear a back ground music sound now.