Version
menu_open
link
Wwise SDK 2022.1.4
AkPlatformFuncs.h
Go to the documentation of this file.
1 /*******************************************************************************
2 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
3 released in source code form as part of the SDK installer package.
4 
5 Commercial License Usage
6 
7 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
8 may use this file in accordance with the end user license agreement provided
9 with the software or, alternatively, in accordance with the terms contained in a
10 written agreement between you and Audiokinetic Inc.
11 
12 Apache License Usage
13 
14 Alternatively, this file may be used under the Apache License, Version 2.0 (the
15 "Apache License"); you may not use this file except in compliance with the
16 Apache License. You may obtain a copy of the Apache License at
17 http://www.apache.org/licenses/LICENSE-2.0.
18 
19 Unless required by applicable law or agreed to in writing, software distributed
20 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
21 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
22 the specific language governing permissions and limitations under the License.
23 
24  Copyright (c) 2023 Audiokinetic Inc.
25 *******************************************************************************/
26 
27 #ifndef _AK_PLATFORM_FUNCS_H_
28 #define _AK_PLATFORM_FUNCS_H_
29 
31 #include <sce_atomic.h>
32 #include <sceerror.h>
33 #include <wchar.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <time.h>
37 #include <kernel/eventflag.h>
38 #include <unistd.h>
39 #include <sys/time.h>
40 #include <stdlib.h>
41 #include <cpuid.h>
42 #include <ajm.h>
43 #include <x86intrin.h>
44 
45 //-----------------------------------------------------------------------------
46 // Platform-specific thread properties definition.
47 //-----------------------------------------------------------------------------
48 struct AkThreadProperties
49 {
50  int nPriority; ///< Thread priority
51  SceKernelCpumask dwAffinityMask; ///< Affinity mask
52  size_t uStackSize; ///< Thread stack size
53  int uSchedPolicy; ///< Thread scheduling policy
54 };
55 
56 //-----------------------------------------------------------------------------
57 // External variables.
58 //-----------------------------------------------------------------------------
59 // These variables are declared and updated by the sound engine.
60 namespace AK
61 {
62  // used by time helpers to return time values in milliseconds.
64 }
65 
66 //-----------------------------------------------------------------------------
67 // Defines for PS5.
68 //-----------------------------------------------------------------------------
69 #define AK_DECLARE_THREAD_ROUTINE( FuncName ) void* FuncName(void* lpParameter)
70 #define AK_THREAD_RETURN( _param_ ) return (_param_);
71 #define AK_THREAD_ROUTINE_PARAMETER lpParameter
72 #define AK_GET_THREAD_ROUTINE_PARAMETER_PTR(type) reinterpret_cast<type*>( AK_THREAD_ROUTINE_PARAMETER )
73 
74 #define AK_RETURN_THREAD_OK 0x00000000
75 #define AK_RETURN_THREAD_ERROR 0x00000001
76 #define AK_DEFAULT_STACK_SIZE (128*1024)
77 #define AK_VM_PAGE_SIZE (16*1024)
78 #define AK_VM_DEVICE_PAGE_SIZE (64*1024)
79 #define AK_THREAD_DEFAULT_SCHED_POLICY SCE_KERNEL_SCHED_FIFO
80 #define AK_THREAD_PRIORITY_NORMAL SCE_KERNEL_PRIO_FIFO_DEFAULT
81 #define AK_THREAD_PRIORITY_ABOVE_NORMAL SCE_KERNEL_PRIO_FIFO_HIGHEST
82 #define AK_THREAD_PRIORITY_BELOW_NORMAL SCE_KERNEL_PRIO_FIFO_LOWEST
83 
84 #define AK_THREAD_AFFINITY_ALL 8191 // from 0b1'1111'1111'1111 -- 13 cores available
85 #define AK_THREAD_AFFINITY_DEFAULT 4095 // from 0b0'1111'1111'1111 -- Default to only the 12 fully-available cores. 13th core is half-available.
86 
87 // NULL objects
88 #define AK_NULL_THREAD NULL
89 
90 #define AK_INFINITE (AK_UINT_MAX)
91 
92 #define AkMax(x1, x2) (((x1) > (x2))? (x1): (x2))
93 #define AkMin(x1, x2) (((x1) < (x2))? (x1): (x2))
94 #define AkClamp(x, min, max) ((x) < (min)) ? (min) : (((x) > (max) ? (max) : (x)))
95 
96 namespace AKPLATFORM
97 {
98 #ifndef AK_OPTIMIZED
99  /// Output a debug message on the console (Ansi string)
100  AkForceInline void OutputDebugMsg( const char* in_pszMsg )
101  {
102  fputs( in_pszMsg, stderr );
103  }
104  /// Output a debug message on the console (Unicode string)
105  AkForceInline void OutputDebugMsg( const wchar_t* in_pszMsg )
106  {
107  fputws( in_pszMsg, stderr );
108  }
109 
110  /// Output a debug message on the console (Unicode string) (variadic function)
111  template <int MaxSize = 0> // Unused
112  AkForceInline void OutputDebugMsgV( const wchar_t* in_pszFmt, ... )
113  {
114  va_list args;
115  va_start(args, in_pszFmt);
116  vfwprintf(stderr, in_pszFmt, args);
117  va_end(args);
118  }
119 
120  /// Output a debug message on the console (Ansi string) (variadic function)
121  template <int MaxSize = 0> // Unused
122  AkForceInline void OutputDebugMsgV( const char* in_pszFmt, ... )
123  {
124  va_list args;
125  va_start(args, in_pszFmt);
126  vfprintf(stderr, in_pszFmt, args);
127  va_end(args);
128  }
129 #else
130  inline void OutputDebugMsg( const wchar_t* ){}
131  inline void OutputDebugMsg( const char* ){}
132 
133  template <int MaxSize = 0> // Unused
134  inline void OutputDebugMsgV( const wchar_t*, ... ){}
135 
136  template <int MaxSize = 0> // Unused
137  inline void OutputDebugMsgV( const char*, ... ){}
138 #endif
139 
140 
141  // Simple automatic event API
142  // ------------------------------------------------------------------
143 
144  /// Platform Independent Helper
145  AkForceInline void AkClearEvent( AkEvent & out_event )
146  {
147  out_event = NULL;
148  }
149 
150  AkForceInline AKRESULT AkCreateNamedEvent( AkEvent & out_event, const char* in_szName )
151  {
152  // NOTE: AkWaitForEvent uses the SCE_KERNEL_EVF_WAITMODE_CLEAR_PAT flag
153  // to get the same behavior as an auto-reset Win32 event
154  int ret = sceKernelCreateEventFlag(
155  &out_event,
156  in_szName,
157  SCE_KERNEL_EVF_ATTR_MULTI,
158  0 /* not signalled by default */,
159  NULL /* No optional params */ );
160 
161  if( ret == SCE_OK )
162  return AK_Success;
163 
164  AkClearEvent( out_event );
165  return AK_Fail;
166  }
167 
168  /// Platform Independent Helper
170  {
171  return AkCreateNamedEvent( out_event, "AkEvent" );
172  }
173 
174  /// Platform Independent Helper
175  AkForceInline void AkDestroyEvent( AkEvent & io_event )
176  {
177  sceKernelDeleteEventFlag(io_event);
178  AkClearEvent( io_event );
179  }
180 
181  /// Platform Independent Helper
182  AkForceInline void AkWaitForEvent( AkEvent & in_event )
183  {
184  AKVERIFY( sceKernelWaitEventFlag(
185  in_event,
186  1,
187  SCE_KERNEL_EVF_WAITMODE_OR | SCE_KERNEL_EVF_WAITMODE_CLEAR_ALL,
188  SCE_NULL,
189  SCE_NULL) == 0 );
190  }
191 
192  /// Platform Independent Helper
193  AkForceInline void AkSignalEvent( const AkEvent & in_event )
194  {
195  AKVERIFY( sceKernelSetEventFlag( in_event, 1 ) == 0 );
196  }
197 
198  /// Platform Independent Helper
199  AkForceInline void AkClearSemaphore(AkSemaphore& io_semaphore)
200  {
201  io_semaphore = NULL;
202  }
203 
204  /// Platform Independent Helper
205  inline AKRESULT AkCreateSemaphore( AkSemaphore& out_semaphore, AkUInt32 in_initialCount )
206  {
207  int ret = sceKernelCreateSema(
208  &out_semaphore,
209  "AkSemaphore",
210  0,
211  in_initialCount,
212  INT_MAX,
213  NULL );
214 
215  return ( ret == SCE_OK ) ? AK_Success : AK_Fail;
216  }
217 
218  /// Platform Independent Helper
219  inline void AkDestroySemaphore(AkSemaphore& io_semaphore)
220  {
221  AKVERIFY(sceKernelDeleteSema(io_semaphore) == SCE_OK);
222  }
223 
224  /// Platform Independent Helper - Semaphore wait, aka Operation P. Decrements value of semaphore, and, if the semaphore would be less than 0, waits for the semaphore to be released.
225  inline void AkWaitForSemaphore(AkSemaphore& in_semaphore)
226  {
227  AKVERIFY(sceKernelWaitSema(in_semaphore, 1, NULL) == SCE_OK);
228  }
229 
230  /// Platform Independent Helper - Semaphore signal, aka Operation V. Increments value of semaphore by an arbitrary count.
231  inline void AkReleaseSemaphore(AkSemaphore& in_semaphore, AkUInt32 in_count)
232  {
233  AKVERIFY(sceKernelSignalSema(in_semaphore, in_count) == SCE_OK);
234  }
235 
236  // Virtual Memory
237  // ------------------------------------------------------------------
238 
239  const int kMemoryFlags = SCE_KERNEL_PROT_CPU_RW | SCE_KERNEL_PROT_GPU_RW | SCE_KERNEL_PROT_AMPR_ALL;
240  const int kDeviceMemoryFlags = SCE_KERNEL_PROT_CPU_RW | SCE_KERNEL_PROT_GPU_RW | SCE_KERNEL_PROT_AMPR_ALL | SCE_KERNEL_PROT_ACP_RW;
241 
242  AkForceInline void* AllocVM(size_t size, size_t* extra)
243  {
244  AKASSERT((size % AK_VM_PAGE_SIZE) == 0);
245  off_t directMemStart = 0;
246  void* ptr = NULL;
247 
248  // In order to use ACM hardware accelerated functions, Wwise must have GPU-visible memory
249  int32_t err;
250  err = sceKernelAllocateDirectMemory(0, SCE_KERNEL_MAIN_DMEM_SIZE, size, AK_VM_PAGE_SIZE, SCE_KERNEL_MTYPE_C_SHARED, &directMemStart);
251  if (err == SCE_OK)
252  {
253  err = sceKernelMapDirectMemory(&ptr, size, kMemoryFlags, 0, directMemStart, AK_VM_PAGE_SIZE);
254  AKASSERT(ptr);
255  AKASSERT(err == SCE_OK);
256 
257  *extra = (size_t)directMemStart;
258  }
259  return (uint8_t*)ptr;
260  }
261 
262  AkForceInline void FreeVM(void* address, size_t size, size_t extra, size_t release)
263  {
264  if (release)
265  {
266  AKASSERT(extra);
267  off_t directMemStart = (off_t)extra;
268  int32_t err = sceKernelReleaseDirectMemory(directMemStart, release);
269  AKASSERT(err == SCE_OK);
270  }
271  }
272 
273  AkForceInline void* AllocDevice(size_t size, size_t* extra)
274  {
275  AKASSERT((size % AK_VM_DEVICE_PAGE_SIZE) == 0);
276  off_t directMemStart = 0;
277  void* ptr = NULL;
278 
279  // In order to use AJM zero-copy operations, Wwise must have ACP-visible memory
280  int32_t err;
281  err = sceKernelAllocateDirectMemory(0, SCE_KERNEL_MAIN_DMEM_SIZE, size, AK_VM_DEVICE_PAGE_SIZE, SCE_KERNEL_MTYPE_C_SHARED, &directMemStart);
282  if (err == SCE_OK)
283  {
284  err = sceKernelMapDirectMemory(&ptr, size, kDeviceMemoryFlags, 0, directMemStart, AK_VM_DEVICE_PAGE_SIZE);
285  AKASSERT(ptr);
286  AKASSERT(err == SCE_OK);
287 
288  *extra = (size_t)directMemStart;
289  }
290  return (uint8_t*)ptr;
291  }
292 
293  AkForceInline void FreeDevice(void* address, size_t size, size_t extra, size_t release)
294  {
295  if (release)
296  {
297  AKASSERT(extra);
298  off_t directMemStart = (off_t)extra;
299  int32_t err = sceKernelReleaseDirectMemory(directMemStart, release);
300  AKASSERT(err == SCE_OK);
301  }
302  }
303 
304  AkForceInline bool CheckMemoryProtection(void* address, size_t size, int expectedProt)
305  {
306  void* pStart, * pEnd;
307  int prot;
308 
309  AkUIntPtr addressEnd = (AkUIntPtr)address + size - 1;
310 
311  // Check protection flags apply to the whole range
312  while ((AkUIntPtr)address < addressEnd)
313  {
314  int err = sceKernelQueryMemoryProtection(address, &pStart, &pEnd, &prot);
315  if (err != SCE_OK)
316  return false;
317 
318  // Check protection flags
319  if ((prot & expectedProt) != expectedProt)
320  return false;
321 
322  if ((AkUIntPtr)pStart > (AkUIntPtr)address)
323  return false;
324 
325  address = pEnd;
326  }
327 
328  return true;
329  }
330 
331  // Threads
332  // ------------------------------------------------------------------
333 
334  /// Platform Independent Helper
335  AkForceInline bool AkIsValidThread( AkThread * in_pThread )
336  {
337  return ( *in_pThread != AK_NULL_THREAD );
338  }
339 
340  /// Platform Independent Helper
341  AkForceInline void AkClearThread( AkThread * in_pThread )
342  {
343  *in_pThread = AK_NULL_THREAD;
344  }
345 
346  /// Platform Independent Helper
347  AkForceInline void AkCloseThread( AkThread * in_pThread )
348  {
349  AKASSERT( in_pThread );
350  AKASSERT( *in_pThread );
351 
352  // #define KILL_THREAD(t) do { void *ret; scePthreadJoin(t,&ret); } while(false)
353  // AKVERIFY( SCE_OK == sceKernelDeleteThread( *in_pThread ) );
354  AkClearThread( in_pThread );
355  }
356 
357  #define AkExitThread( _result ) return _result; // ?????
358 
359  /// Platform Independent Helper
360  AkForceInline void AkGetDefaultThreadProperties( AkThreadProperties & out_threadProperties )
361  {
362  out_threadProperties.uStackSize = AK_DEFAULT_STACK_SIZE;
363  out_threadProperties.uSchedPolicy = AK_THREAD_DEFAULT_SCHED_POLICY;
364  out_threadProperties.nPriority = AK_THREAD_PRIORITY_NORMAL;
365  out_threadProperties.dwAffinityMask = AK_THREAD_AFFINITY_DEFAULT;
366  }
367 
368  /// Platform Independent Helper
369  inline void AkCreateThread(
370  AkThreadRoutine pStartRoutine, // Thread routine.
371  void * pParams, // Routine params.
372  const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
373  AkThread * out_pThread, // Returned thread handle.
374  const char * in_szThreadName ) // Opt thread name.
375  {
376  AKASSERT( out_pThread != NULL );
377 
378  ScePthreadAttr attr;
379 
380  // Create the attr
381  AKVERIFY(!scePthreadAttrInit(&attr));
382  // Set the stack size
383  AKVERIFY(!scePthreadAttrSetstacksize(&attr,in_threadProperties.uStackSize));
384  AKVERIFY(!scePthreadAttrSetdetachstate(&attr, SCE_PTHREAD_CREATE_JOINABLE));
385  AKVERIFY(!scePthreadAttrSetinheritsched(&attr, SCE_PTHREAD_EXPLICIT_SCHED));
386  AKVERIFY(!scePthreadAttrSetaffinity(&attr,in_threadProperties.dwAffinityMask));
387 
388  // Try to set the thread policy
389  int sched_policy = in_threadProperties.uSchedPolicy;
390  if( scePthreadAttrSetschedpolicy( &attr, sched_policy ) )
391  {
392  AKASSERT( !"AKCreateThread invalid sched policy, will automatically set it to FIFO scheduling" );
393  sched_policy = AK_THREAD_DEFAULT_SCHED_POLICY;
394  AKVERIFY( !scePthreadAttrSetschedpolicy( &attr, sched_policy ));
395  }
396 
397  int minPriority, maxPriority;
398  minPriority = SCE_KERNEL_PRIO_FIFO_HIGHEST;
399  maxPriority = SCE_KERNEL_PRIO_FIFO_LOWEST;
400 
401  // Set the thread priority if valid
402  AKASSERT( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority );
403  if( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority )
404  {
405  SceKernelSchedParam schedParam;
406  AKVERIFY( scePthreadAttrGetschedparam(&attr, &schedParam) == 0 );
407  schedParam.sched_priority = in_threadProperties.nPriority;
408  AKVERIFY( scePthreadAttrSetschedparam(&attr, &schedParam) == 0 );
409  }
410 
411  // Create the tread
412  int threadError = scePthreadCreate(out_pThread, &attr, pStartRoutine, pParams, in_szThreadName);
413  AKASSERT( threadError == 0 );
414  AKVERIFY(!scePthreadAttrDestroy(&attr));
415 
416  if( threadError != 0 )
417  {
418  AkClearThread( out_pThread );
419  return;
420  }
421 
422  // ::CreateThread() return NULL if it fails.
423  if ( !*out_pThread )
424  {
425  AkClearThread( out_pThread );
426  return;
427  }
428  }
429 
430  /// Platform Independent Helper
431  AkForceInline void AkWaitForSingleThread( AkThread * in_pThread )
432  {
433  AKASSERT( in_pThread );
434  AKASSERT( *in_pThread );
435  AKVERIFY(!scePthreadJoin( *in_pThread, NULL ));
436  }
437 
438  inline AkThreadID CurrentThread()
439  {
440  return scePthreadSelf();
441  }
442 
443  /// Platform Independent Helper
444  AkForceInline void AkSleep( AkUInt32 in_ulMilliseconds )
445  {
446  usleep( in_ulMilliseconds * 1000 );
447  }
448 
449  // Optimized memory functions
450  // --------------------------------------------------------------------
451 
452  /// Platform Independent Helper
453  AkForceInline void AkMemCpy( void * pDest, const void * pSrc, AkUInt32 uSize )
454  {
455  memcpy( pDest, pSrc, uSize );
456  }
457 
458  /// Platform Independent Helper
459  inline void AkMemMove( void* pDest, const void* pSrc, AkUInt32 uSize )
460  {
461  memmove( pDest, pSrc, uSize );
462  }
463 
464  /// Platform Independent Helper
465  AkForceInline void AkMemSet( void * pDest, AkInt32 iVal, AkUInt32 uSize )
466  {
467  memset( pDest, iVal, uSize );
468  }
469 
470  // Time functions
471  // ------------------------------------------------------------------
472 
473  /// Platform Independent Helper
474  AkForceInline void PerformanceCounter( AkInt64 * out_piLastTime )
475  {
476  uint64_t uTime = sceKernelGetProcessTimeCounter();
477  *out_piLastTime = (AkInt64)uTime;
478  }
479 
480  /// Frequency of the PerformanceCounter() (ticks per second)
481  AkForceInline void PerformanceFrequency( AkInt64 * out_piFreq )
482  {
483  *out_piFreq = (AkInt64)sceKernelGetProcessTimeCounterFrequency();
484  }
485 
486  /// Platform Independent Helper
488  {
489  AkInt64 iFreq;
490  PerformanceFrequency( &iFreq );
491  AK::g_fFreqRatio = (AkReal32)((AkReal64)iFreq / 1000);
492  }
493 
494 
495  // Waits for a limited amount of time for in_pVal to hit zero (without yielding the thread)
496  inline void AkLimitedSpinForZero(AkAtomic32* in_pVal)
497  {
498  // monitorx and waitx are available on certain AMD CPUs, so we can have a custom impl of AkLimitedSpinForZero
499  AkInt64 endSpinTime = 0;
500  AkInt64 currentTime = 0;
501  PerformanceCounter(&endSpinTime);
502  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
503  while (true)
504  {
505  // set up monitorx on pVal
506  _mm_monitorx((void*)in_pVal, 0U, 0U);
507  // if pval is zero, skip out
508  if (AkAtomicLoad32(in_pVal) == 0)
509  {
510  break;
511  }
512  // wait until a store to pVal occurs (or ~1us passes)
513  _mm_mwaitx(2U, 0U, 1000U);
514 
515  // Check if we've hit the deadline for the timeout
516  PerformanceCounter(&currentTime);
517  if (currentTime > endSpinTime)
518  {
519  break;
520  }
521  }
522  }
523 #define AK_LIMITEDSPINFORZERO // mark AkLimitedSpinForZero as defined to avoid duplicate definitions
524 
525  /// Returns a time range in milliseconds, using the sound engine's updated count->milliseconds ratio.
526  AkForceInline AkReal32 Elapsed( const AkInt64 & in_iNow, const AkInt64 & in_iStart )
527  {
528  return ( in_iNow - in_iStart ) / AK::g_fFreqRatio;
529  }
530 
531  /// String conversion helper
532  AkForceInline AkInt32 AkWideCharToChar( const wchar_t* in_pszUnicodeString,
533  AkUInt32 in_uiOutBufferSize,
534  char* io_pszAnsiString )
535  {
536  AKASSERT( io_pszAnsiString != NULL );
537 
538  mbstate_t state;
539  memset (&state, '\0', sizeof (state));
540 
541  return (AkInt32)wcsrtombs(io_pszAnsiString, // destination
542  &in_pszUnicodeString, // source
543  in_uiOutBufferSize, // destination length
544  &state); //
545 
546  }
547 
548  /// String conversion helper
549  AkForceInline AkInt32 AkCharToWideChar( const char* in_pszAnsiString,
550  AkUInt32 in_uiOutBufferSize,
551  void* io_pvUnicodeStringBuffer )
552  {
553  AKASSERT( io_pvUnicodeStringBuffer != NULL );
554 
555  mbstate_t state;
556  memset (&state, '\0', sizeof (state));
557 
558  return (AkInt32)mbsrtowcs((wchar_t*)io_pvUnicodeStringBuffer, // destination
559  &in_pszAnsiString, // source
560  in_uiOutBufferSize, // destination length
561  &state); //
562  }
563 
564  AkForceInline AkInt32 AkUtf8ToWideChar( const char* in_pszUtf8String,
565  AkUInt32 in_uiOutBufferSize,
566  void* io_pvUnicodeStringBuffer )
567  {
568  return AkCharToWideChar( in_pszUtf8String, in_uiOutBufferSize, (wchar_t*)io_pvUnicodeStringBuffer );
569  }
570 
571  /// Safe unicode string copy.
572  AkForceInline void SafeStrCpy( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
573  {
574  size_t uSizeCopy = AkMin( in_uDestMaxNumChars - 1, wcslen( in_pSrc ) + 1 );
575  wcsncpy( in_pDest, in_pSrc, uSizeCopy );
576  in_pDest[uSizeCopy] = '\0';
577  }
578 
579  /// Safe ansi string copy.
580  AkForceInline void SafeStrCpy( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
581  {
582  size_t uSizeCopy = AkMin( in_uDestMaxNumChars - 1, strlen( in_pSrc ) + 1 );
583  strncpy( in_pDest, in_pSrc, uSizeCopy );
584  in_pDest[uSizeCopy] = '\0';
585  }
586 
587  /// Safe unicode string concatenation.
588  AkForceInline void SafeStrCat( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
589  {
590  size_t uAvailableSize = ( in_uDestMaxNumChars - wcslen( in_pDest ) - 1 );
591  wcsncat( in_pDest, in_pSrc, AkMin( uAvailableSize, wcslen( in_pSrc ) ) );
592  }
593 
594  /// Safe ansi string concatenation.
595  AkForceInline void SafeStrCat( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
596  {
597  size_t uAvailableSize = ( in_uDestMaxNumChars - strlen( in_pDest ) - 1 );
598  strncat( in_pDest, in_pSrc, AkMin( uAvailableSize, strlen( in_pSrc ) ) );
599  }
600 
601  inline int SafeStrFormat(wchar_t * in_pDest, size_t in_uDestMaxNumChars, const wchar_t* in_pszFmt, ...)
602  {
603  va_list args;
604  va_start(args, in_pszFmt);
605  int r = vswprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
606  va_end(args);
607  return r;
608  }
609 
610  inline int SafeStrFormat(char * in_pDest, size_t in_uDestMaxNumChars, const char* in_pszFmt, ...)
611  {
612  va_list args;
613  va_start(args, in_pszFmt);
614  int r = vsnprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
615  va_end(args);
616  return r;
617  }
618 
619  /// Stack allocations.
620  #define AkAlloca( _size_ ) alloca( _size_ )
621 
622 
623 
624  /// Converts a wchar_t string to an AkOSChar string.
625  /// \remark On some platforms the AkOSChar string simply points to the same string,
626  /// on others a new buffer is allocated on the stack using AkAlloca. This means
627  /// you must make sure that:
628  /// - The source string stays valid and unmodified for as long as you need the
629  /// AkOSChar string (for cases where they point to the same string)
630  /// - The AkOSChar string is used within this scope only -- for example, do NOT
631  /// return that string from a function (for cases where it is allocated on the stack)
632  #define CONVERT_WIDE_TO_OSCHAR( _wstring_, _oscharstring_ ) \
633  _oscharstring_ = (AkOSChar*)AkAlloca( (1 + wcslen( _wstring_ )) * sizeof(AkOSChar) ); \
634  AKPLATFORM::AkWideCharToChar( _wstring_ , (AkUInt32)(1 + wcslen( _wstring_ )), (AkOSChar*)( _oscharstring_ ) )
635 
636 
637  /// Converts a char string to an AkOSChar string.
638  /// \remark On some platforms the AkOSChar string simply points to the same string,
639  /// on others a new buffer is allocated on the stack using AkAlloca. This means
640  /// you must make sure that:
641  /// - The source string stays valid and unmodified for as long as you need the
642  /// AkOSChar string (for cases where they point to the same string)
643  /// - The AkOSChar string is used within this scope only -- for example, do NOT
644  /// return that string from a function (for cases where it is allocated on the stack)
645  #define CONVERT_CHAR_TO_OSCHAR( _astring_, _oscharstring_ ) ( _oscharstring_ ) = (AkOSChar*)( _astring_ )
646 
647  /// Converts a AkOSChar string into wide char string.
648  /// \remark On some platforms the AkOSChar string simply points to the same string,
649  /// on others a new buffer is allocated on the stack using AkAlloca. This means
650  /// you must make sure that:
651  /// - The source string stays valid and unmodified for as long as you need the
652  /// AkOSChar string (for cases where they point to the same string)
653  /// - The AkOSChar string is used within this scope only -- for example, do NOT
654  /// return that string from a function (for cases where it is allocated on the stack)
655  #define CONVERT_OSCHAR_TO_WIDE( _osstring_, _wstring_ ) \
656  _wstring_ = (wchar_t*)AkAlloca((1+strlen(_osstring_)) * sizeof(wchar_t)); \
657  AKPLATFORM::AkCharToWideChar( _osstring_, (AkUInt32)(1 + strlen(_osstring_ )), _wstring_ )
658 
659  /// Converts a AkOSChar string into char string.
660  /// \remark On some platforms the AkOSChar string simply points to the same string,
661  /// on others a new buffer is allocated on the stack using AkAlloca. This means
662  /// you must make sure that:
663  /// - The source string stays valid and unmodified for as long as you need the
664  /// AkOSChar string (for cases where they point to the same string)
665  /// - The AkOSChar string is used within this scope only -- for example, do NOT
666  /// return that string from a function (for cases where it is allocated on the stack)
667  #define CONVERT_OSCHAR_TO_CHAR( _osstring_, _astring_ ) _astring_ = (char*)_osstring_
668 
669  /// Get the length, in characters, of a NULL-terminated AkUtf16 string
670  /// \return The length, in characters, of the specified string (excluding terminating NULL)
671  AkForceInline size_t AkUtf16StrLen( const AkUtf16* in_pStr )
672  {
673  return ( wcslen( in_pStr ) );
674  }
675 
676  /// Get the length, in characters, of a NULL-terminated AkOSChar string
677  /// \return The length, in characters, of the specified string (excluding terminating NULL)
678  AkForceInline size_t OsStrLen( const AkOSChar* in_pszString )
679  {
680  return ( strlen( in_pszString ) );
681  }
682 
683  /// AkOSChar version of sprintf().
684  #define AK_OSPRINTF snprintf
685 
686  /// Compare two NULL-terminated AkOSChar strings
687  /// \return
688  /// - < 0 if in_pszString1 < in_pszString2
689  /// - 0 if the two strings are identical
690  /// - > 0 if in_pszString1 > in_pszString2
691  /// \remark The comparison is case-sensitive
692  AkForceInline int OsStrCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2 )
693  {
694  return ( strcmp( in_pszString1, in_pszString2 ) );
695  }
696 
697  /// Compare two NULL-terminated AkOSChar strings up to the specified count of characters.
698  /// \return
699  /// - < 0 if in_pszString1 < in_pszString2
700  /// - 0 if the two strings are identical
701  /// - > 0 if in_pszString1 > in_pszString2
702  /// \remark The comparison is case-sensitive
703  inline int OsStrNCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2, size_t in_MaxCountSize )
704  {
705  return ( strncmp(in_pszString1, in_pszString2, in_MaxCountSize) );
706  }
707 
708  /// Detects whether the string represents an absolute path to a file
709  inline bool IsAbsolutePath(const AkOSChar* in_pszPath, size_t in_pathLen)
710  {
711  return in_pathLen >= 1 && in_pszPath[0] == '/';
712  }
713 
714  #define AK_UTF16_TO_WCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
715  #define AK_WCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
716  #define AK_UTF8_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
717  #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
718  #define AK_UTF16_TO_CHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
719  #define AK_CHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
720  #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
721 
722  // Use with AkOSChar.
723  #define AK_PATH_SEPARATOR ("/")
724  #define AK_LIBRARY_PREFIX ("")
725  #define AK_DYNAMIC_LIBRARY_EXTENSION (".prx")
726 
727  #define AK_FILEHANDLE_TO_UINTPTR(_h) ((AkUIntPtr)_h)
728  #define AK_SET_FILEHANDLE_TO_UINTPTR(_h,_u) _h = (AkFileHandle)_u
729 
730  /// Support to fetch the CPUID for the platform. Only valid for X86 targets
731  /// \remark Note that IAkProcessorFeatures should be preferred to fetch this data
732  /// as it will have already translated the feature bits into AK-relevant enums
733  inline void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
734  {
735  __get_cpuid_count( in_uLeafOpcode, in_uSubLeafOpcode,
736  &out_uCPUFeatures[0],
737  &out_uCPUFeatures[1],
738  &out_uCPUFeatures[2],
739  &out_uCPUFeatures[3]);
740  }
741 }
742 
743 #endif // _AK_PLATFORM_FUNCS_H_
AKRESULT AkCreateSemaphore(AkSemaphore &out_semaphore, AkUInt32 in_initialCount)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:99
size_t AkUtf16StrLen(const AkUtf16 *in_pStr)
Definition: AkPlatformFuncs.h:582
Audiokinetic namespace.
@ AK_Fail
The operation failed.
Definition: AkTypes.h:196
semaphore_t AkEvent
Definition: AkTypes.h:73
AkForceInline void FreeVM(void *address, size_t size, size_t extra, size_t release)
Definition: AkPlatformFuncs.h:262
#define AK_THREAD_DEFAULT_SCHED_POLICY
Definition: AkPlatformFuncs.h:79
int nPriority
Thread priority.
Definition: AkPlatformFuncs.h:48
void AkClearEvent(AkEvent &out_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:51
AkForceInline void AkClearSemaphore(AkSemaphore &io_semaphore)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:93
AkForceInline void FreeDevice(void *address, size_t size, size_t extra, size_t release)
Definition: AkPlatformFuncs.h:293
Platform-dependent helpers.
Definition: AkPlatformFuncs.h:156
void AkWaitForEvent(AkEvent &in_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:79
AkForceInline void UpdatePerformanceFrequency()
Platform Independent Helper.
Definition: AkPlatformFuncs.h:429
int AkThreadID
Definition: AkTypes.h:69
AKRESULT
Standard function call result.
Definition: AkTypes.h:193
AkForceInline bool CheckMemoryProtection(void *address, size_t size, int expectedProt)
Definition: AkPlatformFuncs.h:304
void OutputDebugMsg(const char *in_pszMsg)
Output a debug message on the console (Ansi string)
Definition: AkPlatformFuncs.h:120
AkForceInline void * AllocVM(size_t size, size_t *extra)
Definition: AkPlatformFuncs.h:243
void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
Definition: AkPlatformFuncs.h:295
#define AK_NULL_THREAD
Definition: AkPlatformFuncs.h:88
char AkOSChar
Generic character string.
Definition: AkTypes.h:60
int SafeStrFormat(wchar_t *in_pDest, size_t in_uDestMaxNumChars, const wchar_t *in_pszFmt,...)
Definition: AkPlatformFuncs.h:512
AkForceInline void * AllocDevice(size_t size, size_t *extra)
Definition: AkPlatformFuncs.h:273
#define NULL
Definition: AkTypes.h:46
#define AK_THREAD_AFFINITY_DEFAULT
Definition: AkPlatformFuncs.h:85
AkThreadID CurrentThread()
Returns the calling thread's ID.
Definition: AkPlatformFuncs.h:380
bool IsAbsolutePath(const AkOSChar *in_pszPath, size_t in_pathLen)
Detects whether the string represents an absolute path to a file.
Definition: AkPlatformFuncs.h:620
float AkReal32
32-bit floating point
Definition: AkNumeralTypes.h:46
@ AK_Success
The operation was successful.
Definition: AkTypes.h:195
int32_t AkInt32
Signed 32-bit integer.
Definition: AkNumeralTypes.h:43
void AkCreateThread(AkThreadRoutine pStartRoutine, void *pParams, const AkThreadProperties &in_threadProperties, AkThread *out_pThread, const char *)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:182
const int kMemoryFlags
Definition: AkPlatformFuncs.h:239
AkUInt16 AkUtf16
Definition: AkTypes.h:61
uintptr_t AkUIntPtr
Integer (unsigned) type for pointers.
Definition: AkNumeralTypes.h:50
#define AK_VM_PAGE_SIZE
Definition: AkPlatformFuncs.h:77
#define AK_THREAD_PRIORITY_NORMAL
Definition: AkPlatformFuncs.h:80
void OutputDebugMsgV(const char *in_pszFmt,...)
Output a debug message on the console (variadic function).
Definition: AkPlatformFuncs.h:129
void PerformanceCounter(AkInt64 *out_piLastTime)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:142
void AkDestroySemaphore(AkSemaphore &io_semaphore)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:111
void AkDestroyEvent(AkEvent &io_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:69
nn::os::ThreadFunction AkThreadRoutine
Thread routine.
Definition: AkTypes.h:85
AkForceInline bool AkIsValidThread(AkThread *in_pThread)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:277
#define AkMin(x1, x2)
Definition: AkPlatformFuncs.h:93
AkForceInline void AkMemCpy(void *pDest, const void *pSrc, AkUInt32 uSize)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:395
#define AKASSERT(Condition)
Definition: AkAssert.h:67
#define AKVERIFY(x)
Definition: AkAssert.h:69
AkForceInline void AkSleep(AkUInt32 in_ulMilliseconds)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:386
AkForceInline void AkClearThread(AkThread *in_pThread)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:283
AkForceInline void AkGetDefaultThreadProperties(AkThreadProperties &out_threadProperties)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:302
int OsStrNCmp(const AkOSChar *in_pszString1, const AkOSChar *in_pszString2, size_t in_MaxCountSize)
Definition: AkPlatformFuncs.h:614
void AkLimitedSpinForZero(AkAtomic32 *in_pVal)
Definition: AkPlatformFuncs.h:224
AkForceInline void AkMemSet(void *pDest, AkInt32 iVal, AkUInt32 uSize)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:407
void AkMemMove(void *pDest, const void *pSrc, AkUInt32 uSize)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:401
SceKernelCpumask dwAffinityMask
Affinity mask.
Definition: AkPlatformFuncs.h:49
AkReal32 g_fFreqRatio
Definition: AkPlatformFuncs.h:63
double AkReal64
64-bit floating point
Definition: AkNumeralTypes.h:47
AKRESULT AkCreateEvent(AkEvent &out_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:57
AkForceInline void SafeStrCpy(wchar_t *in_pDest, const wchar_t *in_pSrc, size_t in_uDestMaxNumChars)
Safe unicode string copy.
Definition: AkPlatformFuncs.h:483
const int kDeviceMemoryFlags
Definition: AkPlatformFuncs.h:240
int64_t AkInt64
Signed 64-bit integer.
Definition: AkNumeralTypes.h:44
volatile long AkAtomic32
Definition: AkAtomic.h:42
void AkWaitForSemaphore(AkSemaphore &in_semaphore)
Platform Independent Helper - Semaphore wait, aka Operation P. Decrements value of semaphore,...
Definition: AkPlatformFuncs.h:117
size_t uStackSize
Thread stack size.
Definition: AkPlatformFuncs.h:50
void PerformanceFrequency(AkInt64 *out_piFreq)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:45
#define AK_DEFAULT_STACK_SIZE
Definition: AkPlatformFuncs.h:76
int uSchedPolicy
Thread scheduling policy.
Definition: AkPlatformFuncs.h:51
AkForceInline AkInt32 AkCharToWideChar(const char *in_pszAnsiString, AkUInt32 in_uiOutBufferSize, void *io_pvUnicodeStringBuffer)
String conversion helper.
Definition: AkPlatformFuncs.h:460
uint32_t AkUInt32
Unsigned 32-bit integer.
Definition: AkNumeralTypes.h:38
void AkReleaseSemaphore(AkSemaphore &in_semaphore, AkUInt32 in_count)
Platform Independent Helper - Semaphore signal, aka Operation V. Increments value of semaphore by an ...
Definition: AkPlatformFuncs.h:123
AkForceInline void SafeStrCat(wchar_t *in_pDest, const wchar_t *in_pSrc, size_t in_uDestMaxNumChars)
Safe unicode string concatenation.
Definition: AkPlatformFuncs.h:499
AkForceInline AKRESULT AkCreateNamedEvent(AkEvent &out_event, const char *in_szName)
Definition: AkPlatformFuncs.h:154
#define AK_VM_DEVICE_PAGE_SIZE
Definition: AkPlatformFuncs.h:78
AkForceInline AkInt32 AkWideCharToChar(const wchar_t *in_pszUnicodeString, AkUInt32 in_uiOutBufferSize, char *io_pszAnsiString)
String conversion helper.
Definition: AkPlatformFuncs.h:443
AkForceInline void AkWaitForSingleThread(AkThread *in_pThread)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:373
void AkSignalEvent(const AkEvent &in_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:86
Definition: AkTypes.h:90
AkForceInline AkInt32 AkUtf8ToWideChar(const char *in_pszUtf8String, AkUInt32 in_uiOutBufferSize, void *io_pvUnicodeStringBuffer)
String conversion helper.
Definition: AkPlatformFuncs.h:475
semaphore_t AkSemaphore
Definition: AkTypes.h:74
AkForceInline void AkCloseThread(AkThread *in_pThread)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:289
AkForceInline int OsStrCmp(const AkOSChar *in_pszString1, const AkOSChar *in_pszString2)
Definition: AkPlatformFuncs.h:603
#define AkForceInline
Definition: AkTypes.h:61
__forceinline long AkAtomicLoad32(AkAtomic32 *pSrc)
Definition: AkAtomic.h:57
AkForceInline size_t OsStrLen(const AkOSChar *in_pszString)
Definition: AkPlatformFuncs.h:589
AkForceInline AkReal32 Elapsed(const AkInt64 &in_iNow, const AkInt64 &in_iStart)
Returns a time range in milliseconds, using the sound engine's updated count->milliseconds ratio.
Definition: AkPlatformFuncs.h:437

Was this page helpful?

Need Support?

Questions? Problems? Need more info? Contact us, and we can help!

Visit our Support page

Tell us about your project. We're here to help.

Register your project and we'll help you get started with no strings attached!

Get started with Wwise