Version
menu_open
link
Wwise SDK 2023.1.3
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) 2024 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_THREAD_DEFAULT_SCHED_POLICY SCE_KERNEL_SCHED_FIFO
78 #define AK_THREAD_PRIORITY_NORMAL SCE_KERNEL_PRIO_FIFO_DEFAULT
79 #define AK_THREAD_PRIORITY_ABOVE_NORMAL SCE_KERNEL_PRIO_FIFO_HIGHEST
80 #define AK_THREAD_PRIORITY_BELOW_NORMAL SCE_KERNEL_PRIO_FIFO_LOWEST
81 
82 #define AK_THREAD_AFFINITY_ALL 8191 // from 0b1'1111'1111'1111 -- 13 cores available
83 #define AK_THREAD_AFFINITY_DEFAULT 4095 // from 0b0'1111'1111'1111 -- Default to only the 12 fully-available cores. 13th core is half-available.
84 
85 // NULL objects
86 #define AK_NULL_THREAD NULL
87 
88 #define AK_INFINITE (AK_UINT_MAX)
89 
90 #define AkMax(x1, x2) (((x1) > (x2))? (x1): (x2))
91 #define AkMin(x1, x2) (((x1) < (x2))? (x1): (x2))
92 #define AkClamp(x, min, max) ((x) < (min)) ? (min) : (((x) > (max) ? (max) : (x)))
93 
94 namespace AKPLATFORM
95 {
96 #ifndef AK_OPTIMIZED
97  /// Output a debug message on the console (Ansi string)
98  AkForceInline void OutputDebugMsg( const char* in_pszMsg )
99  {
100  fputs( in_pszMsg, stderr );
101  }
102  /// Output a debug message on the console (Unicode string)
103  AkForceInline void OutputDebugMsg( const wchar_t* in_pszMsg )
104  {
105  fputws( in_pszMsg, stderr );
106  }
107 
108  /// Output a debug message on the console (Unicode string) (variadic function)
109  template <int MaxSize = 0> // Unused
110  AkForceInline void OutputDebugMsgV( const wchar_t* in_pszFmt, ... )
111  {
112  va_list args;
113  va_start(args, in_pszFmt);
114  vfwprintf(stderr, in_pszFmt, args);
115  va_end(args);
116  }
117 
118  /// Output a debug message on the console (Ansi string) (variadic function)
119  template <int MaxSize = 0> // Unused
120  AkForceInline void OutputDebugMsgV( const char* in_pszFmt, ... )
121  {
122  va_list args;
123  va_start(args, in_pszFmt);
124  vfprintf(stderr, in_pszFmt, args);
125  va_end(args);
126  }
127 #else
128  inline void OutputDebugMsg( const wchar_t* ){}
129  inline void OutputDebugMsg( const char* ){}
130 
131  template <int MaxSize = 0> // Unused
132  inline void OutputDebugMsgV( const wchar_t*, ... ){}
133 
134  template <int MaxSize = 0> // Unused
135  inline void OutputDebugMsgV( const char*, ... ){}
136 #endif
137 
138 
139  // Simple automatic event API
140  // ------------------------------------------------------------------
141 
142  /// Platform Independent Helper
143  AkForceInline void AkClearEvent( AkEvent & out_event )
144  {
145  out_event = NULL;
146  }
147 
148  AkForceInline AKRESULT AkCreateNamedEvent( AkEvent & out_event, const char* in_szName )
149  {
150  // NOTE: AkWaitForEvent uses the SCE_KERNEL_EVF_WAITMODE_CLEAR_PAT flag
151  // to get the same behavior as an auto-reset Win32 event
152  int ret = sceKernelCreateEventFlag(
153  &out_event,
154  in_szName,
155  SCE_KERNEL_EVF_ATTR_MULTI,
156  0 /* not signalled by default */,
157  NULL /* No optional params */ );
158 
159  if( ret == SCE_OK )
160  return AK_Success;
161 
162  AkClearEvent( out_event );
163  return AK_Fail;
164  }
165 
166  /// Platform Independent Helper
168  {
169  return AkCreateNamedEvent( out_event, "AkEvent" );
170  }
171 
172  /// Platform Independent Helper
173  AkForceInline void AkDestroyEvent( AkEvent & io_event )
174  {
175  sceKernelDeleteEventFlag(io_event);
176  AkClearEvent( io_event );
177  }
178 
179  /// Platform Independent Helper
180  AkForceInline void AkWaitForEvent( AkEvent & in_event )
181  {
182  AKVERIFY( sceKernelWaitEventFlag(
183  in_event,
184  1,
185  SCE_KERNEL_EVF_WAITMODE_OR | SCE_KERNEL_EVF_WAITMODE_CLEAR_ALL,
186  SCE_NULL,
187  SCE_NULL) == 0 );
188  }
189 
190  /// Platform Independent Helper
191  AkForceInline void AkSignalEvent( const AkEvent & in_event )
192  {
193  AKVERIFY( sceKernelSetEventFlag( in_event, 1 ) == 0 );
194  }
195 
196  /// Platform Independent Helper
197  AkForceInline void AkClearSemaphore(AkSemaphore& io_semaphore)
198  {
199  io_semaphore = NULL;
200  }
201 
202  /// Platform Independent Helper
203  inline AKRESULT AkCreateSemaphore( AkSemaphore& out_semaphore, AkUInt32 in_initialCount )
204  {
205  int ret = sceKernelCreateSema(
206  &out_semaphore,
207  "AkSemaphore",
208  0,
209  in_initialCount,
210  INT_MAX,
211  NULL );
212 
213  return ( ret == SCE_OK ) ? AK_Success : AK_Fail;
214  }
215 
216  /// Platform Independent Helper
217  inline void AkDestroySemaphore(AkSemaphore& io_semaphore)
218  {
219  AKVERIFY(sceKernelDeleteSema(io_semaphore) == SCE_OK);
220  }
221 
222  /// 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.
223  inline void AkWaitForSemaphore(AkSemaphore& in_semaphore)
224  {
225  AKVERIFY(sceKernelWaitSema(in_semaphore, 1, NULL) == SCE_OK);
226  }
227 
228  /// Platform Independent Helper - Semaphore signal, aka Operation V. Increments value of semaphore by an arbitrary count.
229  inline void AkReleaseSemaphore(AkSemaphore& in_semaphore, AkUInt32 in_count)
230  {
231  AKVERIFY(sceKernelSignalSema(in_semaphore, in_count) == SCE_OK);
232  }
233 
234 
235  // Threads
236  // ------------------------------------------------------------------
237 
238  /// Platform Independent Helper
239  AkForceInline bool AkIsValidThread( AkThread * in_pThread )
240  {
241  return ( *in_pThread != AK_NULL_THREAD );
242  }
243 
244  /// Platform Independent Helper
245  AkForceInline void AkClearThread( AkThread * in_pThread )
246  {
247  *in_pThread = AK_NULL_THREAD;
248  }
249 
250  /// Platform Independent Helper
251  AkForceInline void AkCloseThread( AkThread * in_pThread )
252  {
253  AKASSERT( in_pThread );
254  AKASSERT( *in_pThread );
255 
256  // #define KILL_THREAD(t) do { void *ret; scePthreadJoin(t,&ret); } while(false)
257  // AKVERIFY( SCE_OK == sceKernelDeleteThread( *in_pThread ) );
258  AkClearThread( in_pThread );
259  }
260 
261  #define AkExitThread( _result ) return _result; // ?????
262 
263  /// Platform Independent Helper
264  AkForceInline void AkGetDefaultThreadProperties( AkThreadProperties & out_threadProperties )
265  {
266  out_threadProperties.uStackSize = AK_DEFAULT_STACK_SIZE;
267  out_threadProperties.uSchedPolicy = AK_THREAD_DEFAULT_SCHED_POLICY;
268  out_threadProperties.nPriority = AK_THREAD_PRIORITY_NORMAL;
269  out_threadProperties.dwAffinityMask = AK_THREAD_AFFINITY_DEFAULT;
270  }
271 
272  /// Platform Independent Helper
273  inline void AkCreateThread(
274  AkThreadRoutine pStartRoutine, // Thread routine.
275  void * pParams, // Routine params.
276  const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
277  AkThread * out_pThread, // Returned thread handle.
278  const char * in_szThreadName ) // Opt thread name.
279  {
280  AKASSERT( out_pThread != NULL );
281 
282  ScePthreadAttr attr;
283 
284  // Create the attr
285  AKVERIFY(!scePthreadAttrInit(&attr));
286  // Set the stack size
287  AKVERIFY(!scePthreadAttrSetstacksize(&attr,in_threadProperties.uStackSize));
288  AKVERIFY(!scePthreadAttrSetdetachstate(&attr, SCE_PTHREAD_CREATE_JOINABLE));
289  AKVERIFY(!scePthreadAttrSetinheritsched(&attr, SCE_PTHREAD_EXPLICIT_SCHED));
290  AKVERIFY(!scePthreadAttrSetaffinity(&attr,in_threadProperties.dwAffinityMask));
291 
292  // Try to set the thread policy
293  int sched_policy = in_threadProperties.uSchedPolicy;
294  if( scePthreadAttrSetschedpolicy( &attr, sched_policy ) )
295  {
296  AKASSERT( !"AKCreateThread invalid sched policy, will automatically set it to FIFO scheduling" );
297  sched_policy = AK_THREAD_DEFAULT_SCHED_POLICY;
298  AKVERIFY( !scePthreadAttrSetschedpolicy( &attr, sched_policy ));
299  }
300 
301  int minPriority, maxPriority;
302  minPriority = SCE_KERNEL_PRIO_FIFO_HIGHEST;
303  maxPriority = SCE_KERNEL_PRIO_FIFO_LOWEST;
304 
305  // Set the thread priority if valid
306  AKASSERT( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority );
307  if( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority )
308  {
309  SceKernelSchedParam schedParam;
310  AKVERIFY( scePthreadAttrGetschedparam(&attr, &schedParam) == 0 );
311  schedParam.sched_priority = in_threadProperties.nPriority;
312  AKVERIFY( scePthreadAttrSetschedparam(&attr, &schedParam) == 0 );
313  }
314 
315  // Create the tread
316  int threadError = scePthreadCreate(out_pThread, &attr, pStartRoutine, pParams, in_szThreadName);
317  AKASSERT( threadError == 0 );
318  AKVERIFY(!scePthreadAttrDestroy(&attr));
319 
320  if( threadError != 0 )
321  {
322  AkClearThread( out_pThread );
323  return;
324  }
325 
326  // ::CreateThread() return NULL if it fails.
327  if ( !*out_pThread )
328  {
329  AkClearThread( out_pThread );
330  return;
331  }
332  }
333 
334  /// Platform Independent Helper
335  AkForceInline void AkWaitForSingleThread( AkThread * in_pThread )
336  {
337  AKASSERT( in_pThread );
338  AKASSERT( *in_pThread );
339  AKVERIFY(!scePthreadJoin( *in_pThread, NULL ));
340  }
341 
342  inline AkThreadID CurrentThread()
343  {
344  return scePthreadSelf();
345  }
346 
347  /// Platform Independent Helper
348  AkForceInline void AkSleep( AkUInt32 in_ulMilliseconds )
349  {
350  usleep( in_ulMilliseconds * 1000 );
351  }
352 
353  // Optimized memory functions
354  // --------------------------------------------------------------------
355 
356  /// Platform Independent Helper
357  AkForceInline void AkMemCpy( void * pDest, const void * pSrc, AkUInt32 uSize )
358  {
359  memcpy( pDest, pSrc, uSize );
360  }
361 
362  /// Platform Independent Helper
363  inline void AkMemMove( void* pDest, const void* pSrc, AkUInt32 uSize )
364  {
365  memmove( pDest, pSrc, uSize );
366  }
367 
368  /// Platform Independent Helper
369  AkForceInline void AkMemSet( void * pDest, AkInt32 iVal, AkUInt32 uSize )
370  {
371  memset( pDest, iVal, uSize );
372  }
373 
374  // Time functions
375  // ------------------------------------------------------------------
376 
377  /// Platform Independent Helper
378  AkForceInline void PerformanceCounter( AkInt64 * out_piLastTime )
379  {
380  uint64_t uTime = sceKernelGetProcessTimeCounter();
381  *out_piLastTime = (AkInt64)uTime;
382  }
383 
384  /// Frequency of the PerformanceCounter() (ticks per second)
385  AkForceInline void PerformanceFrequency( AkInt64 * out_piFreq )
386  {
387  *out_piFreq = (AkInt64)sceKernelGetProcessTimeCounterFrequency();
388  }
389 
390  /// Platform Independent Helper
392  {
393  AkInt64 iFreq;
394  PerformanceFrequency( &iFreq );
395  AK::g_fFreqRatio = (AkReal32)((AkReal64)iFreq / 1000);
396  }
397 
398  // Waits for a limited amount of time for in_pVal to hit zero (without yielding the thread)
399  inline void AkLimitedSpinForZero(AkAtomic32* in_pVal)
400  {
401  // monitorx and waitx are available on certain AMD CPUs, so we can have a custom impl of AkLimitedSpinForZero
402  AkInt64 endSpinTime = 0;
403  AkInt64 currentTime = 0;
404  PerformanceCounter(&endSpinTime);
405  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
406  while (true)
407  {
408  // set up monitorx on pVal
409  _mm_monitorx((void*)in_pVal, 0U, 0U);
410  // if pval is zero, skip out
411  if (AkAtomicLoad32(in_pVal) == 0)
412  {
413  break;
414  }
415  // wait until a store to pVal occurs (or ~1us passes)
416  _mm_mwaitx(2U, 0U, 1000U);
417 
418  // Check if we've hit the deadline for the timeout
419  PerformanceCounter(&currentTime);
420  if (currentTime > endSpinTime)
421  {
422  break;
423  }
424  }
425  }
426 
427  // Waits for a limited amount of time for in_pVal to get atomically shift from the expected value to the proposed one
428  // returns true if acquisition succeeded
429  inline bool AkLimitedSpinToAcquire(AkAtomic32* in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
430  {
431  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
432  {
433  return true;
434  }
435 
436  // Cas failed, start the slower evaluation
437 
438  // monitorx and waitx are available on certain AMD CPUs, so we can use monitorx/waitx
439  AkInt64 endSpinTime = 0;
440  AkInt64 currentTime = 0;
441  PerformanceCounter(&endSpinTime);
442  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
443  while (true)
444  {
445  // set up monitorx on pVal
446  _mm_monitorx((void*)in_pVal, 0U, 0U);
447  // attempt cas to acquire and if successful, skip out
448  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
449  {
450  return true;
451  }
452  // wait until a store to pVal occurs (or ~1us passes)
453  _mm_mwaitx(2U, 0U, 1000U);
454 
455  // Check if we've hit the deadline for the timeout
456  PerformanceCounter(&currentTime);
457  if (currentTime > endSpinTime)
458  {
459  return false;
460  }
461  }
462  }
463 
464 #define AK_LIMITEDSPINFORZERO // mark AkLimitedSpinForZero as defined to avoid duplicate definitions
465 
466  /// Returns a time range in milliseconds, using the sound engine's updated count->milliseconds ratio.
467  AkForceInline AkReal32 Elapsed( const AkInt64 & in_iNow, const AkInt64 & in_iStart )
468  {
469  return ( in_iNow - in_iStart ) / AK::g_fFreqRatio;
470  }
471 
472  /// String conversion helper
473  AkForceInline AkInt32 AkWideCharToChar( const wchar_t* in_pszUnicodeString,
474  AkUInt32 in_uiOutBufferSize,
475  char* io_pszAnsiString )
476  {
477  AKASSERT( io_pszAnsiString != NULL );
478 
479  mbstate_t state;
480  memset (&state, '\0', sizeof (state));
481 
482  return (AkInt32)wcsrtombs(io_pszAnsiString, // destination
483  &in_pszUnicodeString, // source
484  in_uiOutBufferSize, // destination length
485  &state); //
486 
487  }
488 
489  /// String conversion helper
490  AkForceInline AkInt32 AkCharToWideChar( const char* in_pszAnsiString,
491  AkUInt32 in_uiOutBufferSize,
492  void* io_pvUnicodeStringBuffer )
493  {
494  AKASSERT( io_pvUnicodeStringBuffer != NULL );
495 
496  mbstate_t state;
497  memset (&state, '\0', sizeof (state));
498 
499  return (AkInt32)mbsrtowcs((wchar_t*)io_pvUnicodeStringBuffer, // destination
500  &in_pszAnsiString, // source
501  in_uiOutBufferSize, // destination length
502  &state); //
503  }
504 
505  AkForceInline AkInt32 AkUtf8ToWideChar( const char* in_pszUtf8String,
506  AkUInt32 in_uiOutBufferSize,
507  void* io_pvUnicodeStringBuffer )
508  {
509  return AkCharToWideChar( in_pszUtf8String, in_uiOutBufferSize, (wchar_t*)io_pvUnicodeStringBuffer );
510  }
511 
512  /// Safe unicode string copy.
513  AkForceInline void SafeStrCpy( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
514  {
515  size_t uSizeCopy = AkMin( in_uDestMaxNumChars - 1, wcslen( in_pSrc ) + 1 );
516  wcsncpy( in_pDest, in_pSrc, uSizeCopy );
517  in_pDest[uSizeCopy] = '\0';
518  }
519 
520  /// Safe ansi string copy.
521  AkForceInline void SafeStrCpy( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
522  {
523  size_t uSizeCopy = AkMin( in_uDestMaxNumChars - 1, strlen( in_pSrc ) + 1 );
524  strncpy( in_pDest, in_pSrc, uSizeCopy );
525  in_pDest[uSizeCopy] = '\0';
526  }
527 
528  /// Safe unicode string concatenation.
529  AkForceInline void SafeStrCat( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
530  {
531  size_t uAvailableSize = ( in_uDestMaxNumChars - wcslen( in_pDest ) - 1 );
532  wcsncat( in_pDest, in_pSrc, AkMin( uAvailableSize, wcslen( in_pSrc ) ) );
533  }
534 
535  /// Safe ansi string concatenation.
536  AkForceInline void SafeStrCat( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
537  {
538  size_t uAvailableSize = ( in_uDestMaxNumChars - strlen( in_pDest ) - 1 );
539  strncat( in_pDest, in_pSrc, AkMin( uAvailableSize, strlen( in_pSrc ) ) );
540  }
541 
542  inline int SafeStrFormat(wchar_t * in_pDest, size_t in_uDestMaxNumChars, const wchar_t* in_pszFmt, ...)
543  {
544  va_list args;
545  va_start(args, in_pszFmt);
546  int r = vswprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
547  va_end(args);
548  return r;
549  }
550 
551  inline int SafeStrFormat(char * in_pDest, size_t in_uDestMaxNumChars, const char* in_pszFmt, ...)
552  {
553  va_list args;
554  va_start(args, in_pszFmt);
555  int r = vsnprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
556  va_end(args);
557  return r;
558  }
559 
560  /// Stack allocations.
561  #define AkAlloca( _size_ ) alloca( _size_ )
562 
563 
564 
565  /// Converts a wchar_t string to an AkOSChar string.
566  /// \remark On some platforms the AkOSChar string simply points to the same string,
567  /// on others a new buffer is allocated on the stack using AkAlloca. This means
568  /// you must make sure that:
569  /// - The source string stays valid and unmodified for as long as you need the
570  /// AkOSChar string (for cases where they point to the same string)
571  /// - The AkOSChar string is used within this scope only -- for example, do NOT
572  /// return that string from a function (for cases where it is allocated on the stack)
573  #define CONVERT_WIDE_TO_OSCHAR( _wstring_, _oscharstring_ ) \
574  _oscharstring_ = (AkOSChar*)AkAlloca( (1 + wcslen( _wstring_ )) * sizeof(AkOSChar) ); \
575  AKPLATFORM::AkWideCharToChar( _wstring_ , (AkUInt32)(1 + wcslen( _wstring_ )), (AkOSChar*)( _oscharstring_ ) )
576 
577 
578  /// Converts a char string to an AkOSChar string.
579  /// \remark On some platforms the AkOSChar string simply points to the same string,
580  /// on others a new buffer is allocated on the stack using AkAlloca. This means
581  /// you must make sure that:
582  /// - The source string stays valid and unmodified for as long as you need the
583  /// AkOSChar string (for cases where they point to the same string)
584  /// - The AkOSChar string is used within this scope only -- for example, do NOT
585  /// return that string from a function (for cases where it is allocated on the stack)
586  #define CONVERT_CHAR_TO_OSCHAR( _astring_, _oscharstring_ ) ( _oscharstring_ ) = (AkOSChar*)( _astring_ )
587 
588  /// Converts a AkOSChar string into wide char string.
589  /// \remark On some platforms the AkOSChar string simply points to the same string,
590  /// on others a new buffer is allocated on the stack using AkAlloca. This means
591  /// you must make sure that:
592  /// - The source string stays valid and unmodified for as long as you need the
593  /// AkOSChar string (for cases where they point to the same string)
594  /// - The AkOSChar string is used within this scope only -- for example, do NOT
595  /// return that string from a function (for cases where it is allocated on the stack)
596  #define CONVERT_OSCHAR_TO_WIDE( _osstring_, _wstring_ ) \
597  _wstring_ = (wchar_t*)AkAlloca((1+strlen(_osstring_)) * sizeof(wchar_t)); \
598  AKPLATFORM::AkCharToWideChar( _osstring_, (AkUInt32)(1 + strlen(_osstring_ )), _wstring_ )
599 
600  /// Converts a AkOSChar string into char string.
601  /// \remark On some platforms the AkOSChar string simply points to the same string,
602  /// on others a new buffer is allocated on the stack using AkAlloca. This means
603  /// you must make sure that:
604  /// - The source string stays valid and unmodified for as long as you need the
605  /// AkOSChar string (for cases where they point to the same string)
606  /// - The AkOSChar string is used within this scope only -- for example, do NOT
607  /// return that string from a function (for cases where it is allocated on the stack)
608  #define CONVERT_OSCHAR_TO_CHAR( _osstring_, _astring_ ) _astring_ = (char*)_osstring_
609 
610  /// Get the length, in characters, of a NULL-terminated AkUtf16 string
611  /// \return The length, in characters, of the specified string (excluding terminating NULL)
612  AkForceInline size_t AkUtf16StrLen( const AkUtf16* in_pStr )
613  {
614  return ( wcslen( in_pStr ) );
615  }
616 
617  /// Get the length, in characters, of a NULL-terminated AkOSChar string
618  /// \return The length, in characters, of the specified string (excluding terminating NULL)
619  AkForceInline size_t OsStrLen( const AkOSChar* in_pszString )
620  {
621  return ( strlen( in_pszString ) );
622  }
623 
624  /// AkOSChar version of sprintf().
625  #define AK_OSPRINTF snprintf
626 
627  /// Compare two NULL-terminated AkOSChar strings
628  /// \return
629  /// - < 0 if in_pszString1 < in_pszString2
630  /// - 0 if the two strings are identical
631  /// - > 0 if in_pszString1 > in_pszString2
632  /// \remark The comparison is case-sensitive
633  AkForceInline int OsStrCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2 )
634  {
635  return ( strcmp( in_pszString1, in_pszString2 ) );
636  }
637 
638  /// Compare two NULL-terminated AkOSChar strings up to the specified count of characters.
639  /// \return
640  /// - < 0 if in_pszString1 < in_pszString2
641  /// - 0 if the two strings are identical
642  /// - > 0 if in_pszString1 > in_pszString2
643  /// \remark The comparison is case-sensitive
644  inline int OsStrNCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2, size_t in_MaxCountSize )
645  {
646  return ( strncmp(in_pszString1, in_pszString2, in_MaxCountSize) );
647  }
648 
649  /// Detects whether the string represents an absolute path to a file
650  inline bool IsAbsolutePath(const AkOSChar* in_pszPath, size_t in_pathLen)
651  {
652  return in_pathLen >= 1 && in_pszPath[0] == '/';
653  }
654 
655  #define AK_UTF16_TO_WCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
656  #define AK_WCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
657  #define AK_UTF8_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
658  #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
659  #define AK_UTF16_TO_CHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
660  #define AK_CHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
661  #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
662 
663  // Use with AkOSChar.
664  #define AK_PATH_SEPARATOR "/"
665  #define AK_LIBRARY_PREFIX ""
666  #define AK_DYNAMIC_LIBRARY_EXTENSION ".prx"
667 
668  #define AK_FILEHANDLE_TO_UINTPTR(_h) ((AkUIntPtr)_h)
669  #define AK_SET_FILEHANDLE_TO_UINTPTR(_h,_u) _h = (AkFileHandle)_u
670 
671  /// Support to fetch the CPUID for the platform. Only valid for X86 targets
672  /// \remark Note that IAkProcessorFeatures should be preferred to fetch this data
673  /// as it will have already translated the feature bits into AK-relevant enums
674  inline void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
675  {
676  __get_cpuid_count( in_uLeafOpcode, in_uSubLeafOpcode,
677  &out_uCPUFeatures[0],
678  &out_uCPUFeatures[1],
679  &out_uCPUFeatures[2],
680  &out_uCPUFeatures[3]);
681  }
682 }
683 
684 #endif // _AK_PLATFORM_FUNCS_H_
AKRESULT AkCreateSemaphore(AkSemaphore &out_semaphore, AkUInt32 in_initialCount)
Platform Independent Helper.
size_t AkUtf16StrLen(const AkUtf16 *in_pStr)
Audiokinetic namespace.
@ AK_Fail
The operation failed.
Definition: AkTypes.h:216
semaphore_t AkEvent
Definition: AkTypes.h:84
#define AK_THREAD_DEFAULT_SCHED_POLICY
int nPriority
Thread priority.
void AkClearEvent(AkEvent &out_event)
Platform Independent Helper.
AkForceInline void AkClearSemaphore(AkSemaphore &io_semaphore)
Platform Independent Helper.
Platform-dependent helpers.
Definition: AkBitFuncs.h:43
void AkWaitForEvent(AkEvent &in_event)
Platform Independent Helper.
AkForceInline void UpdatePerformanceFrequency()
Platform Independent Helper.
int AkThreadID
Definition: AkTypes.h:69
AKRESULT
Standard function call result.
Definition: AkTypes.h:213
void OutputDebugMsg(const char *in_pszMsg)
Output a debug message on the console (Ansi string)
__forceinline int AkAtomicCas32(AkAtomic32 *pDest, long proposed, long expected)
Definition: AkAtomic.h:68
void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
#define AK_NULL_THREAD
char AkOSChar
Generic character string.
Definition: AkTypes.h:60
int SafeStrFormat(wchar_t *in_pDest, size_t in_uDestMaxNumChars, const wchar_t *in_pszFmt,...)
#define NULL
Definition: AkTypes.h:46
#define AK_THREAD_AFFINITY_DEFAULT
AkThreadID CurrentThread()
Returns the calling thread's ID.
bool IsAbsolutePath(const AkOSChar *in_pszPath, size_t in_pathLen)
Detects whether the string represents an absolute path to a file.
float AkReal32
32-bit floating point
@ AK_Success
The operation was successful.
Definition: AkTypes.h:215
int32_t AkInt32
Signed 32-bit integer.
void AkCreateThread(AkThreadRoutine pStartRoutine, void *pParams, const AkThreadProperties &in_threadProperties, AkThread *out_pThread, const char *)
Platform Independent Helper.
AkUInt16 AkUtf16
Definition: AkTypes.h:61
#define AK_THREAD_PRIORITY_NORMAL
void OutputDebugMsgV(const char *in_pszFmt,...)
Output a debug message on the console (variadic function).
void PerformanceCounter(AkInt64 *out_piLastTime)
Platform Independent Helper.
volatile uint32_t AkAtomic32
Definition: AkAtomic.h:45
void AkDestroySemaphore(AkSemaphore &io_semaphore)
Platform Independent Helper.
void AkDestroyEvent(AkEvent &io_event)
Platform Independent Helper.
nn::os::ThreadFunction AkThreadRoutine
Thread routine.
Definition: AkTypes.h:87
AkForceInline bool AkIsValidThread(AkThread *in_pThread)
Platform Independent Helper.
#define AkMin(x1, x2)
AkForceInline void AkMemCpy(void *pDest, const void *pSrc, AkUInt32 uSize)
Platform Independent Helper.
#define AKASSERT(Condition)
Definition: AkAssert.h:67
#define AKVERIFY(x)
Definition: AkAssert.h:69
AkForceInline void AkSleep(AkUInt32 in_ulMilliseconds)
Platform Independent Helper.
AkForceInline void AkClearThread(AkThread *in_pThread)
Platform Independent Helper.
AkForceInline void AkGetDefaultThreadProperties(AkThreadProperties &out_threadProperties)
Platform Independent Helper.
int OsStrNCmp(const AkOSChar *in_pszString1, const AkOSChar *in_pszString2, size_t in_MaxCountSize)
void AkLimitedSpinForZero(AkAtomic32 *in_pVal)
bool AkLimitedSpinToAcquire(AkAtomic32 *in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
AkForceInline void AkMemSet(void *pDest, AkInt32 iVal, AkUInt32 uSize)
Platform Independent Helper.
void AkMemMove(void *pDest, const void *pSrc, AkUInt32 uSize)
Platform Independent Helper.
SceKernelCpumask dwAffinityMask
Affinity mask.
AkReal32 g_fFreqRatio
double AkReal64
64-bit floating point
AKRESULT AkCreateEvent(AkEvent &out_event)
Platform Independent Helper.
AkForceInline void SafeStrCpy(wchar_t *in_pDest, const wchar_t *in_pSrc, size_t in_uDestMaxNumChars)
Safe unicode string copy.
int64_t AkInt64
Signed 64-bit integer.
void AkWaitForSemaphore(AkSemaphore &in_semaphore)
Platform Independent Helper - Semaphore wait, aka Operation P. Decrements value of semaphore,...
size_t uStackSize
Thread stack size.
void PerformanceFrequency(AkInt64 *out_piFreq)
Platform Independent Helper.
#define AK_DEFAULT_STACK_SIZE
int uSchedPolicy
Thread scheduling policy.
AkForceInline AkInt32 AkCharToWideChar(const char *in_pszAnsiString, AkUInt32 in_uiOutBufferSize, void *io_pvUnicodeStringBuffer)
String conversion helper.
uint32_t AkUInt32
Unsigned 32-bit integer.
void AkReleaseSemaphore(AkSemaphore &in_semaphore, AkUInt32 in_count)
Platform Independent Helper - Semaphore signal, aka Operation V. Increments value of semaphore by an ...
AkForceInline void SafeStrCat(wchar_t *in_pDest, const wchar_t *in_pSrc, size_t in_uDestMaxNumChars)
Safe unicode string concatenation.
AkForceInline AKRESULT AkCreateNamedEvent(AkEvent &out_event, const char *in_szName)
AkForceInline AkInt32 AkWideCharToChar(const wchar_t *in_pszUnicodeString, AkUInt32 in_uiOutBufferSize, char *io_pszAnsiString)
String conversion helper.
AkForceInline void AkWaitForSingleThread(AkThread *in_pThread)
Platform Independent Helper.
void AkSignalEvent(const AkEvent &in_event)
Platform Independent Helper.
AkForceInline AkInt32 AkUtf8ToWideChar(const char *in_pszUtf8String, AkUInt32 in_uiOutBufferSize, void *io_pvUnicodeStringBuffer)
String conversion helper.
semaphore_t AkSemaphore
Definition: AkTypes.h:85
AkForceInline void AkCloseThread(AkThread *in_pThread)
Platform Independent Helper.
AkForceInline int OsStrCmp(const AkOSChar *in_pszString1, const AkOSChar *in_pszString2)
#define AkForceInline
Definition: AkTypes.h:63
__forceinline long AkAtomicLoad32(AkAtomic32 *pSrc)
Definition: AkAtomic.h:58
AkForceInline size_t OsStrLen(const AkOSChar *in_pszString)
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.

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