版本
menu_open
link
目标平台:
Wwise SDK 2023.1.2
AkPlatformFuncs.h
浏览该文件的文档.
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  // Optimized memory functions
357  // --------------------------------------------------------------------
358 
359  /// Platform Independent Helper
360  inline void AkMemCpy( void * pDest, const void * pSrc, AkUInt32 uSize )
361  {
362  memcpy( pDest, pSrc, uSize );
363  }
364 
365  /// Platform Independent Helper
366  inline void AkMemMove( void* pDest, const void* pSrc, AkUInt32 uSize )
367  {
368  memmove( pDest, pSrc, uSize );
369  }
370 
371  /// Platform Independent Helper
372  inline void AkMemSet( void * pDest, AkInt32 iVal, AkUInt32 uSize )
373  {
374  memset( pDest, iVal, uSize );
375  }
376 
377  // Time functions
378  // ------------------------------------------------------------------
379 
380  /// Platform Independent Helper
381  inline void PerformanceCounter( AkInt64 * out_piLastTime )
382  {
383  ::QueryPerformanceCounter( (LARGE_INTEGER*)out_piLastTime );
384  }
385 
386  /// Platform Independent Helper
387  inline void PerformanceFrequency( AkInt64 * out_piFreq )
388  {
389  ::QueryPerformanceFrequency( (LARGE_INTEGER*)out_piFreq );
390  }
391 
392  /// Platform Independent Helper
393  inline void UpdatePerformanceFrequency()
394  {
395  AkInt64 iFreq;
396  PerformanceFrequency( &iFreq );
397  AK::g_fFreqRatio = (AkReal32)((AkReal64)iFreq / 1000);
398  }
399 
400  /// Returns a time range in milliseconds, using the sound engine's updated count->milliseconds ratio.
401  inline AkReal32 Elapsed( const AkInt64 & in_iNow, const AkInt64 & in_iStart )
402  {
403  return ( in_iNow - in_iStart ) / AK::g_fFreqRatio;
404  }
405 
406  /// String conversion helper. If io_pszAnsiString is null, the function returns the required size.
407  inline AkInt32 AkWideCharToChar( const wchar_t* in_pszUnicodeString,
408  AkUInt32 in_uiOutBufferSize,
409  char* io_pszAnsiString )
410  {
411  if(!io_pszAnsiString)
412  return WideCharToMultiByte(CP_UTF8, 0, in_pszUnicodeString, -1, NULL, 0, NULL, NULL);
413 
414  int iWritten = ::WideCharToMultiByte(CP_UTF8, // code page
415  0, // performance and mapping flags
416  in_pszUnicodeString, // wide-character string
417  (int)AkMin( ( (AkUInt32)wcslen( in_pszUnicodeString )), in_uiOutBufferSize-1 ), // number of chars in string : -1 = NULL terminated string.
418  io_pszAnsiString, // buffer for new string
419  in_uiOutBufferSize, // size of buffer
420  NULL, // default for unmappable chars
421  NULL); // set when default char used
422  io_pszAnsiString[iWritten] = 0;
423  return iWritten;
424  }
425 
426  /// String conversion helper
427  inline AkInt32 AkCharToWideChar( const char* in_pszAnsiString,
428  AkUInt32 in_uiOutBufferSize,
429  void* io_pvUnicodeStringBuffer )
430  {
431  return ::MultiByteToWideChar( CP_UTF8, // code page
432  0, // performance and mapping flags
433  in_pszAnsiString, // wide-character string
434  -1, // number of chars in string : -1 = NULL terminated string.
435  (wchar_t*)io_pvUnicodeStringBuffer, // buffer for new string
436  in_uiOutBufferSize); // size of buffer
437  }
438 
439  /// String conversion helper
440  inline AkInt32 AkUtf8ToWideChar( const char* in_pszUtf8String,
441  AkUInt32 in_uiOutBufferSize,
442  void* io_pvUnicodeStringBuffer )
443  {
444  return ::MultiByteToWideChar( CP_UTF8, // code page
445  0, // performance and mapping flags
446  in_pszUtf8String, // wide-character string
447  -1, // number of chars in string : -1 = NULL terminated string.
448  (wchar_t*)io_pvUnicodeStringBuffer, // buffer for new string
449  in_uiOutBufferSize); // size of buffer
450  }
451 
452  /// Safe unicode string copy.
453  inline void SafeStrCpy( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
454  {
455  size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, wcslen( in_pSrc ) + 1 );
456  wcsncpy_s( in_pDest, in_uDestMaxNumChars, in_pSrc, iSizeCopy );
457  in_pDest[iSizeCopy] = '\0';
458  }
459 
460  /// Safe string copy.
461  inline void SafeStrCpy( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
462  {
463  size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, strlen( in_pSrc ) + 1 );
464  strncpy_s( in_pDest, in_uDestMaxNumChars, in_pSrc, iSizeCopy );
465  in_pDest[iSizeCopy] = '\0';
466  }
467 
468  /// Safe unicode string concatenation.
469  inline void SafeStrCat( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
470  {
471  int iAvailableSize = (int)( in_uDestMaxNumChars - wcslen( in_pDest ) - 1 );
472  wcsncat_s( in_pDest, in_uDestMaxNumChars, in_pSrc, AkMin( iAvailableSize, (int)wcslen( in_pSrc ) ) );
473  }
474 
475  /// Safe string concatenation.
476  inline void SafeStrCat( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
477  {
478  int iAvailableSize = (int)( in_uDestMaxNumChars - strlen( in_pDest ) - 1 );
479  strncat_s( in_pDest, in_uDestMaxNumChars, in_pSrc, AkMin( iAvailableSize, (int)strlen( in_pSrc ) ) );
480  }
481 
482  inline int SafeStrFormat(wchar_t * in_pDest, size_t in_uDestMaxNumChars, const wchar_t* in_pszFmt, ...)
483  {
484  va_list args;
485  va_start(args, in_pszFmt);
486  int r = vswprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
487  va_end(args);
488  return r;
489  }
490 
491  inline int SafeStrFormat(char * in_pDest, size_t in_uDestMaxNumChars, const char* in_pszFmt, ...)
492  {
493  va_list args;
494  va_start(args, in_pszFmt);
495  int r = vsnprintf(in_pDest, in_uDestMaxNumChars, in_pszFmt, args);
496  va_end(args);
497  return r;
498  }
499 
500  /// Stack allocations.
501  #define AkAlloca( _size_ ) _alloca( _size_ )
502 
503  /// Output a debug message on the console
504 #if ! defined(AK_OPTIMIZED)
505  inline void OutputDebugMsg( const wchar_t* in_pszMsg )
506  {
507  OutputDebugStringW( in_pszMsg );
508  }
509 
510  /// Output a debug message on the console
511  inline void OutputDebugMsg( const char* in_pszMsg )
512  {
513  OutputDebugStringA( in_pszMsg );
514  }
515 
516  /// Output a debug message on the console (variadic function).
517  /// Use MaxSize to specify the size to reserve for the message.
518  /// Warning: On Win32, OutputDebugMsgV with wchar_t will truncate the string
519  /// to MaxSize.
520  template <int MaxSize = 256>
521  inline void OutputDebugMsgV(const wchar_t* in_pszFmt, ...)
522  {
523  // No equivalent of snprintf for wide string so truncate if necessary
524  // vswprintf returns the number of characters written and not the numbers
525  // that would be written
526 
527  wchar_t* msg = (wchar_t*)AkAlloca(MaxSize * sizeof(wchar_t));
528  msg[MaxSize - 1] = '\0';
529 
530  va_list args;
531  va_start(args, in_pszFmt);
532  vswprintf(msg, MaxSize, in_pszFmt, args);
533  va_end(args);
534 
535  OutputDebugMsg(msg);
536  }
537 
538  /// Output a debug message on the console (variadic function).
539  /// Use MaxSize to specify the expected size of the message.
540  /// If the required size is superior to MaxSize, a new string
541  /// will be allocated on the stack with the required size.
542  template <int MaxSize = 256>
543  inline void OutputDebugMsgV(const char* in_pszFmt, ...)
544  {
545  int size = 0;
546  {
547  // Try with a reasonable guess first
548  char msg[MaxSize];
549  msg[MaxSize - 1] = '\0';
550 
551  va_list args;
552  va_start(args, in_pszFmt);
553  size = vsnprintf(msg, MaxSize, in_pszFmt, args);
554  va_end(args);
555 
556  // If it was enough, print to debug log
557  if (0 <= size && size <= MaxSize)
558  {
559  OutputDebugMsg(msg);
560  return;
561  }
562  }
563 
564  // Else, we need more memory to prevent truncation
565  {
566  // size + 1 more char for the last '\0'
567  size++;
568 
569  char* msg = (char*)AkAlloca((size) * sizeof(char));
570  msg[size - 1] = '\0';
571 
572  va_list args;
573  va_start(args, in_pszFmt);
574  vsnprintf(msg, size, in_pszFmt, args);
575  va_end(args);
576 
577  OutputDebugMsg(msg);
578  }
579  }
580 
581 #else
582  inline void OutputDebugMsg(const wchar_t*){}
583  inline void OutputDebugMsg(const char*){}
584 
585  template <int MaxSize = 0>
586  inline void OutputDebugMsgV(const wchar_t*, ...) {}
587 
588  template <int MaxSize = 0>
589  inline void OutputDebugMsgV(const char*, ...) {}
590 #endif
591 
592  /// Converts a wchar_t string to an AkOSChar string.
593  /// \remark On some platforms the AkOSChar string simply points to the same string,
594  /// on others a new buffer is allocated on the stack using AkAlloca. This means
595  /// you must make sure that:
596  /// - The source string stays valid and unmodified for as long as you need the
597  /// AkOSChar string (for cases where they point to the same string)
598  /// - The AkOSChar string is used within this scope only -- for example, do NOT
599  /// return that string from a function (for cases where it is allocated on the stack)
600  #define CONVERT_WIDE_TO_OSCHAR( _wstring_, _oscharstring_ ) ( _oscharstring_ ) = (AkOSChar*)( _wstring_ )
601 
602  /// Converts a char string to an AkOSChar string.
603  /// \remark On some platforms the AkOSChar string simply points to the same string,
604  /// on others a new buffer is allocated on the stack using AkAlloca. This means
605  /// you must make sure that:
606  /// - The source string stays valid and unmodified for as long as you need the
607  /// AkOSChar string (for cases where they point to the same string)
608  /// - The AkOSChar string is used within this scope only -- for example, do NOT
609  /// return that string from a function (for cases where it is allocated on the stack)
610  #define CONVERT_CHAR_TO_OSCHAR( _astring_, _oscharstring_ ) \
611  _oscharstring_ = (AkOSChar*)AkAlloca( (1 + strlen( _astring_ )) * sizeof(AkOSChar)); \
612  AKPLATFORM::AkCharToWideChar( _astring_, (AkUInt32)(1 + strlen(_astring_ )), (AkOSChar*)( _oscharstring_ ) )
613 
614  /// Converts a AkOSChar string into wide char string.
615  /// \remark On some platforms the AkOSChar string simply points to the same string,
616  /// on others a new buffer is allocated on the stack using AkAlloca. This means
617  /// you must make sure that:
618  /// - The source string stays valid and unmodified for as long as you need the
619  /// AkOSChar string (for cases where they point to the same string)
620  /// - The AkOSChar string is used within this scope only -- for example, do NOT
621  /// return that string from a function (for cases where it is allocated on the stack)
622  #define CONVERT_OSCHAR_TO_WIDE( _osstring_, _wstring_ ) _wstring_ = _osstring_
623 
624  /// Converts a AkOSChar string into char string.
625  /// \remark On some platforms the AkOSChar string simply points to the same string,
626  /// on others a new buffer is allocated on the stack using AkAlloca. This means
627  /// you must make sure that:
628  /// - The source string stays valid and unmodified for as long as you need the
629  /// AkOSChar string (for cases where they point to the same string)
630  /// - The AkOSChar string is used within this scope only -- for example, do NOT
631  /// return that string from a function (for cases where it is allocated on the stack)
632  #define CONVERT_OSCHAR_TO_CHAR( _osstring_, _astring_ ) \
633  _astring_ = (char*)AkAlloca( 1 + AKPLATFORM::AkWideCharToChar( _osstring_, 0, NULL )); \
634  AKPLATFORM::AkWideCharToChar( _osstring_, AkUInt32(1 + AKPLATFORM::AkWideCharToChar( _osstring_, 0, NULL )), _astring_ );
635 
636  /// Get the length, in characters, of a NULL-terminated AkUtf16 string
637  /// \return The length, in characters, of the specified string (excluding terminating NULL)
638  inline size_t AkUtf16StrLen( const AkUtf16* in_pStr )
639  {
640  return ( wcslen( in_pStr ) );
641  }
642 
643  /// Get the length, in characters, of a NULL-terminated AkOSChar string
644  /// \return The length, in characters, of the specified string (excluding terminating NULL)
645  inline size_t OsStrLen( const AkOSChar* in_pszString )
646  {
647  return ( wcslen( in_pszString ) );
648  }
649 
650  /// AkOSChar version of sprintf().
651  #define AK_OSPRINTF swprintf_s
652 
653  /// Compare two NULL-terminated AkOSChar strings
654  /// \return
655  /// - < 0 if in_pszString1 < in_pszString2
656  /// - 0 if the two strings are identical
657  /// - > 0 if in_pszString1 > in_pszString2
658  /// \remark The comparison is case-sensitive
659  inline int OsStrCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2 )
660  {
661  return ( wcscmp( in_pszString1, in_pszString2 ) );
662  }
663 
664  /// Compare two NULL-terminated AkOSChar strings up to the specified count of characters.
665  /// \return
666  /// - < 0 if in_pszString1 < in_pszString2
667  /// - 0 if the two strings are identical
668  /// - > 0 if in_pszString1 > in_pszString2
669  /// \remark The comparison is case-sensitive
670  inline int OsStrNCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2, size_t in_MaxCountSize)
671  {
672  return wcsncmp(in_pszString1, in_pszString2, in_MaxCountSize);
673  }
674 
675  #define AK_UTF16_TO_WCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
676  #define AK_WCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
677  #define AK_UTF8_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
678  #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
679  #define AK_UTF16_TO_CHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
680  #define AK_CHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
681  #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::SafeStrCpy( in_pdDest, in_pSrc, in_MaxSize )
682 
683  /// Detects whether the string represents an absolute path to a file
684  inline bool IsAbsolutePath(const AkOSChar* in_pszPath, size_t in_pathLen)
685  {
686  return
687  (in_pathLen >= 3 && in_pszPath[1] == ':' && in_pszPath[2] == '\\') || // Classic "C:\..." DOS-style path
688  (in_pathLen >= 2 && in_pszPath[0] == '\\'); // Uncommon "\..." absolute path from current drive, or UNC "\\..."
689  }
690 
691  // Use with AkOSChar.
692  #define AK_PATH_SEPARATOR L"\\"
693  #define AK_LIBRARY_PREFIX L""
694  #define AK_DYNAMIC_LIBRARY_EXTENSION L".dll"
695 
696  #define AK_FILEHANDLE_TO_UINTPTR(_h) ((AkUIntPtr)_h)
697  #define AK_SET_FILEHANDLE_TO_UINTPTR(_h,_u) _h = (AkFileHandle)_u
698 
699  #if defined(AK_ENABLE_PERF_RECORDING)
700 
701  static AkUInt32 g_uAkPerfRecExecCount = 0;
702  static AkReal32 g_fAkPerfRecExecTime = 0.f;
703 
704  #define AK_PERF_RECORDING_RESET() \
705  AKPLATFORM::g_uAkPerfRecExecCount = 0;\
706  AKPLATFORM::g_fAkPerfRecExecTime = 0.f;
707 
708  #define AK_PERF_RECORDING_START( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ ) \
709  AkInt64 iAkPerfRecTimeBefore; \
710  if ( (AKPLATFORM::g_uAkPerfRecExecCount >= (__uExecutionCountStart__)) && (AKPLATFORM::g_uAkPerfRecExecCount <= (__uExecutionCountStop__)) ) \
711  AKPLATFORM::PerformanceCounter( &iAkPerfRecTimeBefore );
712 
713  #define AK_PERF_RECORDING_STOP( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ ) \
714  if ( (AKPLATFORM::g_uAkPerfRecExecCount >= (__uExecutionCountStart__)) && (AKPLATFORM::g_uAkPerfRecExecCount <= (__uExecutionCountStop__)) ) \
715  { \
716  AkInt64 iAkPerfRecTimeAfter; \
717  AKPLATFORM::PerformanceCounter( &iAkPerfRecTimeAfter ); \
718  AKPLATFORM::g_fAkPerfRecExecTime += AKPLATFORM::Elapsed( iAkPerfRecTimeAfter, iAkPerfRecTimeBefore ); \
719  if ( AKPLATFORM::g_uAkPerfRecExecCount == (__uExecutionCountStop__) ) \
720  { \
721  AkReal32 fAverageExecutionTime = AKPLATFORM::g_fAkPerfRecExecTime/((__uExecutionCountStop__)-(__uExecutionCountStart__)); \
722  AkOSChar str[256]; \
723  swprintf_s(str, 256, AKTEXT("%s average execution time: %f\n"), AKTEXT(__StorageName__), fAverageExecutionTime);\
724  AKPLATFORM::OutputDebugMsg( str ); \
725  } \
726  } \
727  AKPLATFORM::g_uAkPerfRecExecCount++;
728  #endif // AK_ENABLE_PERF_RECORDING
729 
730 #if (defined(AK_CPU_X86_64) || defined(AK_CPU_X86))
731  /// Support to fetch the CPUID for the platform. Only valid for X86 targets
732  /// \remark Note that IAkProcessorFeatures should be preferred to fetch this data
733  /// as it will have already translated the feature bits into AK-relevant enums
734  inline void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
735  {
736  __cpuidex((int*)out_uCPUFeatures, in_uLeafOpcode, in_uSubLeafOpcode);
737  }
738 #endif
739 }
740 
741 #endif // _AK_PLATFORM_FUNCS_H_
AKRESULT AkCreateSemaphore(AkSemaphore &out_semaphore, AkUInt32 in_initialCount)
Platform Independent Helper
size_t AkUtf16StrLen(const AkUtf16 *in_pStr)
Audiokinetic namespace
@ AK_Fail
The operation failed.
Definition: AkTypes.h:216
#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:213
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:215
int32_t AkInt32
Signed 32-bit integer
void AkCreateThread(AkThreadRoutine pStartRoutine, void *pParams, const AkThreadProperties &in_threadProperties, AkThread *out_pThread, const char *)
Platform Independent Helper
AkUInt16 AkUtf16
Definition: AkTypes.h:61
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:87
AkForceInline bool AkIsValidThread(AkThread *in_pThread)
Platform Independent Helper
AkForceInline void AkMemCpy(void *pDest, const void *pSrc, AkUInt32 uSize)
Platform Independent Helper
#define AKASSERT(Condition)
Definition: AkAssert.h:67
#define AKVERIFY(x)
Definition: AkAssert.h:69
AkForceInline void AkSleep(AkUInt32 in_ulMilliseconds)
Platform Independent Helper
AkForceInline void AkClearThread(AkThread *in_pThread)
Platform Independent Helper
AkForceInline void AkGetDefaultThreadProperties(AkThreadProperties &out_threadProperties)
Platform Independent Helper
#define AK_NULL_THREAD
int OsStrNCmp(const AkOSChar *in_pszString1, const AkOSChar *in_pszString2, size_t in_MaxCountSize)
AkForceInline void AkMemSet(void *pDest, AkInt32 iVal, AkUInt32 uSize)
Platform Independent Helper
void AkMemMove(void *pDest, const void *pSrc, AkUInt32 uSize)
Platform Independent Helper
SceKernelCpumask dwAffinityMask
Affinity mask
AkReal32 g_fFreqRatio
double AkReal64
64-bit floating point
#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.

此页面对您是否有帮助?

需要技术支持?

仍有疑问?或者问题?需要更多信息?欢迎联系我们,我们可以提供帮助!

查看我们的“技术支持”页面

介绍一下自己的项目。我们会竭力为您提供帮助。

来注册自己的项目,我们帮您快速入门,不带任何附加条件!

开始 Wwise 之旅