Version
menu_open
Wwise SDK 2023.1.5
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  // Time functions
354  // ------------------------------------------------------------------
355 
356  /// Platform Independent Helper
357  AkForceInline void PerformanceCounter( AkInt64 * out_piLastTime )
358  {
359  uint64_t uTime = sceKernelGetProcessTimeCounter();
360  *out_piLastTime = (AkInt64)uTime;
361  }
362 
363  /// Frequency of the PerformanceCounter() (ticks per second)
364  AkForceInline void PerformanceFrequency( AkInt64 * out_piFreq )
365  {
366  *out_piFreq = (AkInt64)sceKernelGetProcessTimeCounterFrequency();
367  }
368 
369  /// Platform Independent Helper
371  {
372  AkInt64 iFreq;
373  PerformanceFrequency( &iFreq );
374  AK::g_fFreqRatio = (AkReal32)((AkReal64)iFreq / 1000);
375  }
376 
377  // Waits for a limited amount of time for in_pVal to hit zero (without yielding the thread)
378  inline void AkLimitedSpinForZero(AkAtomic32* in_pVal)
379  {
380  // monitorx and waitx are available on certain AMD CPUs, so we can have a custom impl of AkLimitedSpinForZero
381  AkInt64 endSpinTime = 0;
382  AkInt64 currentTime = 0;
383  PerformanceCounter(&endSpinTime);
384  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
385  while (true)
386  {
387  // set up monitorx on pVal
388  _mm_monitorx((void*)in_pVal, 0U, 0U);
389  // if pval is zero, skip out
390  if (AkAtomicLoad32(in_pVal) == 0)
391  {
392  break;
393  }
394  // wait until a store to pVal occurs (or ~1us passes)
395  _mm_mwaitx(2U, 0U, 1000U);
396 
397  // Check if we've hit the deadline for the timeout
398  PerformanceCounter(&currentTime);
399  if (currentTime > endSpinTime)
400  {
401  break;
402  }
403  }
404  }
405 
406  // Waits for a limited amount of time for in_pVal to get atomically shift from the expected value to the proposed one
407  // returns true if acquisition succeeded
408  inline bool AkLimitedSpinToAcquire(AkAtomic32* in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
409  {
410  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
411  {
412  return true;
413  }
414 
415  // Cas failed, start the slower evaluation
416 
417  // monitorx and waitx are available on certain AMD CPUs, so we can use monitorx/waitx
418  AkInt64 endSpinTime = 0;
419  AkInt64 currentTime = 0;
420  PerformanceCounter(&endSpinTime);
421  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
422  while (true)
423  {
424  // set up monitorx on pVal
425  _mm_monitorx((void*)in_pVal, 0U, 0U);
426  // attempt cas to acquire and if successful, skip out
427  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
428  {
429  return true;
430  }
431  // wait until a store to pVal occurs (or ~1us passes)
432  _mm_mwaitx(2U, 0U, 1000U);
433 
434  // Check if we've hit the deadline for the timeout
435  PerformanceCounter(&currentTime);
436  if (currentTime > endSpinTime)
437  {
438  return false;
439  }
440  }
441  }
442 
443 #define AK_LIMITEDSPINFORZERO // mark AkLimitedSpinForZero as defined to avoid duplicate definitions
444 
445  /// Returns a time range in milliseconds, using the sound engine's updated count->milliseconds ratio.
446  AkForceInline AkReal32 Elapsed( const AkInt64 & in_iNow, const AkInt64 & in_iStart )
447  {
448  return ( in_iNow - in_iStart ) / AK::g_fFreqRatio;
449  }
450 
451  /// String conversion helper
452  AkForceInline AkInt32 AkWideCharToChar( const wchar_t* in_pszUnicodeString,
453  AkUInt32 in_uiOutBufferSize,
454  char* io_pszAnsiString )
455  {
456  AKASSERT( io_pszAnsiString != NULL );
457 
458  mbstate_t state;
459  memset (&state, '\0', sizeof (state));
460 
461  return (AkInt32)wcsrtombs(io_pszAnsiString, // destination
462  &in_pszUnicodeString, // source
463  in_uiOutBufferSize, // destination length
464  &state); //
465 
466  }
467 
468  /// String conversion helper
469  AkForceInline AkInt32 AkCharToWideChar( const char* in_pszAnsiString,
470  AkUInt32 in_uiOutBufferSize,
471  void* io_pvUnicodeStringBuffer )
472  {
473  AKASSERT( io_pvUnicodeStringBuffer != NULL );
474 
475  mbstate_t state;
476  memset (&state, '\0', sizeof (state));
477 
478  return (AkInt32)mbsrtowcs((wchar_t*)io_pvUnicodeStringBuffer, // destination
479  &in_pszAnsiString, // source
480  in_uiOutBufferSize, // destination length
481  &state); //
482  }
483 
484  AkForceInline AkInt32 AkUtf8ToWideChar( const char* in_pszUtf8String,
485  AkUInt32 in_uiOutBufferSize,
486  void* io_pvUnicodeStringBuffer )
487  {
488  return AkCharToWideChar( in_pszUtf8String, in_uiOutBufferSize, (wchar_t*)io_pvUnicodeStringBuffer );
489  }
490 
491  /// Safe unicode string copy.
492  AkForceInline void SafeStrCpy( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
493  {
494  size_t uSizeCopy = AkMin( in_uDestMaxNumChars - 1, wcslen( in_pSrc ) + 1 );
495  wcsncpy( in_pDest, in_pSrc, uSizeCopy );
496  in_pDest[uSizeCopy] = '\0';
497  }
498 
499  /// Safe ansi string copy.
500  AkForceInline void SafeStrCpy( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
501  {
502  size_t uSizeCopy = AkMin( in_uDestMaxNumChars - 1, strlen( in_pSrc ) + 1 );
503  strncpy( in_pDest, in_pSrc, uSizeCopy );
504  in_pDest[uSizeCopy] = '\0';
505  }
506 
507  /// Safe unicode string concatenation.
508  AkForceInline void SafeStrCat( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
509  {
510  size_t uAvailableSize = ( in_uDestMaxNumChars - wcslen( in_pDest ) - 1 );
511  wcsncat( in_pDest, in_pSrc, AkMin( uAvailableSize, wcslen( in_pSrc ) ) );
512  }
513 
514  /// Safe ansi string concatenation.
515  AkForceInline void SafeStrCat( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
516  {
517  size_t uAvailableSize = ( in_uDestMaxNumChars - strlen( in_pDest ) - 1 );
518  strncat( in_pDest, in_pSrc, AkMin( uAvailableSize, strlen( in_pSrc ) ) );
519  }
520 
521  inline int SafeStrFormat(wchar_t * in_pDest, size_t in_uDestMaxNumChars, const wchar_t* in_pszFmt, ...)
522  {
523  va_list args;
524  va_start(args, in_pszFmt);
525  int r = vswprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
526  va_end(args);
527  return r;
528  }
529 
530  inline int SafeStrFormat(char * in_pDest, size_t in_uDestMaxNumChars, const char* in_pszFmt, ...)
531  {
532  va_list args;
533  va_start(args, in_pszFmt);
534  int r = vsnprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
535  va_end(args);
536  return r;
537  }
538 
539  /// Stack allocations.
540  #define AkAlloca( _size_ ) alloca( _size_ )
541 
542 
543 
544  /// Converts a wchar_t string to an AkOSChar string.
545  /// \remark On some platforms the AkOSChar string simply points to the same string,
546  /// on others a new buffer is allocated on the stack using AkAlloca. This means
547  /// you must make sure that:
548  /// - The source string stays valid and unmodified for as long as you need the
549  /// AkOSChar string (for cases where they point to the same string)
550  /// - The AkOSChar string is used within this scope only -- for example, do NOT
551  /// return that string from a function (for cases where it is allocated on the stack)
552  #define CONVERT_WIDE_TO_OSCHAR( _wstring_, _oscharstring_ ) \
553  _oscharstring_ = (AkOSChar*)AkAlloca( (1 + wcslen( _wstring_ )) * sizeof(AkOSChar) ); \
554  AKPLATFORM::AkWideCharToChar( _wstring_ , (AkUInt32)(1 + wcslen( _wstring_ )), (AkOSChar*)( _oscharstring_ ) )
555 
556 
557  /// Converts a char string to an AkOSChar string.
558  /// \remark On some platforms the AkOSChar string simply points to the same string,
559  /// on others a new buffer is allocated on the stack using AkAlloca. This means
560  /// you must make sure that:
561  /// - The source string stays valid and unmodified for as long as you need the
562  /// AkOSChar string (for cases where they point to the same string)
563  /// - The AkOSChar string is used within this scope only -- for example, do NOT
564  /// return that string from a function (for cases where it is allocated on the stack)
565  #define CONVERT_CHAR_TO_OSCHAR( _astring_, _oscharstring_ ) ( _oscharstring_ ) = (AkOSChar*)( _astring_ )
566 
567  /// Converts a AkOSChar string into wide char string.
568  /// \remark On some platforms the AkOSChar string simply points to the same string,
569  /// on others a new buffer is allocated on the stack using AkAlloca. This means
570  /// you must make sure that:
571  /// - The source string stays valid and unmodified for as long as you need the
572  /// AkOSChar string (for cases where they point to the same string)
573  /// - The AkOSChar string is used within this scope only -- for example, do NOT
574  /// return that string from a function (for cases where it is allocated on the stack)
575  #define CONVERT_OSCHAR_TO_WIDE( _osstring_, _wstring_ ) \
576  _wstring_ = (wchar_t*)AkAlloca((1+strlen(_osstring_)) * sizeof(wchar_t)); \
577  AKPLATFORM::AkCharToWideChar( _osstring_, (AkUInt32)(1 + strlen(_osstring_ )), _wstring_ )
578 
579  /// Converts a AkOSChar string into char string.
580  /// \remark On some platforms the AkOSChar string simply points to the same string,
581  /// on others a new buffer is allocated on the stack using AkAlloca. This means
582  /// you must make sure that:
583  /// - The source string stays valid and unmodified for as long as you need the
584  /// AkOSChar string (for cases where they point to the same string)
585  /// - The AkOSChar string is used within this scope only -- for example, do NOT
586  /// return that string from a function (for cases where it is allocated on the stack)
587  #define CONVERT_OSCHAR_TO_CHAR( _osstring_, _astring_ ) _astring_ = (char*)_osstring_
588 
589  /// Get the length, in characters, of a NULL-terminated AkUtf16 string
590  /// \return The length, in characters, of the specified string (excluding terminating NULL)
591  AkForceInline size_t AkUtf16StrLen( const AkUtf16* in_pStr )
592  {
593  return ( wcslen( in_pStr ) );
594  }
595 
596  /// Get the length, in characters, of a NULL-terminated AkOSChar string
597  /// \return The length, in characters, of the specified string (excluding terminating NULL)
598  AkForceInline size_t OsStrLen( const AkOSChar* in_pszString )
599  {
600  return ( strlen( in_pszString ) );
601  }
602 
603  /// AkOSChar version of sprintf().
604  #define AK_OSPRINTF snprintf
605 
606  /// Compare two NULL-terminated AkOSChar strings
607  /// \return
608  /// - < 0 if in_pszString1 < in_pszString2
609  /// - 0 if the two strings are identical
610  /// - > 0 if in_pszString1 > in_pszString2
611  /// \remark The comparison is case-sensitive
612  AkForceInline int OsStrCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2 )
613  {
614  return ( strcmp( in_pszString1, in_pszString2 ) );
615  }
616 
617  /// Compare two NULL-terminated AkOSChar strings up to the specified count of characters.
618  /// \return
619  /// - < 0 if in_pszString1 < in_pszString2
620  /// - 0 if the two strings are identical
621  /// - > 0 if in_pszString1 > in_pszString2
622  /// \remark The comparison is case-sensitive
623  inline int OsStrNCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2, size_t in_MaxCountSize )
624  {
625  return ( strncmp(in_pszString1, in_pszString2, in_MaxCountSize) );
626  }
627 
628  /// Detects whether the string represents an absolute path to a file
629  inline bool IsAbsolutePath(const AkOSChar* in_pszPath, size_t in_pathLen)
630  {
631  return in_pathLen >= 1 && in_pszPath[0] == '/';
632  }
633 
634  #define AK_UTF16_TO_WCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
635  #define AK_WCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
636  #define AK_UTF8_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
637  #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
638  #define AK_UTF16_TO_CHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
639  #define AK_CHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
640  #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
641 
642  // Use with AkOSChar.
643  #define AK_PATH_SEPARATOR "/"
644  #define AK_LIBRARY_PREFIX ""
645  #define AK_DYNAMIC_LIBRARY_EXTENSION ".prx"
646 
647  #define AK_FILEHANDLE_TO_UINTPTR(_h) ((AkUIntPtr)_h)
648  #define AK_SET_FILEHANDLE_TO_UINTPTR(_h,_u) _h = (AkFileHandle)_u
649 
650  /// Support to fetch the CPUID for the platform. Only valid for X86 targets
651  /// \remark Note that IAkProcessorFeatures should be preferred to fetch this data
652  /// as it will have already translated the feature bits into AK-relevant enums
653  inline void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
654  {
655  __get_cpuid_count( in_uLeafOpcode, in_uSubLeafOpcode,
656  &out_uCPUFeatures[0],
657  &out_uCPUFeatures[1],
658  &out_uCPUFeatures[2],
659  &out_uCPUFeatures[3]);
660  }
661 }
662 
663 #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:134
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:131
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:133
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:90
AkForceInline bool AkIsValidThread(AkThread *in_pThread)
Platform Independent Helper.
#define AkMin(x1, x2)
#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)
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