Wwise Version
Target Platform(s):
Wwise SDK 2021.1.2
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  Version: v2021.1.2 Build: 7629
25  Copyright (c) 2006-2021 Audiokinetic Inc.
26 *******************************************************************************/
27 
28 #ifndef _AK_PLATFORM_FUNCS_H_
29 #define _AK_PLATFORM_FUNCS_H_
30 
31 #include "malloc.h"
34 #include <windows.h>
35 #include <stdio.h>
36 
37 #if defined(_WIN64)
38 // on 64 bit, removes warning C4985: 'ceil': attributes not present on previous declaration.
39 // see http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=294649
40 #include <math.h>
41 #endif // _WIN64
42 #include <intrin.h>
43 
44 //-----------------------------------------------------------------------------
45 // Platform-specific thread properties definition.
46 //-----------------------------------------------------------------------------
47 struct AkThreadProperties
48 {
49  int nPriority; ///< Thread priority
50 #ifdef AK_WIN_UNIVERSAL_APP
51  PROCESSOR_NUMBER processorNumber;///< Ideal processor (passed to SetThreadIdealProcessorEx)
52 #else
53  AkUInt32 dwAffinityMask; ///< Affinity mask
54 #endif
55  AkUInt32 uStackSize; ///< Thread stack size.
56 };
57 
58 //-----------------------------------------------------------------------------
59 // External variables.
60 //-----------------------------------------------------------------------------
61 // g_fFreqRatio is used by time helpers to return time values in milliseconds.
62 // It is declared and updated by the sound engine.
63 namespace AK
64 {
65  extern AkReal32 g_fFreqRatio;
66 }
67 
68 //-----------------------------------------------------------------------------
69 // Defines for Win32.
70 //-----------------------------------------------------------------------------
71 #define AK_DECLARE_THREAD_ROUTINE( FuncName ) DWORD WINAPI FuncName(LPVOID lpParameter)
72 #define AK_THREAD_RETURN( _param_ ) return (_param_);
73 #define AK_THREAD_ROUTINE_PARAMETER lpParameter
74 #define AK_GET_THREAD_ROUTINE_PARAMETER_PTR(type) reinterpret_cast<type*>( AK_THREAD_ROUTINE_PARAMETER )
75 #define AK_RETURN_THREAD_OK 0x00000000
76 #define AK_RETURN_THREAD_ERROR 0x00000001
77 #define AK_DEFAULT_STACK_SIZE (128*1024)
78 #define AK_THREAD_PRIORITY_NORMAL THREAD_PRIORITY_NORMAL
79 #define AK_THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_ABOVE_NORMAL
80 #define AK_THREAD_PRIORITY_TIME_CRITICAL THREAD_PRIORITY_TIME_CRITICAL
81 #define AK_THREAD_MODE_BACKGROUND_BEGIN THREAD_MODE_BACKGROUND_BEGIN
82 
83 // NULL objects
84 #define AK_NULL_THREAD NULL
85 
86 #define AK_INFINITE INFINITE
87 
88 #define AkMax(x1, x2) (((x1) > (x2))? (x1): (x2))
89 #define AkMin(x1, x2) (((x1) < (x2))? (x1): (x2))
90 #define AkClamp(x, min, max) ((x) < (min)) ? (min) : (((x) > (max) ? (max) : (x)))
91 
92 namespace AKPLATFORM
93 {
94  // Simple automatic event API
95  // ------------------------------------------------------------------
96 
97  /// Platform Independent Helper
98  inline void AkClearEvent( AkEvent & out_event )
99  {
100  out_event = NULL;
101  }
102 
103  /// Platform Independent Helper
104  inline AKRESULT AkCreateEvent( AkEvent & out_event )
105  {
106 #ifdef AK_USE_UWP_API
107  out_event = CreateEventEx(nullptr, nullptr, 0, STANDARD_RIGHTS_ALL|EVENT_MODIFY_STATE);
108 #else
109  out_event = ::CreateEvent( NULL, // No security attributes
110  false, // Reset type: automatic
111  false, // Initial signaled state: not signaled
112  NULL // No name
113  );
114 #endif
115  return ( out_event ) ? AK_Success : AK_Fail;
116  }
117 
118  /// Platform Independent Helper
119  inline void AkDestroyEvent( AkEvent & io_event )
120  {
121  if ( io_event )
122  ::CloseHandle( io_event );
123  io_event = NULL;
124  }
125 
126  /// Platform Independent Helper
127  inline void AkWaitForEvent( AkEvent & in_event )
128  {
129 #ifdef AK_USE_UWP_API
130  DWORD dwWaitResult = ::WaitForSingleObjectEx( in_event, INFINITE, FALSE );
131  AKASSERT( dwWaitResult == WAIT_OBJECT_0 );
132 #else
133  AKVERIFY( ::WaitForSingleObject( in_event, INFINITE ) == WAIT_OBJECT_0 );
134 #endif
135  }
136 
137  /// Platform Independent Helper
138  inline void AkSignalEvent( const AkEvent & in_event )
139  {
140  AKVERIFY( ::SetEvent( in_event ) );
141  }
142 
143  /// Platform Independent Helper
144  inline AKRESULT AkCreateSemaphore(AkSemaphore * out_semaphore, AkUInt32 in_initialCount)
145  {
146 #ifdef AK_USE_UWP_API
147  (*out_semaphore) = ::CreateSemaphoreEx(
148  NULL, // no security attributes
149  in_initialCount, // initial count
150  INT_MAX, // no maximum -- matches posix semaphore behaviour
151  NULL, // no name
152  0, // reserved
153  STANDARD_RIGHTS_ALL | SEMAPHORE_MODIFY_STATE);
154 #else
155  (*out_semaphore) = ::CreateSemaphore(
156  NULL, // no security attributes
157  in_initialCount, // initial count
158  INT_MAX, // no maximum -- matches posix semaphore behaviour
159  NULL); // no name
160 #endif
161  return (out_semaphore) ? AK_Success : AK_Fail;
162  }
163 
164  /// Platform Independent Helper
165  inline void AkDestroySemaphore(AkSemaphore * io_semaphore)
166  {
167  if (io_semaphore)
168  {
169  ::CloseHandle(*io_semaphore);
170  }
171  io_semaphore = NULL;
172  }
173 
174  /// 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.
175  inline void AkWaitForSemaphore(AkSemaphore * in_semaphore)
176  {
177  AKVERIFY( ::WaitForSingleObject(*in_semaphore, INFINITE) == WAIT_OBJECT_0 );
178  }
179 
180  /// Platform Independent Helper - Semaphore signal, aka Operation V. Increments value of semaphore.
181  inline void AkReleaseSemaphore(AkSemaphore * in_semaphore)
182  {
183  AKVERIFY( ReleaseSemaphore(*in_semaphore, 1, NULL) >= 0 );
184  }
185 
186  // Virtual Memory
187  // ------------------------------------------------------------------
188 
189 #ifdef AK_WIN_UNIVERSAL_APP
190  AkForceInline void* AllocVM(size_t size, size_t* /*extra*/)
191  {
192  return VirtualAllocFromApp(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
193  }
194 #else
195  AkForceInline void* AllocVM(size_t size, size_t* /*extra*/)
196  {
197  return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
198  }
199 
200 #endif
201  AkForceInline void FreeVM(void* address, size_t size, size_t /*extra*/, size_t release)
202  {
203  VirtualFree(address, release ? 0 : size, release ? MEM_RELEASE : MEM_DECOMMIT);
204  }
205 
206  // Threads
207  // ------------------------------------------------------------------
208 
209  /// Platform Independent Helper
210  inline bool AkIsValidThread( AkThread * in_pThread )
211  {
212  return (*in_pThread != AK_NULL_THREAD);
213  }
214 
215  /// Platform Independent Helper
216  inline void AkClearThread( AkThread * in_pThread )
217  {
218  *in_pThread = AK_NULL_THREAD;
219  }
220 
221  /// Platform Independent Helper
222  inline void AkCloseThread( AkThread * in_pThread )
223  {
224  AKASSERT( in_pThread );
225  AKASSERT( *in_pThread );
226  AKVERIFY( ::CloseHandle( *in_pThread ) );
227  AkClearThread( in_pThread );
228  }
229 
230 #define AkExitThread( _result ) return _result;
231 
232  /// Platform Independent Helper
233  inline void AkGetDefaultThreadProperties( AkThreadProperties & out_threadProperties )
234  {
235  out_threadProperties.nPriority = AK_THREAD_PRIORITY_NORMAL;
236  out_threadProperties.uStackSize= AK_DEFAULT_STACK_SIZE;
237 #ifdef AK_WIN_UNIVERSAL_APP
238  out_threadProperties.processorNumber.Group = 0;
239  out_threadProperties.processorNumber.Number = MAXIMUM_PROCESSORS;
240  out_threadProperties.processorNumber.Reserved = 0;
241 #else
242  out_threadProperties.dwAffinityMask = 0;
243 #endif
244  }
245 
246  /// Set the name of a thread: see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
247  inline void AkSetThreadName( DWORD in_dwThreadID, LPCSTR in_szThreadName )
248  {
249  const DWORD MS_VC_EXCEPTION=0x406D1388;
250 
251 #pragma pack(push,8)
252  typedef struct tagTHREADNAME_INFO
253  {
254  DWORD dwType;
255  LPCSTR szName;
256  DWORD dwThreadID;
257  DWORD dwFlags;
258  } THREADNAME_INFO;
259 #pragma pack(pop)
260 
261  THREADNAME_INFO info;
262  info.dwType = 0x1000;
263  info.szName = in_szThreadName;
264  info.dwThreadID = in_dwThreadID;
265  info.dwFlags = 0;
266 
267  __try
268  {
269  RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
270  }
271 #pragma warning(suppress: 6312 6322)
272  __except(EXCEPTION_CONTINUE_EXECUTION)
273  {
274  }
275  }
276 
277  /// Platform Independent Helper
278  inline void AkCreateThread(
279  AkThreadRoutine pStartRoutine, // Thread routine.
280  void * pParams, // Routine params.
281  const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
282  AkThread * out_pThread, // Returned thread handle.
283  const char * in_szThreadName ) // Opt thread name.
284  {
285  AKASSERT( out_pThread != NULL );
286  AKASSERT( (in_threadProperties.nPriority >= THREAD_PRIORITY_LOWEST && in_threadProperties.nPriority <= THREAD_PRIORITY_HIGHEST)
287  || ( in_threadProperties.nPriority == THREAD_PRIORITY_TIME_CRITICAL )
288  || ( in_threadProperties.nPriority == THREAD_MODE_BACKGROUND_BEGIN ) );
289 
290  DWORD dwThreadID;
291  *out_pThread = ::CreateThread( NULL, // No security attributes
292  in_threadProperties.uStackSize, // StackSize (0 uses system default)
293  pStartRoutine, // Thread start routine
294  pParams, // Thread function parameter
295  0, // Creation flags: create running
296  &dwThreadID );
297 
298  // ::CreateThread() return NULL if it fails.
299  if ( !*out_pThread )
300  {
301  AkClearThread( out_pThread );
302  return;
303  }
304 
305  // Set thread name.
306  AkSetThreadName( dwThreadID, in_szThreadName );
307 
308  // Set properties.
309  if ( !::SetThreadPriority( *out_pThread, in_threadProperties.nPriority ) &&
310  in_threadProperties.nPriority != THREAD_MODE_BACKGROUND_BEGIN )
311  {
312  AKASSERT( !"Failed setting thread priority" );
313  AkCloseThread( out_pThread );
314  return;
315  }
316 #ifdef AK_WIN_UNIVERSAL_APP
317  if ( in_threadProperties.processorNumber.Number != MAXIMUM_PROCESSORS)
318  {
319  if ( !SetThreadIdealProcessorEx( *out_pThread, const_cast<PPROCESSOR_NUMBER>(&in_threadProperties.processorNumber), NULL) )
320  {
321  AKASSERT( !"Failed setting thread ideal processor" );
322  AkCloseThread( out_pThread );
323  }
324  }
325 #else
326  if (in_threadProperties.dwAffinityMask)
327  {
328  if (!::SetThreadAffinityMask(*out_pThread, in_threadProperties.dwAffinityMask))
329  {
330  AKASSERT(!"Failed setting thread affinity mask");
331  AkCloseThread(out_pThread);
332  }
333  }
334 #endif
335  }
336 
337  /// Platform Independent Helper
338  inline void AkWaitForSingleThread( AkThread * in_pThread )
339  {
340  AKASSERT( in_pThread );
341  AKASSERT( *in_pThread );
342 #ifdef AK_USE_UWP_API
343  ::WaitForSingleObjectEx( *in_pThread, INFINITE, FALSE );
344 #else
345  ::WaitForSingleObject( *in_pThread, INFINITE );
346 #endif
347  }
348 
349  /// Returns the calling thread's ID.
350  inline AkThreadID CurrentThread()
351  {
352  return ::GetCurrentThreadId();
353  }
354 
355  /// Platform Independent Helper
356  inline void AkSleep( AkUInt32 in_ulMilliseconds )
357  {
358  ::Sleep( in_ulMilliseconds );
359  }
360 
361  // Optimized memory functions
362  // --------------------------------------------------------------------
363 
364  /// Platform Independent Helper
365  inline void AkMemCpy( void * pDest, const void * pSrc, AkUInt32 uSize )
366  {
367  memcpy( pDest, pSrc, uSize );
368  }
369 
370  /// Platform Independent Helper
371  inline void AkMemSet( void * pDest, AkInt32 iVal, AkUInt32 uSize )
372  {
373  memset( pDest, iVal, uSize );
374  }
375 
376  // Time functions
377  // ------------------------------------------------------------------
378 
379  /// Platform Independent Helper
380  inline void PerformanceCounter( AkInt64 * out_piLastTime )
381  {
382  ::QueryPerformanceCounter( (LARGE_INTEGER*)out_piLastTime );
383  }
384 
385  /// Platform Independent Helper
386  inline void PerformanceFrequency( AkInt64 * out_piFreq )
387  {
388  ::QueryPerformanceFrequency( (LARGE_INTEGER*)out_piFreq );
389  }
390 
391  /// Platform Independent Helper
392  inline void UpdatePerformanceFrequency()
393  {
394  AkInt64 iFreq;
395  PerformanceFrequency( &iFreq );
396  AK::g_fFreqRatio = (AkReal32)((AkReal64)iFreq / 1000);
397  }
398 
399  /// Returns a time range in milliseconds, using the sound engine's updated count->milliseconds ratio.
400  inline AkReal32 Elapsed( const AkInt64 & in_iNow, const AkInt64 & in_iStart )
401  {
402  return ( in_iNow - in_iStart ) / AK::g_fFreqRatio;
403  }
404 
405  /// String conversion helper. If io_pszAnsiString is null, the function returns the required size.
406  inline AkInt32 AkWideCharToChar( const wchar_t* in_pszUnicodeString,
407  AkUInt32 in_uiOutBufferSize,
408  char* io_pszAnsiString )
409  {
410  if(!io_pszAnsiString)
411  return WideCharToMultiByte(CP_UTF8, 0, in_pszUnicodeString, -1, NULL, 0, NULL, NULL);
412 
413  int iWritten = ::WideCharToMultiByte(CP_UTF8, // code page
414  0, // performance and mapping flags
415  in_pszUnicodeString, // wide-character string
416  (int)AkMin( ( (AkUInt32)wcslen( in_pszUnicodeString )), in_uiOutBufferSize-1 ), // number of chars in string : -1 = NULL terminated string.
417  io_pszAnsiString, // buffer for new string
418  in_uiOutBufferSize, // size of buffer
419  NULL, // default for unmappable chars
420  NULL); // set when default char used
421  io_pszAnsiString[iWritten] = 0;
422  return iWritten;
423  }
424 
425  /// String conversion helper
426  inline AkInt32 AkCharToWideChar( const char* in_pszAnsiString,
427  AkUInt32 in_uiOutBufferSize,
428  void* io_pvUnicodeStringBuffer )
429  {
430  return ::MultiByteToWideChar( CP_UTF8, // code page
431  0, // performance and mapping flags
432  in_pszAnsiString, // wide-character string
433  -1, // number of chars in string : -1 = NULL terminated string.
434  (wchar_t*)io_pvUnicodeStringBuffer, // buffer for new string
435  in_uiOutBufferSize); // size of buffer
436  }
437 
438  /// String conversion helper
439  inline AkInt32 AkUtf8ToWideChar( const char* in_pszUtf8String,
440  AkUInt32 in_uiOutBufferSize,
441  void* io_pvUnicodeStringBuffer )
442  {
443  return ::MultiByteToWideChar( CP_UTF8, // code page
444  0, // performance and mapping flags
445  in_pszUtf8String, // wide-character string
446  -1, // number of chars in string : -1 = NULL terminated string.
447  (wchar_t*)io_pvUnicodeStringBuffer, // buffer for new string
448  in_uiOutBufferSize); // size of buffer
449  }
450 
451  /// Safe unicode string copy.
452  inline void SafeStrCpy( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
453  {
454  size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, wcslen( in_pSrc ) + 1 );
455  wcsncpy_s( in_pDest, in_uDestMaxNumChars, in_pSrc, iSizeCopy );
456  in_pDest[iSizeCopy] = '\0';
457  }
458 
459  /// Safe string copy.
460  inline void SafeStrCpy( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
461  {
462  size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, strlen( in_pSrc ) + 1 );
463  strncpy_s( in_pDest, in_uDestMaxNumChars, in_pSrc, iSizeCopy );
464  in_pDest[iSizeCopy] = '\0';
465  }
466 
467  /// Safe unicode string concatenation.
468  inline void SafeStrCat( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
469  {
470  int iAvailableSize = (int)( in_uDestMaxNumChars - wcslen( in_pDest ) - 1 );
471  wcsncat_s( in_pDest, in_uDestMaxNumChars, in_pSrc, AkMin( iAvailableSize, (int)wcslen( in_pSrc ) ) );
472  }
473 
474  /// Safe string concatenation.
475  inline void SafeStrCat( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
476  {
477  int iAvailableSize = (int)( in_uDestMaxNumChars - strlen( in_pDest ) - 1 );
478  strncat_s( in_pDest, in_uDestMaxNumChars, in_pSrc, AkMin( iAvailableSize, (int)strlen( in_pSrc ) ) );
479  }
480 
481  /// Stack allocations.
482  #define AkAlloca( _size_ ) _alloca( _size_ )
483 
484  /// Output a debug message on the console
485 #if ! defined(AK_OPTIMIZED)
486  inline void OutputDebugMsg( const wchar_t* in_pszMsg )
487  {
488  OutputDebugStringW( in_pszMsg );
489  }
490 
491  /// Output a debug message on the console
492  inline void OutputDebugMsg( const char* in_pszMsg )
493  {
494  OutputDebugStringA( in_pszMsg );
495  }
496 
497  /// Output a debug message on the console (variadic function).
498  /// Use MaxSize to specify the size to reserve for the message.
499  /// Warning: On Win32, OutputDebugMsgV with wchar_t will truncate the string
500  /// to MaxSize.
501  template <int MaxSize = 256>
502  inline void OutputDebugMsgV(const wchar_t* in_pszFmt, ...)
503  {
504  // No equivalent of snprintf for wide string so truncate if necessary
505  // vswprintf returns the number of characters written and not the numbers
506  // that would be written
507 
508  wchar_t* msg = (wchar_t*)AkAlloca(MaxSize * sizeof(wchar_t));
509  msg[MaxSize - 1] = '\0';
510 
511  va_list args;
512  va_start(args, in_pszFmt);
513  vswprintf(msg, MaxSize, in_pszFmt, args);
514  va_end(args);
515 
516  OutputDebugMsg(msg);
517  }
518 
519  /// Output a debug message on the console (variadic function).
520  /// Use MaxSize to specify the expected size of the message.
521  /// If the required size is superior to MaxSize, a new string
522  /// will be allocated on the stack with the required size.
523  template <int MaxSize = 256>
524  inline void OutputDebugMsgV(const char* in_pszFmt, ...)
525  {
526  int size = 0;
527  {
528  // Try with a reasonable guess first
529  char msg[MaxSize];
530  msg[MaxSize - 1] = '\0';
531 
532  va_list args;
533  va_start(args, in_pszFmt);
534  size = vsnprintf(msg, MaxSize, in_pszFmt, args);
535  va_end(args);
536 
537  // If it was enough, print to debug log
538  if (0 <= size && size <= MaxSize)
539  {
540  OutputDebugMsg(msg);
541  return;
542  }
543  }
544 
545  // Else, we need more memory to prevent truncation
546  {
547  // size + 1 more char for the last '\0'
548  size++;
549 
550  char* msg = (char*)AkAlloca((size) * sizeof(char));
551  msg[size - 1] = '\0';
552 
553  va_list args;
554  va_start(args, in_pszFmt);
555  vsnprintf(msg, size, in_pszFmt, args);
556  va_end(args);
557 
558  OutputDebugMsg(msg);
559  }
560  }
561 
562 #else
563  inline void OutputDebugMsg(const wchar_t*){}
564  inline void OutputDebugMsg(const char*){}
565 
566  template <int MaxSize = 0>
567  inline void OutputDebugMsgV(const wchar_t*, ...) {}
568 
569  template <int MaxSize = 0>
570  inline void OutputDebugMsgV(const char*, ...) {}
571 #endif
572 
573  /// Converts a wchar_t string to an AkOSChar string.
574  /// \remark On some platforms the AkOSChar string simply points to the same string,
575  /// on others a new buffer is allocated on the stack using AkAlloca. This means
576  /// you must make sure that:
577  /// - The source string stays valid and unmodified for as long as you need the
578  /// AkOSChar string (for cases where they point to the same string)
579  /// - The AkOSChar string is used within this scope only -- for example, do NOT
580  /// return that string from a function (for cases where it is allocated on the stack)
581  #define CONVERT_WIDE_TO_OSCHAR( _wstring_, _oscharstring_ ) ( _oscharstring_ ) = (AkOSChar*)( _wstring_ )
582 
583  /// Converts a char string to an AkOSChar string.
584  /// \remark On some platforms the AkOSChar string simply points to the same string,
585  /// on others a new buffer is allocated on the stack using AkAlloca. This means
586  /// you must make sure that:
587  /// - The source string stays valid and unmodified for as long as you need the
588  /// AkOSChar string (for cases where they point to the same string)
589  /// - The AkOSChar string is used within this scope only -- for example, do NOT
590  /// return that string from a function (for cases where it is allocated on the stack)
591  #define CONVERT_CHAR_TO_OSCHAR( _astring_, _oscharstring_ ) \
592  _oscharstring_ = (AkOSChar*)AkAlloca( (1 + strlen( _astring_ )) * sizeof(AkOSChar)); \
593  AKPLATFORM::AkCharToWideChar( _astring_, (AkUInt32)(1 + strlen(_astring_ )), (AkOSChar*)( _oscharstring_ ) )
594 
595  /// Converts a AkOSChar string into wide char string.
596  /// \remark On some platforms the AkOSChar string simply points to the same string,
597  /// on others a new buffer is allocated on the stack using AkAlloca. This means
598  /// you must make sure that:
599  /// - The source string stays valid and unmodified for as long as you need the
600  /// AkOSChar string (for cases where they point to the same string)
601  /// - The AkOSChar string is used within this scope only -- for example, do NOT
602  /// return that string from a function (for cases where it is allocated on the stack)
603  #define CONVERT_OSCHAR_TO_WIDE( _osstring_, _wstring_ ) _wstring_ = _osstring_
604 
605  /// Converts a AkOSChar string into char string.
606  /// \remark On some platforms the AkOSChar string simply points to the same string,
607  /// on others a new buffer is allocated on the stack using AkAlloca. This means
608  /// you must make sure that:
609  /// - The source string stays valid and unmodified for as long as you need the
610  /// AkOSChar string (for cases where they point to the same string)
611  /// - The AkOSChar string is used within this scope only -- for example, do NOT
612  /// return that string from a function (for cases where it is allocated on the stack)
613  #define CONVERT_OSCHAR_TO_CHAR( _osstring_, _astring_ ) \
614  _astring_ = (char*)AkAlloca( 1 + wcslen( _osstring_ )); \
615  AKPLATFORM::AkWideCharToChar( _osstring_, AkUInt32(1 + wcslen( _osstring_ )), _astring_ );
616 
617  /// Get the length, in characters, of a NULL-terminated AkUtf16 string
618  /// \return The length, in characters, of the specified string (excluding terminating NULL)
619  inline size_t AkUtf16StrLen( const AkUtf16* in_pStr )
620  {
621  return ( wcslen( in_pStr ) );
622  }
623 
624  /// Get the length, in characters, of a NULL-terminated AkOSChar string
625  /// \return The length, in characters, of the specified string (excluding terminating NULL)
626  inline size_t OsStrLen( const AkOSChar* in_pszString )
627  {
628  return ( wcslen( in_pszString ) );
629  }
630 
631  /// AkOSChar version of sprintf().
632  #define AK_OSPRINTF swprintf_s
633 
634  /// Compare two NULL-terminated AkOSChar strings
635  /// \return
636  /// - < 0 if in_pszString1 < in_pszString2
637  /// - 0 if the two strings are identical
638  /// - > 0 if in_pszString1 > in_pszString2
639  /// \remark The comparison is case-sensitive
640  inline int OsStrCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2 )
641  {
642  return ( wcscmp( in_pszString1, in_pszString2 ) );
643  }
644 
645  /// Compare two NULL-terminated AkOSChar strings up to the specified count of characters.
646  /// \return
647  /// - < 0 if in_pszString1 < in_pszString2
648  /// - 0 if the two strings are identical
649  /// - > 0 if in_pszString1 > in_pszString2
650  /// \remark The comparison is case-sensitive
651  inline int OsStrNCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2, size_t in_MaxCountSize)
652  {
653  return wcsncmp(in_pszString1, in_pszString2, in_MaxCountSize);
654  }
655 
656  #define AK_UTF16_TO_WCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
657  #define AK_WCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
658  #define AK_UTF8_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
659  #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
660  #define AK_UTF16_TO_CHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
661  #define AK_CHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
662  #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
663 
664  // Use with AkOSChar.
665  #define AK_PATH_SEPARATOR (L"\\")
666  #define AK_LIBRARY_PREFIX (L"")
667  #define AK_DYNAMIC_LIBRARY_EXTENSION (L".dll")
668 
669  #if defined(AK_ENABLE_PERF_RECORDING)
670 
671  static AkUInt32 g_uAkPerfRecExecCount = 0;
672  static AkReal32 g_fAkPerfRecExecTime = 0.f;
673 
674  #define AK_PERF_RECORDING_RESET() \
675  AKPLATFORM::g_uAkPerfRecExecCount = 0;\
676  AKPLATFORM::g_fAkPerfRecExecTime = 0.f;
677 
678  #define AK_PERF_RECORDING_START( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ ) \
679  AkInt64 iAkPerfRecTimeBefore; \
680  if ( (AKPLATFORM::g_uAkPerfRecExecCount >= (__uExecutionCountStart__)) && (AKPLATFORM::g_uAkPerfRecExecCount <= (__uExecutionCountStop__)) ) \
681  AKPLATFORM::PerformanceCounter( &iAkPerfRecTimeBefore );
682 
683  #define AK_PERF_RECORDING_STOP( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ ) \
684  if ( (AKPLATFORM::g_uAkPerfRecExecCount >= (__uExecutionCountStart__)) && (AKPLATFORM::g_uAkPerfRecExecCount <= (__uExecutionCountStop__)) ) \
685  { \
686  AkInt64 iAkPerfRecTimeAfter; \
687  AKPLATFORM::PerformanceCounter( &iAkPerfRecTimeAfter ); \
688  AKPLATFORM::g_fAkPerfRecExecTime += AKPLATFORM::Elapsed( iAkPerfRecTimeAfter, iAkPerfRecTimeBefore ); \
689  if ( AKPLATFORM::g_uAkPerfRecExecCount == (__uExecutionCountStop__) ) \
690  { \
691  AkReal32 fAverageExecutionTime = AKPLATFORM::g_fAkPerfRecExecTime/((__uExecutionCountStop__)-(__uExecutionCountStart__)); \
692  AkOSChar str[256]; \
693  swprintf_s(str, 256, AKTEXT("%s average execution time: %f\n"), AKTEXT(__StorageName__), fAverageExecutionTime);\
694  AKPLATFORM::OutputDebugMsg( str ); \
695  } \
696  } \
697  AKPLATFORM::g_uAkPerfRecExecCount++;
698  #endif // AK_ENABLE_PERF_RECORDING
699 
700 #if (defined(AK_CPU_X86_64) || defined(AK_CPU_X86))
701  /// Support to fetch the CPUID for the platform. Only valid for X86 targets
702  /// \remark Note that IAkProcessorFeatures should be preferred to fetch this data
703  /// as it will have already translated the feature bits into AK-relevant enums
704  inline void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
705  {
706  __cpuidex((int*)out_uCPUFeatures, in_uLeafOpcode, in_uSubLeafOpcode);
707  }
708 #endif
709 }
710 
711 #endif // _AK_PLATFORM_FUNCS_H_
size_t AkUtf16StrLen(const AkUtf16 *in_pStr)
Definition: AkPlatformFuncs.h:558
#define AkForceInline
Force inlining.
Definition: AkTypes.h:61
Audiokinetic namespace.
@ AK_Fail
The operation failed.
Definition: AkTypes.h:130
#define AK_THREAD_PRIORITY_NORMAL
Definition: AkPlatformFuncs.h:78
semaphore_t AkEvent
Definition: AkTypes.h:73
#define AK_DEFAULT_STACK_SIZE
Definition: AkPlatformFuncs.h:77
AkForceInline void FreeVM(void *address, size_t size, size_t extra, size_t release)
Definition: AkPlatformFuncs.h:262
int nPriority
Thread priority.
Definition: AkPlatformFuncs.h:49
void AkClearEvent(AkEvent &out_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:52
Platform-dependent helpers.
Definition: AkPlatformFuncs.h:157
ScePthread AkThreadID
Thread ID.
Definition: AkTypes.h:99
void AkWaitForEvent(AkEvent &in_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:80
AkForceInline void UpdatePerformanceFrequency()
Platform Independent Helper.
Definition: AkPlatformFuncs.h:423
wchar_t AkUtf16
Definition: AkTypes.h:109
AKRESULT
Standard function call result.
Definition: AkTypes.h:127
void OutputDebugMsg(const char *in_pszMsg)
Output a debug message on the console (Ansi string)
Definition: AkPlatformFuncs.h:121
AkForceInline void * AllocVM(size_t size, size_t *extra)
Definition: AkPlatformFuncs.h:243
void AkDestroySemaphore(AkSemaphore *io_semaphore)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:105
void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
Definition: AkPlatformFuncs.h:293
char AkOSChar
Generic character string.
Definition: AkTypes.h:93
#define NULL
Definition: AkTypes.h:47
AkThreadID CurrentThread()
Returns the calling thread's ID.
Definition: AkPlatformFuncs.h:380
@ AK_Success
The operation was successful.
Definition: AkTypes.h:129
void AkCreateThread(AkThreadRoutine pStartRoutine, void *pParams, const AkThreadProperties &in_threadProperties, AkThread *out_pThread, const char *)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:183
void OutputDebugMsgV(const char *in_pszFmt,...)
Output a debug message on the console (variadic function).
Definition: AkPlatformFuncs.h:130
void PerformanceCounter(AkInt64 *out_piLastTime)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:143
AkUInt32 uStackSize
Thread stack size.
Definition: AkPlatformFuncs.h:55
double AkReal64
64-bit floating point
Definition: AkTypes.h:96
void AkDestroyEvent(AkEvent &io_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:70
nn::os::ThreadFunction AkThreadRoutine
Thread routine.
Definition: AkTypes.h:99
AkForceInline bool AkIsValidThread(AkThread *in_pThread)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:277
int64_t AkInt64
Signed 64-bit integer.
Definition: AkTypes.h:91
AkForceInline void AkMemCpy(void *pDest, const void *pSrc, AkUInt32 uSize)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:395
#define AKASSERT(Condition)
Definition: AkAssert.h:76
#define AKVERIFY(x)
Definition: AkAssert.h:78
AkForceInline void AkSleep(AkUInt32 in_ulMilliseconds)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:386
int32_t AkInt32
Signed 32-bit integer.
Definition: AkTypes.h:90
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
#define AK_NULL_THREAD
Definition: AkPlatformFuncs.h:84
int OsStrNCmp(const AkOSChar *in_pszString1, const AkOSChar *in_pszString2, size_t in_MaxCountSize)
Definition: AkPlatformFuncs.h:590
AkForceInline void AkMemSet(void *pDest, AkInt32 iVal, AkUInt32 uSize)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:401
SceKernelCpumask dwAffinityMask
Affinity mask.
Definition: AkPlatformFuncs.h:50
AkReal32 g_fFreqRatio
Definition: AkPlatformFuncs.h:63
#define AkMin(x1, x2)
Definition: AkPlatformFuncs.h:89
AKRESULT AkCreateEvent(AkEvent &out_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:58
AkForceInline void SafeStrCpy(wchar_t *in_pDest, const wchar_t *in_pSrc, size_t in_uDestMaxNumChars)
Safe unicode string copy.
Definition: AkPlatformFuncs.h:477
AkUInt32 dwAffinityMask
Affinity mask.
Definition: AkPlatformFuncs.h:53
size_t uStackSize
Thread stack size.
Definition: AkPlatformFuncs.h:51
void PerformanceFrequency(AkInt64 *out_piFreq)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:46
float AkReal32
32-bit floating point
Definition: AkTypes.h:95
AkForceInline AkInt32 AkCharToWideChar(const char *in_pszAnsiString, AkUInt32 in_uiOutBufferSize, void *io_pvUnicodeStringBuffer)
String conversion helper.
Definition: AkPlatformFuncs.h:454
AKRESULT AkCreateSemaphore(AkSemaphore *out_semaphore, AkUInt32 in_initialCount)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:93
AkForceInline void SafeStrCat(wchar_t *in_pDest, const wchar_t *in_pSrc, size_t in_uDestMaxNumChars)
Safe unicode string concatenation.
Definition: AkPlatformFuncs.h:493
void AkWaitForSemaphore(AkSemaphore *in_semaphore)
Platform Independent Helper - Semaphore wait, aka Operation P. Decrements value of semaphore,...
Definition: AkPlatformFuncs.h:115
AkForceInline AkInt32 AkWideCharToChar(const wchar_t *in_pszUnicodeString, AkUInt32 in_uiOutBufferSize, char *io_pszAnsiString)
String conversion helper.
Definition: AkPlatformFuncs.h:437
AkForceInline void AkWaitForSingleThread(AkThread *in_pThread)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:373
#define AkAlloca(_size_)
Stack allocations.
Definition: AkPlatformFuncs.h:482
void AkSignalEvent(const AkEvent &in_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:87
Definition: AkTypes.h:104
AkForceInline AkInt32 AkUtf8ToWideChar(const char *in_pszUtf8String, AkUInt32 in_uiOutBufferSize, void *io_pvUnicodeStringBuffer)
String conversion helper.
Definition: AkPlatformFuncs.h:469
uint32_t AkUInt32
Unsigned 32-bit integer.
Definition: AkTypes.h:77
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:579
void AkReleaseSemaphore(AkSemaphore *in_semaphore)
Platform Independent Helper - Semaphore signal, aka Operation V. Increments value of semaphore.
Definition: AkPlatformFuncs.h:121
void AkSetThreadName(DWORD in_dwThreadID, LPCSTR in_szThreadName)
Set the name of a thread: see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx.
Definition: AkPlatformFuncs.h:247
AkForceInline size_t OsStrLen(const AkOSChar *in_pszString)
Definition: AkPlatformFuncs.h:565
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:431