CRI ADX  Last Updated: 2024-07-17 10:47 p
About Working Memory
Some functions in CRI Atom library need a working memory area (working memory) during their execution.
This section explains how the working memory is used and how to allocate it.

Tasks Which Need Working Memory

The tasks which need working memory include:
  • Initializing the library
  • Creating Voice Pool
  • Reading ACF file
  • Reading ACB file
  • Creating D-BAS
  • Creating AtomEx player
The following sections describe details of each task.

(1) Initializing the Library
CRI Atom library needs a working memory since it performs tasks such as thread creation when it is initialized.
The size of the working memory required at the time of initialization can be calculable using the criAtomEx_CalculateWorkSize function.
The size of the working memory which the library needs at the time of initialization depends on the settings you specify when you initialize the library such as the framework ( CriAtomExConfig ).
For example, if the thread model is CRIATOMEX_THREAD_MODEL_MULTI, CRI Atom library, creates threads, so it needs memory area for thread creation.
However, if the thread model is CRIATOMEX_THREAD_MODEL_USER_MULTI or CRIATOMEX_THREAD_MODEL_SINGLE, CRI Atom library does not need memory area for thread creation since it does not create threads.
Therefore, when you specify CRIATOMEX_THREAD_MODEL_USER_MULTI or CRIATOMEX_THREAD_MODEL_SINGLE as a thread model, size of the required working memory is smaller than the one when you specify CRIATOMEX_THREAD_MODEL_MULTI .
[Note]
If CRIATOMEX_THREAD_MODEL_USER_MULTI or CRIATOMEX_THREAD_MODEL_SINGLE is specified as the thread model, although the size of the required memory is small, load of the server process is high.
(Because all tasks performed in another thread if CRIATOMEX_THREAD_MODEL_MULTI were specified is performed in the server process.)
Therefore, since user has to implement a mechanism to decrease the fluctuation of the load of the server process itself, implementation becomes difficult.
(2) Creating Voice Pool
When creating a Voice Pool, a working memory is required for buffers used to read data or decode sound data, or for assigning resources for sound playback.
The size of the working memory required for creating a Voice Pool depends on the function used to create a voice player.
Correspondence between Voice Pool creation functions and working memory size calculation functions is as follows.
Voice Pool Creation Functions and Working Memory Size Calculation Functions
Voice Pool Creation Function Working Memory Size Calculation Function
criAtomExVoicePool_AllocateStandardVoicePool criAtomExVoicePool_CalculateWorkSizeForStandardVoicePool
criAtomExVoicePool_AllocateAdxVoicePool criAtomExVoicePool_CalculateWorkSizeForAdxVoicePool
criAtomExVoicePool_AllocateHcaVoicePool criAtomExVoicePool_CalculateWorkSizeForHcaVoicePool
criAtomExVoicePool_AllocateHcaMxVoicePool criAtomExVoicePool_CalculateWorkSizeForHcaMxVoicePool



As in initialization of the library, the size of the working memory required for creating a Voice Pool depends on the setting (such as the CriAtomExAdxVoicePoolConfig ).
Specifically, the smaller the value you specify for the maximum number of output channels or the maximum sampling frequency, the less working memory is required.
For example, when playing back only monophonic sound in the Voice Pool, it is possible to make the working memory smaller by specifying the number of maximum output channels as 1 compared with the case where you specify 2.
Similarly, if you want to play only sounds with smaller sampling frequency than 24 kHz, it is possible to make the working memory smaller by specifying maximum sampling frequency as 24000 compared with the case where you specify 48000.
[Note]
When you create a Voice Pool with the maximum number of output channels set to 1, a stereo sound cannot be played back using that Voice Pool.
Similarly, when you create a Voice Pool with the maximum sampling frequency set to 24kHz, a sound with 32kHz or 48kHz cannot be played back using that Voice Pool.
(3) Registering ACF
When registering ACF, working memory is required to store ACF information or to reserve a buffer for reading data when the data is directly registered from an ACF file.
The size of the working memory required for registering ACF depends on how the ACF is registered.
Correspondence between ACF registration functions and working memory size calculation functions is as follows.
ACF Registration Functions and Working Memory Size Calculation Functions
ACF Registration Function Working Memory Size Calculation Function
criAtomEx_RegisterAcfData criAtomEx_CalculateWorkSizeForRegisterAcfData
criAtomEx_RegisterAcfFile criAtomEx_CalculateWorkSizeForRegisterAcfFile


(4) Loading ACB
When loading ACB, working memory is required to store ACB information or to reserve a buffer for reading data when the data is directly loaded from an ACB file.
The size of the working memory required for loading ACB depends on how the ACB is loaded.
Correspondence between ACB loading functions and working memory size calculation functions is as follows.
ACB Loading Functions and Working Memory Size Calculation Functions
ACB Loading Function Working Memory Size Calculation Function
criAtomExAcb_LoadAcbData criAtomExAcb_CalculateWorkSizeForLoadAcbData
criAtomExAcb_LoadAcbFile criAtomExAcb_CalculateWorkSizeForLoadAcbFile


(5) Creating D-BAS
Since D-BAS is a feature to manage streaming buffers, it needs a working memory for streaming buffers and for managing them.
The size of the working memory required for creating D-BAS depends on each application or scene which uses streaming playback.
D-BAS Creation Functions and Working Memory Size Calculation Functions
D-BAS Creation Function Working Memory Size Calculation Function
criAtomExDbas_Create criAtomExDbas_CalculateWorkSize

The following functions are used when calculating the consumed bit rate to be set to D-BAS.
Functions to Calculate Consumed Bit Rate for Each Codec
ADX HCA(HCA-MX)
criAtomEx_CalculateAdxBitrate criAtomEx_CalculateHcaBitrate

When there are target-specific codecs, functions similar to above are declared in the target-specific header.
(6) Creating AtomEx Player
When creating an AtomEx player, a working memory is required to allocate a player area or an area to store file paths.
The sizes of the working memory required when creating an AtomEx player depends on whether you want to perform playback by specifying file paths.
The correspondence between AtomEx player creation functions and working memory size calculation functions is as follows.
AtomEx Player Creation Functions and Working Memory Size Calculation Functions
AtomEx Player Creation Function Working Memory Size Calculation Function
criAtomExPlayer_Create criAtomExPlayer_CalculateWorkSize


Allocating Working Memory

When using CRI Atom library, you must provide "working memory" when initializing the library or creating an AtomEx player as the working area used by the library.
CRI Atom library provides the following two methods to allocate a working memory for CRI Atom library.
  • Fixed Memory method: A method in which application prepares a memory area and provides it to the library
  • User Allocator method: A method in which memory allocator is registered to CRI Atom library
Details of each method is as follows.
(1) Fixed Memory Method
Fixed Memory method is a method in which required working memory is provided as arguments to the functions which need a working memory when invoking them.
All APIs which need allocated memory such as the criAtomEx_Initialize (library initialization) or the criAtomExPlayer_Create (creation of AtomEx player) have the following two parameters as arguments.
  • Buffer address
  • Buffer size
For example, in the criAtomEx_Initialize function, these are second argument "void *work" and third argument "CriSint32 size."
When invoking such APIs, user must set the memory area allocated beforehand as arguments to the functions.
The size of the working memory set to functions is calculated using specific working memory size calculation function.
For example, for the criAtomEx_Initialize function, the size of the working memory required for the function can be calculated using the criAtomEx_CalculateWorkSize function.
In summary, the procedure to allocate the working memory in Fixed Memory method is as follows.
  1. Calculate the size of the working memory required by working memory requisite functions (*).
  2. Allocate a memory of the size returned by the calculation.
  3. Invoke working memory requisite functions using the allocated memory as arguments.
Working memory requisite functions: functions which need working memory during their execution.
[Example]
The following example shows how to initialize the library using Fixed Memory method.
main()
{
void *work; // Address of the working memory
CriSint32 size; // Size of the working memory
:
// Calculate the size of the working memory required for initializing the library
size = criAtomEx_CalculateWorkSize(&config);
// Allocate the working memory
work = malloc((size_t)size);
// Initialize the library
// -> Specify the allocated working memory
criAtomEx_Initialize(&config, work, size);
:
// Application's main routine
// -> Allocated memory must be kept during these steps.
:
// Finalize the library when exiting the application
// Release the working memory which is now unnecessary
free(work);
:
}
CriSint32 criAtomEx_CalculateWorkSize(const CriAtomExConfig *config)
Calculate the size of the work buffer required to initialize the library.
void criAtomEx_Finalize(void)
Finalize the library.
CriBool criAtomEx_Initialize(const CriAtomExConfig *config, void *work, CriSint32 work_size)
Initialize the library.


[Note]
The area specified as a working memory is used for various purposes in the library until the library is finalized.
User must keep the working memory specified when initializing the library until the library is finalized.
(Working memory should not be used for other purposes or released.)
(2) User Allocator Method
Besides allocating working memory for each function, user can develop a memory allocator and register it to CRI Atom library.
This method is called as User Allocator method.
When using User Allocator method, user must prepare memory allocation and memory release functions and register them to CRI Atom library.
Memory allocation function is a function similar to malloc() in standard library which dynamically allocates a memory with the specified size and returns the address of the memory block.
Similarly, memory release function is a function similar to free() in standard library which frees the memory block allocated by the memory allocation function. User must implement these two functions according to the interfaces defined by CRI Atom library and register them.
Specific interface and registration function are as follows.
Interfaces to Be Implemented and Registration Functions
Interfaces to Be Implemented Registration Function
Memory allocation function CriAtomMallocFunc criAtomEx_SetUserAllocator macro
Memory release function CriAtomFreeFunc criAtomEx_SetUserAllocator macro



By registering memory allocation function and memory release function to CRI Atom library, CRI Atom library changes its behavior so that the registered functions are always used to allocate and release a working memory.
Therefore, when using User Allocator method, you do not have to specify a working memory when invoking working memory requisite functions.
(You should specify NULL as memory address and 0 as memory size.)
In summary, the procedure to allocate working memory in User Allocator method is as follows.
  1. Register memory allocation function and memory release function to CRI Atom library.
  2. Invoke working memory requisite functions.
    (Specify NULL as memory address and 0 as memory size.)
[Example]
The following example shows how to initialize the library using User Allocator method.
// Own memory allocation function
void *user_malloc(void *obj, CriUint32 size)
{
void *mem;
// Allocate a memory
mem = malloc(size);
return (mem);
}
// Prepare own memory release function
void user_free(void *obj, void *mem)
{
// Release the memory
free(mem);
return;
}
main()
{
// Register the own memory allocator function
criAtomEx_SetUserAllocator(user_malloc, user_free, NULL);
// Initialize the library
// Specify NULL and 0 as working memory
// -> Required memory is allocated using the registered memory allocation function.
criAtomEx_Initialize(NULL, NULL, 0);
:
// Application's main routine
:
// Finalize the library when exiting the application
// -> The memory allocated when initializing the library is released using the registered memory release function.
:
}
#define criAtomEx_SetUserAllocator(p_malloc_func, p_free_func, p_obj)
Register a custom memory allocator.
Definition: cri_le_atom_ex.h:309