Version
menu_open
link
Target Platform(s):
Wwise SDK 2021.1.14
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.14 Build: 6590
25  Copyright (c) 2006-2023 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 #if defined(AK_WIN)
190 #ifdef AK_WIN_UNIVERSAL_APP
191  AkForceInline void* AllocVM(size_t size, size_t* /*extra*/)
192  {
193  return VirtualAllocFromApp(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
194  }
195 #else
196  AkForceInline void* AllocVM(size_t size, size_t* /*extra*/)
197  {
198  return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
199  }
200 
201 #endif
202  AkForceInline void FreeVM(void* address, size_t size, size_t /*extra*/, size_t release)
203  {
204  VirtualFree(address, release ? 0 : size, release ? MEM_RELEASE : MEM_DECOMMIT);
205  }
206 #endif
207 
208  // Threads
209  // ------------------------------------------------------------------
210 
211  /// Platform Independent Helper
212  inline bool AkIsValidThread( AkThread * in_pThread )
213  {
214  return (*in_pThread != AK_NULL_THREAD);
215  }
216 
217  /// Platform Independent Helper
218  inline void AkClearThread( AkThread * in_pThread )
219  {
220  *in_pThread = AK_NULL_THREAD;
221  }
222 
223  /// Platform Independent Helper
224  inline void AkCloseThread( AkThread * in_pThread )
225  {
226  AKASSERT( in_pThread );
227  AKASSERT( *in_pThread );
228  AKVERIFY( ::CloseHandle( *in_pThread ) );
229  AkClearThread( in_pThread );
230  }
231 
232 #define AkExitThread( _result ) return _result;
233 
234  /// Platform Independent Helper
235  inline void AkGetDefaultThreadProperties( AkThreadProperties & out_threadProperties )
236  {
237  out_threadProperties.nPriority = AK_THREAD_PRIORITY_NORMAL;
238  out_threadProperties.uStackSize= AK_DEFAULT_STACK_SIZE;
239 #ifdef AK_WIN_UNIVERSAL_APP
240  out_threadProperties.processorNumber.Group = 0;
241  out_threadProperties.processorNumber.Number = MAXIMUM_PROCESSORS;
242  out_threadProperties.processorNumber.Reserved = 0;
243 #else
244  out_threadProperties.dwAffinityMask = 0;
245 #endif
246  }
247 
248  /// Set the name of a thread: see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
249  inline void AkSetThreadName( AkThread in_threadHnd, DWORD in_dwThreadID, LPCSTR in_szThreadName )
250  {
251  const DWORD MS_VC_EXCEPTION=0x406D1388;
252 
253 #pragma pack(push,8)
254  typedef struct tagTHREADNAME_INFO
255  {
256  DWORD dwType;
257  LPCSTR szName;
258  DWORD dwThreadID;
259  DWORD dwFlags;
260  } THREADNAME_INFO;
261 #pragma pack(pop)
262 
263  THREADNAME_INFO info;
264  info.dwType = 0x1000;
265  info.szName = in_szThreadName;
266  info.dwThreadID = in_dwThreadID;
267  info.dwFlags = 0;
268 
269  __try
270  {
271  RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
272  }
273 #pragma warning(suppress: 6312 6322)
274  __except(EXCEPTION_CONTINUE_EXECUTION)
275  {
276  }
277 
278 #if defined(AK_XBOX) || defined(_GAMING_DESKTOP) // also applicable on Windows when Win7 support is dropped. SetThreadDescription is a Win10 only API
279  wchar_t wszThreadName[32];
280  AkUInt32 maxStrLen = (sizeof(wszThreadName) / sizeof(wchar_t)) - 1;
281  AkUInt32 nameStrLen = AkMin((int)strlen(in_szThreadName), maxStrLen);
282  MultiByteToWideChar(CP_UTF8, 0, in_szThreadName, nameStrLen, wszThreadName, maxStrLen);
283  wszThreadName[nameStrLen] = '\0';
284  SetThreadDescription(in_threadHnd, wszThreadName);
285 #endif
286  }
287 
288  /// Platform Independent Helper
289  inline void AkCreateThread(
290  AkThreadRoutine pStartRoutine, // Thread routine.
291  void * pParams, // Routine params.
292  const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
293  AkThread * out_pThread, // Returned thread handle.
294  const char * in_szThreadName ) // Opt thread name.
295  {
296  AKASSERT( out_pThread != NULL );
297  AKASSERT( (in_threadProperties.nPriority >= THREAD_PRIORITY_LOWEST && in_threadProperties.nPriority <= THREAD_PRIORITY_HIGHEST)
298  || ( in_threadProperties.nPriority == THREAD_PRIORITY_TIME_CRITICAL )
299  || ( in_threadProperties.nPriority == THREAD_MODE_BACKGROUND_BEGIN ) );
300 
301  DWORD dwThreadID;
302  *out_pThread = ::CreateThread( NULL, // No security attributes
303  in_threadProperties.uStackSize, // StackSize (0 uses system default)
304  pStartRoutine, // Thread start routine
305  pParams, // Thread function parameter
306  CREATE_SUSPENDED, // Creation flags: create suspended so we can set priority/affinity before starting
307  &dwThreadID );
308 
309  // ::CreateThread() return NULL if it fails.
310  if ( !*out_pThread )
311  {
312  AkClearThread( out_pThread );
313  return;
314  }
315 
316  // Set thread name.
317  if (in_szThreadName)
318  {
319  AkSetThreadName(*out_pThread, dwThreadID, in_szThreadName);
320  }
321 
322  // Set properties.
323  if ( !::SetThreadPriority( *out_pThread, in_threadProperties.nPriority ) &&
324  in_threadProperties.nPriority != THREAD_MODE_BACKGROUND_BEGIN )
325  {
326  AKASSERT( !"Failed setting thread priority" );
327  AkCloseThread( out_pThread );
328  AkClearThread(out_pThread);
329  return;
330  }
331 #ifdef AK_WIN_UNIVERSAL_APP
332  if ( in_threadProperties.processorNumber.Number != MAXIMUM_PROCESSORS)
333  {
334  if ( !SetThreadIdealProcessorEx( *out_pThread, const_cast<PPROCESSOR_NUMBER>(&in_threadProperties.processorNumber), NULL) )
335  {
336  AKASSERT( !"Failed setting thread ideal processor" );
337  AkCloseThread( out_pThread );
338  AkClearThread(out_pThread);
339  return;
340  }
341  }
342 #else
343  if (in_threadProperties.dwAffinityMask)
344  {
345  AkUInt32 dwAffinityMask = in_threadProperties.dwAffinityMask;
346  DWORD_PTR procAffinity, sysAffinity;
347  if (::GetProcessAffinityMask(::GetCurrentProcess(), &procAffinity, &sysAffinity))
348  {
349  // To avoid errors in SetThreadAffinityMask, make sure the user-supplied mask is a subset of what is allowed by the process
350  dwAffinityMask &= procAffinity;
351  }
352  if (!::SetThreadAffinityMask(*out_pThread, dwAffinityMask))
353  {
354  AKASSERT(!"Failed setting thread affinity mask");
355  AkCloseThread(out_pThread);
356  AkClearThread(out_pThread);
357  return;
358  }
359  }
360 #endif
361  // Thread is ready, start it up.
362  if (!::ResumeThread(*out_pThread))
363  {
364  AKASSERT(!"Failed to start the thread");
365  AkCloseThread(out_pThread);
366  AkClearThread(out_pThread);
367  return;
368  }
369  }
370 
371  /// Platform Independent Helper
372  inline void AkWaitForSingleThread( AkThread * in_pThread )
373  {
374  AKASSERT( in_pThread );
375  AKASSERT( *in_pThread );
376 #ifdef AK_USE_UWP_API
377  ::WaitForSingleObjectEx( *in_pThread, INFINITE, FALSE );
378 #else
379  ::WaitForSingleObject( *in_pThread, INFINITE );
380 #endif
381  }
382 
383  /// Returns the calling thread's ID.
384  inline AkThreadID CurrentThread()
385  {
386  return ::GetCurrentThreadId();
387  }
388 
389  /// Platform Independent Helper
390  inline void AkSleep( AkUInt32 in_ulMilliseconds )
391  {
392  ::Sleep( in_ulMilliseconds );
393  }
394 
395  // Optimized memory functions
396  // --------------------------------------------------------------------
397 
398  /// Platform Independent Helper
399  inline void AkMemCpy( void * pDest, const void * pSrc, AkUInt32 uSize )
400  {
401  memcpy( pDest, pSrc, uSize );
402  }
403 
404  /// Platform Independent Helper
405  inline void AkMemSet( void * pDest, AkInt32 iVal, AkUInt32 uSize )
406  {
407  memset( pDest, iVal, uSize );
408  }
409 
410  // Time functions
411  // ------------------------------------------------------------------
412 
413  /// Platform Independent Helper
414  inline void PerformanceCounter( AkInt64 * out_piLastTime )
415  {
416  ::QueryPerformanceCounter( (LARGE_INTEGER*)out_piLastTime );
417  }
418 
419  /// Platform Independent Helper
420  inline void PerformanceFrequency( AkInt64 * out_piFreq )
421  {
422  ::QueryPerformanceFrequency( (LARGE_INTEGER*)out_piFreq );
423  }
424 
425  /// Platform Independent Helper
426  inline void UpdatePerformanceFrequency()
427  {
428  AkInt64 iFreq;
429  PerformanceFrequency( &iFreq );
430  AK::g_fFreqRatio = (AkReal32)((AkReal64)iFreq / 1000);
431  }
432 
433  /// Returns a time range in milliseconds, using the sound engine's updated count->milliseconds ratio.
434  inline AkReal32 Elapsed( const AkInt64 & in_iNow, const AkInt64 & in_iStart )
435  {
436  return ( in_iNow - in_iStart ) / AK::g_fFreqRatio;
437  }
438 
439  /// String conversion helper. If io_pszAnsiString is null, the function returns the required size.
440  inline AkInt32 AkWideCharToChar( const wchar_t* in_pszUnicodeString,
441  AkUInt32 in_uiOutBufferSize,
442  char* io_pszAnsiString )
443  {
444  if(!io_pszAnsiString)
445  return WideCharToMultiByte(CP_UTF8, 0, in_pszUnicodeString, -1, NULL, 0, NULL, NULL);
446 
447  int iWritten = ::WideCharToMultiByte(CP_UTF8, // code page
448  0, // performance and mapping flags
449  in_pszUnicodeString, // wide-character string
450  (int)AkMin( ( (AkUInt32)wcslen( in_pszUnicodeString )), in_uiOutBufferSize-1 ), // number of chars in string : -1 = NULL terminated string.
451  io_pszAnsiString, // buffer for new string
452  in_uiOutBufferSize, // size of buffer
453  NULL, // default for unmappable chars
454  NULL); // set when default char used
455  io_pszAnsiString[iWritten] = 0;
456  return iWritten;
457  }
458 
459  /// String conversion helper
460  inline AkInt32 AkCharToWideChar( const char* in_pszAnsiString,
461  AkUInt32 in_uiOutBufferSize,
462  void* io_pvUnicodeStringBuffer )
463  {
464  return ::MultiByteToWideChar( CP_UTF8, // code page
465  0, // performance and mapping flags
466  in_pszAnsiString, // wide-character string
467  -1, // number of chars in string : -1 = NULL terminated string.
468  (wchar_t*)io_pvUnicodeStringBuffer, // buffer for new string
469  in_uiOutBufferSize); // size of buffer
470  }
471 
472  /// String conversion helper
473  inline AkInt32 AkUtf8ToWideChar( const char* in_pszUtf8String,
474  AkUInt32 in_uiOutBufferSize,
475  void* io_pvUnicodeStringBuffer )
476  {
477  return ::MultiByteToWideChar( CP_UTF8, // code page
478  0, // performance and mapping flags
479  in_pszUtf8String, // wide-character string
480  -1, // number of chars in string : -1 = NULL terminated string.
481  (wchar_t*)io_pvUnicodeStringBuffer, // buffer for new string
482  in_uiOutBufferSize); // size of buffer
483  }
484 
485  /// Safe unicode string copy.
486  inline void SafeStrCpy( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
487  {
488  size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, wcslen( in_pSrc ) + 1 );
489  wcsncpy_s( in_pDest, in_uDestMaxNumChars, in_pSrc, iSizeCopy );
490  in_pDest[iSizeCopy] = '\0';
491  }
492 
493  /// Safe string copy.
494  inline void SafeStrCpy( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
495  {
496  size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, strlen( in_pSrc ) + 1 );
497  strncpy_s( in_pDest, in_uDestMaxNumChars, in_pSrc, iSizeCopy );
498  in_pDest[iSizeCopy] = '\0';
499  }
500 
501  /// Safe unicode string concatenation.
502  inline void SafeStrCat( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
503  {
504  int iAvailableSize = (int)( in_uDestMaxNumChars - wcslen( in_pDest ) - 1 );
505  wcsncat_s( in_pDest, in_uDestMaxNumChars, in_pSrc, AkMin( iAvailableSize, (int)wcslen( in_pSrc ) ) );
506  }
507 
508  /// Safe string concatenation.
509  inline void SafeStrCat( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
510  {
511  int iAvailableSize = (int)( in_uDestMaxNumChars - strlen( in_pDest ) - 1 );
512  strncat_s( in_pDest, in_uDestMaxNumChars, in_pSrc, AkMin( iAvailableSize, (int)strlen( in_pSrc ) ) );
513  }
514 
515  inline int SafeStrFormat(wchar_t * in_pDest, size_t in_uDestMaxNumChars, const wchar_t* in_pszFmt, ...)
516  {
517  va_list args;
518  va_start(args, in_pszFmt);
519  int r = vswprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
520  va_end(args);
521  return r;
522  }
523 
524  inline int SafeStrFormat(char * in_pDest, size_t in_uDestMaxNumChars, const char* in_pszFmt, ...)
525  {
526  va_list args;
527  va_start(args, in_pszFmt);
528  int r = vsnprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
529  va_end(args);
530  return r;
531  }
532 
533  /// Stack allocations.
534  #define AkAlloca( _size_ ) _alloca( _size_ )
535 
536  /// Output a debug message on the console
537 #if ! defined(AK_OPTIMIZED)
538  inline void OutputDebugMsg( const wchar_t* in_pszMsg )
539  {
540  OutputDebugStringW( in_pszMsg );
541  }
542 
543  /// Output a debug message on the console
544  inline void OutputDebugMsg( const char* in_pszMsg )
545  {
546  OutputDebugStringA( in_pszMsg );
547  }
548 
549  /// Output a debug message on the console (variadic function).
550  /// Use MaxSize to specify the size to reserve for the message.
551  /// Warning: On Win32, OutputDebugMsgV with wchar_t will truncate the string
552  /// to MaxSize.
553  template <int MaxSize = 256>
554  inline void OutputDebugMsgV(const wchar_t* in_pszFmt, ...)
555  {
556  // No equivalent of snprintf for wide string so truncate if necessary
557  // vswprintf returns the number of characters written and not the numbers
558  // that would be written
559 
560  wchar_t* msg = (wchar_t*)AkAlloca(MaxSize * sizeof(wchar_t));
561  msg[MaxSize - 1] = '\0';
562 
563  va_list args;
564  va_start(args, in_pszFmt);
565  vswprintf(msg, MaxSize, in_pszFmt, args);
566  va_end(args);
567 
568  OutputDebugMsg(msg);
569  }
570 
571  /// Output a debug message on the console (variadic function).
572  /// Use MaxSize to specify the expected size of the message.
573  /// If the required size is superior to MaxSize, a new string
574  /// will be allocated on the stack with the required size.
575  template <int MaxSize = 256>
576  inline void OutputDebugMsgV(const char* in_pszFmt, ...)
577  {
578  int size = 0;
579  {
580  // Try with a reasonable guess first
581  char msg[MaxSize];
582  msg[MaxSize - 1] = '\0';
583 
584  va_list args;
585  va_start(args, in_pszFmt);
586  size = vsnprintf(msg, MaxSize, in_pszFmt, args);
587  va_end(args);
588 
589  // If it was enough, print to debug log
590  if (0 <= size && size <= MaxSize)
591  {
592  OutputDebugMsg(msg);
593  return;
594  }
595  }
596 
597  // Else, we need more memory to prevent truncation
598  {
599  // size + 1 more char for the last '\0'
600  size++;
601 
602  char* msg = (char*)AkAlloca((size) * sizeof(char));
603  msg[size - 1] = '\0';
604 
605  va_list args;
606  va_start(args, in_pszFmt);
607  vsnprintf(msg, size, in_pszFmt, args);
608  va_end(args);
609 
610  OutputDebugMsg(msg);
611  }
612  }
613 
614 #else
615  inline void OutputDebugMsg(const wchar_t*){}
616  inline void OutputDebugMsg(const char*){}
617 
618  template <int MaxSize = 0>
619  inline void OutputDebugMsgV(const wchar_t*, ...) {}
620 
621  template <int MaxSize = 0>
622  inline void OutputDebugMsgV(const char*, ...) {}
623 #endif
624 
625  /// Converts a wchar_t string to an AkOSChar string.
626  /// \remark On some platforms the AkOSChar string simply points to the same string,
627  /// on others a new buffer is allocated on the stack using AkAlloca. This means
628  /// you must make sure that:
629  /// - The source string stays valid and unmodified for as long as you need the
630  /// AkOSChar string (for cases where they point to the same string)
631  /// - The AkOSChar string is used within this scope only -- for example, do NOT
632  /// return that string from a function (for cases where it is allocated on the stack)
633  #define CONVERT_WIDE_TO_OSCHAR( _wstring_, _oscharstring_ ) ( _oscharstring_ ) = (AkOSChar*)( _wstring_ )
634 
635  /// Converts a char string to an AkOSChar string.
636  /// \remark On some platforms the AkOSChar string simply points to the same string,
637  /// on others a new buffer is allocated on the stack using AkAlloca. This means
638  /// you must make sure that:
639  /// - The source string stays valid and unmodified for as long as you need the
640  /// AkOSChar string (for cases where they point to the same string)
641  /// - The AkOSChar string is used within this scope only -- for example, do NOT
642  /// return that string from a function (for cases where it is allocated on the stack)
643  #define CONVERT_CHAR_TO_OSCHAR( _astring_, _oscharstring_ ) \
644  _oscharstring_ = (AkOSChar*)AkAlloca( (1 + strlen( _astring_ )) * sizeof(AkOSChar)); \
645  AKPLATFORM::AkCharToWideChar( _astring_, (AkUInt32)(1 + strlen(_astring_ )), (AkOSChar*)( _oscharstring_ ) )
646 
647  /// Converts a AkOSChar string into wide char string.
648  /// \remark On some platforms the AkOSChar string simply points to the same string,
649  /// on others a new buffer is allocated on the stack using AkAlloca. This means
650  /// you must make sure that:
651  /// - The source string stays valid and unmodified for as long as you need the
652  /// AkOSChar string (for cases where they point to the same string)
653  /// - The AkOSChar string is used within this scope only -- for example, do NOT
654  /// return that string from a function (for cases where it is allocated on the stack)
655  #define CONVERT_OSCHAR_TO_WIDE( _osstring_, _wstring_ ) _wstring_ = _osstring_
656 
657  /// Converts a AkOSChar string into char string.
658  /// \remark On some platforms the AkOSChar string simply points to the same string,
659  /// on others a new buffer is allocated on the stack using AkAlloca. This means
660  /// you must make sure that:
661  /// - The source string stays valid and unmodified for as long as you need the
662  /// AkOSChar string (for cases where they point to the same string)
663  /// - The AkOSChar string is used within this scope only -- for example, do NOT
664  /// return that string from a function (for cases where it is allocated on the stack)
665  #define CONVERT_OSCHAR_TO_CHAR( _osstring_, _astring_ ) \
666  _astring_ = (char*)AkAlloca( 1 + AKPLATFORM::AkWideCharToChar( _osstring_, 0, NULL )); \
667  AKPLATFORM::AkWideCharToChar( _osstring_, AkUInt32(1 + AKPLATFORM::AkWideCharToChar( _osstring_, 0, NULL )), _astring_ );
668 
669  /// Get the length, in characters, of a NULL-terminated AkUtf16 string
670  /// \return The length, in characters, of the specified string (excluding terminating NULL)
671  inline size_t AkUtf16StrLen( const AkUtf16* in_pStr )
672  {
673  return ( wcslen( in_pStr ) );
674  }
675 
676  /// Get the length, in characters, of a NULL-terminated AkOSChar string
677  /// \return The length, in characters, of the specified string (excluding terminating NULL)
678  inline size_t OsStrLen( const AkOSChar* in_pszString )
679  {
680  return ( wcslen( in_pszString ) );
681  }
682 
683  /// AkOSChar version of sprintf().
684  #define AK_OSPRINTF swprintf_s
685 
686  /// Compare two NULL-terminated AkOSChar strings
687  /// \return
688  /// - < 0 if in_pszString1 < in_pszString2
689  /// - 0 if the two strings are identical
690  /// - > 0 if in_pszString1 > in_pszString2
691  /// \remark The comparison is case-sensitive
692  inline int OsStrCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2 )
693  {
694  return ( wcscmp( in_pszString1, in_pszString2 ) );
695  }
696 
697  /// Compare two NULL-terminated AkOSChar strings up to the specified count of characters.
698  /// \return
699  /// - < 0 if in_pszString1 < in_pszString2
700  /// - 0 if the two strings are identical
701  /// - > 0 if in_pszString1 > in_pszString2
702  /// \remark The comparison is case-sensitive
703  inline int OsStrNCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2, size_t in_MaxCountSize)
704  {
705  return wcsncmp(in_pszString1, in_pszString2, in_MaxCountSize);
706  }
707 
708  #define AK_UTF16_TO_WCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
709  #define AK_WCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
710  #define AK_UTF8_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
711  #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
712  #define AK_UTF16_TO_CHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
713  #define AK_CHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
714  #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
715 
716  // Use with AkOSChar.
717  #define AK_PATH_SEPARATOR (L"\\")
718  #define AK_LIBRARY_PREFIX (L"")
719  #define AK_DYNAMIC_LIBRARY_EXTENSION (L".dll")
720 
721  #if defined(AK_ENABLE_PERF_RECORDING)
722 
723  static AkUInt32 g_uAkPerfRecExecCount = 0;
724  static AkReal32 g_fAkPerfRecExecTime = 0.f;
725 
726  #define AK_PERF_RECORDING_RESET() \
727  AKPLATFORM::g_uAkPerfRecExecCount = 0;\
728  AKPLATFORM::g_fAkPerfRecExecTime = 0.f;
729 
730  #define AK_PERF_RECORDING_START( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ ) \
731  AkInt64 iAkPerfRecTimeBefore; \
732  if ( (AKPLATFORM::g_uAkPerfRecExecCount >= (__uExecutionCountStart__)) && (AKPLATFORM::g_uAkPerfRecExecCount <= (__uExecutionCountStop__)) ) \
733  AKPLATFORM::PerformanceCounter( &iAkPerfRecTimeBefore );
734 
735  #define AK_PERF_RECORDING_STOP( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ ) \
736  if ( (AKPLATFORM::g_uAkPerfRecExecCount >= (__uExecutionCountStart__)) && (AKPLATFORM::g_uAkPerfRecExecCount <= (__uExecutionCountStop__)) ) \
737  { \
738  AkInt64 iAkPerfRecTimeAfter; \
739  AKPLATFORM::PerformanceCounter( &iAkPerfRecTimeAfter ); \
740  AKPLATFORM::g_fAkPerfRecExecTime += AKPLATFORM::Elapsed( iAkPerfRecTimeAfter, iAkPerfRecTimeBefore ); \
741  if ( AKPLATFORM::g_uAkPerfRecExecCount == (__uExecutionCountStop__) ) \
742  { \
743  AkReal32 fAverageExecutionTime = AKPLATFORM::g_fAkPerfRecExecTime/((__uExecutionCountStop__)-(__uExecutionCountStart__)); \
744  AkOSChar str[256]; \
745  swprintf_s(str, 256, AKTEXT("%s average execution time: %f\n"), AKTEXT(__StorageName__), fAverageExecutionTime);\
746  AKPLATFORM::OutputDebugMsg( str ); \
747  } \
748  } \
749  AKPLATFORM::g_uAkPerfRecExecCount++;
750  #endif // AK_ENABLE_PERF_RECORDING
751 
752 #if (defined(AK_CPU_X86_64) || defined(AK_CPU_X86))
753  /// Support to fetch the CPUID for the platform. Only valid for X86 targets
754  /// \remark Note that IAkProcessorFeatures should be preferred to fetch this data
755  /// as it will have already translated the feature bits into AK-relevant enums
756  inline void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
757  {
758  __cpuidex((int*)out_uCPUFeatures, in_uLeafOpcode, in_uSubLeafOpcode);
759  }
760 #endif
761 }
762 
763 #endif // _AK_PLATFORM_FUNCS_H_
float AkReal32
32-bit floating point
Definition: AkTypes.h:70
size_t AkUtf16StrLen(const AkUtf16 *in_pStr)
Definition: AkPlatformFuncs.h:576
Audiokinetic namespace.
@ AK_Fail
The operation failed.
Definition: AkTypes.h:135
#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
void AkWaitForEvent(AkEvent &in_event)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:80
pthread_t AkThreadID
Thread ID.
Definition: AkTypes.h:74
AkForceInline void UpdatePerformanceFrequency()
Platform Independent Helper.
Definition: AkPlatformFuncs.h:423
AKRESULT
Standard function call result.
Definition: AkTypes.h:132
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
double AkReal64
64-bit floating point
Definition: AkTypes.h:71
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:68
int SafeStrFormat(wchar_t *in_pDest, size_t in_uDestMaxNumChars, const wchar_t *in_pszFmt,...)
Definition: AkPlatformFuncs.h:506
#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:134
void AkCreateThread(AkThreadRoutine pStartRoutine, void *pParams, const AkThreadProperties &in_threadProperties, AkThread *out_pThread, const char *)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:183
AkUInt16 AkUtf16
Definition: AkTypes.h:82
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
void AkSetThreadName(AkThread in_threadHnd, 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:249
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
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
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:608
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
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
uint32_t AkUInt32
Unsigned 32-bit integer.
Definition: AkTypes.h:59
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
int32_t AkInt32
Signed 32-bit integer.
Definition: AkTypes.h:64
#define AkAlloca(_size_)
Stack allocations.
Definition: AkPlatformFuncs.h:534
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
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:597
#define AkForceInline
Definition: AkTypes.h:60
void AkReleaseSemaphore(AkSemaphore *in_semaphore)
Platform Independent Helper - Semaphore signal, aka Operation V. Increments value of semaphore.
Definition: AkPlatformFuncs.h:121
AkForceInline size_t OsStrLen(const AkOSChar *in_pszString)
Definition: AkPlatformFuncs.h:583
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
int64_t AkInt64
Signed 64-bit integer.
Definition: AkTypes.h:65

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