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