refactor(fmod): move all original files into fmod directory

This commit is contained in:
phaneron 2025-08-20 04:38:38 -04:00
parent 50fb3c6b1c
commit 35569faecc
544 changed files with 0 additions and 0 deletions

BIN
fmod/win32/bin/nasmw.exe Executable file

Binary file not shown.

View file

@ -0,0 +1,480 @@
///////////////////////////////////////////////////////////////////////////
//
// ASFErr.h - definition of ASF HRESULT codes
//
//=========================================================================
//
// Microsoft Windows Media Technologies
// Copyright (C) Microsoft Corporation. All Rights Reserved.
//
//=========================================================================
//
// This file is generated by the MC tool from ASFErr.mc
//
#ifndef _ASFERR_H
#define _ASFERR_H
#define STATUS_SEVERITY(hr) (((hr) >> 30) & 0x3)
#ifdef RC_INVOKED
#define _ASF_HRESULT_TYPEDEF_(_sc) _sc
#else // RC_INVOKED
#define _ASF_HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc)
#endif // RC_INVOKED
///////////////////////////////////////////////////////////////////////////
//
// Advanced Streaming Format (ASF) Errors (2000 - 2999)
//
//
// Values are 32 bit values layed out as follows:
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---+-+-+-----------------------+-------------------------------+
// |Sev|C|R| Facility | Code |
// +---+-+-+-----------------------+-------------------------------+
//
// where
//
// Sev - is the severity code
//
// 00 - Success
// 01 - Informational
// 10 - Warning
// 11 - Error
//
// C - is the Customer code flag
//
// R - is a reserved bit
//
// Facility - is the facility code
//
// Code - is the facility's status code
//
//
// Define the facility codes
//
#define FACILITY_NS 0xD
//
// Define the severity codes
//
#define STATUS_SEVERITY_WARNING 0x2
#define STATUS_SEVERITY_SUCCESS 0x0
#define STATUS_SEVERITY_INFORMATIONAL 0x1
#define STATUS_SEVERITY_ERROR 0x3
//
// MessageId: ASF_E_BUFFEROVERRUN
//
// MessageText:
//
// An attempt was made to seek or position past the end of a buffer.%0
//
#define ASF_E_BUFFEROVERRUN _ASF_HRESULT_TYPEDEF_(0xC00D07D0L)
//
// MessageId: ASF_E_BUFFERTOOSMALL
//
// MessageText:
//
// The supplied input or output buffer was too small.%0
//
#define ASF_E_BUFFERTOOSMALL _ASF_HRESULT_TYPEDEF_(0xC00D07D1L)
//
// MessageId: ASF_E_BADLANGUAGEID
//
// MessageText:
//
// The language ID was not found.%0
//
#define ASF_E_BADLANGUAGEID _ASF_HRESULT_TYPEDEF_(0xC00D07D2L)
//
// MessageId: ASF_E_NOPAYLOADLENGTH
//
// MessageText:
//
// The multiple payload packet is missing the payload length.%0
//
#define ASF_E_NOPAYLOADLENGTH _ASF_HRESULT_TYPEDEF_(0xC00D07DBL)
//
// MessageId: ASF_E_TOOMANYPAYLOADS
//
// MessageText:
//
// The packet contains too many payloads.%0
//
#define ASF_E_TOOMANYPAYLOADS _ASF_HRESULT_TYPEDEF_(0xC00D07DCL)
//
// MessageId: ASF_E_PACKETCONTENTTOOLARGE
//
// MessageText:
//
// ASF_E_PACKETCONTENTTOOLARGE
//
#define ASF_E_PACKETCONTENTTOOLARGE _ASF_HRESULT_TYPEDEF_(0xC00D07DEL)
//
// MessageId: ASF_E_UNKNOWNPACKETSIZE
//
// MessageText:
//
// Expecting a fixed packet size but min. and max. are not equal.%0
//
#define ASF_E_UNKNOWNPACKETSIZE _ASF_HRESULT_TYPEDEF_(0xC00D07E0L)
//
// MessageId: ASF_E_INVALIDHEADER
//
// MessageText:
//
// ASF_E_INVALIDHEADER
//
#define ASF_E_INVALIDHEADER _ASF_HRESULT_TYPEDEF_(0xC00D07E2L)
//
// MessageId: ASF_E_NOCLOCKOBJECT
//
// MessageText:
//
// The object does not have a valid clock object.%0
//
#define ASF_E_NOCLOCKOBJECT _ASF_HRESULT_TYPEDEF_(0xC00D07E6L)
//
// MessageId: ASF_E_UNKNOWNCLOCKTYPE
//
// MessageText:
//
// ASF_E_UNKNOWNCLOCKTYPE
//
#define ASF_E_UNKNOWNCLOCKTYPE _ASF_HRESULT_TYPEDEF_(0xC00D07EBL)
//
// MessageId: ASF_E_OPAQUEPACKET
//
// MessageText:
//
// An attempt was made to restore or access an opaque packet.%0
//
#define ASF_E_OPAQUEPACKET _ASF_HRESULT_TYPEDEF_(0xC00D07EDL)
//
// MessageId: ASF_E_WRONGVERSION
//
// MessageText:
//
// ASF_E_WRONGVERSION
//
#define ASF_E_WRONGVERSION _ASF_HRESULT_TYPEDEF_(0xC00D07EEL)
//
// MessageId: ASF_E_OVERFLOW
//
// MessageText:
//
// An attempt was made to store a value which was larger than then destination's maximum value.%0
//
#define ASF_E_OVERFLOW _ASF_HRESULT_TYPEDEF_(0xC00D07EFL)
//
// MessageId: ASF_E_NOTFOUND
//
// MessageText:
//
// The object was not found.%0
//
#define ASF_E_NOTFOUND _ASF_HRESULT_TYPEDEF_(0xC00D07F0L)
//
// Someone else is using MessageIds 2033 & 2034, so we skip them
//
// 2033 = NS_E_NOTHING_TO_DO
// 2034 = NS_E_NO_MULTICAST
//
// MessageId: ASF_E_OBJECTTOOBIG
//
// MessageText:
//
// The object is too large to be processed in the requested manner.%0
//
#define ASF_E_OBJECTTOOBIG _ASF_HRESULT_TYPEDEF_(0xC00D07F3L)
//
// MessageId: ASF_E_UNEXPECTEDVALUE
//
// MessageText:
//
// A value was not set as expected.%0
//
#define ASF_E_UNEXPECTEDVALUE _ASF_HRESULT_TYPEDEF_(0xC00D07F4L)
//
// MessageId: ASF_E_INVALIDSTATE
//
// MessageText:
//
// The request is not valid in the object's current state.%0
//
#define ASF_E_INVALIDSTATE _ASF_HRESULT_TYPEDEF_(0xC00D07F5L)
//
// MessageId: ASF_E_NOLIBRARY
//
// MessageText:
//
// This object does not have a valid library pointer; it was not properly created or it has been Shutdown().%0
//
#define ASF_E_NOLIBRARY _ASF_HRESULT_TYPEDEF_(0xC00D07F6L)
//
// MessageId: ASF_E_ALREADYINITIALIZED
//
// MessageText:
//
// This object has already been initialized; the setting cannot be changed.%0
//
#define ASF_E_ALREADYINITIALIZED _ASF_HRESULT_TYPEDEF_(0xC00D07F7L)
//
// MessageId: ASF_E_INVALIDINIT
//
// MessageText:
//
// This object has not been initialized properly; that operation cannot be performed.%0
//
#define ASF_E_INVALIDINIT _ASF_HRESULT_TYPEDEF_(0xC00D07F8L)
//
// MessageId: ASF_E_NOHEADEROBJECT
//
// MessageText:
//
// The ASF Header object could not be found.%0
//
#define ASF_E_NOHEADEROBJECT _ASF_HRESULT_TYPEDEF_(0xC00D07F9L)
//
// MessageId: ASF_E_NODATAOBJECT
//
// MessageText:
//
// The ASF Data object could not be found.%0
//
#define ASF_E_NODATAOBJECT _ASF_HRESULT_TYPEDEF_(0xC00D07FAL)
//
// MessageId: ASF_E_NOINDEXOBJECT
//
// MessageText:
//
// The ASF Index object could not be found.%0
//
#define ASF_E_NOINDEXOBJECT _ASF_HRESULT_TYPEDEF_(0xC00D07FBL)
//
// MessageId: ASF_E_NOSTREAMPROPS
//
// MessageText:
//
// A Stream Properties object with the correct stream number could not be found.%0
//
#define ASF_E_NOSTREAMPROPS _ASF_HRESULT_TYPEDEF_(0xC00D07FCL)
//
// MessageId: ASF_E_NOFILEPROPS
//
// MessageText:
//
// The File Properties object could not be found.%0
//
#define ASF_E_NOFILEPROPS _ASF_HRESULT_TYPEDEF_(0xC00D07FDL)
//
// MessageId: ASF_E_NOLANGUAGELIST
//
// MessageText:
//
// The Language List object could not be found.%0
//
#define ASF_E_NOLANGUAGELIST _ASF_HRESULT_TYPEDEF_(0xC00D07FEL)
//
// MessageId: ASF_E_NOINDEXPARAMETERS
//
// MessageText:
//
// The Index Parameters object could not be found.%0
//
#define ASF_E_NOINDEXPARAMETERS _ASF_HRESULT_TYPEDEF_(0xC00D07FFL)
//
// MessageId: ASF_E_UNSUPPORTEDERRORCONCEALMENT
//
// MessageText:
//
// The requested error concealment strategy is not supported by this component.%0
//
#define ASF_E_UNSUPPORTEDERRORCONCEALMENT _ASF_HRESULT_TYPEDEF_(0xC00D0800L)
//
// MessageId: ASF_E_INVALIDFLAGS
//
// MessageText:
//
// The flags for this object or set of objects are not properly set.%0
//
#define ASF_E_INVALIDFLAGS _ASF_HRESULT_TYPEDEF_(0xC00D0801L)
//
// MessageId: ASF_E_BADDATADESCRIPTOR
//
// MessageText:
//
// One or more data descriptors is not properly set.%0
//
#define ASF_E_BADDATADESCRIPTOR _ASF_HRESULT_TYPEDEF_(0xC00D0802L)
//
// MessageId: ASF_E_BADINDEXINTERVAL
//
// MessageText:
//
// The index has an invalid time interval (probably zero).%0
//
#define ASF_E_BADINDEXINTERVAL _ASF_HRESULT_TYPEDEF_(0xC00D0803L)
//
// MessageId: ASF_E_INVALIDTIME
//
// MessageText:
//
// The given time value is not valid.%0
//
#define ASF_E_INVALIDTIME _ASF_HRESULT_TYPEDEF_(0xC00D0804L)
//
// MessageId: ASF_E_INVALIDINDEX
//
// MessageText:
//
// The given index value is not valid.%0
//
#define ASF_E_INVALIDINDEX _ASF_HRESULT_TYPEDEF_(0xC00D0805L)
//
// MessageId: ASF_E_STREAMNUMBERINUSE
//
// MessageText:
//
// The specified stream number is already in use.%0
//
#define ASF_E_STREAMNUMBERINUSE _ASF_HRESULT_TYPEDEF_(0xC00D0806L)
//
// MessageId: ASF_E_BADMEDIATYPE
//
// MessageText:
//
// The specified media type does not work with this component.%0
//
#define ASF_E_BADMEDIATYPE _ASF_HRESULT_TYPEDEF_(0xC00D0807L)
//
// MessageId: ASF_E_WRITEFAILED
//
// MessageText:
//
// The object could not be written as specified.%0
//
#define ASF_E_WRITEFAILED _ASF_HRESULT_TYPEDEF_(0xC00D0808L)
//
// MessageId: ASF_E_NOTENOUGHDESCRIPTORS
//
// MessageText:
//
// The given data unit requires a larger number of descriptors to be fully parsed.%0
//
#define ASF_E_NOTENOUGHDESCRIPTORS _ASF_HRESULT_TYPEDEF_(0xC00D0809L)
//
// MessageId: ASF_E_INDEXBLOCKUNLOADED
//
// MessageText:
//
// The index entries for the specified index block have been unloaded from memory and are not available.%0
//
#define ASF_E_INDEXBLOCKUNLOADED _ASF_HRESULT_TYPEDEF_(0xC00D080AL)
//
// MessageId: ASF_E_NOTENOUGHBANDWIDTH
//
// MessageText:
//
// The specified bandwidth is not large enough.%0
//
#define ASF_E_NOTENOUGHBANDWIDTH _ASF_HRESULT_TYPEDEF_(0xC00D080BL)
//
// MessageId: ASF_E_EXCEEDEDMAXIMUMOBJECTSIZE
//
// MessageText:
//
// The object has exceeded its maximum size.%0
//
#define ASF_E_EXCEEDEDMAXIMUMOBJECTSIZE _ASF_HRESULT_TYPEDEF_(0xC00D080CL)
//
// MessageId: ASF_E_BADDATAUNIT
//
// MessageText:
//
// The given data unit is corrupted, badly formatted, or otherwise not valid.%0
//
#define ASF_E_BADDATAUNIT _ASF_HRESULT_TYPEDEF_(0xC00D080DL)
//
// MessageId: ASF_E_HEADERSIZE
//
// MessageText:
//
// The ASF header has exceeded the specified maximum size.%0
//
#define ASF_E_HEADERSIZE _ASF_HRESULT_TYPEDEF_(0xC00D080EL)
///////////////////////////////////////////////////////////////////////////
//
// Advanced Streaming Format (ASF) Success Codes (2000 - 2999)
//
//
// MessageId: ASF_S_OPAQUEPACKET
//
// MessageText:
//
// ASF_S_OPAQUEPACKET
//
#define ASF_S_OPAQUEPACKET _ASF_HRESULT_TYPEDEF_(0x000D07F0L)
///////////////////////////////////////////////////////////////////////////
//
// Advanced Streaming Format (ASF) Warnings (2000 - 2999)
//
#endif // _ASFERR_H

View file

@ -0,0 +1,170 @@
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 6.00.0361 */
/* Compiler settings for drmexternals.idl:
Oicf, W1, Zp8, env=Win32 (32b run)
protocol : dce , ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING( )
#pragma warning( disable: 4049 ) /* more than 64k source lines */
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__
#ifndef __drmexternals_h__
#define __drmexternals_h__
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
/* Forward Declarations */
/* header files for imported files */
#include "oaidl.h"
#ifdef __cplusplus
extern "C"{
#endif
void * __RPC_USER MIDL_user_allocate(size_t);
void __RPC_USER MIDL_user_free( void * );
/* interface __MIDL_itf_drmexternals_0000 */
/* [local] */
//=========================================================================
//
// Microsoft Windows Media Technologies
// Copyright (C) Microsoft Corporation. All Rights Reserved.
//
//=========================================================================
static const WCHAR *g_wszWMDRM_RIGHT_PLAYBACK = L"Play";
static const WCHAR *g_wszWMDRM_RIGHT_COPY_TO_CD = L"Print.redbook";
static const WCHAR *g_wszWMDRM_RIGHT_COPY_TO_SDMI_DEVICE = L"Transfer.SDMI";
static const WCHAR *g_wszWMDRM_RIGHT_COPY_TO_NON_SDMI_DEVICE = L"Transfer.NONSDMI";
static const WCHAR *g_wszWMDRM_RIGHT_BACKUP = L"Backup";
static const WCHAR *g_wszWMDRM_IsDRM = L"IsDRM";
static const WCHAR *g_wszWMDRM_IsDRMCached = L"IsDRMCached";
static const WCHAR *g_wszWMDRM_BaseLicenseAcqURL = L"BaseLAURL";
static const WCHAR *g_wszWMDRM_Rights = L"Rights";
static const WCHAR *g_wszWMDRM_LicenseID = L"LID";
static const WCHAR *g_wszWMDRM_ActionAllowed = L"ActionAllowed.";
static const WCHAR *g_wszWMDRM_ActionAllowed_Playback = L"ActionAllowed.Play";
static const WCHAR *g_wszWMDRM_ActionAllowed_CopyToCD = L"ActionAllowed.Print.redbook";
static const WCHAR *g_wszWMDRM_ActionAllowed_CopyToSDMIDevice = L"ActionAllowed.Transfer.SDMI";
static const WCHAR *g_wszWMDRM_ActionAllowed_CopyToNonSDMIDevice = L"ActionAllowed.Transfer.NONSDMI";
static const WCHAR *g_wszWMDRM_ActionAllowed_Backup = L"ActionAllowed.Backup";
static const WCHAR *g_wszWMDRM_LicenseState = L"LicenseStateData.";
static const WCHAR *g_wszWMDRM_LicenseState_Playback = L"LicenseStateData.Play";
static const WCHAR *g_wszWMDRM_LicenseState_CopyToCD = L"LicenseStateData.Print.redbook";
static const WCHAR *g_wszWMDRM_LicenseState_CopyToSDMIDevice = L"LicenseStateData.Transfer.SDMI";
static const WCHAR *g_wszWMDRM_LicenseState_CopyToNonSDMIDevice = L"LicenseStateData.Transfer.NONSDMI";
static const WCHAR *g_wszWMDRM_DRMHeader = L"DRMHeader.";
static const WCHAR *g_wszWMDRM_DRMHeader_KeyID = L"DRMHeader.KID";
static const WCHAR *g_wszWMDRM_DRMHeader_LicenseAcqURL = L"DRMHeader.LAINFO";
static const WCHAR *g_wszWMDRM_DRMHeader_ContentID = L"DRMHeader.CID";
static const WCHAR *g_wszWMDRM_DRMHeader_IndividualizedVersion = L"DRMHeader.SECURITYVERSION";
static const WCHAR *g_wszWMDRM_DRMHeader_ContentDistributor = L"DRMHeader.ContentDistributor";
static const WCHAR *g_wszWMDRM_DRMHeader_SubscriptionContentID = L"DRMHeader.SubscriptionContentID";
typedef
enum DRM_LICENSE_STATE_CATEGORY
{ WM_DRM_LICENSE_STATE_NORIGHT = 0,
WM_DRM_LICENSE_STATE_UNLIM = WM_DRM_LICENSE_STATE_NORIGHT + 1,
WM_DRM_LICENSE_STATE_COUNT = WM_DRM_LICENSE_STATE_UNLIM + 1,
WM_DRM_LICENSE_STATE_FROM = WM_DRM_LICENSE_STATE_COUNT + 1,
WM_DRM_LICENSE_STATE_UNTIL = WM_DRM_LICENSE_STATE_FROM + 1,
WM_DRM_LICENSE_STATE_FROM_UNTIL = WM_DRM_LICENSE_STATE_UNTIL + 1,
WM_DRM_LICENSE_STATE_COUNT_FROM = WM_DRM_LICENSE_STATE_FROM_UNTIL + 1,
WM_DRM_LICENSE_STATE_COUNT_UNTIL = WM_DRM_LICENSE_STATE_COUNT_FROM + 1,
WM_DRM_LICENSE_STATE_COUNT_FROM_UNTIL = WM_DRM_LICENSE_STATE_COUNT_UNTIL + 1,
WM_DRM_LICENSE_STATE_EXPIRATION_AFTER_FIRSTUSE = WM_DRM_LICENSE_STATE_COUNT_FROM_UNTIL + 1
} DRM_LICENSE_STATE_CATEGORY;
typedef struct _DRM_LICENSE_STATE_DATA
{
DWORD dwStreamId;
DRM_LICENSE_STATE_CATEGORY dwCategory;
DWORD dwNumCounts;
DWORD dwCount[ 4 ];
DWORD dwNumDates;
FILETIME datetime[ 4 ];
DWORD dwVague;
} DRM_LICENSE_STATE_DATA;
typedef
enum DRM_HTTP_STATUS
{ HTTP_NOTINITIATED = 0,
HTTP_CONNECTING = HTTP_NOTINITIATED + 1,
HTTP_REQUESTING = HTTP_CONNECTING + 1,
HTTP_RECEIVING = HTTP_REQUESTING + 1,
HTTP_COMPLETED = HTTP_RECEIVING + 1
} DRM_HTTP_STATUS;
typedef
enum DRM_INDIVIDUALIZATION_STATUS
{ INDI_UNDEFINED = 0,
INDI_BEGIN = 0x1,
INDI_SUCCEED = 0x2,
INDI_FAIL = 0x4,
INDI_CANCEL = 0x8,
INDI_DOWNLOAD = 0x10,
INDI_INSTALL = 0x20
} DRM_INDIVIDUALIZATION_STATUS;
typedef struct _WMIndividualizeStatus
{
HRESULT hr;
DRM_INDIVIDUALIZATION_STATUS enIndiStatus;
LPSTR pszIndiRespUrl;
DWORD dwHTTPRequest;
DRM_HTTP_STATUS enHTTPStatus;
DWORD dwHTTPReadProgress;
DWORD dwHTTPReadTotal;
} WM_INDIVIDUALIZE_STATUS;
typedef struct _WMGetLicenseData
{
DWORD dwSize;
HRESULT hr;
WCHAR *wszURL;
WCHAR *wszLocalFilename;
BYTE *pbPostData;
DWORD dwPostDataSize;
} WM_GET_LICENSE_DATA;
extern RPC_IF_HANDLE __MIDL_itf_drmexternals_0000_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_drmexternals_0000_v0_0_s_ifspec;
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,947 @@
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 6.00.0361 */
/* Compiler settings for wmsbuffer.idl:
Oicf, W1, Zp8, env=Win32 (32b run)
protocol : dce , ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING( )
#pragma warning( disable: 4049 ) /* more than 64k source lines */
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__
#ifndef COM_NO_WINDOWS_H
#include "windows.h"
#include "ole2.h"
#endif /*COM_NO_WINDOWS_H*/
#ifndef __wmsbuffer_h__
#define __wmsbuffer_h__
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
/* Forward Declarations */
#ifndef __INSSBuffer_FWD_DEFINED__
#define __INSSBuffer_FWD_DEFINED__
typedef interface INSSBuffer INSSBuffer;
#endif /* __INSSBuffer_FWD_DEFINED__ */
#ifndef __INSSBuffer2_FWD_DEFINED__
#define __INSSBuffer2_FWD_DEFINED__
typedef interface INSSBuffer2 INSSBuffer2;
#endif /* __INSSBuffer2_FWD_DEFINED__ */
#ifndef __INSSBuffer3_FWD_DEFINED__
#define __INSSBuffer3_FWD_DEFINED__
typedef interface INSSBuffer3 INSSBuffer3;
#endif /* __INSSBuffer3_FWD_DEFINED__ */
#ifndef __INSSBuffer4_FWD_DEFINED__
#define __INSSBuffer4_FWD_DEFINED__
typedef interface INSSBuffer4 INSSBuffer4;
#endif /* __INSSBuffer4_FWD_DEFINED__ */
#ifndef __IWMSBufferAllocator_FWD_DEFINED__
#define __IWMSBufferAllocator_FWD_DEFINED__
typedef interface IWMSBufferAllocator IWMSBufferAllocator;
#endif /* __IWMSBufferAllocator_FWD_DEFINED__ */
/* header files for imported files */
#include "objidl.h"
#ifdef __cplusplus
extern "C"{
#endif
void * __RPC_USER MIDL_user_allocate(size_t);
void __RPC_USER MIDL_user_free( void * );
/* interface __MIDL_itf_wmsbuffer_0000 */
/* [local] */
//=========================================================================
//
// Microsoft Windows Media Technologies
// Copyright (C) Microsoft Corporation. All Rights Reserved.
//
//=========================================================================
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
EXTERN_GUID( IID_INSSBuffer, 0xE1CD3524,0x03D7,0x11d2,0x9E,0xED,0x00,0x60,0x97,0xD2,0xD7,0xCF );
EXTERN_GUID( IID_IWMSBuffer, 0xE1CD3524,0x03D7,0x11d2,0x9E,0xED,0x00,0x60,0x97,0xD2,0xD7,0xCF );
EXTERN_GUID( IID_INSSBuffer2,0x4f528693,0x1035,0x43fe,0xb4,0x28,0x75,0x75,0x61,0xad,0x3a,0x68 );
EXTERN_GUID( IID_INSSBuffer3,0xc87ceaaf,0x75be,0x4bc4,0x84,0xeb,0xac,0x27,0x98,0x50,0x76,0x72 );
EXTERN_GUID( IID_INSSBuffer4,0xb6b8fd5a,0x32e2,0x49d4,0xa9,0x10,0xc2,0x6c,0xc8,0x54,0x65,0xed );
EXTERN_GUID( IID_IWMSBufferAllocator, 0x61103CA4,0x2033,0x11d2,0x9E,0xF1,0x00,0x60,0x97,0xD2,0xD7,0xCF );
#define IWMSBuffer INSSBuffer
extern RPC_IF_HANDLE __MIDL_itf_wmsbuffer_0000_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_wmsbuffer_0000_v0_0_s_ifspec;
#ifndef __INSSBuffer_INTERFACE_DEFINED__
#define __INSSBuffer_INTERFACE_DEFINED__
/* interface INSSBuffer */
/* [version][uuid][unique][object][local] */
EXTERN_C const IID IID_INSSBuffer;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("E1CD3524-03D7-11d2-9EED-006097D2D7CF")
INSSBuffer : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetLength(
/* [out] */ DWORD *pdwLength) = 0;
virtual HRESULT STDMETHODCALLTYPE SetLength(
/* [in] */ DWORD dwLength) = 0;
virtual HRESULT STDMETHODCALLTYPE GetMaxLength(
/* [out] */ DWORD *pdwLength) = 0;
virtual HRESULT STDMETHODCALLTYPE GetBuffer(
/* [out] */ BYTE **ppdwBuffer) = 0;
virtual HRESULT STDMETHODCALLTYPE GetBufferAndLength(
/* [out] */ BYTE **ppdwBuffer,
/* [out] */ DWORD *pdwLength) = 0;
};
#else /* C style interface */
typedef struct INSSBufferVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
INSSBuffer * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
INSSBuffer * This);
ULONG ( STDMETHODCALLTYPE *Release )(
INSSBuffer * This);
HRESULT ( STDMETHODCALLTYPE *GetLength )(
INSSBuffer * This,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *SetLength )(
INSSBuffer * This,
/* [in] */ DWORD dwLength);
HRESULT ( STDMETHODCALLTYPE *GetMaxLength )(
INSSBuffer * This,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *GetBuffer )(
INSSBuffer * This,
/* [out] */ BYTE **ppdwBuffer);
HRESULT ( STDMETHODCALLTYPE *GetBufferAndLength )(
INSSBuffer * This,
/* [out] */ BYTE **ppdwBuffer,
/* [out] */ DWORD *pdwLength);
END_INTERFACE
} INSSBufferVtbl;
interface INSSBuffer
{
CONST_VTBL struct INSSBufferVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define INSSBuffer_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define INSSBuffer_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define INSSBuffer_Release(This) \
(This)->lpVtbl -> Release(This)
#define INSSBuffer_GetLength(This,pdwLength) \
(This)->lpVtbl -> GetLength(This,pdwLength)
#define INSSBuffer_SetLength(This,dwLength) \
(This)->lpVtbl -> SetLength(This,dwLength)
#define INSSBuffer_GetMaxLength(This,pdwLength) \
(This)->lpVtbl -> GetMaxLength(This,pdwLength)
#define INSSBuffer_GetBuffer(This,ppdwBuffer) \
(This)->lpVtbl -> GetBuffer(This,ppdwBuffer)
#define INSSBuffer_GetBufferAndLength(This,ppdwBuffer,pdwLength) \
(This)->lpVtbl -> GetBufferAndLength(This,ppdwBuffer,pdwLength)
#endif /* COBJMACROS */
#endif /* C style interface */
HRESULT STDMETHODCALLTYPE INSSBuffer_GetLength_Proxy(
INSSBuffer * This,
/* [out] */ DWORD *pdwLength);
void __RPC_STUB INSSBuffer_GetLength_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
HRESULT STDMETHODCALLTYPE INSSBuffer_SetLength_Proxy(
INSSBuffer * This,
/* [in] */ DWORD dwLength);
void __RPC_STUB INSSBuffer_SetLength_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
HRESULT STDMETHODCALLTYPE INSSBuffer_GetMaxLength_Proxy(
INSSBuffer * This,
/* [out] */ DWORD *pdwLength);
void __RPC_STUB INSSBuffer_GetMaxLength_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
HRESULT STDMETHODCALLTYPE INSSBuffer_GetBuffer_Proxy(
INSSBuffer * This,
/* [out] */ BYTE **ppdwBuffer);
void __RPC_STUB INSSBuffer_GetBuffer_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
HRESULT STDMETHODCALLTYPE INSSBuffer_GetBufferAndLength_Proxy(
INSSBuffer * This,
/* [out] */ BYTE **ppdwBuffer,
/* [out] */ DWORD *pdwLength);
void __RPC_STUB INSSBuffer_GetBufferAndLength_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __INSSBuffer_INTERFACE_DEFINED__ */
#ifndef __INSSBuffer2_INTERFACE_DEFINED__
#define __INSSBuffer2_INTERFACE_DEFINED__
/* interface INSSBuffer2 */
/* [version][uuid][unique][object][local] */
EXTERN_C const IID IID_INSSBuffer2;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("4F528693-1035-43fe-B428-757561AD3A68")
INSSBuffer2 : public INSSBuffer
{
public:
virtual HRESULT STDMETHODCALLTYPE GetSampleProperties(
/* [in] */ DWORD cbProperties,
/* [out] */ BYTE *pbProperties) = 0;
virtual HRESULT STDMETHODCALLTYPE SetSampleProperties(
/* [in] */ DWORD cbProperties,
/* [in] */ BYTE *pbProperties) = 0;
};
#else /* C style interface */
typedef struct INSSBuffer2Vtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
INSSBuffer2 * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
INSSBuffer2 * This);
ULONG ( STDMETHODCALLTYPE *Release )(
INSSBuffer2 * This);
HRESULT ( STDMETHODCALLTYPE *GetLength )(
INSSBuffer2 * This,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *SetLength )(
INSSBuffer2 * This,
/* [in] */ DWORD dwLength);
HRESULT ( STDMETHODCALLTYPE *GetMaxLength )(
INSSBuffer2 * This,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *GetBuffer )(
INSSBuffer2 * This,
/* [out] */ BYTE **ppdwBuffer);
HRESULT ( STDMETHODCALLTYPE *GetBufferAndLength )(
INSSBuffer2 * This,
/* [out] */ BYTE **ppdwBuffer,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *GetSampleProperties )(
INSSBuffer2 * This,
/* [in] */ DWORD cbProperties,
/* [out] */ BYTE *pbProperties);
HRESULT ( STDMETHODCALLTYPE *SetSampleProperties )(
INSSBuffer2 * This,
/* [in] */ DWORD cbProperties,
/* [in] */ BYTE *pbProperties);
END_INTERFACE
} INSSBuffer2Vtbl;
interface INSSBuffer2
{
CONST_VTBL struct INSSBuffer2Vtbl *lpVtbl;
};
#ifdef COBJMACROS
#define INSSBuffer2_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define INSSBuffer2_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define INSSBuffer2_Release(This) \
(This)->lpVtbl -> Release(This)
#define INSSBuffer2_GetLength(This,pdwLength) \
(This)->lpVtbl -> GetLength(This,pdwLength)
#define INSSBuffer2_SetLength(This,dwLength) \
(This)->lpVtbl -> SetLength(This,dwLength)
#define INSSBuffer2_GetMaxLength(This,pdwLength) \
(This)->lpVtbl -> GetMaxLength(This,pdwLength)
#define INSSBuffer2_GetBuffer(This,ppdwBuffer) \
(This)->lpVtbl -> GetBuffer(This,ppdwBuffer)
#define INSSBuffer2_GetBufferAndLength(This,ppdwBuffer,pdwLength) \
(This)->lpVtbl -> GetBufferAndLength(This,ppdwBuffer,pdwLength)
#define INSSBuffer2_GetSampleProperties(This,cbProperties,pbProperties) \
(This)->lpVtbl -> GetSampleProperties(This,cbProperties,pbProperties)
#define INSSBuffer2_SetSampleProperties(This,cbProperties,pbProperties) \
(This)->lpVtbl -> SetSampleProperties(This,cbProperties,pbProperties)
#endif /* COBJMACROS */
#endif /* C style interface */
HRESULT STDMETHODCALLTYPE INSSBuffer2_GetSampleProperties_Proxy(
INSSBuffer2 * This,
/* [in] */ DWORD cbProperties,
/* [out] */ BYTE *pbProperties);
void __RPC_STUB INSSBuffer2_GetSampleProperties_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
HRESULT STDMETHODCALLTYPE INSSBuffer2_SetSampleProperties_Proxy(
INSSBuffer2 * This,
/* [in] */ DWORD cbProperties,
/* [in] */ BYTE *pbProperties);
void __RPC_STUB INSSBuffer2_SetSampleProperties_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __INSSBuffer2_INTERFACE_DEFINED__ */
#ifndef __INSSBuffer3_INTERFACE_DEFINED__
#define __INSSBuffer3_INTERFACE_DEFINED__
/* interface INSSBuffer3 */
/* [version][uuid][unique][object][local] */
EXTERN_C const IID IID_INSSBuffer3;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("C87CEAAF-75BE-4bc4-84EB-AC2798507672")
INSSBuffer3 : public INSSBuffer2
{
public:
virtual HRESULT STDMETHODCALLTYPE SetProperty(
/* [in] */ GUID guidBufferProperty,
/* [in] */ void *pvBufferProperty,
/* [in] */ DWORD dwBufferPropertySize) = 0;
virtual HRESULT STDMETHODCALLTYPE GetProperty(
/* [in] */ GUID guidBufferProperty,
/* [out] */ void *pvBufferProperty,
/* [out][in] */ DWORD *pdwBufferPropertySize) = 0;
};
#else /* C style interface */
typedef struct INSSBuffer3Vtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
INSSBuffer3 * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
INSSBuffer3 * This);
ULONG ( STDMETHODCALLTYPE *Release )(
INSSBuffer3 * This);
HRESULT ( STDMETHODCALLTYPE *GetLength )(
INSSBuffer3 * This,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *SetLength )(
INSSBuffer3 * This,
/* [in] */ DWORD dwLength);
HRESULT ( STDMETHODCALLTYPE *GetMaxLength )(
INSSBuffer3 * This,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *GetBuffer )(
INSSBuffer3 * This,
/* [out] */ BYTE **ppdwBuffer);
HRESULT ( STDMETHODCALLTYPE *GetBufferAndLength )(
INSSBuffer3 * This,
/* [out] */ BYTE **ppdwBuffer,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *GetSampleProperties )(
INSSBuffer3 * This,
/* [in] */ DWORD cbProperties,
/* [out] */ BYTE *pbProperties);
HRESULT ( STDMETHODCALLTYPE *SetSampleProperties )(
INSSBuffer3 * This,
/* [in] */ DWORD cbProperties,
/* [in] */ BYTE *pbProperties);
HRESULT ( STDMETHODCALLTYPE *SetProperty )(
INSSBuffer3 * This,
/* [in] */ GUID guidBufferProperty,
/* [in] */ void *pvBufferProperty,
/* [in] */ DWORD dwBufferPropertySize);
HRESULT ( STDMETHODCALLTYPE *GetProperty )(
INSSBuffer3 * This,
/* [in] */ GUID guidBufferProperty,
/* [out] */ void *pvBufferProperty,
/* [out][in] */ DWORD *pdwBufferPropertySize);
END_INTERFACE
} INSSBuffer3Vtbl;
interface INSSBuffer3
{
CONST_VTBL struct INSSBuffer3Vtbl *lpVtbl;
};
#ifdef COBJMACROS
#define INSSBuffer3_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define INSSBuffer3_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define INSSBuffer3_Release(This) \
(This)->lpVtbl -> Release(This)
#define INSSBuffer3_GetLength(This,pdwLength) \
(This)->lpVtbl -> GetLength(This,pdwLength)
#define INSSBuffer3_SetLength(This,dwLength) \
(This)->lpVtbl -> SetLength(This,dwLength)
#define INSSBuffer3_GetMaxLength(This,pdwLength) \
(This)->lpVtbl -> GetMaxLength(This,pdwLength)
#define INSSBuffer3_GetBuffer(This,ppdwBuffer) \
(This)->lpVtbl -> GetBuffer(This,ppdwBuffer)
#define INSSBuffer3_GetBufferAndLength(This,ppdwBuffer,pdwLength) \
(This)->lpVtbl -> GetBufferAndLength(This,ppdwBuffer,pdwLength)
#define INSSBuffer3_GetSampleProperties(This,cbProperties,pbProperties) \
(This)->lpVtbl -> GetSampleProperties(This,cbProperties,pbProperties)
#define INSSBuffer3_SetSampleProperties(This,cbProperties,pbProperties) \
(This)->lpVtbl -> SetSampleProperties(This,cbProperties,pbProperties)
#define INSSBuffer3_SetProperty(This,guidBufferProperty,pvBufferProperty,dwBufferPropertySize) \
(This)->lpVtbl -> SetProperty(This,guidBufferProperty,pvBufferProperty,dwBufferPropertySize)
#define INSSBuffer3_GetProperty(This,guidBufferProperty,pvBufferProperty,pdwBufferPropertySize) \
(This)->lpVtbl -> GetProperty(This,guidBufferProperty,pvBufferProperty,pdwBufferPropertySize)
#endif /* COBJMACROS */
#endif /* C style interface */
HRESULT STDMETHODCALLTYPE INSSBuffer3_SetProperty_Proxy(
INSSBuffer3 * This,
/* [in] */ GUID guidBufferProperty,
/* [in] */ void *pvBufferProperty,
/* [in] */ DWORD dwBufferPropertySize);
void __RPC_STUB INSSBuffer3_SetProperty_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
HRESULT STDMETHODCALLTYPE INSSBuffer3_GetProperty_Proxy(
INSSBuffer3 * This,
/* [in] */ GUID guidBufferProperty,
/* [out] */ void *pvBufferProperty,
/* [out][in] */ DWORD *pdwBufferPropertySize);
void __RPC_STUB INSSBuffer3_GetProperty_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __INSSBuffer3_INTERFACE_DEFINED__ */
#ifndef __INSSBuffer4_INTERFACE_DEFINED__
#define __INSSBuffer4_INTERFACE_DEFINED__
/* interface INSSBuffer4 */
/* [version][uuid][unique][object][local] */
EXTERN_C const IID IID_INSSBuffer4;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("B6B8FD5A-32E2-49d4-A910-C26CC85465ED")
INSSBuffer4 : public INSSBuffer3
{
public:
virtual HRESULT STDMETHODCALLTYPE GetPropertyCount(
/* [out] */ DWORD *pcBufferProperties) = 0;
virtual HRESULT STDMETHODCALLTYPE GetPropertyByIndex(
/* [in] */ DWORD dwBufferPropertyIndex,
/* [out] */ GUID *pguidBufferProperty,
/* [out] */ void *pvBufferProperty,
/* [out][in] */ DWORD *pdwBufferPropertySize) = 0;
};
#else /* C style interface */
typedef struct INSSBuffer4Vtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
INSSBuffer4 * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
INSSBuffer4 * This);
ULONG ( STDMETHODCALLTYPE *Release )(
INSSBuffer4 * This);
HRESULT ( STDMETHODCALLTYPE *GetLength )(
INSSBuffer4 * This,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *SetLength )(
INSSBuffer4 * This,
/* [in] */ DWORD dwLength);
HRESULT ( STDMETHODCALLTYPE *GetMaxLength )(
INSSBuffer4 * This,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *GetBuffer )(
INSSBuffer4 * This,
/* [out] */ BYTE **ppdwBuffer);
HRESULT ( STDMETHODCALLTYPE *GetBufferAndLength )(
INSSBuffer4 * This,
/* [out] */ BYTE **ppdwBuffer,
/* [out] */ DWORD *pdwLength);
HRESULT ( STDMETHODCALLTYPE *GetSampleProperties )(
INSSBuffer4 * This,
/* [in] */ DWORD cbProperties,
/* [out] */ BYTE *pbProperties);
HRESULT ( STDMETHODCALLTYPE *SetSampleProperties )(
INSSBuffer4 * This,
/* [in] */ DWORD cbProperties,
/* [in] */ BYTE *pbProperties);
HRESULT ( STDMETHODCALLTYPE *SetProperty )(
INSSBuffer4 * This,
/* [in] */ GUID guidBufferProperty,
/* [in] */ void *pvBufferProperty,
/* [in] */ DWORD dwBufferPropertySize);
HRESULT ( STDMETHODCALLTYPE *GetProperty )(
INSSBuffer4 * This,
/* [in] */ GUID guidBufferProperty,
/* [out] */ void *pvBufferProperty,
/* [out][in] */ DWORD *pdwBufferPropertySize);
HRESULT ( STDMETHODCALLTYPE *GetPropertyCount )(
INSSBuffer4 * This,
/* [out] */ DWORD *pcBufferProperties);
HRESULT ( STDMETHODCALLTYPE *GetPropertyByIndex )(
INSSBuffer4 * This,
/* [in] */ DWORD dwBufferPropertyIndex,
/* [out] */ GUID *pguidBufferProperty,
/* [out] */ void *pvBufferProperty,
/* [out][in] */ DWORD *pdwBufferPropertySize);
END_INTERFACE
} INSSBuffer4Vtbl;
interface INSSBuffer4
{
CONST_VTBL struct INSSBuffer4Vtbl *lpVtbl;
};
#ifdef COBJMACROS
#define INSSBuffer4_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define INSSBuffer4_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define INSSBuffer4_Release(This) \
(This)->lpVtbl -> Release(This)
#define INSSBuffer4_GetLength(This,pdwLength) \
(This)->lpVtbl -> GetLength(This,pdwLength)
#define INSSBuffer4_SetLength(This,dwLength) \
(This)->lpVtbl -> SetLength(This,dwLength)
#define INSSBuffer4_GetMaxLength(This,pdwLength) \
(This)->lpVtbl -> GetMaxLength(This,pdwLength)
#define INSSBuffer4_GetBuffer(This,ppdwBuffer) \
(This)->lpVtbl -> GetBuffer(This,ppdwBuffer)
#define INSSBuffer4_GetBufferAndLength(This,ppdwBuffer,pdwLength) \
(This)->lpVtbl -> GetBufferAndLength(This,ppdwBuffer,pdwLength)
#define INSSBuffer4_GetSampleProperties(This,cbProperties,pbProperties) \
(This)->lpVtbl -> GetSampleProperties(This,cbProperties,pbProperties)
#define INSSBuffer4_SetSampleProperties(This,cbProperties,pbProperties) \
(This)->lpVtbl -> SetSampleProperties(This,cbProperties,pbProperties)
#define INSSBuffer4_SetProperty(This,guidBufferProperty,pvBufferProperty,dwBufferPropertySize) \
(This)->lpVtbl -> SetProperty(This,guidBufferProperty,pvBufferProperty,dwBufferPropertySize)
#define INSSBuffer4_GetProperty(This,guidBufferProperty,pvBufferProperty,pdwBufferPropertySize) \
(This)->lpVtbl -> GetProperty(This,guidBufferProperty,pvBufferProperty,pdwBufferPropertySize)
#define INSSBuffer4_GetPropertyCount(This,pcBufferProperties) \
(This)->lpVtbl -> GetPropertyCount(This,pcBufferProperties)
#define INSSBuffer4_GetPropertyByIndex(This,dwBufferPropertyIndex,pguidBufferProperty,pvBufferProperty,pdwBufferPropertySize) \
(This)->lpVtbl -> GetPropertyByIndex(This,dwBufferPropertyIndex,pguidBufferProperty,pvBufferProperty,pdwBufferPropertySize)
#endif /* COBJMACROS */
#endif /* C style interface */
HRESULT STDMETHODCALLTYPE INSSBuffer4_GetPropertyCount_Proxy(
INSSBuffer4 * This,
/* [out] */ DWORD *pcBufferProperties);
void __RPC_STUB INSSBuffer4_GetPropertyCount_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
HRESULT STDMETHODCALLTYPE INSSBuffer4_GetPropertyByIndex_Proxy(
INSSBuffer4 * This,
/* [in] */ DWORD dwBufferPropertyIndex,
/* [out] */ GUID *pguidBufferProperty,
/* [out] */ void *pvBufferProperty,
/* [out][in] */ DWORD *pdwBufferPropertySize);
void __RPC_STUB INSSBuffer4_GetPropertyByIndex_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __INSSBuffer4_INTERFACE_DEFINED__ */
#ifndef __IWMSBufferAllocator_INTERFACE_DEFINED__
#define __IWMSBufferAllocator_INTERFACE_DEFINED__
/* interface IWMSBufferAllocator */
/* [version][uuid][unique][object][local] */
EXTERN_C const IID IID_IWMSBufferAllocator;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("61103CA4-2033-11d2-9EF1-006097D2D7CF")
IWMSBufferAllocator : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE AllocateBuffer(
/* [in] */ DWORD dwMaxBufferSize,
/* [out] */ INSSBuffer **ppBuffer) = 0;
virtual HRESULT STDMETHODCALLTYPE AllocatePageSizeBuffer(
/* [in] */ DWORD dwMaxBufferSize,
/* [out] */ INSSBuffer **ppBuffer) = 0;
};
#else /* C style interface */
typedef struct IWMSBufferAllocatorVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IWMSBufferAllocator * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IWMSBufferAllocator * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IWMSBufferAllocator * This);
HRESULT ( STDMETHODCALLTYPE *AllocateBuffer )(
IWMSBufferAllocator * This,
/* [in] */ DWORD dwMaxBufferSize,
/* [out] */ INSSBuffer **ppBuffer);
HRESULT ( STDMETHODCALLTYPE *AllocatePageSizeBuffer )(
IWMSBufferAllocator * This,
/* [in] */ DWORD dwMaxBufferSize,
/* [out] */ INSSBuffer **ppBuffer);
END_INTERFACE
} IWMSBufferAllocatorVtbl;
interface IWMSBufferAllocator
{
CONST_VTBL struct IWMSBufferAllocatorVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IWMSBufferAllocator_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IWMSBufferAllocator_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define IWMSBufferAllocator_Release(This) \
(This)->lpVtbl -> Release(This)
#define IWMSBufferAllocator_AllocateBuffer(This,dwMaxBufferSize,ppBuffer) \
(This)->lpVtbl -> AllocateBuffer(This,dwMaxBufferSize,ppBuffer)
#define IWMSBufferAllocator_AllocatePageSizeBuffer(This,dwMaxBufferSize,ppBuffer) \
(This)->lpVtbl -> AllocatePageSizeBuffer(This,dwMaxBufferSize,ppBuffer)
#endif /* COBJMACROS */
#endif /* C style interface */
HRESULT STDMETHODCALLTYPE IWMSBufferAllocator_AllocateBuffer_Proxy(
IWMSBufferAllocator * This,
/* [in] */ DWORD dwMaxBufferSize,
/* [out] */ INSSBuffer **ppBuffer);
void __RPC_STUB IWMSBufferAllocator_AllocateBuffer_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
HRESULT STDMETHODCALLTYPE IWMSBufferAllocator_AllocatePageSizeBuffer_Proxy(
IWMSBufferAllocator * This,
/* [in] */ DWORD dwMaxBufferSize,
/* [out] */ INSSBuffer **ppBuffer);
void __RPC_STUB IWMSBufferAllocator_AllocatePageSizeBuffer_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __IWMSBufferAllocator_INTERFACE_DEFINED__ */
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,12 @@
//*@@@+++@@@@******************************************************************
//
// Microsoft Windows Media
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//*@@@---@@@@******************************************************************
//
#pragma once
#include <windows.h>
#include "wmsdkidl.h"
#include "asferr.h"
#include "nserror.h"

File diff suppressed because it is too large Load diff

774
fmod/win32/src/AFXRES.H Executable file
View file

@ -0,0 +1,774 @@
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#ifndef __AFXRES_H__
#define __AFXRES_H__
#ifdef RC_INVOKED
#ifndef _INC_WINDOWS
#define _INC_WINDOWS
#include "winres.h" // extract from windows header
#endif
#endif
#ifdef _AFX_MINREBUILD
#pragma component(minrebuild, off)
#endif
#ifdef APSTUDIO_INVOKED
#define APSTUDIO_HIDDEN_SYMBOLS
#endif
/////////////////////////////////////////////////////////////////////////////
// MFC resource types (see Technical note TN024 for implementation details)
#ifndef RC_INVOKED
#define RT_DLGINIT MAKEINTRESOURCE(240)
#define RT_TOOLBAR MAKEINTRESOURCE(241)
#endif
/////////////////////////////////////////////////////////////////////////////
#ifdef APSTUDIO_INVOKED
#undef APSTUDIO_HIDDEN_SYMBOLS
#endif
/////////////////////////////////////////////////////////////////////////////
// General style bits etc
// ControlBar styles
#define CBRS_ALIGN_LEFT 0x1000L
#define CBRS_ALIGN_TOP 0x2000L
#define CBRS_ALIGN_RIGHT 0x4000L
#define CBRS_ALIGN_BOTTOM 0x8000L
#define CBRS_ALIGN_ANY 0xF000L
#define CBRS_BORDER_LEFT 0x0100L
#define CBRS_BORDER_TOP 0x0200L
#define CBRS_BORDER_RIGHT 0x0400L
#define CBRS_BORDER_BOTTOM 0x0800L
#define CBRS_BORDER_ANY 0x0F00L
#define CBRS_TOOLTIPS 0x0010L
#define CBRS_FLYBY 0x0020L
#define CBRS_FLOAT_MULTI 0x0040L
#define CBRS_BORDER_3D 0x0080L
#define CBRS_HIDE_INPLACE 0x0008L
#define CBRS_SIZE_DYNAMIC 0x0004L
#define CBRS_SIZE_FIXED 0x0002L
#define CBRS_FLOATING 0x0001L
#define CBRS_GRIPPER 0x00400000L
#define CBRS_ORIENT_HORZ (CBRS_ALIGN_TOP|CBRS_ALIGN_BOTTOM)
#define CBRS_ORIENT_VERT (CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT)
#define CBRS_ORIENT_ANY (CBRS_ORIENT_HORZ|CBRS_ORIENT_VERT)
#define CBRS_ALL 0x0040FFFFL
// the CBRS_ style is made up of an alignment style and a draw border style
// the alignment styles are mutually exclusive
// the draw border styles may be combined
#define CBRS_NOALIGN 0x00000000L
#define CBRS_LEFT (CBRS_ALIGN_LEFT|CBRS_BORDER_RIGHT)
#define CBRS_TOP (CBRS_ALIGN_TOP|CBRS_BORDER_BOTTOM)
#define CBRS_RIGHT (CBRS_ALIGN_RIGHT|CBRS_BORDER_LEFT)
#define CBRS_BOTTOM (CBRS_ALIGN_BOTTOM|CBRS_BORDER_TOP)
/////////////////////////////////////////////////////////////////////////////
// Standard window components
// Mode indicators in status bar - these are routed like commands
#define ID_INDICATOR_EXT 0xE700 // extended selection indicator
#define ID_INDICATOR_CAPS 0xE701 // cap lock indicator
#define ID_INDICATOR_NUM 0xE702 // num lock indicator
#define ID_INDICATOR_SCRL 0xE703 // scroll lock indicator
#define ID_INDICATOR_OVR 0xE704 // overtype mode indicator
#define ID_INDICATOR_REC 0xE705 // record mode indicator
#define ID_INDICATOR_KANA 0xE706 // kana lock indicator
#define ID_SEPARATOR 0 // special separator value
#ifndef RC_INVOKED // code only
// Standard control bars (IDW = window ID)
#define AFX_IDW_CONTROLBAR_FIRST 0xE800
#define AFX_IDW_CONTROLBAR_LAST 0xE8FF
#define AFX_IDW_TOOLBAR 0xE800 // main Toolbar for window
#define AFX_IDW_STATUS_BAR 0xE801 // Status bar window
#define AFX_IDW_PREVIEW_BAR 0xE802 // PrintPreview Dialog Bar
#define AFX_IDW_RESIZE_BAR 0xE803 // OLE in-place resize bar
#define AFX_IDW_REBAR 0xE804 // COMCTL32 "rebar" Bar
#define AFX_IDW_DIALOGBAR 0xE805 // CDialogBar
// Note: If your application supports docking toolbars, you should
// not use the following IDs for your own toolbars. The IDs chosen
// are at the top of the first 32 such that the bars will be hidden
// while in print preview mode, and are not likely to conflict with
// IDs your application may have used succesfully in the past.
#define AFX_IDW_DOCKBAR_TOP 0xE81B
#define AFX_IDW_DOCKBAR_LEFT 0xE81C
#define AFX_IDW_DOCKBAR_RIGHT 0xE81D
#define AFX_IDW_DOCKBAR_BOTTOM 0xE81E
#define AFX_IDW_DOCKBAR_FLOAT 0xE81F
// Macro for mapping standard control bars to bitmask (limit of 32)
#define AFX_CONTROLBAR_MASK(nIDC) (1L << (nIDC - AFX_IDW_CONTROLBAR_FIRST))
// parts of Main Frame
#define AFX_IDW_PANE_FIRST 0xE900 // first pane (256 max)
#define AFX_IDW_PANE_LAST 0xE9ff
#define AFX_IDW_HSCROLL_FIRST 0xEA00 // first Horz scrollbar (16 max)
#define AFX_IDW_VSCROLL_FIRST 0xEA10 // first Vert scrollbar (16 max)
#define AFX_IDW_SIZE_BOX 0xEA20 // size box for splitters
#define AFX_IDW_PANE_SAVE 0xEA21 // to shift AFX_IDW_PANE_FIRST
#endif //!RC_INVOKED
#ifndef APSTUDIO_INVOKED
// common style for form views
#define AFX_WS_DEFAULT_VIEW (WS_CHILD | WS_VISIBLE | WS_BORDER)
#endif //!APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
// Standard app configurable strings
// for application title (defaults to EXE name or name in constructor)
#define AFX_IDS_APP_TITLE 0xE000
// idle message bar line
#define AFX_IDS_IDLEMESSAGE 0xE001
// message bar line when in shift-F1 help mode
#define AFX_IDS_HELPMODEMESSAGE 0xE002
// document title when editing OLE embedding
#define AFX_IDS_APP_TITLE_EMBEDDING 0xE003
// company name
#define AFX_IDS_COMPANY_NAME 0xE004
// object name when server is inplace
#define AFX_IDS_OBJ_TITLE_INPLACE 0xE005
/////////////////////////////////////////////////////////////////////////////
// Standard Commands
// File commands
#define ID_FILE_NEW 0xE100
#define ID_FILE_OPEN 0xE101
#define ID_FILE_CLOSE 0xE102
#define ID_FILE_SAVE 0xE103
#define ID_FILE_SAVE_AS 0xE104
#define ID_FILE_PAGE_SETUP 0xE105
#define ID_FILE_PRINT_SETUP 0xE106
#define ID_FILE_PRINT 0xE107
#define ID_FILE_PRINT_DIRECT 0xE108
#define ID_FILE_PRINT_PREVIEW 0xE109
#define ID_FILE_UPDATE 0xE10A
#define ID_FILE_SAVE_COPY_AS 0xE10B
#define ID_FILE_SEND_MAIL 0xE10C
#define ID_FILE_MRU_FIRST 0xE110
#define ID_FILE_MRU_FILE1 0xE110 // range - 16 max
#define ID_FILE_MRU_FILE2 0xE111
#define ID_FILE_MRU_FILE3 0xE112
#define ID_FILE_MRU_FILE4 0xE113
#define ID_FILE_MRU_FILE5 0xE114
#define ID_FILE_MRU_FILE6 0xE115
#define ID_FILE_MRU_FILE7 0xE116
#define ID_FILE_MRU_FILE8 0xE117
#define ID_FILE_MRU_FILE9 0xE118
#define ID_FILE_MRU_FILE10 0xE119
#define ID_FILE_MRU_FILE11 0xE11A
#define ID_FILE_MRU_FILE12 0xE11B
#define ID_FILE_MRU_FILE13 0xE11C
#define ID_FILE_MRU_FILE14 0xE11D
#define ID_FILE_MRU_FILE15 0xE11E
#define ID_FILE_MRU_FILE16 0xE11F
#define ID_FILE_MRU_LAST 0xE11F
// Edit commands
#define ID_EDIT_CLEAR 0xE120
#define ID_EDIT_CLEAR_ALL 0xE121
#define ID_EDIT_COPY 0xE122
#define ID_EDIT_CUT 0xE123
#define ID_EDIT_FIND 0xE124
#define ID_EDIT_PASTE 0xE125
#define ID_EDIT_PASTE_LINK 0xE126
#define ID_EDIT_PASTE_SPECIAL 0xE127
#define ID_EDIT_REPEAT 0xE128
#define ID_EDIT_REPLACE 0xE129
#define ID_EDIT_SELECT_ALL 0xE12A
#define ID_EDIT_UNDO 0xE12B
#define ID_EDIT_REDO 0xE12C
// Window commands
#define ID_WINDOW_NEW 0xE130
#define ID_WINDOW_ARRANGE 0xE131
#define ID_WINDOW_CASCADE 0xE132
#define ID_WINDOW_TILE_HORZ 0xE133
#define ID_WINDOW_TILE_VERT 0xE134
#define ID_WINDOW_SPLIT 0xE135
#ifndef RC_INVOKED // code only
#define AFX_IDM_WINDOW_FIRST 0xE130
#define AFX_IDM_WINDOW_LAST 0xE13F
#define AFX_IDM_FIRST_MDICHILD 0xFF00 // window list starts here
#endif //!RC_INVOKED
// Help and App commands
#define ID_APP_ABOUT 0xE140
#define ID_APP_EXIT 0xE141
#define ID_HELP_INDEX 0xE142
#define ID_HELP_FINDER 0xE143
#define ID_HELP_USING 0xE144
#define ID_CONTEXT_HELP 0xE145 // shift-F1
// special commands for processing help
#define ID_HELP 0xE146 // first attempt for F1
#define ID_DEFAULT_HELP 0xE147 // last attempt
// Misc
#define ID_NEXT_PANE 0xE150
#define ID_PREV_PANE 0xE151
// Format
#define ID_FORMAT_FONT 0xE160
// OLE commands
#define ID_OLE_INSERT_NEW 0xE200
#define ID_OLE_EDIT_LINKS 0xE201
#define ID_OLE_EDIT_CONVERT 0xE202
#define ID_OLE_EDIT_CHANGE_ICON 0xE203
#define ID_OLE_EDIT_PROPERTIES 0xE204
#define ID_OLE_VERB_FIRST 0xE210 // range - 16 max
#ifndef RC_INVOKED // code only
#define ID_OLE_VERB_LAST 0xE21F
#endif //!RC_INVOKED
// for print preview dialog bar
#define AFX_ID_PREVIEW_CLOSE 0xE300
#define AFX_ID_PREVIEW_NUMPAGE 0xE301 // One/Two Page button
#define AFX_ID_PREVIEW_NEXT 0xE302
#define AFX_ID_PREVIEW_PREV 0xE303
#define AFX_ID_PREVIEW_PRINT 0xE304
#define AFX_ID_PREVIEW_ZOOMIN 0xE305
#define AFX_ID_PREVIEW_ZOOMOUT 0xE306
// View commands (same number used as IDW used for control bar)
#define ID_VIEW_TOOLBAR 0xE800
#define ID_VIEW_STATUS_BAR 0xE801
#define ID_VIEW_REBAR 0xE804
#define ID_VIEW_AUTOARRANGE 0xE805
// E810 -> E81F must be kept in order for RANGE macros
#define ID_VIEW_SMALLICON 0xE810
#define ID_VIEW_LARGEICON 0xE811
#define ID_VIEW_LIST 0xE812
#define ID_VIEW_DETAILS 0xE813
#define ID_VIEW_LINEUP 0xE814
#define ID_VIEW_BYNAME 0xE815
#define AFX_ID_VIEW_MINIMUM ID_VIEW_SMALLICON
#define AFX_ID_VIEW_MAXIMUM ID_VIEW_BYNAME
// E800 -> E8FF reserved for other control bar commands
// RecordForm commands
#define ID_RECORD_FIRST 0xE900
#define ID_RECORD_LAST 0xE901
#define ID_RECORD_NEXT 0xE902
#define ID_RECORD_PREV 0xE903
/////////////////////////////////////////////////////////////////////////////
// Standard control IDs
#ifdef IDC_STATIC
#undef IDC_STATIC
#endif
#define IDC_STATIC (-1) // all static controls
/////////////////////////////////////////////////////////////////////////////
// Standard string error/warnings
#ifndef RC_INVOKED // code only
#define AFX_IDS_SCFIRST 0xEF00
#endif //!RC_INVOKED
#define AFX_IDS_SCSIZE 0xEF00
#define AFX_IDS_SCMOVE 0xEF01
#define AFX_IDS_SCMINIMIZE 0xEF02
#define AFX_IDS_SCMAXIMIZE 0xEF03
#define AFX_IDS_SCNEXTWINDOW 0xEF04
#define AFX_IDS_SCPREVWINDOW 0xEF05
#define AFX_IDS_SCCLOSE 0xEF06
#define AFX_IDS_SCRESTORE 0xEF12
#define AFX_IDS_SCTASKLIST 0xEF13
#define AFX_IDS_MDICHILD 0xEF1F
#define AFX_IDS_DESKACCESSORY 0xEFDA
// General strings
#define AFX_IDS_OPENFILE 0xF000
#define AFX_IDS_SAVEFILE 0xF001
#define AFX_IDS_ALLFILTER 0xF002
#define AFX_IDS_UNTITLED 0xF003
#define AFX_IDS_SAVEFILECOPY 0xF004
#define AFX_IDS_PREVIEW_CLOSE 0xF005
#define AFX_IDS_UNNAMED_FILE 0xF006
#define AFX_IDS_HIDE 0xF011
// MFC Standard Exception Error messages
#define AFX_IDP_NO_ERROR_AVAILABLE 0xF020
#define AFX_IDS_NOT_SUPPORTED_EXCEPTION 0xF021
#define AFX_IDS_RESOURCE_EXCEPTION 0xF022
#define AFX_IDS_MEMORY_EXCEPTION 0xF023
#define AFX_IDS_USER_EXCEPTION 0xF024
// Printing and print preview strings
#define AFX_IDS_PRINTONPORT 0xF040
#define AFX_IDS_ONEPAGE 0xF041
#define AFX_IDS_TWOPAGE 0xF042
#define AFX_IDS_PRINTPAGENUM 0xF043
#define AFX_IDS_PREVIEWPAGEDESC 0xF044
#define AFX_IDS_PRINTDEFAULTEXT 0xF045
#define AFX_IDS_PRINTDEFAULT 0xF046
#define AFX_IDS_PRINTFILTER 0xF047
#define AFX_IDS_PRINTCAPTION 0xF048
#define AFX_IDS_PRINTTOFILE 0xF049
// OLE strings
#define AFX_IDS_OBJECT_MENUITEM 0xF080
#define AFX_IDS_EDIT_VERB 0xF081
#define AFX_IDS_ACTIVATE_VERB 0xF082
#define AFX_IDS_CHANGE_LINK 0xF083
#define AFX_IDS_AUTO 0xF084
#define AFX_IDS_MANUAL 0xF085
#define AFX_IDS_FROZEN 0xF086
#define AFX_IDS_ALL_FILES 0xF087
// dynamically changing menu items
#define AFX_IDS_SAVE_MENU 0xF088
#define AFX_IDS_UPDATE_MENU 0xF089
#define AFX_IDS_SAVE_AS_MENU 0xF08A
#define AFX_IDS_SAVE_COPY_AS_MENU 0xF08B
#define AFX_IDS_EXIT_MENU 0xF08C
#define AFX_IDS_UPDATING_ITEMS 0xF08D
// COlePasteSpecialDialog defines
#define AFX_IDS_METAFILE_FORMAT 0xF08E
#define AFX_IDS_DIB_FORMAT 0xF08F
#define AFX_IDS_BITMAP_FORMAT 0xF090
#define AFX_IDS_LINKSOURCE_FORMAT 0xF091
#define AFX_IDS_EMBED_FORMAT 0xF092
// other OLE utility strings
#define AFX_IDS_PASTELINKEDTYPE 0xF094
#define AFX_IDS_UNKNOWNTYPE 0xF095
#define AFX_IDS_RTF_FORMAT 0xF096
#define AFX_IDS_TEXT_FORMAT 0xF097
// OLE datatype format error strings
#define AFX_IDS_INVALID_CURRENCY 0xF098
#define AFX_IDS_INVALID_DATETIME 0xF099
#define AFX_IDS_INVALID_DATETIMESPAN 0xF09A
// General error / prompt strings
#define AFX_IDP_INVALID_FILENAME 0xF100
#define AFX_IDP_FAILED_TO_OPEN_DOC 0xF101
#define AFX_IDP_FAILED_TO_SAVE_DOC 0xF102
#define AFX_IDP_ASK_TO_SAVE 0xF103
#define AFX_IDP_FAILED_TO_CREATE_DOC 0xF104
#define AFX_IDP_FILE_TOO_LARGE 0xF105
#define AFX_IDP_FAILED_TO_START_PRINT 0xF106
#define AFX_IDP_FAILED_TO_LAUNCH_HELP 0xF107
#define AFX_IDP_INTERNAL_FAILURE 0xF108 // general failure
#define AFX_IDP_COMMAND_FAILURE 0xF109 // command failure
#define AFX_IDP_FAILED_MEMORY_ALLOC 0xF10A
#define AFX_IDP_UNREG_DONE 0xF10B
#define AFX_IDP_UNREG_FAILURE 0xF10C
#define AFX_IDP_DLL_LOAD_FAILED 0xF10D
#define AFX_IDP_DLL_BAD_VERSION 0xF10E
// DDV parse errors
#define AFX_IDP_PARSE_INT 0xF110
#define AFX_IDP_PARSE_REAL 0xF111
#define AFX_IDP_PARSE_INT_RANGE 0xF112
#define AFX_IDP_PARSE_REAL_RANGE 0xF113
#define AFX_IDP_PARSE_STRING_SIZE 0xF114
#define AFX_IDP_PARSE_RADIO_BUTTON 0xF115
#define AFX_IDP_PARSE_BYTE 0xF116
#define AFX_IDP_PARSE_UINT 0xF117
#define AFX_IDP_PARSE_DATETIME 0xF118
#define AFX_IDP_PARSE_CURRENCY 0xF119
// CFile/CArchive error strings for user failure
#define AFX_IDP_FAILED_INVALID_FORMAT 0xF120
#define AFX_IDP_FAILED_INVALID_PATH 0xF121
#define AFX_IDP_FAILED_DISK_FULL 0xF122
#define AFX_IDP_FAILED_ACCESS_READ 0xF123
#define AFX_IDP_FAILED_ACCESS_WRITE 0xF124
#define AFX_IDP_FAILED_IO_ERROR_READ 0xF125
#define AFX_IDP_FAILED_IO_ERROR_WRITE 0xF126
// OLE errors / prompt strings
#define AFX_IDP_STATIC_OBJECT 0xF180
#define AFX_IDP_FAILED_TO_CONNECT 0xF181
#define AFX_IDP_SERVER_BUSY 0xF182
#define AFX_IDP_BAD_VERB 0xF183
#define AFX_IDS_NOT_DOCOBJECT 0xF184
#define AFX_IDP_FAILED_TO_NOTIFY 0xF185
#define AFX_IDP_FAILED_TO_LAUNCH 0xF186
#define AFX_IDP_ASK_TO_UPDATE 0xF187
#define AFX_IDP_FAILED_TO_UPDATE 0xF188
#define AFX_IDP_FAILED_TO_REGISTER 0xF189
#define AFX_IDP_FAILED_TO_AUTO_REGISTER 0xF18A
#define AFX_IDP_FAILED_TO_CONVERT 0xF18B
#define AFX_IDP_GET_NOT_SUPPORTED 0xF18C
#define AFX_IDP_SET_NOT_SUPPORTED 0xF18D
#define AFX_IDP_ASK_TO_DISCARD 0xF18E
#define AFX_IDP_FAILED_TO_CREATE 0xF18F
// MAPI errors / prompt strings
#define AFX_IDP_FAILED_MAPI_LOAD 0xF190
#define AFX_IDP_INVALID_MAPI_DLL 0xF191
#define AFX_IDP_FAILED_MAPI_SEND 0xF192
#define AFX_IDP_FILE_NONE 0xF1A0
#define AFX_IDP_FILE_GENERIC 0xF1A1
#define AFX_IDP_FILE_NOT_FOUND 0xF1A2
#define AFX_IDP_FILE_BAD_PATH 0xF1A3
#define AFX_IDP_FILE_TOO_MANY_OPEN 0xF1A4
#define AFX_IDP_FILE_ACCESS_DENIED 0xF1A5
#define AFX_IDP_FILE_INVALID_FILE 0xF1A6
#define AFX_IDP_FILE_REMOVE_CURRENT 0xF1A7
#define AFX_IDP_FILE_DIR_FULL 0xF1A8
#define AFX_IDP_FILE_BAD_SEEK 0xF1A9
#define AFX_IDP_FILE_HARD_IO 0xF1AA
#define AFX_IDP_FILE_SHARING 0xF1AB
#define AFX_IDP_FILE_LOCKING 0xF1AC
#define AFX_IDP_FILE_DISKFULL 0xF1AD
#define AFX_IDP_FILE_EOF 0xF1AE
#define AFX_IDP_ARCH_NONE 0xF1B0
#define AFX_IDP_ARCH_GENERIC 0xF1B1
#define AFX_IDP_ARCH_READONLY 0xF1B2
#define AFX_IDP_ARCH_ENDOFFILE 0xF1B3
#define AFX_IDP_ARCH_WRITEONLY 0xF1B4
#define AFX_IDP_ARCH_BADINDEX 0xF1B5
#define AFX_IDP_ARCH_BADCLASS 0xF1B6
#define AFX_IDP_ARCH_BADSCHEMA 0xF1B7
#define AFX_IDS_OCC_SCALEUNITS_PIXELS 0xF1C0
// 0xf200-0xf20f reserved
// font names and point sizes
#define AFX_IDS_STATUS_FONT 0xF230
#define AFX_IDS_TOOLTIP_FONT 0xF231
#define AFX_IDS_UNICODE_FONT 0xF232
#define AFX_IDS_MINI_FONT 0xF233
// ODBC Database errors / prompt strings
#ifndef RC_INVOKED // code only
#define AFX_IDP_SQL_FIRST 0xF280
#endif //!RC_INVOKED
#define AFX_IDP_SQL_CONNECT_FAIL 0xF281
#define AFX_IDP_SQL_RECORDSET_FORWARD_ONLY 0xF282
#define AFX_IDP_SQL_EMPTY_COLUMN_LIST 0xF283
#define AFX_IDP_SQL_FIELD_SCHEMA_MISMATCH 0xF284
#define AFX_IDP_SQL_ILLEGAL_MODE 0xF285
#define AFX_IDP_SQL_MULTIPLE_ROWS_AFFECTED 0xF286
#define AFX_IDP_SQL_NO_CURRENT_RECORD 0xF287
#define AFX_IDP_SQL_NO_ROWS_AFFECTED 0xF288
#define AFX_IDP_SQL_RECORDSET_READONLY 0xF289
#define AFX_IDP_SQL_SQL_NO_TOTAL 0xF28A
#define AFX_IDP_SQL_ODBC_LOAD_FAILED 0xF28B
#define AFX_IDP_SQL_DYNASET_NOT_SUPPORTED 0xF28C
#define AFX_IDP_SQL_SNAPSHOT_NOT_SUPPORTED 0xF28D
#define AFX_IDP_SQL_API_CONFORMANCE 0xF28E
#define AFX_IDP_SQL_SQL_CONFORMANCE 0xF28F
#define AFX_IDP_SQL_NO_DATA_FOUND 0xF290
#define AFX_IDP_SQL_ROW_UPDATE_NOT_SUPPORTED 0xF291
#define AFX_IDP_SQL_ODBC_V2_REQUIRED 0xF292
#define AFX_IDP_SQL_NO_POSITIONED_UPDATES 0xF293
#define AFX_IDP_SQL_LOCK_MODE_NOT_SUPPORTED 0xF294
#define AFX_IDP_SQL_DATA_TRUNCATED 0xF295
#define AFX_IDP_SQL_ROW_FETCH 0xF296
#define AFX_IDP_SQL_INCORRECT_ODBC 0xF297
#define AFX_IDP_SQL_UPDATE_DELETE_FAILED 0xF298
#define AFX_IDP_SQL_DYNAMIC_CURSOR_NOT_SUPPORTED 0xF299
#define AFX_IDP_SQL_FIELD_NOT_FOUND 0xF29A
#define AFX_IDP_SQL_BOOKMARKS_NOT_SUPPORTED 0xF29B
#define AFX_IDP_SQL_BOOKMARKS_NOT_ENABLED 0xF29C
// ODBC Database strings
#define AFX_IDS_DELETED 0xF29D
// DAO Database errors / prompt strings
#ifndef RC_INVOKED // code only
#define AFX_IDP_DAO_FIRST 0xF2B0
#endif //!RC_INVOKED
#define AFX_IDP_DAO_ENGINE_INITIALIZATION 0xF2B0
#define AFX_IDP_DAO_DFX_BIND 0xF2B1
#define AFX_IDP_DAO_OBJECT_NOT_OPEN 0xF2B2
// ICDAORecordset::GetRows Errors
// These are not placed in DAO Errors collection
// and must be handled directly by MFC.
#define AFX_IDP_DAO_ROWTOOSHORT 0xF2B3
#define AFX_IDP_DAO_BADBINDINFO 0xF2B4
#define AFX_IDP_DAO_COLUMNUNAVAILABLE 0xF2B5
/////////////////////////////////////////////////////////////////////////////
// Strings for ISAPI support
#define AFX_IDS_HTTP_TITLE 0xF2D1
#define AFX_IDS_HTTP_NO_TEXT 0xF2D2
#define AFX_IDS_HTTP_BAD_REQUEST 0xF2D3
#define AFX_IDS_HTTP_AUTH_REQUIRED 0xF2D4
#define AFX_IDS_HTTP_FORBIDDEN 0xF2D5
#define AFX_IDS_HTTP_NOT_FOUND 0xF2D6
#define AFX_IDS_HTTP_SERVER_ERROR 0xF2D7
#define AFX_IDS_HTTP_NOT_IMPLEMENTED 0xF2D8
/////////////////////////////////////////////////////////////////////////////
// AFX implementation - control IDs (AFX_IDC)
// Parts of dialogs
#define AFX_IDC_LISTBOX 100
#define AFX_IDC_CHANGE 101
// for print dialog
#define AFX_IDC_PRINT_DOCNAME 201
#define AFX_IDC_PRINT_PRINTERNAME 202
#define AFX_IDC_PRINT_PORTNAME 203
#define AFX_IDC_PRINT_PAGENUM 204
// Property Sheet control id's (determined with Spy++)
#define ID_APPLY_NOW 0x3021
#define ID_WIZBACK 0x3023
#define ID_WIZNEXT 0x3024
#define ID_WIZFINISH 0x3025
#define AFX_IDC_TAB_CONTROL 0x3020
/////////////////////////////////////////////////////////////////////////////
// IDRs for standard components
#ifndef RC_INVOKED // code only
// These are really COMMDLG dialogs, so there usually isn't a resource
// for them, but these IDs are used as help IDs.
#define AFX_IDD_FILEOPEN 28676
#define AFX_IDD_FILESAVE 28677
#define AFX_IDD_FONT 28678
#define AFX_IDD_COLOR 28679
#define AFX_IDD_PRINT 28680
#define AFX_IDD_PRINTSETUP 28681
#define AFX_IDD_FIND 28682
#define AFX_IDD_REPLACE 28683
#endif //!RC_INVOKED
// Standard dialogs app should leave alone (0x7801->)
#define AFX_IDD_NEWTYPEDLG 30721
#define AFX_IDD_PRINTDLG 30722
#define AFX_IDD_PREVIEW_TOOLBAR 30723
// Dialogs defined for OLE2UI library
#define AFX_IDD_INSERTOBJECT 30724
#define AFX_IDD_CHANGEICON 30725
#define AFX_IDD_CONVERT 30726
#define AFX_IDD_PASTESPECIAL 30727
#define AFX_IDD_EDITLINKS 30728
#define AFX_IDD_FILEBROWSE 30729
#define AFX_IDD_BUSY 30730
#define AFX_IDD_OBJECTPROPERTIES 30732
#define AFX_IDD_CHANGESOURCE 30733
// Standard cursors (0x7901->)
// AFX_IDC = Cursor resources
#define AFX_IDC_CONTEXTHELP 30977 // context sensitive help
#define AFX_IDC_MAGNIFY 30978 // print preview zoom
#define AFX_IDC_SMALLARROWS 30979 // splitter
#define AFX_IDC_HSPLITBAR 30980 // splitter
#define AFX_IDC_VSPLITBAR 30981 // splitter
#define AFX_IDC_NODROPCRSR 30982 // No Drop Cursor
#define AFX_IDC_TRACKNWSE 30983 // tracker
#define AFX_IDC_TRACKNESW 30984 // tracker
#define AFX_IDC_TRACKNS 30985 // tracker
#define AFX_IDC_TRACKWE 30986 // tracker
#define AFX_IDC_TRACK4WAY 30987 // tracker
#define AFX_IDC_MOVE4WAY 30988 // resize bar (server only)
// Mini frame window bitmap ID
#define AFX_IDB_MINIFRAME_MENU 30994
// CheckListBox checks bitmap ID
#define AFX_IDB_CHECKLISTBOX_NT 30995
#define AFX_IDB_CHECKLISTBOX_95 30996
// AFX standard accelerator resources
#define AFX_IDR_PREVIEW_ACCEL 30997
// AFX standard ICON IDs (for MFC V1 apps) (0x7A01->)
#define AFX_IDI_STD_MDIFRAME 31233
#define AFX_IDI_STD_FRAME 31234
/////////////////////////////////////////////////////////////////////////////
// AFX OLE control implementation - control IDs (AFX_IDC)
// Font property page
#define AFX_IDC_FONTPROP 1000
#define AFX_IDC_FONTNAMES 1001
#define AFX_IDC_FONTSTYLES 1002
#define AFX_IDC_FONTSIZES 1003
#define AFX_IDC_STRIKEOUT 1004
#define AFX_IDC_UNDERLINE 1005
#define AFX_IDC_SAMPLEBOX 1006
// Color property page
#define AFX_IDC_COLOR_BLACK 1100
#define AFX_IDC_COLOR_WHITE 1101
#define AFX_IDC_COLOR_RED 1102
#define AFX_IDC_COLOR_GREEN 1103
#define AFX_IDC_COLOR_BLUE 1104
#define AFX_IDC_COLOR_YELLOW 1105
#define AFX_IDC_COLOR_MAGENTA 1106
#define AFX_IDC_COLOR_CYAN 1107
#define AFX_IDC_COLOR_GRAY 1108
#define AFX_IDC_COLOR_LIGHTGRAY 1109
#define AFX_IDC_COLOR_DARKRED 1110
#define AFX_IDC_COLOR_DARKGREEN 1111
#define AFX_IDC_COLOR_DARKBLUE 1112
#define AFX_IDC_COLOR_LIGHTBROWN 1113
#define AFX_IDC_COLOR_DARKMAGENTA 1114
#define AFX_IDC_COLOR_DARKCYAN 1115
#define AFX_IDC_COLORPROP 1116
#define AFX_IDC_SYSTEMCOLORS 1117
// Picture porperty page
#define AFX_IDC_PROPNAME 1201
#define AFX_IDC_PICTURE 1202
#define AFX_IDC_BROWSE 1203
#define AFX_IDC_CLEAR 1204
/////////////////////////////////////////////////////////////////////////////
// IDRs for OLE control standard components
// Standard propery page dialogs app should leave alone (0x7E01->)
#define AFX_IDD_PROPPAGE_COLOR 32257
#define AFX_IDD_PROPPAGE_FONT 32258
#define AFX_IDD_PROPPAGE_PICTURE 32259
#define AFX_IDB_TRUETYPE 32384
/////////////////////////////////////////////////////////////////////////////
// Standard OLE control strings
// OLE Control page strings
#define AFX_IDS_PROPPAGE_UNKNOWN 0xFE01
#define AFX_IDS_COLOR_DESKTOP 0xFE04
#define AFX_IDS_COLOR_APPWORKSPACE 0xFE05
#define AFX_IDS_COLOR_WNDBACKGND 0xFE06
#define AFX_IDS_COLOR_WNDTEXT 0xFE07
#define AFX_IDS_COLOR_MENUBAR 0xFE08
#define AFX_IDS_COLOR_MENUTEXT 0xFE09
#define AFX_IDS_COLOR_ACTIVEBAR 0xFE0A
#define AFX_IDS_COLOR_INACTIVEBAR 0xFE0B
#define AFX_IDS_COLOR_ACTIVETEXT 0xFE0C
#define AFX_IDS_COLOR_INACTIVETEXT 0xFE0D
#define AFX_IDS_COLOR_ACTIVEBORDER 0xFE0E
#define AFX_IDS_COLOR_INACTIVEBORDER 0xFE0F
#define AFX_IDS_COLOR_WNDFRAME 0xFE10
#define AFX_IDS_COLOR_SCROLLBARS 0xFE11
#define AFX_IDS_COLOR_BTNFACE 0xFE12
#define AFX_IDS_COLOR_BTNSHADOW 0xFE13
#define AFX_IDS_COLOR_BTNTEXT 0xFE14
#define AFX_IDS_COLOR_BTNHIGHLIGHT 0xFE15
#define AFX_IDS_COLOR_DISABLEDTEXT 0xFE16
#define AFX_IDS_COLOR_HIGHLIGHT 0xFE17
#define AFX_IDS_COLOR_HIGHLIGHTTEXT 0xFE18
#define AFX_IDS_REGULAR 0xFE19
#define AFX_IDS_BOLD 0xFE1A
#define AFX_IDS_ITALIC 0xFE1B
#define AFX_IDS_BOLDITALIC 0xFE1C
#define AFX_IDS_SAMPLETEXT 0xFE1D
#define AFX_IDS_DISPLAYSTRING_FONT 0xFE1E
#define AFX_IDS_DISPLAYSTRING_COLOR 0xFE1F
#define AFX_IDS_DISPLAYSTRING_PICTURE 0xFE20
#define AFX_IDS_PICTUREFILTER 0xFE21
#define AFX_IDS_PICTYPE_UNKNOWN 0xFE22
#define AFX_IDS_PICTYPE_NONE 0xFE23
#define AFX_IDS_PICTYPE_BITMAP 0xFE24
#define AFX_IDS_PICTYPE_METAFILE 0xFE25
#define AFX_IDS_PICTYPE_ICON 0xFE26
#define AFX_IDS_COLOR_PPG 0xFE28
#define AFX_IDS_COLOR_PPG_CAPTION 0xFE29
#define AFX_IDS_FONT_PPG 0xFE2A
#define AFX_IDS_FONT_PPG_CAPTION 0xFE2B
#define AFX_IDS_PICTURE_PPG 0xFE2C
#define AFX_IDS_PICTURE_PPG_CAPTION 0xFE2D
#define AFX_IDS_PICTUREBROWSETITLE 0xFE30
#define AFX_IDS_BORDERSTYLE_0 0xFE31
#define AFX_IDS_BORDERSTYLE_1 0xFE32
// OLE Control verb names
#define AFX_IDS_VERB_EDIT 0xFE40
#define AFX_IDS_VERB_PROPERTIES 0xFE41
// OLE Control internal error messages
#define AFX_IDP_PICTURECANTOPEN 0xFE83
#define AFX_IDP_PICTURECANTLOAD 0xFE84
#define AFX_IDP_PICTURETOOLARGE 0xFE85
#define AFX_IDP_PICTUREREADFAILED 0xFE86
// Standard OLE Control error strings
#define AFX_IDP_E_ILLEGALFUNCTIONCALL 0xFEA0
#define AFX_IDP_E_OVERFLOW 0xFEA1
#define AFX_IDP_E_OUTOFMEMORY 0xFEA2
#define AFX_IDP_E_DIVISIONBYZERO 0xFEA3
#define AFX_IDP_E_OUTOFSTRINGSPACE 0xFEA4
#define AFX_IDP_E_OUTOFSTACKSPACE 0xFEA5
#define AFX_IDP_E_BADFILENAMEORNUMBER 0xFEA6
#define AFX_IDP_E_FILENOTFOUND 0xFEA7
#define AFX_IDP_E_BADFILEMODE 0xFEA8
#define AFX_IDP_E_FILEALREADYOPEN 0xFEA9
#define AFX_IDP_E_DEVICEIOERROR 0xFEAA
#define AFX_IDP_E_FILEALREADYEXISTS 0xFEAB
#define AFX_IDP_E_BADRECORDLENGTH 0xFEAC
#define AFX_IDP_E_DISKFULL 0xFEAD
#define AFX_IDP_E_BADRECORDNUMBER 0xFEAE
#define AFX_IDP_E_BADFILENAME 0xFEAF
#define AFX_IDP_E_TOOMANYFILES 0xFEB0
#define AFX_IDP_E_DEVICEUNAVAILABLE 0xFEB1
#define AFX_IDP_E_PERMISSIONDENIED 0xFEB2
#define AFX_IDP_E_DISKNOTREADY 0xFEB3
#define AFX_IDP_E_PATHFILEACCESSERROR 0xFEB4
#define AFX_IDP_E_PATHNOTFOUND 0xFEB5
#define AFX_IDP_E_INVALIDPATTERNSTRING 0xFEB6
#define AFX_IDP_E_INVALIDUSEOFNULL 0xFEB7
#define AFX_IDP_E_INVALIDFILEFORMAT 0xFEB8
#define AFX_IDP_E_INVALIDPROPERTYVALUE 0xFEB9
#define AFX_IDP_E_INVALIDPROPERTYARRAYINDEX 0xFEBA
#define AFX_IDP_E_SETNOTSUPPORTEDATRUNTIME 0xFEBB
#define AFX_IDP_E_SETNOTSUPPORTED 0xFEBC
#define AFX_IDP_E_NEEDPROPERTYARRAYINDEX 0xFEBD
#define AFX_IDP_E_SETNOTPERMITTED 0xFEBE
#define AFX_IDP_E_GETNOTSUPPORTEDATRUNTIME 0xFEBF
#define AFX_IDP_E_GETNOTSUPPORTED 0xFEC0
#define AFX_IDP_E_PROPERTYNOTFOUND 0xFEC1
#define AFX_IDP_E_INVALIDCLIPBOARDFORMAT 0xFEC2
#define AFX_IDP_E_INVALIDPICTURE 0xFEC3
#define AFX_IDP_E_PRINTERERROR 0xFEC4
#define AFX_IDP_E_CANTSAVEFILETOTEMP 0xFEC5
#define AFX_IDP_E_SEARCHTEXTNOTFOUND 0xFEC6
#define AFX_IDP_E_REPLACEMENTSTOOLONG 0xFEC7
/////////////////////////////////////////////////////////////////////////////
#ifdef _AFX_MINREBUILD
#pragma component(minrebuild, on)
#endif
#endif //__AFXRES_H__
/////////////////////////////////////////////////////////////////////////////

329
fmod/win32/src/MeteredSection.cpp Executable file
View file

@ -0,0 +1,329 @@
/************************************************************
Module Name: MeteredSection.c
Author: Dan Chou
Description: Implements the metered section synchronization object
************************************************************/
#include <windows.h>
#include <tchar.h>
#include "MeteredSection.h"
#include "../../src/fmod_memory.h"
// Internal function declarations
BOOL InitMeteredSection(LPMETERED_SECTION lpMetSect, LONG lInitialCount,
LONG lMaximumCount, LPCTSTR lpName, BOOL bOpenOnly);
BOOL CreateMetSectEvent(LPMETERED_SECTION lpMetSect, LPCTSTR lpName, BOOL
bOpenOnly);
BOOL CreateMetSectFileView(LPMETERED_SECTION lpMetSect, LONG lInitialCount,
LONG lMaximumCount, LPCTSTR lpName, BOOL bOpenOnly);
void GetMeteredSectionLock(LPMETERED_SECTION lpMetSect);
void ReleaseMeteredSectionLock(LPMETERED_SECTION lpMetSect);
/*
* CreateMeteredSection
*/
LPMETERED_SECTION CreateMeteredSection(LONG lInitialCount,
LONG lMaximumCount, LPCTSTR lpName)
{
LPMETERED_SECTION lpMetSect;
// Verify the parameters
if ((lMaximumCount < 1) ||
(lInitialCount > lMaximumCount) ||
(lInitialCount < 0) ||
((lpName) && (_tcslen(lpName) > MAX_METSECT_NAMELEN)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
// Allocate memory for the metered section
lpMetSect = (LPMETERED_SECTION)FMOD_Memory_Alloc(sizeof(METERED_SECTION));
// If the memory for the metered section was allocated okay,
// initialize it
if (lpMetSect)
{
if (!InitMeteredSection(lpMetSect, lInitialCount,
lMaximumCount, lpName, FALSE))
{
CloseMeteredSection(lpMetSect);
lpMetSect = NULL;
}
}
return lpMetSect;
}
/*
* OpenMeteredSection
*/
#ifndef _WIN32_WCE
LPMETERED_SECTION OpenMeteredSection(LPCTSTR lpName)
{
LPMETERED_SECTION lpMetSect = NULL;
if (lpName)
{
lpMetSect = (LPMETERED_SECTION)FMOD_Memory_Alloc(sizeof(METERED_SECTION));
// If the memory for the metered section was allocated okay
if (lpMetSect)
{
if (!InitMeteredSection(lpMetSect, 0, 0, lpName, TRUE))
{
// Metered section failed to initialize
CloseMeteredSection(lpMetSect);
lpMetSect = NULL;
}
}
}
return lpMetSect;
}
#endif
/*
* EnterMeteredSection
*/
DWORD EnterMeteredSection(LPMETERED_SECTION lpMetSect,
DWORD dwMilliseconds)
{
while (TRUE)
{
GetMeteredSectionLock(lpMetSect);
// We have access to the metered section, everything we
// do now will be atomic
if (lpMetSect->lpSharedInfo->lAvailableCount >= 1)
{
lpMetSect->lpSharedInfo->lAvailableCount--;
ReleaseMeteredSectionLock(lpMetSect);
return WAIT_OBJECT_0;
}
// Couldn't get in. Wait on the event object
lpMetSect->lpSharedInfo->lThreadsWaiting++;
ResetEvent(lpMetSect->hEvent);
ReleaseMeteredSectionLock(lpMetSect);
if (WaitForSingleObject(lpMetSect->hEvent,
dwMilliseconds) == WAIT_TIMEOUT)
{
return WAIT_TIMEOUT;
}
}
}
/*
* LeaveMeteredSection
*/
BOOL LeaveMeteredSection(LPMETERED_SECTION lpMetSect, LONG lReleaseCount,
LPLONG lpPreviousCount)
{
int iCount;
GetMeteredSectionLock(lpMetSect);
// Save the old value if they want it
if (lpPreviousCount)
{
*lpPreviousCount = lpMetSect->lpSharedInfo->lAvailableCount;
}
// We have access to the metered section,
// everything we do now will be atomic
if ((lReleaseCount < 0) ||
(lpMetSect->lpSharedInfo->lAvailableCount+lReleaseCount >
lpMetSect->lpSharedInfo->lMaximumCount))
{
ReleaseMeteredSectionLock(lpMetSect);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
lpMetSect->lpSharedInfo->lAvailableCount += lReleaseCount;
// Set the event the appropriate number of times
lReleaseCount =
min(lReleaseCount,lpMetSect->lpSharedInfo->lThreadsWaiting);
if (lpMetSect->lpSharedInfo->lThreadsWaiting)
{
for (iCount=0; iCount < lReleaseCount ; iCount++)
{
lpMetSect->lpSharedInfo->lThreadsWaiting--;
SetEvent(lpMetSect->hEvent);
}
}
ReleaseMeteredSectionLock(lpMetSect);
return TRUE;
}
/*
* CloseMeteredSection
*/
void CloseMeteredSection(LPMETERED_SECTION lpMetSect)
{
if (lpMetSect)
{
// Clean up
#ifdef FILEMAPPING
if (lpMetSect->lpSharedInfo) UnmapViewOfFile(lpMetSect->lpSharedInfo);
if (lpMetSect->hFileMap) CloseHandle(lpMetSect->hFileMap);
#else
DeleteCriticalSection(&lpMetSect->hCrit);
#endif
if (lpMetSect->hEvent) CloseHandle(lpMetSect->hEvent);
FMOD_Memory_Free(lpMetSect);
}
}
/*
* InitMeteredSection
*/
BOOL InitMeteredSection(LPMETERED_SECTION lpMetSect,
LONG lInitialCount, LONG lMaximumCount,
LPCTSTR lpName, BOOL bOpenOnly)
{
// Try to create the event object
if (CreateMetSectEvent(lpMetSect, lpName, bOpenOnly))
{
#ifdef FILEMAPPING
// Try to create the memory mapped file
if (CreateMetSectFileView(lpMetSect, lInitialCount, lMaximumCount, lpName, bOpenOnly))
#else
lpMetSect->lpSharedInfo = &lpMetSect->SharedInfo;
lpMetSect->lpSharedInfo->lThreadsWaiting = 0;
lpMetSect->lpSharedInfo->lAvailableCount = lInitialCount;
lpMetSect->lpSharedInfo->lMaximumCount = lMaximumCount;
InitializeCriticalSection(&lpMetSect->hCrit);
InterlockedExchange((long *)&(lpMetSect->lpSharedInfo->fInitialized), TRUE);
#endif
{
return TRUE;
}
}
// Error occured, return FALSE so the caller knows to clean up
return FALSE;
}
/*
* CreateMetSectEvent
*/
BOOL CreateMetSectEvent(LPMETERED_SECTION lpMetSect,
LPCTSTR lpName, BOOL bOpenOnly)
{
TCHAR sz[MAX_PATH];
if (lpName)
{
//wsprintf(sz, _TEXT("DKC_MSECT_EVT_%s"), lpName);
#ifndef _WIN32_WCE
if (bOpenOnly)
{
lpMetSect->hEvent = OpenEvent(0, FALSE, sz);
}
else
{
#endif
// Create an auto-reset named event object
lpMetSect->hEvent = CreateEvent(NULL, FALSE, FALSE, sz);
#ifndef _WIN32_WCE
}
#endif
}
else
{
// Create an auto-reset unnamed event object
lpMetSect->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}
return (lpMetSect->hEvent ? TRUE : FALSE);
}
#ifdef FILEMAPPING
/*
* CreateMetSectFileView
*/
BOOL CreateMetSectFileView(LPMETERED_SECTION lpMetSect,
LONG lInitialCount, LONG lMaximumCount,
LPCTSTR lpName, BOOL bOpenOnly)
{
TCHAR sz[MAX_PATH];
DWORD dwLastError;
if (lpName)
{
//wsprintf(sz, _TEXT("DKC_MSECT_MMF_%s"), lpName);
#ifndef _WIN32_WCE
if (bOpenOnly)
{
lpMetSect->hFileMap = OpenFileMapping(0, FALSE, sz);
}
else
{
#endif
// Create a named file mapping
lpMetSect->hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL, PAGE_READWRITE, 0, sizeof(METSECT_SHARED_INFO), sz);
#ifndef _WIN32_WCE
}
#endif
}
else
{
// Create an unnamed file mapping
lpMetSect->hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL, PAGE_READWRITE, 0, sizeof(METSECT_SHARED_INFO), NULL);
}
// Map a view of the file
if (lpMetSect->hFileMap)
{
dwLastError = GetLastError();
lpMetSect->lpSharedInfo = (LPMETSECT_SHARED_INFO)
MapViewOfFile(lpMetSect->hFileMap, FILE_MAP_WRITE, 0, 0, 0);
if (lpMetSect->lpSharedInfo)
{
if (dwLastError != ERROR_ALREADY_EXISTS)
{
lpMetSect->lpSharedInfo->lSpinLock = 0;
lpMetSect->lpSharedInfo->lThreadsWaiting = 0;
lpMetSect->lpSharedInfo->lAvailableCount = lInitialCount;
lpMetSect->lpSharedInfo->lMaximumCount = lMaximumCount;
InterlockedExchange((long *)&(lpMetSect->lpSharedInfo->fInitialized), TRUE);
}
else
{ // Already exists; wait for it to be initialized by the creator
while (!lpMetSect->lpSharedInfo->fInitialized) Sleep(0);
}
return TRUE;
}
}
return FALSE;
}
#endif
/*
* GetMeteredSectionLock
*/
void GetMeteredSectionLock(LPMETERED_SECTION lpMetSect)
{
#if FILEMAPPING
// Spin and get access to the metered section lock
while (InterlockedExchange(&(lpMetSect->lpSharedInfo->lSpinLock), 1) != 0)
Sleep(1);
#else
EnterCriticalSection(&lpMetSect->hCrit);
#endif
}
/*
* ReleaseMeteredSectionLock
*/
void ReleaseMeteredSectionLock(LPMETERED_SECTION lpMetSect)
{
#if FILEMAPPING
InterlockedExchange(&(lpMetSect->lpSharedInfo->lSpinLock), 0);
#else
LeaveCriticalSection(&lpMetSect->hCrit);
#endif
}

62
fmod/win32/src/MeteredSection.h Executable file
View file

@ -0,0 +1,62 @@
/************************************************************
Module Name: MeteredSection.h
Author: Dan Chou
Description: Defines the metered section synchronization object
************************************************************/
#include <windows.h>
#ifndef _METERED_SECTION_H_
#define _METERED_SECTION_H_
#define MAX_METSECT_NAMELEN 128
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
//#define FILEMAPPING
// Shared info needed for metered section
typedef struct _METSECT_SHARED_INFO {
BOOL fInitialized; // Is the metered section initialized?
#ifdef FILEMAPPING
LONG lSpinLock; // Used to gain access to this structure
#endif
LONG lThreadsWaiting; // Count of threads waiting
LONG lAvailableCount; // Available resource count
LONG lMaximumCount; // Maximum resource count
} METSECT_SHARED_INFO, *LPMETSECT_SHARED_INFO;
// The opaque Metered Section data structure
typedef struct _METERED_SECTION {
HANDLE hEvent; // Handle to a kernel event object
#ifdef FILEMAPPING
HANDLE hFileMap; // Handle to memory mapped file
#else
METSECT_SHARED_INFO SharedInfo;
CRITICAL_SECTION hCrit;
#endif
LPMETSECT_SHARED_INFO lpSharedInfo;
} METERED_SECTION, *LPMETERED_SECTION;
// Interface functions
LPMETERED_SECTION
CreateMeteredSection(LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);
#ifndef _WIN32_WCE
LPMETERED_SECTION OpenMeteredSection(LPCTSTR lpName);
#endif
DWORD EnterMeteredSection(LPMETERED_SECTION lpMetSect,
DWORD dwMilliseconds);
BOOL LeaveMeteredSection(LPMETERED_SECTION lpMetSect,
LONG lReleaseCount, LPLONG lpPreviousCount);
void CloseMeteredSection(LPMETERED_SECTION lpMetSect);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // _METERED_SECTION_H_

259
fmod/win32/src/asio/asio.cpp Executable file
View file

@ -0,0 +1,259 @@
/*
Steinberg Audio Stream I/O API
(c) 1996, Steinberg Soft- und Hardware GmbH
asio.cpp
asio functions entries which translate the
asio interface to the asiodrvr class methods
*/
#include "asiosys.h" // platform definition
#include "asio.h"
#if MAC
#include "asiodrvr.h"
#pragma export on
AsioDriver *theAsioDriver = 0;
extern "C"
{
long main()
{
return 'ASIO';
}
#elif WINDOWS
#include "windows.h"
#include "iasiodrv.h"
#include "asiodrivers.h"
IASIO *theAsioDriver = 0;
extern AsioDrivers *asioDrivers;
#elif SGI || SUN || BEOS || LINUX
#include "asiodrvr.h"
static AsioDriver *theAsioDriver = 0;
#endif
//-----------------------------------------------------------------------------------------------------
ASIOError ASIOInit(ASIODriverInfo *info)
{
#if MAC || SGI || SUN || BEOS || LINUX
if(theAsioDriver)
{
delete theAsioDriver;
theAsioDriver = 0;
}
info->driverVersion = 0;
strcpy(info->name, "No ASIO Driver");
theAsioDriver = getDriver();
if(!theAsioDriver)
{
strcpy(info->errorMessage, "Not enough memory for the ASIO driver!");
return ASE_NotPresent;
}
if(!theAsioDriver->init(info->sysRef))
{
theAsioDriver->getErrorMessage(info->errorMessage);
delete theAsioDriver;
theAsioDriver = 0;
return ASE_NotPresent;
}
strcpy(info->errorMessage, "No ASIO Driver Error");
theAsioDriver->getDriverName(info->name);
info->driverVersion = theAsioDriver->getDriverVersion();
return ASE_OK;
#else
info->driverVersion = 0;
strcpy(info->name, "No ASIO Driver");
if(theAsioDriver) // must be loaded!
{
if(!theAsioDriver->init(info->sysRef))
{
theAsioDriver->getErrorMessage(info->errorMessage);
theAsioDriver = 0;
return ASE_NotPresent;
}
strcpy(info->errorMessage, "No ASIO Driver Error");
theAsioDriver->getDriverName(info->name);
info->driverVersion = theAsioDriver->getDriverVersion();
return ASE_OK;
}
return ASE_NotPresent;
#endif // !MAC
}
ASIOError ASIOExit(void)
{
if(theAsioDriver)
{
#if WINDOWS
if (asioDrivers)
{
asioDrivers->removeCurrentDriver();
}
#else
delete theAsioDriver;
#endif
}
theAsioDriver = 0;
return ASE_OK;
}
ASIOError ASIOStart(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->start();
}
ASIOError ASIOStop(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->stop();
}
ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels)
{
if(!theAsioDriver)
{
*numInputChannels = *numOutputChannels = 0;
return ASE_NotPresent;
}
return theAsioDriver->getChannels(numInputChannels, numOutputChannels);
}
ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency)
{
if(!theAsioDriver)
{
*inputLatency = *outputLatency = 0;
return ASE_NotPresent;
}
return theAsioDriver->getLatencies(inputLatency, outputLatency);
}
ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity)
{
if(!theAsioDriver)
{
*minSize = *maxSize = *preferredSize = *granularity = 0;
return ASE_NotPresent;
}
return theAsioDriver->getBufferSize(minSize, maxSize, preferredSize, granularity);
}
ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->canSampleRate(sampleRate);
}
ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->getSampleRate(currentRate);
}
ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->setSampleRate(sampleRate);
}
ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources)
{
if(!theAsioDriver)
{
*numSources = 0;
return ASE_NotPresent;
}
return theAsioDriver->getClockSources(clocks, numSources);
}
ASIOError ASIOSetClockSource(long reference)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->setClockSource(reference);
}
ASIOError ASIOGetSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->getSamplePosition(sPos, tStamp);
}
ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info)
{
if(!theAsioDriver)
{
info->channelGroup = -1;
info->type = ASIOSTInt16MSB;
strcpy(info->name, "None");
return ASE_NotPresent;
}
return theAsioDriver->getChannelInfo(info);
}
ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks)
{
if(!theAsioDriver)
{
ASIOBufferInfo *info = bufferInfos;
for(long i = 0; i < numChannels; i++, info++)
info->buffers[0] = info->buffers[1] = 0;
return ASE_NotPresent;
}
return theAsioDriver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks);
}
ASIOError ASIODisposeBuffers(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->disposeBuffers();
}
ASIOError ASIOControlPanel(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->controlPanel();
}
ASIOError ASIOFuture(long selector, void *opt)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->future(selector, opt);
}
ASIOError ASIOOutputReady(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->outputReady();
}
#if MAC
} // extern "C"
#pragma export off
#endif

963
fmod/win32/src/asio/asio.h Executable file
View file

@ -0,0 +1,963 @@
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
/*
Steinberg Audio Stream I/O API
(c) 1997 - 1999, Steinberg Soft- und Hardware GmbH
ASIO Interface Specification v 2.0
basic concept is an i/o synchronous double-buffer scheme:
on bufferSwitch(index == 0), host will read/write:
after ASIOStart(), the
read first input buffer A (index 0)
| will be invalid (empty)
* ------------------------
|------------------------|-----------------------|
| | |
| Input Buffer A (0) | Input Buffer B (1) |
| | |
|------------------------|-----------------------|
| | |
| Output Buffer A (0) | Output Buffer B (1) |
| | |
|------------------------|-----------------------|
* -------------------------
| before calling ASIOStart(),
write host will have filled output
buffer B (index 1) already
*please* take special care of proper statement of input
and output latencies (see ASIOGetLatencies()), these
control sequencer sync accuracy
*/
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
/*
prototypes summary:
ASIOError ASIOInit(ASIODriverInfo *info);
ASIOError ASIOExit(void);
ASIOError ASIOStart(void);
ASIOError ASIOStop(void);
ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);
ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);
ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);
ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);
ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);
ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);
ASIOError ASIOSetClockSource(long reference);
ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);
ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);
ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks);
ASIOError ASIODisposeBuffers(void);
ASIOError ASIOControlPanel(void);
void *ASIOFuture(long selector, void *params);
ASIOError ASIOOutputReady(void);
*/
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
#ifndef __ASIO_H
#define __ASIO_H
// force 4 byte alignment
#if defined(_MSC_VER) && !defined(__MWERKS__)
#pragma pack(push,4)
#elif PRAGMA_ALIGN_SUPPORTED
#pragma options align = native
#endif
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Type definitions
//- - - - - - - - - - - - - - - - - - - - - - - - -
// number of samples data type is 64 bit integer
#if NATIVE_INT64
typedef long long int ASIOSamples;
#else
typedef struct ASIOSamples {
unsigned long hi;
unsigned long lo;
} ASIOSamples;
#endif
// Timestamp data type is 64 bit integer,
// Time format is Nanoseconds.
#if NATIVE_INT64
typedef long long int ASIOTimeStamp ;
#else
typedef struct ASIOTimeStamp {
unsigned long hi;
unsigned long lo;
} ASIOTimeStamp;
#endif
// Samplerates are expressed in IEEE 754 64 bit double float,
// native format as host computer
#if IEEE754_64FLOAT
typedef double ASIOSampleRate;
#else
typedef struct ASIOSampleRate {
char ieee[8];
} ASIOSampleRate;
#endif
// Boolean values are expressed as long
typedef long ASIOBool;
enum {
ASIOFalse = 0,
ASIOTrue = 1
};
// Sample Types are expressed as long
typedef long ASIOSampleType;
enum {
ASIOSTInt16MSB = 0,
ASIOSTInt24MSB = 1, // used for 20 bits as well
ASIOSTInt32MSB = 2,
ASIOSTFloat32MSB = 3, // IEEE 754 32 bit float
ASIOSTFloat64MSB = 4, // IEEE 754 64 bit double float
// these are used for 32 bit data buffer, with different alignment of the data inside
// 32 bit PCI bus systems can be more easily used with these
ASIOSTInt32MSB16 = 8, // 32 bit data with 18 bit alignment
ASIOSTInt32MSB18 = 9, // 32 bit data with 18 bit alignment
ASIOSTInt32MSB20 = 10, // 32 bit data with 20 bit alignment
ASIOSTInt32MSB24 = 11, // 32 bit data with 24 bit alignment
ASIOSTInt16LSB = 16,
ASIOSTInt24LSB = 17, // used for 20 bits as well
ASIOSTInt32LSB = 18,
ASIOSTFloat32LSB = 19, // IEEE 754 32 bit float, as found on Intel x86 architecture
ASIOSTFloat64LSB = 20, // IEEE 754 64 bit double float, as found on Intel x86 architecture
// these are used for 32 bit data buffer, with different alignment of the data inside
// 32 bit PCI bus systems can more easily used with these
ASIOSTInt32LSB16 = 24, // 32 bit data with 18 bit alignment
ASIOSTInt32LSB18 = 25, // 32 bit data with 18 bit alignment
ASIOSTInt32LSB20 = 26, // 32 bit data with 20 bit alignment
ASIOSTInt32LSB24 = 27 // 32 bit data with 24 bit alignment
};
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Error codes
//- - - - - - - - - - - - - - - - - - - - - - - - -
typedef long ASIOError;
enum {
ASE_OK = 0, // This value will be returned whenever the call succeeded
ASE_SUCCESS = 0x3f4847a0, // unique success return value for ASIOFuture calls
ASE_NotPresent = -1000, // hardware input or output is not present or available
ASE_HWMalfunction, // hardware is malfunctioning (can be returned by any ASIO function)
ASE_InvalidParameter, // input parameter invalid
ASE_InvalidMode, // hardware is in a bad mode or used in a bad mode
ASE_SPNotAdvancing, // hardware is not running when sample position is inquired
ASE_NoClock, // sample clock or rate cannot be determined or is not present
ASE_NoMemory // not enough memory for completing the request
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Time Info support
//- - - - - - - - - - - - - - - - - - - - - - - - -
typedef struct ASIOTimeCode
{
double speed; // speed relation (fraction of nominal speed)
// optional; set to 0. or 1. if not supported
ASIOSamples timeCodeSamples; // time in samples
unsigned long flags; // some information flags (see below)
char future[64];
} ASIOTimeCode;
typedef enum ASIOTimeCodeFlags
{
kTcValid = 1,
kTcRunning = 1 << 1,
kTcReverse = 1 << 2,
kTcOnspeed = 1 << 3,
kTcStill = 1 << 4,
kTcSpeedValid = 1 << 8
} ASIOTimeCodeFlags;
typedef struct AsioTimeInfo
{
double speed; // absolute speed (1. = nominal)
ASIOTimeStamp systemTime; // system time related to samplePosition, in nanoseconds
// on mac, must be derived from Microseconds() (not UpTime()!)
// on windows, must be derived from timeGetTime()
ASIOSamples samplePosition;
ASIOSampleRate sampleRate; // current rate
unsigned long flags; // (see below)
char reserved[12];
} AsioTimeInfo;
typedef enum AsioTimeInfoFlags
{
kSystemTimeValid = 1, // must always be valid
kSamplePositionValid = 1 << 1, // must always be valid
kSampleRateValid = 1 << 2,
kSpeedValid = 1 << 3,
kSampleRateChanged = 1 << 4,
kClockSourceChanged = 1 << 5
} AsioTimeInfoFlags;
typedef struct ASIOTime // both input/output
{
long reserved[4]; // must be 0
struct AsioTimeInfo timeInfo; // required
struct ASIOTimeCode timeCode; // optional, evaluated if (timeCode.flags & kTcValid)
} ASIOTime;
#ifdef __cplusplus
extern "C" {
#endif
/*
using time info:
it is recommended to use the new method with time info even if the asio
device does not support timecode; continuous calls to ASIOGetSamplePosition
and ASIOGetSampleRate are avoided, and there is a more defined relationship
between callback time and the time info.
see the example below.
to initiate time info mode, after you have received the callbacks pointer in
ASIOCreateBuffers, you will call the asioMessage callback with kAsioSupportsTimeInfo
as the argument. if this returns 1, host has accepted time info mode.
now host expects the new callback bufferSwitchTimeInfo to be used instead
of the old bufferSwitch method. the ASIOTime structure is assumed to be valid
and accessible until the callback returns.
using time code:
if the device supports reading time code, it will call host's asioMessage callback
with kAsioSupportsTimeCode as the selector. it may then fill the according
fields and set the kTcValid flag.
host will call the future method with the kAsioEnableTimeCodeRead selector when
it wants to enable or disable tc reading by the device. you should also support
the kAsioCanTimeInfo and kAsioCanTimeCode selectors in ASIOFuture (see example).
note:
the AsioTimeInfo/ASIOTimeCode pair is supposed to work in both directions.
as a matter of convention, the relationship between the sample
position counter and the time code at buffer switch time is
(ignoring offset between tc and sample pos when tc is running):
on input: sample 0 -> input buffer sample 0 -> time code 0
on output: sample 0 -> output buffer sample 0 -> time code 0
this means that for 'real' calculations, one has to take into account
the according latencies.
example:
ASIOTime asioTime;
in createBuffers()
{
FMOD_memset(&asioTime, 0, sizeof(ASIOTime));
AsioTimeInfo* ti = &asioTime.timeInfo;
ti->sampleRate = theSampleRate;
ASIOTimeCode* tc = &asioTime.timeCode;
tc->speed = 1.;
timeInfoMode = false;
canTimeCode = false;
if(callbacks->asioMessage(kAsioSupportsTimeInfo, 0, 0, 0) == 1)
{
timeInfoMode = true;
#if kCanTimeCode
if(callbacks->asioMessage(kAsioSupportsTimeCode, 0, 0, 0) == 1)
canTimeCode = true;
#endif
}
}
void switchBuffers(long doubleBufferIndex, bool processNow)
{
if(timeInfoMode)
{
AsioTimeInfo* ti = &asioTime.timeInfo;
ti->flags = kSystemTimeValid | kSamplePositionValid | kSampleRateValid;
ti->systemTime = theNanoSeconds;
ti->samplePosition = theSamplePosition;
if(ti->sampleRate != theSampleRate)
ti->flags |= kSampleRateChanged;
ti->sampleRate = theSampleRate;
#if kCanTimeCode
if(canTimeCode && timeCodeEnabled)
{
ASIOTimeCode* tc = &asioTime.timeCode;
tc->timeCodeSamples = tcSamples; // tc in samples
tc->flags = kTcValid | kTcRunning | kTcOnspeed; // if so...
}
ASIOTime* bb = callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);
#else
callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);
#endif
}
else
callbacks->bufferSwitch(doubleBufferIndex, ASIOFalse);
}
ASIOError ASIOFuture(long selector, void *params)
{
switch(selector)
{
case kAsioEnableTimeCodeRead:
timeCodeEnabled = true;
return ASE_SUCCESS;
case kAsioDisableTimeCodeRead:
timeCodeEnabled = false;
return ASE_SUCCESS;
case kAsioCanTimeInfo:
return ASE_SUCCESS;
#if kCanTimeCode
case kAsioCanTimeCode:
return ASE_SUCCESS;
#endif
}
return ASE_NotPresent;
};
*/
//- - - - - - - - - - - - - - - - - - - - - - - - -
// application's audio stream handler callbacks
//- - - - - - - - - - - - - - - - - - - - - - - - -
typedef struct ASIOCallbacks
{
void (*bufferSwitch) (long doubleBufferIndex, ASIOBool directProcess);
// bufferSwitch indicates that both input and output are to be processed.
// the current buffer half index (0 for A, 1 for B) determines
// - the output buffer that the host should start to fill. the other buffer
// will be passed to output hardware regardless of whether it got filled
// in time or not.
// - the input buffer that is now filled with incoming data. Note that
// because of the synchronicity of i/o, the input always has at
// least one buffer latency in relation to the output.
// directProcess suggests to the host whether it should immedeately
// start processing (directProcess == ASIOTrue), or whether its process
// should be deferred because the call comes from a very low level
// (for instance, a high level priority interrupt), and direct processing
// would cause timing instabilities for the rest of the system. If in doubt,
// directProcess should be set to ASIOFalse.
// Note: bufferSwitch may be called at interrupt time for highest efficiency.
void (*sampleRateDidChange) (ASIOSampleRate sRate);
// gets called when the AudioStreamIO detects a sample rate change
// If sample rate is unknown, 0 is passed (for instance, clock loss
// when externally synchronized).
long (*asioMessage) (long selector, long value, void* message, double* opt);
// generic callback for various purposes, see selectors below.
// note this is only present if the asio version is 2 or higher
ASIOTime* (*bufferSwitchTimeInfo) (ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess);
// new callback with time info. makes ASIOGetSamplePosition() and various
// calls to ASIOGetSampleRate obsolete,
// and allows for timecode sync etc. to be preferred; will be used if
// the driver calls asioMessage with selector kAsioSupportsTimeInfo.
} ASIOCallbacks;
// asioMessage selectors
enum
{
kAsioSelectorSupported = 1, // selector in <value>, returns 1L if supported,
// 0 otherwise
kAsioEngineVersion, // returns engine (host) asio implementation version,
// 2 or higher
kAsioResetRequest, // request driver reset. if accepted, this
// will close the driver (ASIO_Exit() ) and
// re-open it again (ASIO_Init() etc). some
// drivers need to reconfigure for instance
// when the sample rate changes, or some basic
// changes have been made in ASIO_ControlPanel().
// returns 1L; note the request is merely passed
// to the application, there is no way to determine
// if it gets accepted at this time (but it usually
// will be).
kAsioBufferSizeChange, // not yet supported, will currently always return 0L.
// for now, use kAsioResetRequest instead.
// once implemented, the new buffer size is expected
// in <value>, and on success returns 1L
kAsioResyncRequest, // the driver went out of sync, such that
// the timestamp is no longer valid. this
// is a request to re-start the engine and
// slave devices (sequencer). returns 1 for ok,
// 0 if not supported.
kAsioLatenciesChanged, // the drivers latencies have changed. The engine
// will refetch the latencies.
kAsioSupportsTimeInfo, // if host returns true here, it will expect the
// callback bufferSwitchTimeInfo to be called instead
// of bufferSwitch
kAsioSupportsTimeCode, // supports time code reading/writing
kAsioSupportsInputMonitor, // supports input monitoring
kAsioNumMessageSelectors
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
//- - - - - - - - - - - - - - - - - - - - - - - - -
// (De-)Construction
//- - - - - - - - - - - - - - - - - - - - - - - - -
typedef struct ASIODriverInfo
{
long asioVersion; // currently, 2
long driverVersion; // driver specific
char name[32];
char errorMessage[124];
void *sysRef; // on input: system reference
// (Windows: application main window handle, Mac & SGI: 0)
} ASIODriverInfo;
ASIOError ASIOInit(ASIODriverInfo *info);
/* Purpose:
Initialize the AudioStreamIO.
Parameter:
info: pointer to an ASIODriver structure:
- asioVersion:
- on input, the host version. *** Note *** this is 0 for earlier asio
implementations, and the asioMessage callback is implemeted
only if asioVersion is 2 or greater. sorry but due to a design fault
the driver doesn't have access to the host version in ASIOInit :-(
added selector for host (engine) version in the asioMessage callback
so we're ok from now on.
- on return, asio implementation version.
older versions are 1
if you support this version (namely, ASIO_outputReady() )
this should be 2 or higher. also see the note in
ASIO_getTimeStamp() !
- version: on return, the driver version (format is driver specific)
- name: on return, a null-terminated string containing the driver's name
- error message: on return, should contain a user message describing
the type of error that occured during ASIOInit(), if any.
- sysRef: platform specific
Returns:
If neither input nor output is present ASE_NotPresent
will be returned.
ASE_NoMemory, ASE_HWMalfunction are other possible error conditions
*/
ASIOError ASIOExit(void);
/* Purpose:
Terminates the AudioStreamIO.
Parameter:
None.
Returns:
If neither input nor output is present ASE_NotPresent
will be returned.
Notes: this implies ASIOStop() and ASIODisposeBuffers(),
meaning that no host callbacks must be accessed after ASIOExit().
*/
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Start/Stop
//- - - - - - - - - - - - - - - - - - - - - - - - -
ASIOError ASIOStart(void);
/* Purpose:
Start input and output processing synchronously.
This will
- reset the sample counter to zero
- start the hardware (both input and output)
The first call to the hosts' bufferSwitch(index == 0) then tells
the host to read from input buffer A (index 0), and start
processing to output buffer A while output buffer B (which
has been filled by the host prior to calling ASIOStart())
is possibly sounding (see also ASIOGetLatencies())
Parameter:
None.
Returns:
If neither input nor output is present, ASE_NotPresent
will be returned.
If the hardware fails to start, ASE_HWMalfunction will be returned.
Notes:
There is no restriction on the time that ASIOStart() takes
to perform (that is, it is not considered a realtime trigger).
*/
ASIOError ASIOStop(void);
/* Purpose:
Stops input and output processing altogether.
Parameter:
None.
Returns:
If neither input nor output is present ASE_NotPresent
will be returned.
Notes:
On return from ASIOStop(), the driver must in no
case call the hosts' bufferSwitch() routine.
*/
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Inquiry methods and sample rate
//- - - - - - - - - - - - - - - - - - - - - - - - -
ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);
/* Purpose:
Returns number of individual input/output channels.
Parameter:
numInputChannels will hold the number of available input channels
numOutputChannels will hold the number of available output channels
Returns:
If no input/output is present ASE_NotPresent will be returned.
If only inputs, or only outputs are available, the according
other parameter will be zero, and ASE_OK is returned.
*/
ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);
/* Purpose:
Returns the input and output latencies. This includes
device specific delays, like FIFOs etc.
Parameter:
inputLatency will hold the 'age' of the first sample frame
in the input buffer when the hosts reads it in bufferSwitch()
(this is theoretical, meaning it does not include the overhead
and delay between the actual physical switch, and the time
when bufferSitch() enters).
This will usually be the size of one block in sample frames, plus
device specific latencies.
outputLatency will specify the time between the buffer switch,
and the time when the next play buffer will start to sound.
The next play buffer is defined as the one the host starts
processing after (or at) bufferSwitch(), indicated by the
index parameter (0 for buffer A, 1 for buffer B).
It will usually be either one block, if the host writes directly
to a dma buffer, or two or more blocks if the buffer is 'latched' by
the driver. As an example, on ASIOStart(), the host will have filled
the play buffer at index 1 already; when it gets the callback (with
the parameter index == 0), this tells it to read from the input
buffer 0, and start to fill the play buffer 0 (assuming that now
play buffer 1 is already sounding). In this case, the output
latency is one block. If the driver decides to copy buffer 1
at that time, and pass it to the hardware at the next slot (which
is most commonly done, but should be avoided), the output latency
becomes two blocks instead, resulting in a total i/o latency of at least
3 blocks. As memory access is the main bottleneck in native dsp processing,
and to acheive less latency, it is highly recommended to try to avoid
copying (this is also why the driver is the owner of the buffers). To
summarize, the minimum i/o latency can be acheived if the input buffer
is processed by the host into the output buffer which will physically
start to sound on the next time slice. Also note that the host expects
the bufferSwitch() callback to be accessed for each time slice in order
to retain sync, possibly recursively; if it fails to process a block in
time, it will suspend its operation for some time in order to recover.
Returns:
If no input/output is present ASE_NotPresent will be returned.
*/
ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
/* Purpose:
Returns min, max, and preferred buffer sizes for input/output
Parameter:
minSize will hold the minimum buffer size
maxSize will hold the maxium possible buffer size
preferredSize will hold the preferred buffer size (a size which
best fits performance and hardware requirements)
granularity will hold the granularity at which buffer sizes
may differ. Usually, the buffer size will be a power of 2;
in this case, granularity will hold -1 on return, signalling
possible buffer sizes starting from minSize, increased in
powers of 2 up to maxSize.
Returns:
If no input/output is present ASE_NotPresent will be returned.
Notes:
When minimum and maximum buffer size are equal,
the preferred buffer size has to be the same value as well; granularity
should be 0 in this case.
*/
ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);
/* Purpose:
Inquires the hardware for the available sample rates.
Parameter:
sampleRate is the rate in question.
Returns:
If the inquired sample rate is not supported, ASE_NoClock will be returned.
If no input/output is present ASE_NotPresent will be returned.
*/
ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);
/* Purpose:
Get the current sample Rate.
Parameter:
currentRate will hold the current sample rate on return.
Returns:
If sample rate is unknown, sampleRate will be 0 and ASE_NoClock will be returned.
If no input/output is present ASE_NotPresent will be returned.
Notes:
*/
ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);
/* Purpose:
Set the hardware to the requested sample Rate. If sampleRate == 0,
enable external sync.
Parameter:
sampleRate: on input, the requested rate
Returns:
If sampleRate is unknown ASE_NoClock will be returned.
If the current clock is external, and sampleRate is != 0,
ASE_InvalidMode will be returned
If no input/output is present ASE_NotPresent will be returned.
Notes:
*/
typedef struct ASIOClockSource
{
long index; // as used for ASIOSetClockSource()
long associatedChannel; // for instance, S/PDIF or AES/EBU
long associatedGroup; // see channel groups (ASIOGetChannelInfo())
ASIOBool isCurrentSource; // ASIOTrue if this is the current clock source
char name[32]; // for user selection
} ASIOClockSource;
ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);
/* Purpose:
Get the available external audio clock sources
Parameter:
clocks points to an array of ASIOClockSource structures:
- index: this is used to identify the clock source
when ASIOSetClockSource() is accessed, should be
an index counting from zero
- associatedInputChannel: the first channel of an associated
input group, if any.
- associatedGroup: the group index of that channel.
groups of channels are defined to seperate for
instance analog, S/PDIF, AES/EBU, ADAT connectors etc,
when present simultaniously. Note that associated channel
is enumerated according to numInputs/numOutputs, means it
is independant from a group (see also ASIOGetChannelInfo())
inputs are associated to a clock if the physical connection
transfers both data and clock (like S/PDIF, AES/EBU, or
ADAT inputs). if there is no input channel associated with
the clock source (like Word Clock, or internal oscillator), both
associatedChannel and associatedGroup should be set to -1.
- isCurrentSource: on exit, ASIOTrue if this is the current clock
source, ASIOFalse else
- name: a null-terminated string for user selection of the available sources.
numSources:
on input: the number of allocated array members
on output: the number of available clock sources, at least
1 (internal clock generator).
Returns:
If no input/output is present ASE_NotPresent will be returned.
Notes:
*/
ASIOError ASIOSetClockSource(long index);
/* Purpose:
Set the audio clock source
Parameter:
index as obtained from an inquiry to ASIOGetClockSources()
Returns:
If no input/output is present ASE_NotPresent will be returned.
If the clock can not be selected because an input channel which
carries the current clock source is active, ASE_InvalidMode
*may* be returned (this depends on the properties of the driver
and/or hardware).
Notes:
Should *not* return ASE_NoClock if there is no clock signal present
at the selected source; this will be inquired via ASIOGetSampleRate().
It should call the host callback procedure sampleRateHasChanged(),
if the switch causes a sample rate change, or if no external clock
is present at the selected source.
*/
ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);
/* Purpose:
Inquires the sample position/time stamp pair.
Parameter:
sPos will hold the sample position on return. The sample
position is reset to zero when ASIOStart() gets called.
tStamp will hold the system time when the sample position
was latched.
Returns:
If no input/output is present, ASE_NotPresent will be returned.
If there is no clock, ASE_SPNotAdvancing will be returned.
Notes:
in order to be able to synchronise properly,
the sample position / time stamp pair must refer to the current block,
that is, the engine will call ASIOGetSamplePosition() in its bufferSwitch()
callback and expect the time for the current block. thus, when requested
in the very first bufferSwitch after ASIO_Start(), the sample position
should be zero, and the time stamp should refer to the very time where
the stream was started. it also means that the sample position must be
block aligned. the driver must ensure proper interpolation if the system
time can not be determined for the block position. the driver is responsible
for precise time stamps as it usually has most direct access to lower
level resources. proper behaviour of ASIO_GetSamplePosition() and ASIO_GetLatencies()
are essential for precise media synchronization!
*/
typedef struct ASIOChannelInfo
{
long channel; // on input, channel index
ASIOBool isInput; // on input
ASIOBool isActive; // on exit
long channelGroup; // dto
ASIOSampleType type; // dto
char name[32]; // dto
} ASIOChannelInfo;
ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);
/* Purpose:
retreive information about the nature of a channel
Parameter:
info: pointer to a ASIOChannelInfo structure with
- channel: on input, the channel index of the channel in question.
- isInput: on input, ASIOTrue if info for an input channel is
requested, else output
- channelGroup: on return, the channel group that the channel
belongs to. For drivers which support different types of
channels, like analog, S/PDIF, AES/EBU, ADAT etc interfaces,
there should be a reasonable grouping of these types. Groups
are always independant form a channel index, that is, a channel
index always counts from 0 to numInputs/numOutputs regardless
of the group it may belong to.
There will always be at least one group (group 0). Please
also note that by default, the host may decide to activate
channels 0 and 1; thus, these should belong to the most
useful type (analog i/o, if present).
- type: on return, contains the sample type of the channel
- isActive: on return, ASIOTrue if channel is active as it was
installed by ASIOCreateBuffers(), ASIOFalse else
- name: describing the type of channel in question. Used to allow
for user selection, and enabling of specific channels. examples:
"Analog In", "SPDIF Out" etc
Returns:
If no input/output is present ASE_NotPresent will be returned.
Notes:
If possible, the string should be organised such that the first
characters are most significantly describing the nature of the
port, to allow for identification even if the view showing the
port name is too small to display more than 8 characters, for
instance.
*/
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Buffer preparation
//- - - - - - - - - - - - - - - - - - - - - - - - -
typedef struct ASIOBufferInfo
{
ASIOBool isInput; // on input: ASIOTrue: input, else output
long channelNum; // on input: channel index
void *buffers[2]; // on output: double buffer addresses
} ASIOBufferInfo;
ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks);
/* Purpose:
Allocates input/output buffers for all input and output channels to be activated.
Parameter:
bufferInfos is a pointer to an array of ASIOBufferInfo structures:
- isInput: on input, ASIOTrue if the buffer is to be allocated
for an input, output buffer else
- channelNum: on input, the index of the channel in question
(counting from 0)
- buffers: on exit, 2 pointers to the halves of the channels' double-buffer.
the size of the buffer(s) of course depend on both the ASIOSampleType
as obtained from ASIOGetChannelInfo(), and bufferSize
numChannels is the sum of all input and output channels to be created;
thus bufferInfos is a pointer to an array of numChannels ASIOBufferInfo
structures.
bufferSize selects one of the possible buffer sizes as obtained from
ASIOGetBufferSizes().
callbacks is a pointer to an ASIOCallbacks structure.
Returns:
If not enough memory is available ASE_NoMemory will be returned.
If no input/output is present ASE_NotPresent will be returned.
If bufferSize is not supported, or one or more of the bufferInfos elements
contain invalid settings, ASE_InvalidMode will be returned.
Notes:
If individual channel selection is not possible but requested,
the driver has to handle this. namely, bufferSwitch() will only
have filled buffers of enabled outputs. If possible, processing
and buss activities overhead should be avoided for channels which
were not enabled here.
*/
ASIOError ASIODisposeBuffers(void);
/* Purpose:
Releases all buffers for the device.
Parameter:
None.
Returns:
If no buffer were ever prepared, ASE_InvalidMode will be returned.
If no input/output is present ASE_NotPresent will be returned.
Notes:
This implies ASIOStop().
*/
ASIOError ASIOControlPanel(void);
/* Purpose:
request the driver to start a control panel component
for device specific user settings. This will not be
accessed on some platforms (where the component is accessed
instead).
Parameter:
None.
Returns:
If no panel is available ASE_NotPresent will be returned.
Actually, the return code is ignored.
Notes:
if the user applied settings which require a re-configuration
of parts or all of the enigine and/or driver (such as a change of
the block size), the asioMessage callback can be used (see
ASIO_Callbacks).
*/
ASIOError ASIOFuture(long selector, void *params);
/* Purpose:
various
Parameter:
selector: operation Code as to be defined. zero is reserved for
testing purposes.
params: depends on the selector; usually pointer to a structure
for passing and retreiving any type and amount of parameters.
Returns:
the return value is also selector dependant. if the selector
is unknown, ASE_InvalidParameter should be returned to prevent
further calls with this selector. on success, ASE_SUCCESS
must be returned (note: ASE_OK is *not* sufficient!)
Notes:
see selectors defined below.
*/
enum
{
kAsioEnableTimeCodeRead = 1, // no arguments
kAsioDisableTimeCodeRead, // no arguments
kAsioSetInputMonitor, // ASIOInputMonitor* in params
kAsioTransport, // ASIOTransportParameters* in params
kAsioSetInputGain, // ASIOChannelControls* in params, apply gain
kAsioGetInputMeter, // ASIOChannelControls* in params, fill meter
kAsioSetOutputGain, // ASIOChannelControls* in params, apply gain
kAsioGetOutputMeter, // ASIOChannelControls* in params, fill meter
kAsioCanInputMonitor, // no arguments for kAsioCanXXX selectors
kAsioCanTimeInfo,
kAsioCanTimeCode,
kAsioCanTransport,
kAsioCanInputGain,
kAsioCanInputMeter,
kAsioCanOutputGain,
kAsioCanOutputMeter
};
typedef struct ASIOInputMonitor
{
long input; // this input was set to monitor (or off), -1: all
long output; // suggested output for monitoring the input (if so)
long gain; // suggested gain, ranging 0 - 0x7fffffffL (-inf to +12 dB)
ASIOBool state; // ASIOTrue => on, ASIOFalse => off
long pan; // suggested pan, 0 => all left, 0x7fffffff => right
} ASIOInputMonitor;
typedef struct ASIOChannelControls
{
long channel; // on input, channel index
ASIOBool isInput; // on input
long gain; // on input, ranges 0 thru 0x7fffffff
long meter; // on return, ranges 0 thru 0x7fffffff
char future[32];
} ASIOChannelControls;
typedef struct ASIOTransportParameters
{
long command; // see enum below
ASIOSamples samplePosition;
long track;
long trackSwitches[16]; // 512 tracks on/off
char future[64];
} ASIOTransportParameters;
enum
{
kTransStart = 1,
kTransStop,
kTransLocate, // to samplePosition
kTransPunchIn,
kTransPunchOut,
kTransArmOn, // track
kTransArmOff, // track
kTransMonitorOn, // track
kTransMonitorOff, // track
kTransArm, // trackSwitches
kTransMonitor // trackSwitches
};
ASIOError ASIOOutputReady(void);
/* Purpose:
this tells the driver that the host has completed processing
the output buffers. if the data format required by the hardware
differs from the supported asio formats, but the hardware
buffers are DMA buffers, the driver will have to convert
the audio stream data; as the bufferSwitch callback is
usually issued at dma block switch time, the driver will
have to convert the *previous* host buffer, which increases
the output latency by one block.
when the host finds out that ASIOOutputReady() returns
true, it will issue this call whenever it completed
output processing. then the driver can convert the
host data directly to the dma buffer to be played next,
reducing output latency by one block.
another way to look at it is, that the buffer switch is called
in order to pass the *input* stream to the host, so that it can
process the input into the output, and the output stream is passed
to the driver when the host has completed its process.
Parameter:
None
Returns:
only if the above mentioned scenario is given, and a reduction
of output latency can be acheived by this mechanism, should
ASE_OK be returned. otherwise (and usually), ASE_NotPresent
should be returned in order to prevent further calls to this
function. note that the host may want to determine if it is
to use this when the system is not yet fully initialized, so
ASE_OK should always be returned if the mechanism makes sense.
Notes:
please remeber to adjust ASIOGetLatencies() according to
whether ASIOOutputReady() was ever called or not, if your
driver supports this scenario.
also note that the engine may fail to call ASIO_OutputReady()
in time in overload cases. as already mentioned, bufferSwitch
should be called for every block regardless of whether a block
could be processed in time.
*/
#ifdef __cplusplus
}
#endif
// restore old alignment
#if defined(_MSC_VER) && !defined(__MWERKS__)
#pragma pack(pop)
#elif PRAGMA_ALIGN_SUPPORTED
#pragma options align = reset
#endif
#endif

View file

@ -0,0 +1,190 @@
#include "asiodrivers.h"
AsioDrivers* asioDrivers = 0;
bool loadAsioDriver(char *name);
bool loadAsioDriver(char *name)
{
if(!asioDrivers)
asioDrivers = new AsioDrivers();
if(asioDrivers)
return asioDrivers->loadDriver(name);
return false;
}
//------------------------------------------------------------------------------------
#if MAC
bool resolveASIO(unsigned long aconnID);
AsioDrivers::AsioDrivers() : CodeFragments("ASIO Drivers", 'AsDr', 'Asio')
{
connID = -1;
curIndex = -1;
}
bool AsioDrivers::close()
{
removeCurrentDriver();
return true;
}
bool AsioDrivers::getCurrentDriverName(char *name)
{
if(curIndex >= 0)
return getName(curIndex, name);
return false;
}
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
{
for(long i = 0; i < getNumFragments() && i < maxDrivers; i++)
getName(i, names[i]);
return getNumFragments() < maxDrivers ? getNumFragments() : maxDrivers;
}
bool AsioDrivers::loadDriver(char *name)
{
char dname[64];
unsigned long newID;
for(long i = 0; i < getNumFragments(); i++)
{
if(getName(i, dname) && !strcmp(name, dname))
{
if(newInstance(i, &newID))
{
if(resolveASIO(newID))
{
if(connID != -1)
removeInstance(curIndex, connID);
curIndex = i;
connID = newID;
return true;
}
}
break;
}
}
return false;
}
void AsioDrivers::removeCurrentDriver()
{
if(connID != -1)
removeInstance(curIndex, connID);
connID = -1;
curIndex = -1;
}
//------------------------------------------------------------------------------------
#elif WINDOWS
#include "iasiodrv.h"
extern IASIO* theAsioDriver;
AsioDrivers::AsioDrivers() : AsioDriverList()
{
curIndex = -1;
}
bool AsioDrivers::close()
{
AsioDriverList::close();
return true;
}
bool AsioDrivers::getCurrentDriverName(char *name)
{
if(curIndex >= 0)
return asioGetDriverName(curIndex, name, 32) == 0 ? true : false;
name[0] = 0;
return false;
}
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
{
for(long i = 0; i < asioGetNumDev() && i < maxDrivers; i++)
asioGetDriverName(i, names[i], 32);
return asioGetNumDev() < maxDrivers ? asioGetNumDev() : maxDrivers;
}
bool AsioDrivers::loadDriver(char *name)
{
char dname[64];
char curName[64];
for(long i = 0; i < asioGetNumDev(); i++)
{
if(!asioGetDriverName(i, dname, 32) && !strcmp(name, dname))
{
curName[0] = 0;
getCurrentDriverName(curName); // in case we fail...
removeCurrentDriver();
if(!asioOpenDriver(i, (void **)&theAsioDriver))
{
curIndex = i;
return true;
}
else
{
theAsioDriver = 0;
if(curName[0] && strcmp(dname, curName))
loadDriver(curName); // try restore
}
break;
}
}
return false;
}
void AsioDrivers::removeCurrentDriver()
{
if(curIndex != -1)
asioCloseDriver(curIndex);
curIndex = -1;
}
#elif SGI || BEOS
#include "asiolist.h"
AsioDrivers::AsioDrivers()
: AsioDriverList()
{
curIndex = -1;
}
bool AsioDrivers::close()
{
return true;
}
bool AsioDrivers::getCurrentDriverName(char *name)
{
return false;
}
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
{
return 0;
}
bool AsioDrivers::loadDriver(char *name)
{
return false;
}
void AsioDrivers::removeCurrentDriver()
{
}
#else
#error implement me
#endif

View file

@ -0,0 +1,41 @@
#ifndef __AsioDrivers__
#define __AsioDrivers__
#include "ginclude.h"
#if MAC
#include "CodeFragments.hpp"
class AsioDrivers : public CodeFragments
#elif WINDOWS
#include <windows.h>
#include "asiolist.h"
class AsioDrivers : public AsioDriverList
#elif SGI || BEOS
#include "asiolist.h"
class AsioDrivers : public AsioDriverList
#else
#error implement me
#endif
{
public:
AsioDrivers();
bool close();
bool getCurrentDriverName(char *name);
long getDriverNames(char **names, long maxDrivers);
bool loadDriver(char *name);
void removeCurrentDriver();
long getCurrentDriverIndex() {return curIndex;}
protected:
unsigned long connID;
long curIndex;
};
#endif

273
fmod/win32/src/asio/asiolist.cpp Executable file
View file

@ -0,0 +1,273 @@
#include <windows.h>
#include "iasiodrv.h"
#include "asiolist.h"
#include "fmod_memory.h"
#define ASIODRV_DESC "description"
#define INPROC_SERVER "InprocServer32"
#define ASIO_PATH "software\\asio"
#define COM_CLSID "clsid"
// ******************************************************************
// Local Functions
// ******************************************************************
static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)
{
HKEY hkEnum,hksub,hkpath;
char databuf[512];
LONG cr,rc = -1;
DWORD datatype,datasize;
DWORD index;
OFSTRUCT ofs;
HFILE hfile;
BOOL found = FALSE;
CharLowerBuff(clsidstr,(DWORD)strlen(clsidstr));
if ((cr = RegOpenKey(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
index = 0;
while (cr == ERROR_SUCCESS && !found) {
cr = RegEnumKey(hkEnum,index++,(LPTSTR)databuf,512);
if (cr == ERROR_SUCCESS) {
CharLowerBuff(databuf,(DWORD)strlen(databuf));
if (!(strcmp(databuf,clsidstr))) {
if ((cr = RegOpenKeyEx(hkEnum,(LPCTSTR)databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
if ((cr = RegOpenKeyEx(hksub,(LPCTSTR)INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {
datatype = REG_SZ; datasize = (DWORD)dllpathsize;
cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);
if (cr == ERROR_SUCCESS) {
FMOD_memset(&ofs,0,sizeof(OFSTRUCT));
ofs.cBytes = sizeof(OFSTRUCT);
hfile = OpenFile(dllpath,&ofs,OF_EXIST);
if (hfile) rc = 0;
}
RegCloseKey(hkpath);
}
RegCloseKey(hksub);
}
found = TRUE; // break out
}
}
}
RegCloseKey(hkEnum);
}
return rc;
}
static LPASIODRVSTRUCT newDrvStruct (HKEY hkey,char *keyname,int drvID,LPASIODRVSTRUCT lpdrv)
{
HKEY hksub;
char databuf[256];
char dllpath[MAXPATHLEN];
WORD wData[100];
CLSID clsid;
DWORD datatype,datasize;
LONG cr,rc;
if (!lpdrv) {
if ((cr = RegOpenKeyEx(hkey,(LPCTSTR)keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
datatype = REG_SZ; datasize = 256;
cr = RegQueryValueEx(hksub,COM_CLSID,0,&datatype,(LPBYTE)databuf,&datasize);
if (cr == ERROR_SUCCESS) {
rc = findDrvPath (databuf,dllpath,MAXPATHLEN);
if (rc == 0) {
lpdrv = FMOD_Object_Calloc(ASIODRVSTRUCT);
if (lpdrv) {
FMOD_memset(lpdrv,0,sizeof(ASIODRVSTRUCT));
lpdrv->drvID = drvID;
MultiByteToWideChar(CP_ACP,0,(LPCSTR)databuf,-1,(LPWSTR)wData,100);
if ((cr = CLSIDFromString((LPOLESTR)wData,(LPCLSID)&clsid)) == S_OK) {
FMOD_memcpy(&lpdrv->clsid,&clsid,sizeof(CLSID));
}
datatype = REG_SZ; datasize = 256;
cr = RegQueryValueEx(hksub,ASIODRV_DESC,0,&datatype,(LPBYTE)databuf,&datasize);
if (cr == ERROR_SUCCESS) {
strcpy(lpdrv->drvname,databuf);
}
else strcpy(lpdrv->drvname,keyname);
}
}
}
RegCloseKey(hksub);
}
}
else lpdrv->next = newDrvStruct(hkey,keyname,drvID+1,lpdrv->next);
return lpdrv;
}
static void deleteDrvStruct (LPASIODRVSTRUCT lpdrv)
{
IASIO *iasio;
if (lpdrv != 0) {
deleteDrvStruct(lpdrv->next);
if (lpdrv->asiodrv) {
iasio = (IASIO *)lpdrv->asiodrv;
iasio->Release();
}
FMOD_Memory_Free(lpdrv);
}
}
static LPASIODRVSTRUCT getDrvStruct (int drvID,LPASIODRVSTRUCT lpdrv)
{
while (lpdrv) {
if (lpdrv->drvID == drvID) return lpdrv;
lpdrv = lpdrv->next;
}
return 0;
}
// ******************************************************************
// ******************************************************************
// AsioDriverList
// ******************************************************************
AsioDriverList::AsioDriverList ()
{
HKEY hkEnum = 0;
char keyname[MAXDRVNAMELEN];
LPASIODRVSTRUCT pdl;
LONG cr;
DWORD index = 0;
BOOL fin = FALSE;
numdrv = 0;
lpdrvlist = 0;
cr = RegOpenKey(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);
while (cr == ERROR_SUCCESS) {
if ((cr = RegEnumKey(hkEnum,index++,(LPTSTR)keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist);
}
else fin = TRUE;
}
if (hkEnum) RegCloseKey(hkEnum);
pdl = lpdrvlist;
while (pdl) {
numdrv++;
pdl = pdl->next;
}
if (numdrv) CoInitialize(0); // initialize COM
}
bool AsioDriverList::close()
{
if (numdrv) {
deleteDrvStruct(lpdrvlist);
CoUninitialize();
}
return true;
}
LONG AsioDriverList::asioGetNumDev (VOID)
{
return (LONG)numdrv;
}
LONG AsioDriverList::asioOpenDriver (int drvID,LPVOID *asiodrv)
{
LPASIODRVSTRUCT lpdrv = 0;
long rc;
if (!asiodrv) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (!lpdrv->asiodrv) {
rc = CoCreateInstance(lpdrv->clsid,0,CLSCTX_INPROC_SERVER,lpdrv->clsid,asiodrv);
if (rc == S_OK) {
lpdrv->asiodrv = *asiodrv;
return 0;
}
// else if (rc == REGDB_E_CLASSNOTREG)
// strcpy (info->messageText, "Driver not registered in the Registration Database!");
}
else rc = DRVERR_DEVICE_ALREADY_OPEN;
}
else rc = DRVERR_DEVICE_NOT_FOUND;
return rc;
}
LONG AsioDriverList::asioCloseDriver (int drvID)
{
LPASIODRVSTRUCT lpdrv = 0;
IASIO *iasio;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (lpdrv->asiodrv) {
iasio = (IASIO *)lpdrv->asiodrv;
iasio->Release();
lpdrv->asiodrv = 0;
}
}
return 0;
}
LONG AsioDriverList::asioGetDriverName (int drvID,char *drvname,int drvnamesize)
{
LPASIODRVSTRUCT lpdrv = 0;
if (!drvname) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (strlen(lpdrv->drvname) < (unsigned int)drvnamesize) {
strcpy(drvname,lpdrv->drvname);
}
else {
FMOD_memcpy(drvname,lpdrv->drvname,drvnamesize-4);
drvname[drvnamesize-4] = '.';
drvname[drvnamesize-3] = '.';
drvname[drvnamesize-2] = '.';
drvname[drvnamesize-1] = 0;
}
return 0;
}
return DRVERR_DEVICE_NOT_FOUND;
}
LONG AsioDriverList::asioGetDriverPath (int drvID,char *dllpath,int dllpathsize)
{
LPASIODRVSTRUCT lpdrv = 0;
if (!dllpath) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (strlen(lpdrv->dllpath) < (unsigned int)dllpathsize) {
strcpy(dllpath,lpdrv->dllpath);
return 0;
}
dllpath[0] = 0;
return DRVERR_INVALID_PARAM;
}
return DRVERR_DEVICE_NOT_FOUND;
}
LONG AsioDriverList::asioGetDriverCLSID (int drvID,CLSID *clsid)
{
LPASIODRVSTRUCT lpdrv = 0;
if (!clsid) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
FMOD_memcpy(clsid,&lpdrv->clsid,sizeof(CLSID));
return 0;
}
return DRVERR_DEVICE_NOT_FOUND;
}

46
fmod/win32/src/asio/asiolist.h Executable file
View file

@ -0,0 +1,46 @@
#ifndef __asiolist__
#define __asiolist__
#define DRVERR -5000
#define DRVERR_INVALID_PARAM DRVERR-1
#define DRVERR_DEVICE_ALREADY_OPEN DRVERR-2
#define DRVERR_DEVICE_NOT_FOUND DRVERR-3
#define MAXPATHLEN 512
#define MAXDRVNAMELEN 128
struct asiodrvstruct
{
int drvID;
CLSID clsid;
char dllpath[MAXPATHLEN];
char drvname[MAXDRVNAMELEN];
LPVOID asiodrv;
struct asiodrvstruct *next;
};
typedef struct asiodrvstruct ASIODRVSTRUCT;
typedef ASIODRVSTRUCT *LPASIODRVSTRUCT;
class AsioDriverList {
public:
AsioDriverList();
bool close();
LONG asioOpenDriver (int,VOID **);
LONG asioCloseDriver (int);
// nice to have
LONG asioGetNumDev (VOID);
LONG asioGetDriverName (int,char *,int);
LONG asioGetDriverPath (int,char *,int);
LONG asioGetDriverCLSID (int,CLSID *);
// or use directly access
LPASIODRVSTRUCT lpdrvlist;
int numdrv;
};
typedef class AsioDriverList *LPASIODRIVERLIST;
#endif

82
fmod/win32/src/asio/asiosys.h Executable file
View file

@ -0,0 +1,82 @@
#ifndef __asiosys__
#define __asiosys__
#ifdef WIN32
#undef MAC
#define PPC 0
#define WINDOWS 1
#define SGI 0
#define SUN 0
#define LINUX 0
#define BEOS 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#elif BEOS
#define MAC 0
#define PPC 0
#define WINDOWS 0
#define PC 0
#define SGI 0
#define SUN 0
#define LINUX 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#ifndef DEBUG
#define DEBUG 0
#if DEBUG
void DEBUGGERMESSAGE(char *string);
#else
#define DEBUGGERMESSAGE(a)
#endif
#endif
#elif SGI
#define MAC 0
#define PPC 0
#define WINDOWS 0
#define PC 0
#define SUN 0
#define LINUX 0
#define BEOS 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#ifndef DEBUG
#define DEBUG 0
#if DEBUG
void DEBUGGERMESSAGE(char *string);
#else
#define DEBUGGERMESSAGE(a)
#endif
#endif
#else // MAC
#define MAC 1
#define PPC 1
#define WINDOWS 0
#define PC 0
#define SGI 0
#define SUN 0
#define LINUX 0
#define BEOS 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#ifndef DEBUG
#define DEBUG 0
#if DEBUG
void DEBUGGERMESSAGE(char *string);
#else
#define DEBUGGERMESSAGE(a)
#endif
#endif
#endif
#endif

38
fmod/win32/src/asio/ginclude.h Executable file
View file

@ -0,0 +1,38 @@
#ifndef __gInclude__
#define __gInclude__
#if SGI
#undef BEOS
#undef MAC
#undef WINDOWS
//
#define ASIO_BIG_ENDIAN 1
#define ASIO_CPU_MIPS 1
#elif defined WIN32
#undef BEOS
#undef MAC
#undef SGI
#define WINDOWS 1
#define ASIO_LITTLE_ENDIAN 1
#define ASIO_CPU_X86 1
#elif BEOS
#undef MAC
#undef SGI
#undef WINDOWS
#define ASIO_LITTLE_ENDIAN 1
#define ASIO_CPU_X86 1
//
#else
#define MAC 1
#undef BEOS
#undef WINDOWS
#undef SGI
#define ASIO_BIG_ENDIAN 1
#define ASIO_CPU_PPC 1
#endif
// always
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#endif // __gInclude__

37
fmod/win32/src/asio/iasiodrv.h Executable file
View file

@ -0,0 +1,37 @@
#include "asiosys.h"
#include "asio.h"
/* Forward Declarations */
#ifndef __ASIODRIVER_FWD_DEFINED__
#define __ASIODRIVER_FWD_DEFINED__
typedef interface IASIO IASIO;
#endif /* __ASIODRIVER_FWD_DEFINED__ */
interface IASIO : public IUnknown
{
virtual ASIOBool init(void *sysHandle) = 0;
virtual void getDriverName(char *name) = 0;
virtual long getDriverVersion() = 0;
virtual void getErrorMessage(char *string) = 0;
virtual ASIOError start() = 0;
virtual ASIOError stop() = 0;
virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels) = 0;
virtual ASIOError getLatencies(long *inputLatency, long *outputLatency) = 0;
virtual ASIOError getBufferSize(long *minSize, long *maxSize,
long *preferredSize, long *granularity) = 0;
virtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0;
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate) = 0;
virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0;
virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources) = 0;
virtual ASIOError setClockSource(long reference) = 0;
virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
virtual ASIOError getChannelInfo(ASIOChannelInfo *info) = 0;
virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks) = 0;
virtual ASIOError disposeBuffers() = 0;
virtual ASIOError controlPanel() = 0;
virtual ASIOError future(long selector,void *opt) = 0;
virtual ASIOError outputReady() = 0;
};

59
fmod/win32/src/c32.mac Executable file
View file

@ -0,0 +1,59 @@
; NASM macro set to make interfacing to 32-bit programs easier -*- nasm -*-
%imacro proc 1 ; begin a procedure definition
%push proc
%ifdef PLATFORM_LINUX
global _%1:function
global %1:function
%else
global _%1
global %1
%endif
_%1:
%1: push ebp
mov ebp,esp
%assign %$arg 8
%define %$procname %1
%endmacro
%imacro arg 0-1 4 ; used with the argument name as a label
%00 equ %$arg
%assign %$arg %1+%$arg
%endmacro
%imacro endproc 0
%ifnctx proc
%error Mismatched `endproc'/`proc'
%else
leave
ret
__end_%$procname: ; useful for calculating function size
___end_%$procname:
%pop
%endif
%endmacro

211
fmod/win32/src/fmod_3dl2.h Executable file
View file

@ -0,0 +1,211 @@
// 3DL2.H
//
#ifndef _3DL2_H_INCLUDED
#define _3DL2_H_INCLUDED
#include <dxsdkver.h>
#if (_DXSDK_PRODUCT_MAJOR < 9 || (_DXSDK_PRODUCT_MAJOR == 9 && _DXSDK_PRODUCT_MINOR < 21))
#include <dplay.h> /* This defines DWORD_PTR for dsound.h to use. */
#endif
#include <dsound.h>
#define FLOAT float
#define LONG long
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#pragma pack(push, 4)
// I3DL2 listener property set {DA0F0520-300A-11D3-8A2B-0060970DB011}
DEFINE_GUID(DSPROPSETID_I3DL2_ListenerProperties,
0xDA0F0520,
0x300A,
0x11D3,
0x8A, 0x2B, 0x00, 0x60, 0x97, 0x0D, 0xB0, 0x11);
typedef enum
{
DSPROPERTY_I3DL2LISTENER_ALL, // sets all I3DL2 listener properties
DSPROPERTY_I3DL2LISTENER_ROOM, // room effect level at low frequencies
DSPROPERTY_I3DL2LISTENER_ROOMHF, // room effect high-frequency level re. low frequency level
DSPROPERTY_I3DL2LISTENER_ROOMROLLOFFFACTOR, // like DS3D flRolloffFactor but for room effect
DSPROPERTY_I3DL2LISTENER_DECAYTIME, // reverberation decay time at low-frequencies
DSPROPERTY_I3DL2LISTENER_DECAYHFRATIO, // high-frequency to low-frequency decay time ratio
DSPROPERTY_I3DL2LISTENER_REFLECTIONS, // early reflections level relative to room effect
DSPROPERTY_I3DL2LISTENER_REFLECTIONSDELAY, // delay time of first reflection
DSPROPERTY_I3DL2LISTENER_REVERB, // late reverberation level relative to room effect
DSPROPERTY_I3DL2LISTENER_REVERBDELAY, // late reverberation delay time relative to first reflection
DSPROPERTY_I3DL2LISTENER_DIFFUSION, // reverberation diffusion (echo density)
DSPROPERTY_I3DL2LISTENER_DENSITY, // reverberation density (modal density)
DSPROPERTY_I3DL2LISTENER_HFREFERENCE // reference high frequency
} DSPROPERTY_I3DL2_LISTENERPROPERTY;
// use this structure for DSPROPERTY_I3DL2LISTENER_ALL
// - all levels are hundredths of decibels (mB)
// - all times are in seconds (s)
typedef struct _I3DL2_LISTENERPROPERTIES
{
LONG lRoom; // [-10000, 0] default: -10000 mB
LONG lRoomHF; // [-10000, 0] default: 0 mB
FLOAT flRoomRolloffFactor; // [0.0, 10.0] default: 0.0
FLOAT flDecayTime; // [0.1, 20.0] default: 1.0 s
FLOAT flDecayHFRatio; // [0.1, 2.0] default: 0.5
LONG lReflections; // [-10000, 1000] default: -10000 mB
FLOAT flReflectionsDelay; // [0.0, 0.3] default: 0.02 s
LONG lReverb; // [-10000, 2000] default: -10000 mB
FLOAT flReverbDelay; // [0.0, 0.1] default: 0.04 s
FLOAT flDiffusion ; // [0.0, 100.0] default: 100.0 %
FLOAT flDensity; // [0.0, 100.0] default: 100.0 %
FLOAT flHFReference; // [20.0, 20000.0] default: 5000.0 Hz
} I3DL2_LISTENERPROPERTIES, *LPI3DL2_LISTENERPROPERTIES;
// property ranges and defaults:
#define I3DL2LISTENER_MINROOM -10000
#define I3DL2LISTENER_MAXROOM 0
#define I3DL2LISTENER_DEFAULTROOM -10000
#define I3DL2LISTENER_MINROOMHF -10000
#define I3DL2LISTENER_MAXROOMHF 0
#define I3DL2LISTENER_DEFAULTROOMHF 0
#define I3DL2LISTENER_MINROOMROLLOFFFACTOR 0.0f
#define I3DL2LISTENER_MAXROOMROLLOFFFACTOR 10.0f
#define I3DL2LISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f
#define I3DL2LISTENER_MINDECAYTIME 0.1f
#define I3DL2LISTENER_MAXDECAYTIME 20.0f
#define I3DL2LISTENER_DEFAULTDECAYTIME 1.0f
#define I3DL2LISTENER_MINDECAYHFRATIO 0.1f
#define I3DL2LISTENER_MAXDECAYHFRATIO 2.0f
#define I3DL2LISTENER_DEFAULTDECAYHFRATIO 0.5f
#define I3DL2LISTENER_MINREFLECTIONS -10000
#define I3DL2LISTENER_MAXREFLECTIONS 1000
#define I3DL2LISTENER_DEFAULTREFLECTIONS -10000
#define I3DL2LISTENER_MINREFLECTIONSDELAY 0.0f
#define I3DL2LISTENER_MAXREFLECTIONSDELAY 0.3f
#define I3DL2LISTENER_DEFAULTREFLECTIONSDELAY 0.02f
#define I3DL2LISTENER_MINREVERB -10000
#define I3DL2LISTENER_MAXREVERB 2000
#define I3DL2LISTENER_DEFAULTREVERB -10000
#define I3DL2LISTENER_MINREVERBDELAY 0.0f
#define I3DL2LISTENER_MAXREVERBDELAY 0.1f
#define I3DL2LISTENER_DEFAULTREVERBDELAY 0.04f
#define I3DL2LISTENER_MINDIFFUSION 0.0f
#define I3DL2LISTENER_MAXDIFFUSION 100.0f
#define I3DL2LISTENER_DEFAULTDIFFUSION 100.0f
#define I3DL2LISTENER_MINDENSITY 0.0f
#define I3DL2LISTENER_MAXDENSITY 100.0f
#define I3DL2LISTENER_DEFAULTDENSITY 100.0f
#define I3DL2LISTENER_MINHFREFERENCE 20.0f
#define I3DL2LISTENER_MAXHFREFERENCE 20000.0f
#define I3DL2LISTENER_DEFAULTHFREFERENCE 5000.0f
// I3DL2 buffer property set {DA0F0521-300A-11D3-8A2B-0060970DB011}
DEFINE_GUID(DSPROPSETID_I3DL2_BufferProperties,
0xDA0F0521,
0x300A,
0x11D3,
0x8A, 0x2B, 0x00, 0x60, 0x97, 0x0D, 0xB0, 0x11);
typedef enum
{
DSPROPERTY_I3DL2BUFFER_ALL, // sets all I3DL2 buffer properties
DSPROPERTY_I3DL2BUFFER_OBSTRUCTIONALL, // sets both obstruction properties
DSPROPERTY_I3DL2BUFFER_OCCLUSIONALL, // sets both occlusion properties
DSPROPERTY_I3DL2BUFFER_DIRECT, // additional direct path level correction
DSPROPERTY_I3DL2BUFFER_DIRECTHF, // additional direct path high-frequency re. low-frequency level correction
DSPROPERTY_I3DL2BUFFER_ROOM, // additional room effect level correction
DSPROPERTY_I3DL2BUFFER_ROOMHF, // additional room effect high-frequency re. low-frequency level correction
DSPROPERTY_I3DL2BUFFER_ROOMROLLOFFFACTOR, // like DS3D flRolloffFactor but for room effect
DSPROPERTY_I3DL2BUFFER_OBSTRUCTION, // main obstruction control (attenuation at high frequencies)
DSPROPERTY_I3DL2BUFFER_OBSTRUCTIONLFRATIO, // obstruction low-frequency re. high-frequency ratio
DSPROPERTY_I3DL2BUFFER_OCCLUSION, // main occlusion control (attenuation at high frequencies)
DSPROPERTY_I3DL2BUFFER_OCCLUSIONLFRATIO // occlusion low-frequency re. high-frequency ratio
} DSPROPERTY_I3DL2_BUFFERPROPERTY;
// use this structure for DSPROPERTY_I3DL2BUFFER_OBSTRUCTIONALL
// - all levels are hundredths of decibels (mB)
typedef struct _I3DL2_OBSTRUCTIONPROPERTIES
{
LONG lHFLevel; // [-10000, 0] default: 0 mB
FLOAT flLFRatio; // [0.0, 1.0] default: 0.0
} I3DL2_OBSTRUCTIONPROPERTIES, *LPI3DL2_OBSTRUCTIONPROPERTIES;
// use this structure for DSPROPERTY_I3DL2BUFFER_OCCLUSIONALL
// - all levels are hundredths of decibels (mB)
typedef struct _I3DL2_OCCLUSIONPROPERTIES
{
LONG lHFLevel; // [-10000, 0] default: 0 mB
FLOAT flLFRatio; // [0.0, 1.0] default: 0.25
} I3DL2_OCCLUSIONPROPERTIES, *LPI3DL2_OCCLUSIONPROPERTIES;
// use this structure for DSPROPERTY_I3DL2BUFFER_ALL
// - all levels are hundredths of decibels (mB)
typedef struct _I3DL2_BUFFERPROPERTIES
{
LONG lDirect; // [-10000, 1000] default: 0 mB
LONG lDirectHF; // [-10000, 0] default: 0 mB
LONG lRoom; // [-10000, 1000] default: 0 mB
LONG lRoomHF; // [-10000, 0] default: 0 mB
FLOAT flRoomRolloffFactor; // [0.0, 10.0] default: 0.0
I3DL2_OBSTRUCTIONPROPERTIES Obstruction;
I3DL2_OCCLUSIONPROPERTIES Occlusion;
} I3DL2_BUFFERPROPERTIES, *LPI3DL2_BUFFERPROPERTIES;
// property ranges and defaults:
#define I3DL2BUFFER_MINDIRECT -10000
#define I3DL2BUFFER_MAXDIRECT 1000
#define I3DL2BUFFER_DEFAULTDIRECT 0
#define I3DL2BUFFER_MINDIRECTHF -10000
#define I3DL2BUFFER_MAXDIRECTHF 0
#define I3DL2BUFFER_DEFAULTDIRECTHF 0
#define I3DL2BUFFER_MINROOM -10000
#define I3DL2BUFFER_MAXROOM 1000
#define I3DL2BUFFER_DEFAULTROOM 0
#define I3DL2BUFFER_MINROOMHF -10000
#define I3DL2BUFFER_MAXROOMHF 0
#define I3DL2BUFFER_DEFAULTROOMHF 0
#define I3DL2BUFFER_MINROOMROLLOFFFACTOR 0.0f
#define I3DL2BUFFER_MAXROOMROLLOFFFACTOR 10.f
#define I3DL2BUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f
#define I3DL2BUFFER_MINOBSTRUCTION -10000
#define I3DL2BUFFER_MAXOBSTRUCTION 0
#define I3DL2BUFFER_DEFAULTOBSTRUCTION 0
#define I3DL2BUFFER_MINOBSTRUCTIONLFRATIO 0.0f
#define I3DL2BUFFER_MAXOBSTRUCTIONLFRATIO 1.0f
#define I3DL2BUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f
#define I3DL2BUFFER_MINOCCLUSION -10000
#define I3DL2BUFFER_MAXOCCLUSION 0
#define I3DL2BUFFER_DEFAULTOCCLUSION 0
#define I3DL2BUFFER_MINOCCLUSIONLFRATIO 0.0f
#define I3DL2BUFFER_MAXOCCLUSIONLFRATIO 1.0f
#define I3DL2BUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f
#pragma pack(pop)
#ifdef __cplusplus
}
#endif // __cplusplus
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,67 @@
#ifndef _FMOD_CHANNEL_DSOUND_H
#define _FMOD_CHANNEL_DSOUND_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_DSOUND
#include "fmod_channel_real.h"
#ifdef PLATFORM_32BIT
typedef unsigned long DWORD;
typedef DWORD DWORD_PTR;
#endif
#include <dsound.h>
namespace FMOD
{
class Output;
class ChannelDSound : public ChannelReal
{
friend class OutputDSound;
private:
bool mLOCSoftware;
protected:
OutputDSound *mOutputDSound;
IDirectSoundBuffer8 *mBuffer;
IDirectSound3DBuffer *mBuffer3D;
IKsPropertySet *mBufferReverb;
IKsPropertySet *mBufferQuality;
public:
ChannelDSound() {}
FMOD_RESULT init (int index, SystemI *system, Output *output, DSPI *dspmixtarget);
FMOD_RESULT alloc ();
FMOD_RESULT start ();
FMOD_RESULT stop ();
FMOD_RESULT setVolume (float volume);
FMOD_RESULT setFrequency (float frequency);
FMOD_RESULT setPan (float pan, float fbpan = 1);
FMOD_RESULT setSpeakerLevels (int speaker, float *levels, int numlevels);
FMOD_RESULT setSpeakerMix (float frontleft, float frontright, float center, float lfe, float backleft, float backright, float sideleft, float sideright);
FMOD_RESULT setPaused (bool paused);
FMOD_RESULT setPosition (unsigned int position, FMOD_TIMEUNIT postype);
FMOD_RESULT getPosition (unsigned int *position, FMOD_TIMEUNIT postype);
FMOD_RESULT set3DAttributes ();
FMOD_RESULT set3DMinMaxDistance ();
FMOD_RESULT set3DOcclusion (float directOcclusion, float reverbOcclusion);
FMOD_RESULT isPlaying (bool *isplaying, bool includethreadlatency = false);
FMOD_RESULT setMode (FMOD_MODE mode);
FMOD_RESULT getBuffer3D (IDirectSound3DBuffer **buffer3d);
};
}
#endif /* FMOD_SUPPORT_DSOUND */
#endif

View file

@ -0,0 +1,193 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_EAX
#include "fmod_output_dsound.h"
#include "fmod_channel_dsound_eax2.h"
#include "fmod_eax2.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelDSoundEAX2::setReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop)
{
HRESULT hr;
EAXBUFFERPROPERTIES dsprops;
GUID guid;
if (!mOutputDSound)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mBuffer3D)
{
return FMOD_ERR_UNSUPPORTED;
}
/*
OBTAIN REVERB INTERFACE
*/
if (!mBufferReverb)
{
if (mFlags & CHANNELREAL_FLAG_PAUSED && mOutputDSound->mDirectXVersion >= 8)
{
mBuffer->AcquireResources(DSBPLAY_LOCHARDWARE, 0, NULL);
}
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
hr = mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb);
if (hr != DS_OK)
{
return FMOD_ERR_UNSUPPORTED;
}
}
/*
NOW SET CHANNEL PROPERTIES
*/
dsprops.lDirect = prop->Direct;
dsprops.lDirectHF = prop->DirectHF;
dsprops.lRoom = prop->Room;
dsprops.lRoomHF = prop->RoomHF;
dsprops.lObstruction = prop->Obstruction;
dsprops.flObstructionLFRatio = prop->ObstructionLFRatio;
dsprops.lOcclusion = prop->Occlusion;
dsprops.flOcclusionLFRatio = prop->OcclusionLFRatio;
dsprops.flOcclusionRoomRatio = prop->OcclusionRoomRatio;
dsprops.lOutsideVolumeHF = prop->OutsideVolumeHF;
dsprops.flRoomRolloffFactor = prop->RoomRolloffFactor;
dsprops.flAirAbsorptionFactor = prop->AirAbsorptionFactor;
dsprops.dwFlags = prop->Flags;
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX20_BufferProperties, sizeof(GUID));
hr = mBufferReverb->Set(guid, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, NULL, 0, &dsprops, sizeof(EAXBUFFERPROPERTIES));
if (FAILED(hr))
{
return FMOD_ERR_INVALID_PARAM;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelDSoundEAX2::getReverbProperties(FMOD_REVERB_CHANNELPROPERTIES *prop)
{
HRESULT hr;
EAXBUFFERPROPERTIES dsprops;
GUID guid;
ULONG ulReceived;
if (!mOutputDSound)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mBuffer3D)
{
return FMOD_ERR_UNSUPPORTED;
}
/*
OBTAIN REVERB INTERFACE
*/
if (!mBufferReverb)
{
if (mFlags & CHANNELREAL_FLAG_PAUSED && mOutputDSound->mDirectXVersion >= 8)
{
mBuffer->AcquireResources(DSBPLAY_LOCHARDWARE, 0, NULL);
}
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
hr = mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb);
if (hr != DS_OK)
{
return FMOD_ERR_UNSUPPORTED;
}
}
/*
Get reverb properties
*/
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX20_BufferProperties, sizeof(GUID));
hr = mBufferReverb->Get(guid, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, NULL, 0, &dsprops, sizeof(EAXBUFFERPROPERTIES), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_UNSUPPORTED;
}
prop->Direct = dsprops.lDirect;
prop->DirectHF = dsprops.lDirectHF;
prop->Room = dsprops.lRoom;
prop->RoomHF = dsprops.lRoomHF;
prop->Obstruction = dsprops.lObstruction;
prop->ObstructionLFRatio = dsprops.flObstructionLFRatio;
prop->Occlusion = dsprops.lOcclusion;
prop->OcclusionLFRatio = dsprops.flOcclusionLFRatio;
prop->OcclusionRoomRatio = dsprops.flOcclusionRoomRatio;
prop->OcclusionDirectRatio = 0;
prop->Exclusion = 0;
prop->ExclusionLFRatio = 0;
prop->OutsideVolumeHF = dsprops.lOutsideVolumeHF;
prop->DopplerFactor = 0;
prop->RolloffFactor = 0;
prop->RoomRolloffFactor = dsprops.flRoomRolloffFactor;
prop->AirAbsorptionFactor = dsprops.flAirAbsorptionFactor;
prop->Flags = dsprops.dwFlags;
return FMOD_OK;
}
}
#endif

View file

@ -0,0 +1,25 @@
#ifndef _FMOD_CHANNEL_DSOUND_EAX2_H
#define _FMOD_CHANNEL_DSOUND_EAX2_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_dsound.h"
namespace FMOD
{
class ChannelDSoundEAX2 : public ChannelDSound
{
public:
ChannelDSoundEAX2() {};
FMOD_RESULT setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop);
};
}
#endif /* FMOD_SUPPORT_EAX */
#endif

View file

@ -0,0 +1,197 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_dsound_eax3.h"
#include "fmod_eax3.h"
#include "fmod_output_dsound.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelDSoundEAX3::setReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop)
{
HRESULT hr;
EAXBUFFERPROPERTIES dsprops;
GUID guid;
if (!mOutputDSound)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mBuffer3D)
{
return FMOD_ERR_UNSUPPORTED;
}
/*
OBTAIN REVERB INTERFACE
*/
if (!mBufferReverb)
{
if (mFlags & CHANNELREAL_FLAG_PAUSED && mOutputDSound->mDirectXVersion >= 8)
{
mBuffer->AcquireResources(DSBPLAY_LOCHARDWARE, 0, NULL);
}
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
hr = mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb);
if (hr != DS_OK)
{
return FMOD_ERR_UNSUPPORTED;
}
}
/*
NOW SET CHANNEL PROPERTIES
*/
dsprops.lDirect = prop->Direct;
dsprops.lDirectHF = prop->DirectHF;
dsprops.lRoom = prop->Room;
dsprops.lRoomHF = prop->RoomHF;
dsprops.lObstruction = prop->Obstruction;
dsprops.flObstructionLFRatio = prop->ObstructionLFRatio;
dsprops.lOcclusion = prop->Occlusion;
dsprops.flOcclusionLFRatio = prop->OcclusionLFRatio;
dsprops.flOcclusionRoomRatio = prop->OcclusionRoomRatio;
dsprops.flOcclusionDirectRatio = prop->OcclusionDirectRatio;
dsprops.lExclusion = prop->Exclusion;
dsprops.flExclusionLFRatio = prop->ExclusionLFRatio;
dsprops.lOutsideVolumeHF = prop->OutsideVolumeHF;
dsprops.flDopplerFactor = prop->DopplerFactor;
dsprops.flRolloffFactor = prop->RolloffFactor;
dsprops.flRoomRolloffFactor = prop->RoomRolloffFactor;
dsprops.flAirAbsorptionFactor = prop->AirAbsorptionFactor;
dsprops.ulFlags = prop->Flags;
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX30_BufferProperties, sizeof(GUID));
hr = mBufferReverb->Set(guid, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, NULL, 0, &dsprops, sizeof(EAXBUFFERPROPERTIES));
if (FAILED(hr))
{
return FMOD_ERR_INVALID_PARAM;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelDSoundEAX3::getReverbProperties(FMOD_REVERB_CHANNELPROPERTIES *prop)
{
HRESULT hr;
EAXBUFFERPROPERTIES dsprops;
GUID guid;
ULONG ulReceived;
if (!mOutputDSound)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mBuffer3D)
{
return FMOD_ERR_UNSUPPORTED;
}
/*
OBTAIN REVERB INTERFACE
*/
if (!mBufferReverb)
{
if (mFlags & CHANNELREAL_FLAG_PAUSED && mOutputDSound->mDirectXVersion >= 8)
{
mBuffer->AcquireResources(DSBPLAY_LOCHARDWARE, 0, NULL);
}
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
hr = mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb);
if (hr != DS_OK)
{
return FMOD_ERR_UNSUPPORTED;
}
}
/*
Get reverb properties
*/
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX30_BufferProperties, sizeof(GUID));
hr = mBufferReverb->Get(guid, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, NULL, 0, &dsprops, sizeof(EAXBUFFERPROPERTIES), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_UNSUPPORTED;
}
prop->Direct = dsprops.lDirect;
prop->DirectHF = dsprops.lDirectHF;
prop->Room = dsprops.lRoom;
prop->RoomHF = dsprops.lRoomHF;
prop->Obstruction = dsprops.lObstruction;
prop->ObstructionLFRatio = dsprops.flObstructionLFRatio;
prop->Occlusion = dsprops.lOcclusion;
prop->OcclusionLFRatio = dsprops.flOcclusionLFRatio;
prop->OcclusionRoomRatio = dsprops.flOcclusionRoomRatio;
prop->OcclusionDirectRatio = dsprops.flOcclusionDirectRatio;
prop->Exclusion = dsprops.lExclusion;
prop->ExclusionLFRatio = dsprops.flExclusionLFRatio;
prop->OutsideVolumeHF = dsprops.lOutsideVolumeHF;
prop->DopplerFactor = dsprops.flDopplerFactor;
prop->RolloffFactor = dsprops.flRolloffFactor;
prop->RoomRolloffFactor = dsprops.flRoomRolloffFactor;
prop->AirAbsorptionFactor = dsprops.flAirAbsorptionFactor;
prop->Flags = dsprops.ulFlags;
return FMOD_OK;
}
}
#endif

View file

@ -0,0 +1,25 @@
#ifndef _FMOD_CHANNEL_DSOUND_EAX3_H
#define _FMOD_CHANNEL_DSOUND_EAX3_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_dsound.h"
namespace FMOD
{
class ChannelDSoundEAX3 : public ChannelDSound
{
public:
ChannelDSoundEAX3() {}
FMOD_RESULT setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop);
};
}
#endif /* FMOD_SUPPORT_EAX */
#endif

View file

@ -0,0 +1,314 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_dsound_eax4.h"
#include "fmod_eax4.h"
#include "fmod_output_dsound.h"
#include "fmod_soundi.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelDSoundEAX4::setReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop)
{
HRESULT hr;
EAXSOURCEPROPERTIES eaxsrcprops;
EAXACTIVEFXSLOTS eaxslots;
GUID guid;
unsigned int flags = prop->Flags;
if (!mOutputDSound)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mBuffer3D)
{
return FMOD_ERR_UNSUPPORTED;
}
/*
OBTAIN REVERB INTERFACE
*/
if (!mBufferReverb)
{
if (mFlags & CHANNELREAL_FLAG_PAUSED && mOutputDSound->mDirectXVersion >= 8)
{
mBuffer->AcquireResources(DSBPLAY_LOCHARDWARE, 0, NULL);
}
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
hr = mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb);
if (hr != DS_OK)
{
return FMOD_ERR_UNSUPPORTED;
}
}
/*
Set the target FX slot(s) for this source
*/
if ((flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE0) &&
(flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE1) &&
(flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2))
{
return FMOD_ERR_UNSUPPORTED;
}
/*
Set ACTIVE FX slot(s)
*/
if (flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE0)
{
FMOD_memcpy(&eaxslots.guidActiveFXSlots[0], &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
FMOD_memcpy(&eaxslots.guidActiveFXSlots[1], &FMOD_EAX_NULL_GUID, sizeof(GUID));
flags = (flags & ~FMOD_REVERB_CHANNELFLAGS_INSTANCE0);
if (flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE1)
{
FMOD_memcpy(&eaxslots.guidActiveFXSlots[1], &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
flags = (flags & ~FMOD_REVERB_CHANNELFLAGS_INSTANCE1);
}
else if (flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
FMOD_memcpy(&eaxslots.guidActiveFXSlots[1], &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
flags = (flags & ~FMOD_REVERB_CHANNELFLAGS_INSTANCE2);
}
}
else if (flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE1)
{
FMOD_memcpy(&eaxslots.guidActiveFXSlots[0], &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
FMOD_memcpy(&eaxslots.guidActiveFXSlots[1], &FMOD_EAX_NULL_GUID, sizeof(GUID));
flags = (flags & ~FMOD_REVERB_CHANNELFLAGS_INSTANCE1);
if (flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
FMOD_memcpy(&eaxslots.guidActiveFXSlots[1], &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
flags = (flags & ~FMOD_REVERB_CHANNELFLAGS_INSTANCE2);
}
}
else if (flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
FMOD_memcpy(&eaxslots.guidActiveFXSlots[0], &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
FMOD_memcpy(&eaxslots.guidActiveFXSlots[1], &FMOD_EAX_NULL_GUID, sizeof(GUID));
flags = (flags & ~FMOD_REVERB_CHANNELFLAGS_INSTANCE2);
}
else // Set to Slot 0 by default
{
FMOD_memcpy(&eaxslots.guidActiveFXSlots[0], &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
FMOD_memcpy(&eaxslots.guidActiveFXSlots[1], &FMOD_EAX_NULL_GUID, sizeof(GUID));
}
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_Source, sizeof(GUID));
hr = mBufferReverb->Set(guid, EAXSOURCE_ACTIVEFXSLOTID, NULL, 0, &eaxslots, sizeof(EAXACTIVEFXSLOTS));
if (FAILED(hr))
{
return FMOD_ERR_REVERB_INSTANCE;
}
/*
NOW SET CHANNEL PROPERTIES
*/
eaxsrcprops.lDirect = prop->Direct;
eaxsrcprops.lDirectHF = prop->DirectHF;
eaxsrcprops.lRoom = prop->Room;
eaxsrcprops.lRoomHF = prop->RoomHF;
eaxsrcprops.lObstruction = prop->Obstruction;
eaxsrcprops.flObstructionLFRatio = prop->ObstructionLFRatio;
eaxsrcprops.lOcclusion = prop->Occlusion;
eaxsrcprops.flOcclusionLFRatio = prop->OcclusionLFRatio;
eaxsrcprops.flOcclusionRoomRatio = prop->OcclusionRoomRatio;
eaxsrcprops.flOcclusionDirectRatio = prop->OcclusionDirectRatio;
eaxsrcprops.lExclusion = prop->Exclusion;
eaxsrcprops.flExclusionLFRatio = prop->ExclusionLFRatio;
eaxsrcprops.lOutsideVolumeHF = prop->OutsideVolumeHF;
eaxsrcprops.flDopplerFactor = prop->DopplerFactor;
eaxsrcprops.flRolloffFactor = prop->RolloffFactor;
eaxsrcprops.flRoomRolloffFactor = prop->RoomRolloffFactor;
eaxsrcprops.flAirAbsorptionFactor = prop->AirAbsorptionFactor;
eaxsrcprops.ulFlags = flags;
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_Source, sizeof(GUID));
hr = mBufferReverb->Set(guid, EAXSOURCE_ALLPARAMETERS, NULL, 0, &eaxsrcprops, sizeof(EAXSOURCEPROPERTIES));
if (FAILED(hr))
{
return FMOD_ERR_INVALID_PARAM;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelDSoundEAX4::getReverbProperties(FMOD_REVERB_CHANNELPROPERTIES *prop)
{
HRESULT hr;
EAXSOURCEPROPERTIES eaxsrcprops;
EAXACTIVEFXSLOTS eaxslots;
GUID guid;
GUID guidfx0, guidfx2, guidfx3;
ULONG ulReceived;
int noActiveSlots = 0;
if (!mOutputDSound)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mBuffer3D)
{
return FMOD_ERR_UNSUPPORTED;
}
/*
OBTAIN REVERB INTERFACE
*/
if (!mBufferReverb)
{
if (mFlags & CHANNELREAL_FLAG_PAUSED && mOutputDSound->mDirectXVersion >= 8)
{
mBuffer->AcquireResources(DSBPLAY_LOCHARDWARE, 0, NULL);
}
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
hr = mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb);
if (hr != DS_OK)
{
return FMOD_ERR_UNSUPPORTED;
}
}
/*
Get reverb properties
*/
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_Source, sizeof(GUID));
hr = mBufferReverb->Get(guid, EAXSOURCE_ALLPARAMETERS, NULL, 0, &eaxsrcprops, sizeof(EAXSOURCEPROPERTIES), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_UNSUPPORTED;
}
prop->Direct = eaxsrcprops.lDirect;
prop->DirectHF = eaxsrcprops.lDirectHF;
prop->Room = eaxsrcprops.lRoom;
prop->RoomHF = eaxsrcprops.lRoomHF;
prop->Obstruction = eaxsrcprops.lObstruction;
prop->ObstructionLFRatio = eaxsrcprops.flObstructionLFRatio;
prop->Occlusion = eaxsrcprops.lOcclusion;
prop->OcclusionLFRatio = eaxsrcprops.flOcclusionLFRatio;
prop->OcclusionRoomRatio = eaxsrcprops.flOcclusionRoomRatio;
prop->OcclusionDirectRatio = eaxsrcprops.flOcclusionDirectRatio;
prop->Exclusion = eaxsrcprops.lExclusion;
prop->ExclusionLFRatio = eaxsrcprops.flExclusionLFRatio;
prop->OutsideVolumeHF = eaxsrcprops.lOutsideVolumeHF;
prop->DopplerFactor = eaxsrcprops.flDopplerFactor;
prop->RolloffFactor = eaxsrcprops.flRolloffFactor;
prop->RoomRolloffFactor = eaxsrcprops.flRoomRolloffFactor;
prop->AirAbsorptionFactor = eaxsrcprops.flAirAbsorptionFactor;
prop->Flags = eaxsrcprops.ulFlags;
hr = mBufferReverb->Get(guid, EAXSOURCE_ACTIVEFXSLOTID, NULL, 0, &eaxslots, sizeof(EAXACTIVEFXSLOTS), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_UNSUPPORTED;
}
FMOD_memcpy(&guidfx0, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
FMOD_memcpy(&guidfx2, &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
FMOD_memcpy(&guidfx3, &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
if (!memcmp(&eaxslots.guidActiveFXSlots[0], &guidfx0, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE0;
}
else if (!memcmp(&eaxslots.guidActiveFXSlots[0], &guidfx2, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE1;
}
else if (!memcmp(&eaxslots.guidActiveFXSlots[0], &guidfx3, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE2;
}
else
{
noActiveSlots++;
}
if (!memcmp(&eaxslots.guidActiveFXSlots[1], &guidfx0, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE0;
}
else if (!memcmp(&eaxslots.guidActiveFXSlots[1], &guidfx2, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE1;
}
else if (!memcmp(&eaxslots.guidActiveFXSlots[1], &guidfx3, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE2;
}
else
{
noActiveSlots++;
}
if (noActiveSlots == 2) // If no slots have been assigned, assign to slot 0
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE0;
}
return FMOD_OK;
}
}
#endif

View file

@ -0,0 +1,25 @@
#ifndef _FMOD_CHANNEL_DSOUND_EAX4_H
#define _FMOD_CHANNEL_DSOUND_EAX4_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_dsound.h"
namespace FMOD
{
class ChannelDSoundEAX4 : public ChannelDSound
{
public:
ChannelDSoundEAX4() { };
FMOD_RESULT setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop);
};
}
#endif /* FMOD_SUPPORT_EAX */
#endif

View file

@ -0,0 +1,188 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_I3DL2
#include "fmod_3dl2.h"
#include "fmod_channel_dsound_i3dl2.h"
#include "fmod_output_dsound.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelDSoundI3DL2::setReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop)
{
HRESULT hr;
I3DL2_BUFFERPROPERTIES dsprops;
GUID guid;
if (!mOutputDSound)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mBuffer3D)
{
return FMOD_ERR_UNSUPPORTED;
}
/*
OBTAIN REVERB INTERFACE
*/
if (!mBufferReverb)
{
if (mFlags & CHANNELREAL_FLAG_PAUSED && mOutputDSound->mDirectXVersion >= 8)
{
mBuffer->AcquireResources(DSBPLAY_LOCHARDWARE, 0, NULL);
}
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
hr = mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb);
if (hr != DS_OK)
{
return FMOD_ERR_UNSUPPORTED;
}
}
/*
NOW SET CHANNEL PROPERTIES
*/
dsprops.lDirect = prop->Direct;
dsprops.lDirectHF = prop->DirectHF;
dsprops.lRoom = prop->Room;
dsprops.lRoomHF = prop->RoomHF;
dsprops.flRoomRolloffFactor = prop->RoomRolloffFactor;
dsprops.Obstruction.flLFRatio = prop->ObstructionLFRatio;
dsprops.Obstruction.lHFLevel = prop->Obstruction;
dsprops.Occlusion.flLFRatio = prop->OcclusionLFRatio;
dsprops.Occlusion.lHFLevel = prop->Occlusion;
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_I3DL2_BufferProperties, sizeof(GUID));
hr = mBufferReverb->Set(guid, DSPROPERTY_I3DL2BUFFER_ALL, NULL, 0, &dsprops, sizeof(I3DL2_BUFFERPROPERTIES));
if (FAILED(hr))
{
return FMOD_ERR_INVALID_PARAM;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelDSoundI3DL2::getReverbProperties(FMOD_REVERB_CHANNELPROPERTIES *prop)
{
HRESULT hr;
I3DL2_BUFFERPROPERTIES dsprops;
GUID guid;
ULONG ulReceived;
if (!mOutputDSound)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mBuffer3D)
{
return FMOD_ERR_UNSUPPORTED;
}
/*
OBTAIN REVERB INTERFACE
*/
if (!mBufferReverb)
{
if (mFlags & CHANNELREAL_FLAG_PAUSED && mOutputDSound->mDirectXVersion >= 8)
{
mBuffer->AcquireResources(DSBPLAY_LOCHARDWARE, 0, NULL);
}
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
hr = mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb);
if (hr != DS_OK)
{
return FMOD_ERR_UNSUPPORTED;
}
}
/*
Get reverb properties
*/
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_I3DL2_BufferProperties, sizeof(GUID));
hr = mBufferReverb->Get(guid, DSPROPERTY_I3DL2BUFFER_ALL, NULL, 0, &dsprops, sizeof(I3DL2_BUFFERPROPERTIES), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_UNSUPPORTED;
}
prop->Direct = dsprops.lDirect;
prop->DirectHF = dsprops.lDirectHF;
prop->Room = dsprops.lRoom;
prop->RoomHF = dsprops.lRoomHF;
prop->Obstruction = dsprops.Obstruction.lHFLevel;
prop->ObstructionLFRatio = dsprops.Obstruction.flLFRatio;
prop->Occlusion = dsprops.Occlusion.lHFLevel;
prop->OcclusionLFRatio = dsprops.Occlusion.flLFRatio;
prop->OcclusionRoomRatio = 0;
prop->OcclusionDirectRatio = 0;
prop->Exclusion = 0;
prop->ExclusionLFRatio = 0;
prop->OutsideVolumeHF = 0;
prop->DopplerFactor = 0;
prop->RolloffFactor = 0;
prop->RoomRolloffFactor = dsprops.flRoomRolloffFactor;
prop->AirAbsorptionFactor = 0;
prop->Flags = 0;
return FMOD_OK;
}
}
#endif

View file

@ -0,0 +1,25 @@
#ifndef _FMOD_CHANNEL_DSOUND_I3DL2_H
#define _FMOD_CHANNEL_DSOUND_I3DL2_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_I3DL2
#include "fmod_channel_dsound.h"
namespace FMOD
{
class ChannelDSoundI3DL2 : public ChannelDSound
{
public:
ChannelDSoundI3DL2() {};
FMOD_RESULT setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop);
};
}
#endif /* FMOD_SUPPORT_I3DL2 */
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,76 @@
#ifndef _FMOD_CHANNEL_OPENAL_H
#define _FMOD_CHANNEL_OPENAL_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#include "fmod_channel_real.h"
#include "fmod_output_openal.h"
#include "fmod_dsp_wavetable.h"
namespace FMOD
{
class ChannelOpenAL : public ChannelReal
{
friend class OutputOpenAL;
protected:
DSPI *mDSPHead;
DSPFilter mDSPHeadMemory;
DSPWaveTable *mDSPWaveTable;
DSPWaveTable mDSPWaveTableMemory;
DSPResampler *mDSPResampler; // Connected between mDSPHead and mDSPWaveTable sometimes
DSPI *mDSPLowPass; // Optional if the user specifies FMOD_INIT_SOFTWARE_OCCLUSION
DSPCodec *mDSPCodec;
DSPConnection *mDSPConnection;
OutputOpenAL *mOutputOAL;
int mNumSources;
SourceOpenAL *mSources[16];
short *mBuffer;
float *mTempBuffer;
bool mInitialFill;
unsigned int mDSPTick;
public:
ChannelOpenAL();
FMOD_RESULT init (int index, SystemI *system, Output *output, DSPI *dspmixtarget);
FMOD_RESULT close ();
FMOD_RESULT alloc ();
FMOD_RESULT alloc (DSPI *dsp);
FMOD_RESULT start ();
FMOD_RESULT stop ();
FMOD_RESULT setVolume (float volume);
FMOD_RESULT setFrequency (float frequency);
FMOD_RESULT setPan (float pan, float fbpan = 1);
FMOD_RESULT setSpeakerLevels (int speaker, float *levels, int numlevels);
FMOD_RESULT setPaused (bool paused);
FMOD_RESULT setPosition (unsigned int position, FMOD_TIMEUNIT postype);
FMOD_RESULT getPosition (unsigned int *position, FMOD_TIMEUNIT postype);
FMOD_RESULT setLoopPoints (unsigned int loopstart, unsigned int looplength);
FMOD_RESULT setLoopCount (int loopcount);
FMOD_RESULT setMode (FMOD_MODE mode);
FMOD_RESULT set3DAttributes ();
FMOD_RESULT set3DMinMaxDistance ();
FMOD_RESULT set3DOcclusion (float directOcclusion, float reverbOcclusion);
FMOD_RESULT isPlaying (bool *isplaying, bool includethreadlatency = false);
FMOD_RESULT getSpectrum (float *spectrumarray, int numentries, int channeloffset, FMOD_DSP_FFT_WINDOW windowtype);
FMOD_RESULT getWaveData (float *wavearray, int numentries, int channeloffset);
FMOD_RESULT getDSPHead (DSPI **dsp) { *dsp = mDSPHead; return FMOD_OK; }
FMOD_RESULT setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT setupDSPCodec (DSPI *dsp);
FMOD_RESULT getDSPCodec (DSPCodec **dsp) { *dsp = mDSPCodec; return FMOD_OK; }
virtual FMOD_RESULT setupChannel ();
FMOD_RESULT updateChannel ();
};
}
#endif /* FMOD_SUPPORT_OPENAL */
#endif /* _FMOD_CHANNEL_OPENAL_H */

View file

@ -0,0 +1,210 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_openal_eax2.h"
#include "fmod_eax2.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
Initialise this channel for EAX2 specific settings
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
This will also reset the sources back to defaults when a new channel
is reusing sources
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX2::setupChannel()
{
EAXBUFFERPROPERTIES eaxBufferProperties;
GUID eaxBufferGuid;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
FMOD_memcpy(&eaxBufferGuid, &FMOD_DSPROPSETID_EAX20_BufferProperties, sizeof(GUID));
/*
Set the default channel reverb properties
*/
eaxBufferProperties.lDirect = EAXBUFFER_DEFAULTDIRECT;
eaxBufferProperties.lDirectHF = EAXBUFFER_DEFAULTDIRECTHF;
eaxBufferProperties.lRoom = EAXBUFFER_DEFAULTROOM;
eaxBufferProperties.lRoomHF = EAXBUFFER_DEFAULTROOMHF;
eaxBufferProperties.flRoomRolloffFactor = EAXBUFFER_DEFAULTROOMROLLOFFFACTOR;
eaxBufferProperties.lObstruction = EAXBUFFER_DEFAULTOBSTRUCTION;
eaxBufferProperties.flObstructionLFRatio = EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO;
eaxBufferProperties.lOcclusion = EAXBUFFER_DEFAULTOCCLUSION;
eaxBufferProperties.flOcclusionLFRatio = EAXBUFFER_DEFAULTOCCLUSIONLFRATIO;
eaxBufferProperties.flOcclusionRoomRatio = EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO;
eaxBufferProperties.lOutsideVolumeHF = EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF;
eaxBufferProperties.flAirAbsorptionFactor = EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR;
eaxBufferProperties.dwFlags = EAXBUFFER_DEFAULTFLAGS;
/*
Apply the defaults to each source
*/
for (int i = 0; i < mNumSources; i++)
{
mOutputOAL->mEAXSet(&eaxBufferGuid, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, mSources[i]->sid, &eaxBufferProperties, sizeof(EAXBUFFERPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Set the reverb properties on the hardware
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX2::setReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop)
{
EAXBUFFERPROPERTIES eaxBufferProperties;
GUID eaxBufferGuid;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FMOD_memcpy(&eaxBufferGuid, &FMOD_DSPROPSETID_EAX20_BufferProperties, sizeof(GUID));
/*
Set the channel reverb properties
*/
eaxBufferProperties.lDirect = prop->Direct;
eaxBufferProperties.lDirectHF = prop->DirectHF;
eaxBufferProperties.lRoom = prop->Room;
eaxBufferProperties.lRoomHF = prop->RoomHF;
eaxBufferProperties.lObstruction = prop->Obstruction;
eaxBufferProperties.flObstructionLFRatio = prop->ObstructionLFRatio;
eaxBufferProperties.lOcclusion = prop->Occlusion;
eaxBufferProperties.flOcclusionLFRatio = prop->OcclusionLFRatio;
eaxBufferProperties.flOcclusionRoomRatio = prop->OcclusionRoomRatio;
eaxBufferProperties.lOutsideVolumeHF = prop->OutsideVolumeHF;
eaxBufferProperties.flRoomRolloffFactor = prop->RoomRolloffFactor;
eaxBufferProperties.flAirAbsorptionFactor = prop->AirAbsorptionFactor;
eaxBufferProperties.dwFlags = prop->Flags;
/*
Apply the values to each source
*/
for (int i = 0; i < mNumSources; i++)
{
mOutputOAL->mEAXSet(&eaxBufferGuid, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, mSources[i]->sid, &eaxBufferProperties, sizeof(EAXBUFFERPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Get the reverb properties from the hardware
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX2::getReverbProperties(FMOD_REVERB_CHANNELPROPERTIES *prop)
{
EAXBUFFERPROPERTIES eaxBufferProperties;
GUID eaxBufferGuid;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FMOD_memcpy(&eaxBufferGuid, &FMOD_DSPROPSETID_EAX20_BufferProperties, sizeof(GUID));
/*
Get the channel reverb properties
*/
mOutputOAL->mEAXGet(&eaxBufferGuid, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, mSources[0]->sid, &eaxBufferProperties, sizeof(EAXBUFFERPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
FMOD_memset(prop, 0, sizeof(FMOD_REVERB_CHANNELPROPERTIES));
prop->Direct = eaxBufferProperties.lDirect;
prop->DirectHF = eaxBufferProperties.lDirectHF;
prop->Room = eaxBufferProperties.lRoom;
prop->RoomHF = eaxBufferProperties.lRoomHF;
prop->Obstruction = eaxBufferProperties.lObstruction;
prop->ObstructionLFRatio = eaxBufferProperties.flObstructionLFRatio;
prop->Occlusion = eaxBufferProperties.lOcclusion;
prop->OcclusionLFRatio = eaxBufferProperties.flOcclusionLFRatio;
prop->OcclusionRoomRatio = eaxBufferProperties.flOcclusionRoomRatio;
prop->OutsideVolumeHF = eaxBufferProperties.lOutsideVolumeHF;
prop->RoomRolloffFactor = eaxBufferProperties.flRoomRolloffFactor;
prop->AirAbsorptionFactor = eaxBufferProperties.flAirAbsorptionFactor;
prop->Flags = eaxBufferProperties.dwFlags;
return FMOD_OK;
}
}
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */

View file

@ -0,0 +1,29 @@
#ifndef _FMOD_CHANNEL_OPENAL_EAX2_H
#define _FMOD_CHANNEL_OPENAL_EAX2_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_openal.h"
namespace FMOD
{
class ChannelOpenALEAX2 : public ChannelOpenAL
{
public:
ChannelOpenALEAX2() {};
FMOD_RESULT setupChannel ();
FMOD_RESULT setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop);
};
}
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */
#endif /* _FMOD_CHANNEL_OPENAL_EAX2_H */

View file

@ -0,0 +1,225 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_openal_eax3.h"
#include "fmod_eax3.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
Initialise this channel for EAX3 specific settings
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
This will also reset the sources back to defaults when a new channel
is reusing sources
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX3::setupChannel()
{
EAXBUFFERPROPERTIES eaxBufferProperties;
GUID eaxBufferGuid;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
FMOD_memcpy(&eaxBufferGuid, &FMOD_DSPROPSETID_EAX30_BufferProperties, sizeof(GUID));
/*
Set the default channel reverb properties
*/
eaxBufferProperties.lDirect = EAXBUFFER_DEFAULTDIRECT;
eaxBufferProperties.lDirectHF = EAXBUFFER_DEFAULTDIRECTHF;
eaxBufferProperties.lRoom = EAXBUFFER_DEFAULTROOM;
eaxBufferProperties.lRoomHF = EAXBUFFER_DEFAULTROOMHF;
eaxBufferProperties.lObstruction = EAXBUFFER_DEFAULTOBSTRUCTION;
eaxBufferProperties.flObstructionLFRatio = EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO;
eaxBufferProperties.lOcclusion = EAXBUFFER_DEFAULTOCCLUSION;
eaxBufferProperties.flOcclusionLFRatio = EAXBUFFER_DEFAULTOCCLUSIONLFRATIO;
eaxBufferProperties.flOcclusionRoomRatio = EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO;
eaxBufferProperties.flOcclusionDirectRatio = EAXBUFFER_DEFAULTOCCLUSIONDIRECTRATIO;
eaxBufferProperties.lExclusion = EAXBUFFER_DEFAULTEXCLUSION;
eaxBufferProperties.flExclusionLFRatio = EAXBUFFER_DEFAULTEXCLUSIONLFRATIO;
eaxBufferProperties.lOutsideVolumeHF = EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF;
eaxBufferProperties.flDopplerFactor = EAXBUFFER_DEFAULTDOPPLERFACTOR;
eaxBufferProperties.flRolloffFactor = EAXBUFFER_DEFAULTROLLOFFFACTOR;
eaxBufferProperties.flRoomRolloffFactor = EAXBUFFER_DEFAULTROOMROLLOFFFACTOR;
eaxBufferProperties.flAirAbsorptionFactor = EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR;
eaxBufferProperties.ulFlags = EAXBUFFER_DEFAULTFLAGS;
/*
Apply the defaults to each source
*/
for (int i = 0; i < mNumSources; i++)
{
mOutputOAL->mEAXSet(&eaxBufferGuid, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, mSources[i]->sid, &eaxBufferProperties, sizeof(EAXBUFFERPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Set the reverb properties on the hardware
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX3::setReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop)
{
EAXBUFFERPROPERTIES eaxBufferProperties;
GUID eaxBufferGuid;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FMOD_memcpy(&eaxBufferGuid, &FMOD_DSPROPSETID_EAX30_BufferProperties, sizeof(GUID));
/*
Set the channel reverb properties
*/
eaxBufferProperties.lDirect = prop->Direct;
eaxBufferProperties.lDirectHF = prop->DirectHF;
eaxBufferProperties.lRoom = prop->Room;
eaxBufferProperties.lRoomHF = prop->RoomHF;
eaxBufferProperties.lObstruction = prop->Obstruction;
eaxBufferProperties.flObstructionLFRatio = prop->ObstructionLFRatio;
eaxBufferProperties.lOcclusion = prop->Occlusion;
eaxBufferProperties.flOcclusionLFRatio = prop->OcclusionLFRatio;
eaxBufferProperties.flOcclusionRoomRatio = prop->OcclusionRoomRatio;
eaxBufferProperties.flOcclusionDirectRatio = prop->OcclusionDirectRatio;
eaxBufferProperties.lExclusion = prop->Exclusion;
eaxBufferProperties.flExclusionLFRatio = prop->ExclusionLFRatio;
eaxBufferProperties.lOutsideVolumeHF = prop->OutsideVolumeHF;
eaxBufferProperties.flDopplerFactor = prop->DopplerFactor;
eaxBufferProperties.flRolloffFactor = prop->RolloffFactor;
eaxBufferProperties.flRoomRolloffFactor = prop->RoomRolloffFactor;
eaxBufferProperties.flAirAbsorptionFactor = prop->AirAbsorptionFactor;
eaxBufferProperties.ulFlags = prop->Flags;
/*
Apply the values to each source
*/
for (int i = 0; i < mNumSources; i++)
{
mOutputOAL->mEAXSet(&eaxBufferGuid, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, mSources[i]->sid, &eaxBufferProperties, sizeof(EAXBUFFERPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Get the reverb properties from the hardware
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX3::getReverbProperties(FMOD_REVERB_CHANNELPROPERTIES *prop)
{
EAXBUFFERPROPERTIES eaxBufferProperties;
GUID eaxBufferGuid;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FMOD_memcpy(&eaxBufferGuid, &FMOD_DSPROPSETID_EAX30_BufferProperties, sizeof(GUID));
/*
Get the channel reverb properties
*/
mOutputOAL->mEAXGet(&eaxBufferGuid, DSPROPERTY_EAXBUFFER_ALLPARAMETERS, mSources[0]->sid, &eaxBufferProperties, sizeof(EAXBUFFERPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
FMOD_memset(prop, 0, sizeof(FMOD_REVERB_CHANNELPROPERTIES));
prop->Direct = eaxBufferProperties.lDirect;
prop->DirectHF = eaxBufferProperties.lDirectHF;
prop->Room = eaxBufferProperties.lRoom;
prop->RoomHF = eaxBufferProperties.lRoomHF;
prop->Obstruction = eaxBufferProperties.lObstruction;
prop->ObstructionLFRatio = eaxBufferProperties.flObstructionLFRatio;
prop->Occlusion = eaxBufferProperties.lOcclusion;
prop->OcclusionLFRatio = eaxBufferProperties.flOcclusionLFRatio;
prop->OcclusionRoomRatio = eaxBufferProperties.flOcclusionRoomRatio;
prop->OcclusionDirectRatio = eaxBufferProperties.flOcclusionDirectRatio;
prop->Exclusion = eaxBufferProperties.lExclusion;
prop->ExclusionLFRatio = eaxBufferProperties.flExclusionLFRatio;
prop->OutsideVolumeHF = eaxBufferProperties.lOutsideVolumeHF;
prop->DopplerFactor = eaxBufferProperties.flDopplerFactor;
prop->RolloffFactor = eaxBufferProperties.flRolloffFactor;
prop->RoomRolloffFactor = eaxBufferProperties.flRoomRolloffFactor;
prop->AirAbsorptionFactor = eaxBufferProperties.flAirAbsorptionFactor;
prop->Flags = eaxBufferProperties.ulFlags;
return FMOD_OK;
}
}
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */

View file

@ -0,0 +1,29 @@
#ifndef _FMOD_CHANNEL_OPENAL_EAX3_H
#define _FMOD_CHANNEL_OPENAL_EAX3_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_openal.h"
namespace FMOD
{
class ChannelOpenALEAX3 : public ChannelOpenAL
{
public:
ChannelOpenALEAX3() {};
FMOD_RESULT setupChannel ();
FMOD_RESULT setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop);
};
}
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */
#endif /* _FMOD_CHANNEL_OPENAL_EAX3_H */

View file

@ -0,0 +1,392 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_openal_eax4.h"
#include "fmod_eax4.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
Initialise this channel for EAX4 specific settings
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
This will also reset the sources back to defaults when a new channel
is reusing sources
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX4::setupChannel()
{
EAXACTIVEFXSLOTS eaxSlots;
EAXSOURCEPROPERTIES eaxSourceProperties;
GUID eaxSourceGuid;
GUID eaxFXSlot0, eaxFXSlotNull;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
FMOD_memcpy(&eaxFXSlot0, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
FMOD_memcpy(&eaxFXSlotNull, &FMOD_EAX_NULL_GUID, sizeof(GUID));
FMOD_memcpy(&eaxSourceGuid, &FMOD_EAXPROPERTYID_EAX40_Source, sizeof(GUID));
/*
Set the default slot 0 to on
*/
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot0, sizeof(GUID));
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlotNull, sizeof(GUID));
/*
Set the default channel reverb properties
*/
eaxSourceProperties.lDirect = EAXSOURCE_DEFAULTDIRECT;
eaxSourceProperties.lDirectHF = EAXSOURCE_DEFAULTDIRECTHF;
eaxSourceProperties.lRoom = EAXSOURCE_DEFAULTROOM;
eaxSourceProperties.lRoomHF = EAXSOURCE_DEFAULTROOMHF;
eaxSourceProperties.lObstruction = EAXSOURCE_DEFAULTOBSTRUCTION;
eaxSourceProperties.flObstructionLFRatio = EAXSOURCE_DEFAULTOBSTRUCTIONLFRATIO;
eaxSourceProperties.lOcclusion = EAXSOURCE_DEFAULTOCCLUSION;
eaxSourceProperties.flOcclusionLFRatio = EAXSOURCE_DEFAULTOCCLUSIONLFRATIO;
eaxSourceProperties.flOcclusionRoomRatio = EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO;
eaxSourceProperties.flOcclusionDirectRatio = EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO;
eaxSourceProperties.lExclusion = EAXSOURCE_DEFAULTEXCLUSION;
eaxSourceProperties.flExclusionLFRatio = EAXSOURCE_DEFAULTEXCLUSIONLFRATIO;
eaxSourceProperties.lOutsideVolumeHF = EAXSOURCE_DEFAULTOUTSIDEVOLUMEHF;
eaxSourceProperties.flDopplerFactor = EAXSOURCE_DEFAULTDOPPLERFACTOR;
eaxSourceProperties.flRolloffFactor = EAXSOURCE_DEFAULTROLLOFFFACTOR;
eaxSourceProperties.flRoomRolloffFactor = EAXSOURCE_DEFAULTROOMROLLOFFFACTOR;
eaxSourceProperties.flAirAbsorptionFactor = EAXSOURCE_DEFAULTAIRABSORPTIONFACTOR;
eaxSourceProperties.ulFlags = EAXSOURCE_DEFAULTFLAGS;
/*
Apply the defaults to each source
*/
for (int i = 0; i < mNumSources; i++)
{
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_ACTIVEFXSLOTID, mSources[i]->sid, &eaxSlots, sizeof(EAXACTIVEFXSLOTS));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_ALLPARAMETERS, mSources[i]->sid, &eaxSourceProperties, sizeof(EAXSOURCEPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Set the reverb properties on the hardware
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
EAX4 has 4 effects slots, but can only have 2 active on any one source.
The first slot is dedicated to reverb, the second slot is dedicated chorus,
any of the remaining two slots can be tasked for reverb
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX4::setReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop)
{
EAXSOURCEPROPERTIES eaxSourceProperties;
EAXACTIVEFXSLOTS eaxSlots;
unsigned long eaxSourceFlags;
GUID eaxSourceGuid;
GUID eaxFXSlot0, eaxFXSlot2, eaxFXSlot3, eaxFXSlotNull;
int numActiveSlots;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FMOD_memcpy(&eaxFXSlot0, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
FMOD_memcpy(&eaxFXSlot2, &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
FMOD_memcpy(&eaxFXSlot3, &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
FMOD_memcpy(&eaxFXSlotNull, &FMOD_EAX_NULL_GUID, sizeof(GUID));
FMOD_memcpy(&eaxSourceGuid, &FMOD_EAXPROPERTYID_EAX40_Source, sizeof(GUID));
/*
Only support a maximum 2 active slots per channel
*/
numActiveSlots = 0;
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE0)
{
numActiveSlots++;
}
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE1)
{
numActiveSlots++;
}
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
numActiveSlots++;
}
if (numActiveSlots > 2)
{
return FMOD_ERR_UNSUPPORTED;
}
/*
Store the slot IDs for the chosen environment
*/
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlotNull, sizeof(GUID));
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlotNull, sizeof(GUID));
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE0)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot0, sizeof(GUID));
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE1)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot2, sizeof(GUID));
}
else if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot3, sizeof(GUID));
}
}
else if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE1)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot2, sizeof(GUID));
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot3, sizeof(GUID));
}
}
else if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot2, sizeof(GUID));
}
else // Set to Slot 0 by default
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot0, sizeof(GUID));
}
/*
Set the channel reverb properties
*/
mOutputOAL->mEAXGet(&eaxSourceGuid, EAXSOURCE_FLAGS, mSources[0]->sid, &eaxSourceFlags, sizeof(unsigned long));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
eaxSourceProperties.lDirect = prop->Direct;
eaxSourceProperties.lDirectHF = prop->DirectHF;
eaxSourceProperties.lRoom = prop->Room;
eaxSourceProperties.lRoomHF = prop->RoomHF;
eaxSourceProperties.lObstruction = prop->Obstruction;
eaxSourceProperties.flObstructionLFRatio = prop->ObstructionLFRatio;
eaxSourceProperties.lOcclusion = prop->Occlusion;
eaxSourceProperties.flOcclusionLFRatio = prop->OcclusionLFRatio;
eaxSourceProperties.flOcclusionRoomRatio = prop->OcclusionRoomRatio;
eaxSourceProperties.flOcclusionDirectRatio = prop->OcclusionDirectRatio;
eaxSourceProperties.lExclusion = prop->Exclusion;
eaxSourceProperties.flExclusionLFRatio = prop->ExclusionLFRatio;
eaxSourceProperties.lOutsideVolumeHF = prop->OutsideVolumeHF;
eaxSourceProperties.flDopplerFactor = prop->DopplerFactor;
eaxSourceProperties.flRolloffFactor = prop->RolloffFactor;
eaxSourceProperties.flRoomRolloffFactor = prop->RoomRolloffFactor;
eaxSourceProperties.flAirAbsorptionFactor = prop->AirAbsorptionFactor;
eaxSourceFlags = (prop->Flags & FMOD_REVERB_CHANNELFLAGS_DIRECTHFAUTO) ? (eaxSourceFlags | EAXSOURCEFLAGS_DIRECTHFAUTO) : (eaxSourceFlags & ~EAXSOURCEFLAGS_DIRECTHFAUTO);
eaxSourceFlags = (prop->Flags & FMOD_REVERB_CHANNELFLAGS_ROOMAUTO) ? (eaxSourceFlags | EAXSOURCEFLAGS_ROOMAUTO) : (eaxSourceFlags & ~EAXSOURCEFLAGS_ROOMAUTO);
eaxSourceFlags = (prop->Flags & FMOD_REVERB_CHANNELFLAGS_ROOMHFAUTO) ? (eaxSourceFlags | EAXSOURCEFLAGS_ROOMHFAUTO) : (eaxSourceFlags & ~EAXSOURCEFLAGS_ROOMHFAUTO);
eaxSourceProperties.ulFlags = eaxSourceFlags;
/*
Apply the active slots and properties to the sources
*/
for (int i = 0; i < mNumSources; i++)
{
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_ACTIVEFXSLOTID, mSources[i]->sid, &eaxSlots, sizeof(EAXACTIVEFXSLOTS));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_ALLPARAMETERS, mSources[i]->sid, &eaxSourceProperties, sizeof(EAXSOURCEPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Get the reverb properties from the hardware
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
EAX4 has 4 effects slots, but can only have 2 active on any one source.
The first slot is dedicated to reverb, the second slot is dedicated chorus,
any of the remaining two slots can be tasked for reverb
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX4::getReverbProperties(FMOD_REVERB_CHANNELPROPERTIES *prop)
{
EAXSOURCEPROPERTIES eaxSourceProperties;
EAXACTIVEFXSLOTS eaxSlots;
GUID eaxSourceGuid;
GUID eaxFXSlot0, eaxFXSlot2, eaxFXSlot3;
int numInactiveSlots;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
FMOD_memcpy(&eaxFXSlot0, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
FMOD_memcpy(&eaxFXSlot2, &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
FMOD_memcpy(&eaxFXSlot3, &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
FMOD_memcpy(&eaxSourceGuid, &FMOD_EAXPROPERTYID_EAX40_Source, sizeof(GUID));
/*
Get the channel reverb properties
*/
mOutputOAL->mEAXGet(&eaxSourceGuid, EAXSOURCE_ALLPARAMETERS, mSources[0]->sid, &eaxSourceProperties, sizeof(EAXSOURCEPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
FMOD_memset(prop, 0, sizeof(FMOD_REVERB_CHANNELPROPERTIES));
prop->Direct = eaxSourceProperties.lDirect;
prop->DirectHF = eaxSourceProperties.lDirectHF;
prop->Room = eaxSourceProperties.lRoom;
prop->RoomHF = eaxSourceProperties.lRoomHF;
prop->Obstruction = eaxSourceProperties.lObstruction;
prop->ObstructionLFRatio = eaxSourceProperties.flObstructionLFRatio;
prop->Occlusion = eaxSourceProperties.lOcclusion;
prop->OcclusionLFRatio = eaxSourceProperties.flOcclusionLFRatio;
prop->OcclusionRoomRatio = eaxSourceProperties.flOcclusionRoomRatio;
prop->OcclusionDirectRatio = eaxSourceProperties.flOcclusionDirectRatio;
prop->Exclusion = eaxSourceProperties.lExclusion;
prop->ExclusionLFRatio = eaxSourceProperties.flExclusionLFRatio;
prop->OutsideVolumeHF = eaxSourceProperties.lOutsideVolumeHF;
prop->DopplerFactor = eaxSourceProperties.flDopplerFactor;
prop->RolloffFactor = eaxSourceProperties.flRolloffFactor;
prop->RoomRolloffFactor = eaxSourceProperties.flRoomRolloffFactor;
prop->AirAbsorptionFactor = eaxSourceProperties.flAirAbsorptionFactor;
prop->Flags = 0;
prop->Flags |= (eaxSourceProperties.ulFlags & EAXSOURCEFLAGS_DIRECTHFAUTO) ? FMOD_REVERB_CHANNELFLAGS_DIRECTHFAUTO : 0;
prop->Flags |= (eaxSourceProperties.ulFlags & EAXSOURCEFLAGS_ROOMAUTO) ? FMOD_REVERB_CHANNELFLAGS_ROOMAUTO : 0;
prop->Flags |= (eaxSourceProperties.ulFlags & EAXSOURCEFLAGS_ROOMHFAUTO) ? FMOD_REVERB_CHANNELFLAGS_ROOMHFAUTO : 0;
// Get all the effect slots associated with this source
mOutputOAL->mEAXGet(&eaxSourceGuid, EAXSOURCE_ACTIVEFXSLOTID, mSources[0]->sid, &eaxSlots, sizeof(EAXACTIVEFXSLOTS));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
/*
See if there are any active effect slots
*/
numInactiveSlots = 0;
// Check active slot 0 for any of the 3 possible effect IDs
if (!memcmp(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot0, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE0;
}
else if (!memcmp(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot2, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE2;
}
else if (!memcmp(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot3, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE3;
}
else
{
numInactiveSlots++;
}
// Check active slot 1 for any of the 3 possible effect IDs
if (!memcmp(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot0, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE0;
}
else if (!memcmp(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot2, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE2;
}
else if (!memcmp(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot3, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE3;
}
else
{
numInactiveSlots++;
}
// If no slots have been assigned (max slots = 2), assign to slot 0
if (numInactiveSlots == 2)
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE0;
}
return FMOD_OK;
}
}
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */

View file

@ -0,0 +1,29 @@
#ifndef _FMOD_CHANNEL_OPENAL_EAX4_H
#define _FMOD_CHANNEL_OPENAL_EAX4_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_openal.h"
namespace FMOD
{
class ChannelOpenALEAX4 : public ChannelOpenAL
{
public:
ChannelOpenALEAX4() {};
FMOD_RESULT setupChannel ();
FMOD_RESULT setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop);
};
}
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */
#endif /* _FMOD_CHANNEL_OPENAL_EAX4_H */

View file

@ -0,0 +1,633 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_openal_eax5.h"
#include "fmod_eax5.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
Initialise this channel for EAX5 specific settings
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
This will also reset the sources back to defaults when a new channel
is reusing sources
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX5::setupChannel()
{
EAXSPEAKERLEVELPROPERTIES eaxSourceSpeakerLevels[8];
EAXACTIVEFXSLOTS eaxSlots;
EAXSOURCEPROPERTIES eaxSourceProperties;
GUID eaxSourceGuid;
GUID eaxFXSlot0, eaxFXSlotNull;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
FMOD_memcpy(&eaxFXSlot0, &FMOD_EAXPROPERTYID_EAX50_FXSlot0, sizeof(GUID));
FMOD_memcpy(&eaxFXSlotNull, &FMOD_EAX_NULL_GUID, sizeof(GUID));
FMOD_memcpy(&eaxSourceGuid, &FMOD_EAXPROPERTYID_EAX50_Source, sizeof(GUID));
/*
Set the default speaker levels
*/
eaxSourceSpeakerLevels[0].lSpeakerID = EAXSPEAKER_FRONT_LEFT;
eaxSourceSpeakerLevels[0].lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
eaxSourceSpeakerLevels[1].lSpeakerID = EAXSPEAKER_FRONT_CENTER;
eaxSourceSpeakerLevels[1].lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
eaxSourceSpeakerLevels[2].lSpeakerID = EAXSPEAKER_FRONT_RIGHT;
eaxSourceSpeakerLevels[2].lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
eaxSourceSpeakerLevels[3].lSpeakerID = EAXSPEAKER_SIDE_RIGHT;
eaxSourceSpeakerLevels[3].lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
eaxSourceSpeakerLevels[4].lSpeakerID = EAXSPEAKER_REAR_RIGHT;
eaxSourceSpeakerLevels[4].lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
eaxSourceSpeakerLevels[5].lSpeakerID = EAXSPEAKER_REAR_LEFT;
eaxSourceSpeakerLevels[5].lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
eaxSourceSpeakerLevels[6].lSpeakerID = EAXSPEAKER_SIDE_LEFT;
eaxSourceSpeakerLevels[6].lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
eaxSourceSpeakerLevels[7].lSpeakerID = EAXSPEAKER_LOW_FREQUENCY;
eaxSourceSpeakerLevels[7].lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
/*
Set the default slot 0 to on
*/
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot0, sizeof(GUID));
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlotNull, sizeof(GUID));
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[2], &eaxFXSlotNull, sizeof(GUID));
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[3], &eaxFXSlotNull, sizeof(GUID));
/*
Set the default channel reverb properties
*/
eaxSourceProperties.lDirect = EAXSOURCE_DEFAULTDIRECT;
eaxSourceProperties.lDirectHF = EAXSOURCE_DEFAULTDIRECTHF;
eaxSourceProperties.lRoom = EAXSOURCE_DEFAULTROOM;
eaxSourceProperties.lRoomHF = EAXSOURCE_DEFAULTROOMHF;
eaxSourceProperties.lObstruction = EAXSOURCE_DEFAULTOBSTRUCTION;
eaxSourceProperties.flObstructionLFRatio = EAXSOURCE_DEFAULTOBSTRUCTIONLFRATIO;
eaxSourceProperties.lOcclusion = EAXSOURCE_DEFAULTOCCLUSION;
eaxSourceProperties.flOcclusionLFRatio = EAXSOURCE_DEFAULTOCCLUSIONLFRATIO;
eaxSourceProperties.flOcclusionRoomRatio = EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO;
eaxSourceProperties.flOcclusionDirectRatio = EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO;
eaxSourceProperties.lExclusion = EAXSOURCE_DEFAULTEXCLUSION;
eaxSourceProperties.flExclusionLFRatio = EAXSOURCE_DEFAULTEXCLUSIONLFRATIO;
eaxSourceProperties.lOutsideVolumeHF = EAXSOURCE_DEFAULTOUTSIDEVOLUMEHF;
eaxSourceProperties.flDopplerFactor = EAXSOURCE_DEFAULTDOPPLERFACTOR;
eaxSourceProperties.flRolloffFactor = EAXSOURCE_DEFAULTROLLOFFFACTOR;
eaxSourceProperties.flRoomRolloffFactor = EAXSOURCE_DEFAULTROOMROLLOFFFACTOR;
eaxSourceProperties.flAirAbsorptionFactor = EAXSOURCE_DEFAULTAIRABSORPTIONFACTOR;
eaxSourceProperties.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
eaxSourceProperties.ulFlags = EAXSOURCE_DEFAULTFLAGS;
/*
Apply the defaults to each source
*/
for (int i = 0; i < mNumSources; i++)
{
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_SPEAKERLEVELS, mSources[i]->sid, &eaxSourceSpeakerLevels, 8 * sizeof(EAXSPEAKERLEVELPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_ACTIVEFXSLOTID, mSources[i]->sid, &eaxSlots, sizeof(EAXACTIVEFXSLOTS));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_ALLPARAMETERS, mSources[i]->sid, &eaxSourceProperties, sizeof(EAXSOURCEPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Sets the channel's speaker volume levels for each speaker individually
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX5::setSpeakerMix(float frontleft, float frontright, float center, float lfe, float backleft, float backright, float sideleft, float sideright)
{
EAXSPEAKERLEVELPROPERTIES eaxSourceSpeakerLevels[8];
unsigned long eaxSourceFlags;
GUID eaxSourceGuid;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
FMOD_memcpy(&eaxSourceGuid, &FMOD_EAXPROPERTYID_EAX50_Source, sizeof(GUID));
eaxSourceSpeakerLevels[0].lSpeakerID = EAXSPEAKER_FRONT_LEFT;
eaxSourceSpeakerLevels[0].lLevel = (long)(100.0f * 20.0f * FMOD_LOG10(max(0.00001f, frontleft)));
eaxSourceSpeakerLevels[1].lSpeakerID = EAXSPEAKER_FRONT_CENTER;
eaxSourceSpeakerLevels[1].lLevel = (long)(100.0f * 20.0f * FMOD_LOG10(max(0.00001f, center)));
eaxSourceSpeakerLevels[2].lSpeakerID = EAXSPEAKER_FRONT_RIGHT;
eaxSourceSpeakerLevels[2].lLevel = (long)(100.0f * 20.0f * FMOD_LOG10(max(0.00001f, frontright)));
eaxSourceSpeakerLevels[3].lSpeakerID = EAXSPEAKER_SIDE_RIGHT;
eaxSourceSpeakerLevels[3].lLevel = (long)(100.0f * 20.0f * FMOD_LOG10(max(0.00001f, sideright)));
eaxSourceSpeakerLevels[4].lSpeakerID = EAXSPEAKER_REAR_RIGHT;
eaxSourceSpeakerLevels[4].lLevel = (long)(100.0f * 20.0f * FMOD_LOG10(max(0.00001f, backright)));
eaxSourceSpeakerLevels[5].lSpeakerID = EAXSPEAKER_REAR_LEFT;
eaxSourceSpeakerLevels[5].lLevel = (long)(100.0f * 20.0f * FMOD_LOG10(max(0.00001f, backleft)));
eaxSourceSpeakerLevels[6].lSpeakerID = EAXSPEAKER_SIDE_LEFT;
eaxSourceSpeakerLevels[6].lLevel = (long)(100.0f * 20.0f * FMOD_LOG10(max(0.00001f, sideleft)));
eaxSourceSpeakerLevels[7].lSpeakerID = EAXSPEAKER_LOW_FREQUENCY;
eaxSourceSpeakerLevels[7].lLevel = (long)(100.0f * 20.0f * FMOD_LOG10(max(0.00001f, lfe)));
/*
Enable or disable speaker mode usage for OpenAL
*/
mOutputOAL->mEAXGet(&eaxSourceGuid, EAXSOURCE_FLAGS, mSources[0]->sid, &eaxSourceFlags, sizeof(unsigned long));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
if (mParent->m3DPanLevel >= 0.5f)
{
eaxSourceFlags |= EAXSOURCEFLAGS_APPLYSPEAKERLEVELS;
}
else
{
eaxSourceFlags &= ~EAXSOURCEFLAGS_APPLYSPEAKERLEVELS;
}
/*
Set the speaker levels for each source
*/
for (int i = 0; i < mNumSources; i++)
{
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_FLAGS, mSources[i]->sid, &eaxSourceFlags, sizeof(unsigned long));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_SPEAKERLEVELS, mSources[i]->sid, &eaxSourceSpeakerLevels, 8 * sizeof(EAXSPEAKERLEVELPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Sets the incoming sound levels for a particular speaker
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX5::setSpeakerLevels(int speaker, float *levels, int numlevels)
{
long FMOD_SPEAKER_TO_EAXSPEAKER[11] = { EAXSPEAKER_FRONT_LEFT, EAXSPEAKER_FRONT_RIGHT, EAXSPEAKER_FRONT_CENTER, EAXSPEAKER_LOW_FREQUENCY, EAXSPEAKER_REAR_LEFT, EAXSPEAKER_REAR_RIGHT, EAXSPEAKER_SIDE_LEFT, EAXSPEAKER_SIDE_RIGHT, EAXSPEAKER_FRONT_LEFT, EAXSPEAKER_FRONT_LEFT, EAXSPEAKER_REAR_CENTER };
EAXSPEAKERLEVELPROPERTIES eaxSourceSpeakerLevels;
unsigned long eaxSourceFlags;
GUID eaxSourceGuid;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
FMOD_memcpy(&eaxSourceGuid, &FMOD_EAXPROPERTYID_EAX50_Source, sizeof(GUID));
/*
Enable or disable speaker mode usage for OpenAL
*/
mOutputOAL->mEAXGet(&eaxSourceGuid, EAXSOURCE_FLAGS, mSources[0]->sid, &eaxSourceFlags, sizeof(unsigned long));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
if (mParent->m3DPanLevel >= 0.5f)
{
eaxSourceFlags |= EAXSOURCEFLAGS_APPLYSPEAKERLEVELS;
}
else
{
eaxSourceFlags &= ~EAXSOURCEFLAGS_APPLYSPEAKERLEVELS;
}
/*
Set the speaker levels for each source, there may be less sources than levels
*/
numlevels = (mNumSources < numlevels) ? mNumSources : numlevels;
for (int i = 0; i < numlevels; i++)
{
eaxSourceSpeakerLevels.lSpeakerID = FMOD_SPEAKER_TO_EAXSPEAKER[speaker];
eaxSourceSpeakerLevels.lLevel = (long)(100.0f * 20.0f * FMOD_LOG10(max(0.00001f, levels[i])));
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_FLAGS, mSources[i]->sid, &eaxSourceFlags, sizeof(unsigned long));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_SPEAKERLEVELS, mSources[i]->sid, &eaxSourceSpeakerLevels, sizeof(EAXSPEAKERLEVELPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Set the reverb properties on the hardware
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
EAX5 has 4 effects slots, and is currently set up to allow only 2 to be active on
any one source, any of the four slots can be tasked for reverb
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX5::setReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop)
{
EAXSOURCEPROPERTIES eaxSourceProperties;
EAXACTIVEFXSLOTS eaxSlots;
unsigned long eaxSourceFlags;
GUID eaxSourceGuid;
GUID eaxFXSlot0, eaxFXSlot1, eaxFXSlot2, eaxFXSlot3, eaxFXSlotNull;
int numActiveSlots;
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FMOD_memcpy(&eaxFXSlot0, &FMOD_EAXPROPERTYID_EAX50_FXSlot0, sizeof(GUID));
FMOD_memcpy(&eaxFXSlot1, &FMOD_EAXPROPERTYID_EAX50_FXSlot1, sizeof(GUID));
FMOD_memcpy(&eaxFXSlot2, &FMOD_EAXPROPERTYID_EAX50_FXSlot2, sizeof(GUID));
FMOD_memcpy(&eaxFXSlot3, &FMOD_EAXPROPERTYID_EAX50_FXSlot3, sizeof(GUID));
FMOD_memcpy(&eaxFXSlotNull, &FMOD_EAX_NULL_GUID, sizeof(GUID));
FMOD_memcpy(&eaxSourceGuid, &FMOD_EAXPROPERTYID_EAX50_Source, sizeof(GUID));
/*
Only support a maximum 2 active slots per channel
*/
numActiveSlots = 0;
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE0)
{
numActiveSlots++;
}
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE1)
{
numActiveSlots++;
}
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
numActiveSlots++;
}
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE3)
{
numActiveSlots++;
}
if (numActiveSlots > 2)
{
return FMOD_ERR_UNSUPPORTED;
}
/*
Store the slot IDs for the chosen environment
*/
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlotNull, sizeof(GUID));
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlotNull, sizeof(GUID));
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[2], &eaxFXSlotNull, sizeof(GUID));
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[3], &eaxFXSlotNull, sizeof(GUID));
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE0)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot0, sizeof(GUID));
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE1)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot1, sizeof(GUID));
}
else if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot2, sizeof(GUID));
}
else if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE3)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot3, sizeof(GUID));
}
}
else if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE1)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot1, sizeof(GUID));
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot2, sizeof(GUID));
}
else if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE3)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot3, sizeof(GUID));
}
}
else if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot2, sizeof(GUID));
if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE3)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot3, sizeof(GUID));
}
}
else if (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE3)
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot3, sizeof(GUID));
}
else // Set to Slot 0 by default
{
FMOD_memcpy(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot0, sizeof(GUID));
}
/*
Set the channel reverb properties
*/
mOutputOAL->mEAXGet(&eaxSourceGuid, EAXSOURCE_FLAGS, mSources[0]->sid, &eaxSourceFlags, sizeof(unsigned long));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
eaxSourceProperties.lDirect = prop->Direct;
eaxSourceProperties.lDirectHF = prop->DirectHF;
eaxSourceProperties.lRoom = prop->Room;
eaxSourceProperties.lRoomHF = prop->RoomHF;
eaxSourceProperties.lObstruction = prop->Obstruction;
eaxSourceProperties.flObstructionLFRatio = prop->ObstructionLFRatio;
eaxSourceProperties.lOcclusion = prop->Occlusion;
eaxSourceProperties.flOcclusionLFRatio = prop->OcclusionLFRatio;
eaxSourceProperties.flOcclusionRoomRatio = prop->OcclusionRoomRatio;
eaxSourceProperties.flOcclusionDirectRatio = prop->OcclusionDirectRatio;
eaxSourceProperties.lExclusion = prop->Exclusion;
eaxSourceProperties.flExclusionLFRatio = prop->ExclusionLFRatio;
eaxSourceProperties.lOutsideVolumeHF = prop->OutsideVolumeHF;
eaxSourceProperties.flDopplerFactor = prop->DopplerFactor;
eaxSourceProperties.flRolloffFactor = prop->RolloffFactor;
eaxSourceProperties.flRoomRolloffFactor = prop->RoomRolloffFactor;
eaxSourceProperties.flAirAbsorptionFactor = prop->AirAbsorptionFactor;
eaxSourceProperties.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
eaxSourceFlags = (prop->Flags & FMOD_REVERB_CHANNELFLAGS_DIRECTHFAUTO) ? (eaxSourceFlags | EAXSOURCEFLAGS_DIRECTHFAUTO) : (eaxSourceFlags & ~EAXSOURCEFLAGS_DIRECTHFAUTO);
eaxSourceFlags = (prop->Flags & FMOD_REVERB_CHANNELFLAGS_ROOMAUTO) ? (eaxSourceFlags | EAXSOURCEFLAGS_ROOMAUTO) : (eaxSourceFlags & ~EAXSOURCEFLAGS_ROOMAUTO);
eaxSourceFlags = (prop->Flags & FMOD_REVERB_CHANNELFLAGS_ROOMHFAUTO) ? (eaxSourceFlags | EAXSOURCEFLAGS_ROOMHFAUTO) : (eaxSourceFlags & ~EAXSOURCEFLAGS_ROOMHFAUTO);
eaxSourceProperties.ulFlags = eaxSourceFlags;
/*
Apply the active slots and properties to the sources
*/
for (int i = 0; i < mNumSources; i++)
{
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_ACTIVEFXSLOTID, mSources[i]->sid, &eaxSlots, sizeof(EAXACTIVEFXSLOTS));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
mOutputOAL->mEAXSet(&eaxSourceGuid, EAXSOURCE_ALLPARAMETERS, mSources[i]->sid, &eaxSourceProperties, sizeof(EAXSOURCEPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Get the reverb properties from the hardware
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
EAX5 has 4 effects slots, and is currently set up to allow only 2 to be active on
any one source, any of the four slots can be tasked for reverb
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT ChannelOpenALEAX5::getReverbProperties(FMOD_REVERB_CHANNELPROPERTIES *prop)
{
EAXSOURCEPROPERTIES eaxSourceProperties;
EAXACTIVEFXSLOTS eaxSlots;
GUID eaxSourceGuid;
GUID eaxFXSlot0, eaxFXSlot1, eaxFXSlot2, eaxFXSlot3;
int numInactiveSlots;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mOutputOAL)
{
return FMOD_ERR_UNINITIALIZED;
}
FMOD_memcpy(&eaxFXSlot0, &FMOD_EAXPROPERTYID_EAX50_FXSlot0, sizeof(GUID));
FMOD_memcpy(&eaxFXSlot1, &FMOD_EAXPROPERTYID_EAX50_FXSlot1, sizeof(GUID));
FMOD_memcpy(&eaxFXSlot2, &FMOD_EAXPROPERTYID_EAX50_FXSlot2, sizeof(GUID));
FMOD_memcpy(&eaxFXSlot3, &FMOD_EAXPROPERTYID_EAX50_FXSlot3, sizeof(GUID));
FMOD_memcpy(&eaxSourceGuid, &FMOD_EAXPROPERTYID_EAX50_Source, sizeof(GUID));
/*
Get the channel reverb properties
*/
mOutputOAL->mEAXGet(&eaxSourceGuid, EAXSOURCE_ALLPARAMETERS, mSources[0]->sid, &eaxSourceProperties, sizeof(EAXSOURCEPROPERTIES));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
FMOD_memset(prop, 0, sizeof(FMOD_REVERB_CHANNELPROPERTIES));
prop->Direct = eaxSourceProperties.lDirect;
prop->DirectHF = eaxSourceProperties.lDirectHF;
prop->Room = eaxSourceProperties.lRoom;
prop->RoomHF = eaxSourceProperties.lRoomHF;
prop->Obstruction = eaxSourceProperties.lObstruction;
prop->ObstructionLFRatio = eaxSourceProperties.flObstructionLFRatio;
prop->Occlusion = eaxSourceProperties.lOcclusion;
prop->OcclusionLFRatio = eaxSourceProperties.flOcclusionLFRatio;
prop->OcclusionRoomRatio = eaxSourceProperties.flOcclusionRoomRatio;
prop->OcclusionDirectRatio = eaxSourceProperties.flOcclusionDirectRatio;
prop->Exclusion = eaxSourceProperties.lExclusion;
prop->ExclusionLFRatio = eaxSourceProperties.flExclusionLFRatio;
prop->OutsideVolumeHF = eaxSourceProperties.lOutsideVolumeHF;
prop->DopplerFactor = eaxSourceProperties.flDopplerFactor;
prop->RolloffFactor = eaxSourceProperties.flRolloffFactor;
prop->RoomRolloffFactor = eaxSourceProperties.flRoomRolloffFactor;
prop->AirAbsorptionFactor = eaxSourceProperties.flAirAbsorptionFactor;
prop->Flags = 0;
prop->Flags |= (eaxSourceProperties.ulFlags & EAXSOURCEFLAGS_DIRECTHFAUTO) ? FMOD_REVERB_CHANNELFLAGS_DIRECTHFAUTO : 0;
prop->Flags |= (eaxSourceProperties.ulFlags & EAXSOURCEFLAGS_ROOMAUTO) ? FMOD_REVERB_CHANNELFLAGS_ROOMAUTO : 0;
prop->Flags |= (eaxSourceProperties.ulFlags & EAXSOURCEFLAGS_ROOMHFAUTO) ? FMOD_REVERB_CHANNELFLAGS_ROOMHFAUTO : 0;
// Get all the effect slots associated with this source
mOutputOAL->mEAXGet(&eaxSourceGuid, EAXSOURCE_ACTIVEFXSLOTID, mSources[0]->sid, &eaxSlots, sizeof(EAXACTIVEFXSLOTS));
if (mOutputOAL->mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
/*
See if there are any active effect slots
*/
numInactiveSlots = 0;
// Check active slot 0 for any of the 4 possible effect IDs
if (!memcmp(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot0, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE0;
}
else if (!memcmp(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot1, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE1;
}
else if (!memcmp(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot2, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE2;
}
else if (!memcmp(&eaxSlots.guidActiveFXSlots[0], &eaxFXSlot3, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE3;
}
else
{
numInactiveSlots++;
}
// Check active slot 1 for any of the 4 possible effect IDs
if (!memcmp(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot0, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE0;
}
else if (!memcmp(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot1, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE1;
}
else if (!memcmp(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot2, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE2;
}
else if (!memcmp(&eaxSlots.guidActiveFXSlots[1], &eaxFXSlot3, sizeof(GUID)))
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE3;
}
else
{
numInactiveSlots++;
}
// If no slots have been assigned (max slots = 2), assign to slot 0
if (numInactiveSlots == 2)
{
prop->Flags |= FMOD_REVERB_CHANNELFLAGS_INSTANCE0;
}
return FMOD_OK;
}
}
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */

View file

@ -0,0 +1,32 @@
#ifndef _FMOD_CHANNEL_OPENAL_EAX5_H
#define _FMOD_CHANNEL_OPENAL_EAX5_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_channel_openal.h"
namespace FMOD
{
class ChannelOpenALEAX5 : public ChannelOpenAL
{
public:
ChannelOpenALEAX5() {};
FMOD_RESULT setupChannel ();
FMOD_RESULT setSpeakerMix (float frontleft, float frontright, float center, float lfe, float backleft, float backright, float sideleft, float sideright);
FMOD_RESULT setSpeakerLevels (int speaker, float *levels, int numlevels);
FMOD_RESULT setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop);
};
}
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */
#endif /* _FMOD_CHANNEL_OPENAL_EAX5_H */

1180
fmod/win32/src/fmod_codec_asf.cpp Executable file

File diff suppressed because it is too large Load diff

131
fmod/win32/src/fmod_codec_asf.h Executable file
View file

@ -0,0 +1,131 @@
#ifndef _FMOD_CODEC_ASF_H
#define _FMOD_CODEC_ASF_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_ASF
#include "fmod_codeci.h"
#include <objidl.h>
#include "../lib/wmsdk/include/wmsdk.h"
namespace FMOD
{
class CROStream : public IStream
{
public:
CROStream();
//
// IUnknown methods
//
HRESULT STDMETHODCALLTYPE QueryInterface( /* [in] */ REFIID riid,
/* [out] */ void **ppvObject );
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
//
// Methods of IStream
//
HRESULT STDMETHODCALLTYPE Read( void *pv, ULONG cb, ULONG *pcbRead );
HRESULT STDMETHODCALLTYPE Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition );
HRESULT STDMETHODCALLTYPE Stat( STATSTG *pstatstg, DWORD grfStatFlag );
//
// Non-implemented methods of IStream
//
HRESULT STDMETHODCALLTYPE Write( void const *pv, ULONG cb, ULONG *pcbWritten )
{
return( E_NOTIMPL );
}
HRESULT STDMETHODCALLTYPE SetSize( ULARGE_INTEGER libNewSize )
{
return( E_NOTIMPL );
}
HRESULT STDMETHODCALLTYPE CopyTo( IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten )
{
return( E_NOTIMPL );
}
HRESULT STDMETHODCALLTYPE Commit( DWORD grfCommitFlags )
{
return( E_NOTIMPL );
}
HRESULT STDMETHODCALLTYPE Revert()
{
return( E_NOTIMPL );
}
HRESULT STDMETHODCALLTYPE LockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType )
{
return( E_NOTIMPL );
}
HRESULT STDMETHODCALLTYPE UnlockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType )
{
return( E_NOTIMPL );
}
HRESULT STDMETHODCALLTYPE Clone( IStream **ppstm )
{
return( E_NOTIMPL );
}
//
// CROStream method
//
HRESULT Open( /* [in] */ LPCTSTR ptszURL );
protected:
~CROStream();
File *mFile;
LONG m_cRefs;
};
typedef HRESULT (STDMETHODCALLTYPE *PFN_WMCREATESYNCREADER)( IUnknown* pUnkCert, DWORD dwRights, IWMSyncReader **ppSyncReader );
class SyncPointNamed;
static const unsigned int FMOD_ASF_MAXIMUM_SEEK_POS_MS = 2000;
class CodecASF : public Codec
{
private:
bool mCoInitialized;
IWMSyncReader *mReader; // IWMReader pointer
CROStream *mStream;
WORD mAudioStreamNum;
WORD mVideoStreamNum;
QWORD mSampleTime;
bool mSeekable;
int mNumSyncPoints;
SyncPointNamed *mSyncPoint;
unsigned int mExcessBytes;
static PFN_WMCREATESYNCREADER gWMCreateSyncReader;
static HMODULE gDLLHandle;
FMOD_RESULT getStreamNumbers(IWMProfile* pProfile);
FMOD_RESULT openInternal(FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
FMOD_RESULT closeInternal();
FMOD_RESULT readInternal(void *buffer, unsigned int size, unsigned int *read);
FMOD_RESULT setPositionInternal(int subsound, unsigned int position, FMOD_TIMEUNIT postype);
FMOD_RESULT soundCreateInternal(int subsound, FMOD_SOUND *sound);
public:
static FMOD_RESULT F_CALLBACK openCallback(FMOD_CODEC_STATE *codec, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
static FMOD_RESULT F_CALLBACK closeCallback(FMOD_CODEC_STATE *codec);
static FMOD_RESULT F_CALLBACK readCallback(FMOD_CODEC_STATE *codec, void *buffer, unsigned int sizebytes, unsigned int *bytesread);
static FMOD_RESULT F_CALLBACK setPositionCallback(FMOD_CODEC_STATE *codec, int subsound, unsigned int position, FMOD_TIMEUNIT postype);
static FMOD_RESULT F_CALLBACK soundCreateCallback(FMOD_CODEC_STATE *codec, int subsound, FMOD_SOUND *sound);
static FMOD_CODEC_DESCRIPTION_EX *getDescriptionEx();
};
}
#endif /* FMOD_SUPPORT_ASF */
#endif

View file

@ -0,0 +1,373 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_CDDA
#include "fmod.h"
#include "fmod_codec_cdda.h"
#include "fmod_debug.h"
#include "fmod_file.h"
#include "fmod_file_cdda.h"
#include "fmod_metadata.h"
#include "fmod_os_cdda.h"
#include "fmod_soundi.h"
#include "fmod_string.h"
#include <memory.h>
#include <stdio.h>
namespace FMOD
{
FMOD_CODEC_DESCRIPTION_EX cddacodec;
#ifdef PLUGIN_EXPORTS
#ifdef __cplusplus
extern "C" {
#endif
/*
FMODGetCodecDescriptionEx is mandatory for every fmod plugin. This is the symbol the registerplugin function searches for.
Must be declared with F_API to make it export as stdcall.
*/
F_DECLSPEC F_DLLEXPORT FMOD_CODEC_DESCRIPTION_EX * F_API FMODGetCodecDescriptionEx()
{
return CodecCDDA::getDescriptionEx();
}
#ifdef __cplusplus
}
#endif
#endif /* PLUGIN_EXPORTS */
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_CODEC_DESCRIPTION_EX *CodecCDDA::getDescriptionEx()
{
FMOD_memset(&cddacodec, 0, sizeof(FMOD_CODEC_DESCRIPTION_EX));
cddacodec.name = "FMOD CDDA Codec";
cddacodec.version = 0x00010100;
cddacodec.timeunits = FMOD_TIMEUNIT_PCM;
cddacodec.open = &CodecCDDA::openCallback;
cddacodec.close = &CodecCDDA::closeCallback;
cddacodec.read = &CodecCDDA::readCallback;
cddacodec.setposition = &CodecCDDA::setPositionCallback;
cddacodec.mType = FMOD_SOUND_TYPE_CDDA;
cddacodec.mSize = sizeof(CodecCDDA);
return &cddacodec;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT CodecCDDA::openInternal(FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo)
{
int count;
char *filename;
CddaFile *cddafile;
FMOD_RESULT result = FMOD_OK;
mCurrentTrack = -1;
init(FMOD_SOUND_TYPE_CDDA);
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "CodecCDDA::openInternal", "attempting to open as CDDA..\n"));
mFile->getName(&filename);
if (!FMOD_OS_CDDA_IsDeviceName(filename))
{
return FMOD_ERR_FORMAT;
}
cddafile = SAFE_CAST(CddaFile, mFile);
result = cddafile->getNumTracks(&numsubsounds);
if (result != FMOD_OK)
{
return result;
}
if (!numsubsounds)
{
return FMOD_ERR_CDDA_NOAUDIO;
}
waveformat = (FMOD_CODEC_WAVEFORMAT *)FMOD_Memory_Calloc(sizeof(FMOD_CODEC_WAVEFORMAT) * numsubsounds);
if (!waveformat)
{
return FMOD_ERR_MEMORY;
}
for (count = 0; count < numsubsounds; count++)
{
unsigned int tracklength;
result = cddafile->getTrackLength(count, &tracklength);
if (result != FMOD_OK)
{
return result;
}
sprintf(waveformat[count].name, "Track %d", count+1);
waveformat[count].format = FMOD_SOUND_FORMAT_PCM16;
waveformat[count].channels = 2;
waveformat[count].frequency = 44100;
waveformat[count].lengthpcm = tracklength >> 2;
waveformat[count].blockalign = waveformat[count].channels * 16 / 8;
}
mPCMBufferLengthBytes = 256 * 1024;
result = setPositionInternal(0, 0, FMOD_TIMEUNIT_PCM);
return result;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT CodecCDDA::closeInternal()
{
if (waveformat)
{
FMOD_Memory_Free(waveformat);
waveformat = 0;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT CodecCDDA::readInternal(void *buffer, unsigned int sizebytes, unsigned int *bytesread)
{
FMOD_RESULT result = FMOD_OK;
result = mFile->read(buffer, 1, sizebytes, bytesread);
if (result != FMOD_OK && result != FMOD_ERR_FILE_EOF)
{
return result;
}
return result;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT CodecCDDA::setPositionInternal(int subsound, unsigned int position, FMOD_TIMEUNIT postype)
{
CddaFile *cddafile;
FMOD_RESULT result = FMOD_OK;
unsigned int offset;
if (subsound < 0 || (numsubsounds && subsound >= numsubsounds))
{
return FMOD_ERR_INVALID_POSITION;
}
cddafile = SAFE_CAST(CddaFile, mFile);
if (subsound != mCurrentTrack)
{
mCurrentTrack = subsound;
result = cddafile->openTrack(mCurrentTrack);
if (result != FMOD_OK)
{
return result;
}
}
result = SoundI::getBytesFromSamples(position, &offset, waveformat[mCurrentTrack].channels, waveformat[mCurrentTrack].format);
if (result != FMOD_OK)
{
return result;
}
result = cddafile->seek(offset, SEEK_SET);
if (result != FMOD_OK)
{
return result;
}
return result;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK CodecCDDA::openCallback(FMOD_CODEC_STATE *codec, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo)
{
CodecCDDA *cdda = (CodecCDDA *)codec;
return cdda->openInternal(usermode, userexinfo);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK CodecCDDA::closeCallback(FMOD_CODEC_STATE *codec)
{
CodecCDDA *cdda = (CodecCDDA *)codec;
return cdda->closeInternal();
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK CodecCDDA::readCallback(FMOD_CODEC_STATE *codec, void *buffer, unsigned int sizebytes, unsigned int *bytesread)
{
CodecCDDA *cdda = (CodecCDDA *)codec;
return cdda->readInternal(buffer, sizebytes, bytesread);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK CodecCDDA::setPositionCallback(FMOD_CODEC_STATE *codec, int subsound, unsigned int position, FMOD_TIMEUNIT postype)
{
CodecCDDA *cdda = (CodecCDDA *)codec;
return cdda->setPositionInternal(subsound, position, postype);
}
}
#endif

View file

@ -0,0 +1,36 @@
#ifndef _FMOD_CODEC_CDDA_H
#define _FMOD_CODEC_CDDA_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_CDDA
#include "fmod_codeci.h"
namespace FMOD
{
class CodecCDDA : public Codec
{
private:
int mCurrentTrack;
FMOD_RESULT openInternal(FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
FMOD_RESULT closeInternal();
FMOD_RESULT readInternal(void *buffer, unsigned int size, unsigned int *read);
FMOD_RESULT setPositionInternal(int subsound, unsigned int position, FMOD_TIMEUNIT postype);
public:
static FMOD_RESULT F_CALLBACK openCallback(FMOD_CODEC_STATE *codec, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
static FMOD_RESULT F_CALLBACK closeCallback(FMOD_CODEC_STATE *codec);
static FMOD_RESULT F_CALLBACK readCallback(FMOD_CODEC_STATE *codec, void *buffer, unsigned int sizebytes, unsigned int *bytesread);
static FMOD_RESULT F_CALLBACK setPositionCallback(FMOD_CODEC_STATE *codec, int subsound, unsigned int position, FMOD_TIMEUNIT postype);
static FMOD_CODEC_DESCRIPTION_EX *getDescriptionEx();
};
}
#endif /* FMOD_SUPPORT_CDDA */
#endif

View file

@ -0,0 +1,6 @@
#include <windows.h>
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}

View file

@ -0,0 +1,732 @@
%include "./FMOD_static/win32/src/c32.mac"
; ==========================================================================================
; GLOBAL UNINITIALIZED DATA
; ==========================================================================================
[SEGMENT .data use32 align=32]
; ==========================================================================================
; CODE
; ==========================================================================================
[SEGMENT .text use32 align=32]
; =================================================================================================================================
; void FMOD_DSP_Connection_MixMonoToStereo_SIMD (float *inbuffer, float *outbuffer, unsigned int length, float lvolume, float rvolume);
; =================================================================================================================================
proc FMOD_DSP_Connection_MixMonoToStereo_SIMD
%$inbuffer arg
%$outbuffer arg
%$length arg
%$lvolume arg
%$rvolume arg
push eax
push ebx
push ecx
push edx
push esi
push edi
mov esi, [ebp+%$inbuffer]
mov edi, [ebp+%$outbuffer]
; xmm0 = [lvolume ][rvolume ][lvolume ][rvolume ]
; xmm1 = [samp1 ][samp1 ][samp2 ][samp2 ]
; xmm2 = [samp3 ][samp3 ][samp4 ][samp4 ]
; xmm3 = [ ][ ][ ][ ]
; xmm4 = [ ][ ][ ][ ]
; xmm5 = [ ][ ][ ][ ]
; xmm6 = [ ][ ][ ][ ]
; xmm7 = [ ][ ][ ][ ]
movss xmm0, [ebp+%$lvolume]
movss xmm1, [ebp+%$rvolume]
shufps xmm0, xmm0, 0
shufps xmm1, xmm1, 0
unpcklps xmm0, xmm1
mov edx, [ebp+%$length]
mov ecx, edx
%if 1
shr ecx, 2
test ecx, ecx
jz mixloopMtoSrolledstart
mixloopMtoSunrolled:
movups xmm1, [esi]
movaps xmm2, xmm1
movaps xmm3, [edi]
movaps xmm4, [edi + 16]
unpcklps xmm1, xmm1
unpckhps xmm2, xmm2
mulps xmm1, xmm0
mulps xmm2, xmm0
addps xmm3, xmm1
addps xmm4, xmm2
movaps [edi], xmm3
movaps [edi+16], xmm4
add edi, 32
add esi, 16
dec ecx
jnz near mixloopMtoSunrolled
mixloopMtoSrolledstart:
mov ecx, edx
and ecx, 3
%endif
test ecx, ecx
jz mixMtoSdone
mixloopMtoSrolled:
movss xmm1, [esi]
movss xmm2, xmm1
movss xmm3, [edi]
movss xmm4, [edi+4]
mulss xmm1, [ebp+%$lvolume]
mulss xmm2, [ebp+%$rvolume]
addss xmm3, xmm1
addss xmm4, xmm2
movss [edi], xmm3
movss [edi+4], xmm4
add edi, 8
add esi, 4
dec ecx
jnz near mixloopMtoSrolled
mixMtoSdone:
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
endproc
; =================================================================================================================================
; void FMOD_DSP_Connection_MixStereoToStereo_SIMD(float *inbuffer, float *outbuffer, unsigned int length, float lvolume, float rvolume);
; =================================================================================================================================
proc FMOD_DSP_Connection_MixStereoToStereo_SIMD
%$inbuffer arg
%$outbuffer arg
%$length arg
%$lvolume arg
%$rvolume arg
push eax
push ebx
push ecx
push edx
push esi
push edi
mov esi, [ebp+%$inbuffer]
mov edi, [ebp+%$outbuffer]
; xmm0 = [lvolume ][rvolume ][lvolume ][rvolume ]
; xmm1 = [samp1 ][samp1 ][samp2 ][samp2 ]
; xmm2 = [samp3 ][samp3 ][samp4 ][samp4 ]
; xmm3 = [ ][ ][ ][ ]
; xmm4 = [ ][ ][ ][ ]
; xmm5 = [ ][ ][ ][ ]
; xmm6 = [ ][ ][ ][ ]
; xmm7 = [ ][ ][ ][ ]
movss xmm0, [ebp+%$lvolume]
movss xmm1, [ebp+%$rvolume]
shufps xmm0, xmm0, 0
shufps xmm1, xmm1, 0
unpcklps xmm0, xmm1
mov edx, [ebp+%$length]
mov ecx, edx
%if 1
shr ecx, 2
test ecx, ecx
jz mixloopStoSrolledstart
mixloopStoSunrolled:
movups xmm1, [esi]
movups xmm2, [esi+16]
movaps xmm3, [edi]
movaps xmm4, [edi+16]
mulps xmm1, xmm0
mulps xmm2, xmm0
addps xmm3, xmm1
addps xmm4, xmm2
movaps [edi], xmm3
movaps [edi+16], xmm4
add edi, 32
add esi, 32
dec ecx
jnz near mixloopStoSunrolled
mixloopStoSrolledstart:
mov ecx, edx
and ecx, 3
%endif
test ecx, ecx
jz mixStoSdone
mixloopStoSrolled:
movss xmm1, [esi]
movss xmm2, [esi+4]
movss xmm3, [edi]
movss xmm4, [edi+4]
mulss xmm1, [ebp+%$lvolume]
mulss xmm2, [ebp+%$rvolume]
addss xmm3, xmm1
addss xmm4, xmm2
movss [edi], xmm3
movss [edi+4], xmm4
add edi, 8
add esi, 8
dec ecx
jnz near mixloopStoSrolled
mixStoSdone:
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
endproc
; =================================================================================================================================
; void FMOD_DSP_Connection_MixMonoTo5_1_SIMD(float *inbuffer, float *outbuffer, unsigned int length, float *volume0to3, float *volume4to1, float *volume2to5);
; =================================================================================================================================
proc FMOD_DSP_Connection_MixMonoTo5_1_SIMD
%$inbuffer arg
%$outbuffer arg
%$length arg
%$volume0to3 arg
%$volume4to1 arg
%$volume2to5 arg
push eax
push ebx
push ecx
push edx
push esi
push edi
mov esi, [ebp+%$inbuffer]
mov edi, [ebp+%$outbuffer]
; xmm0 = [l00 ][l10 ][l20 ][l30 ]
; xmm1 = [l40 ][l50 ][l00 ][l10 ]
; xmm2 = [l20 ][l30 ][l40 ][l50 ]
; xmm3 = [ ][ ][ ][ ]
; xmm4 = [ ][ ][ ][ ]
; xmm5 = [ ][ ][ ][ ]
; xmm6 = [ ][ ][ ][ ]
; xmm7 = [ ][ ][ ][ ]
mov edx, [ebp+%$length]
mov ecx, edx
mov eax, [ebp+%$volume0to3]
movups xmm0, [eax]
mov eax, [ebp+%$volume4to1]
movups xmm1, [eax]
mov eax, [ebp+%$volume2to5]
movups xmm2, [eax]
%if 1
shr ecx, 2
test ecx, ecx
jz near mixloopMto51rolledstart
mixloopMto51unrolled:
movss xmm3, [esi + 0]
movlps xmm4, [esi + 0]
shufps xmm3, xmm3, 0
shufps xmm4, xmm4, 50h
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi]
addps xmm4, [edi + 16]
movaps [edi], xmm3
movaps [edi+16], xmm4
movss xmm3, [esi + 4]
movss xmm4, [esi + 8]
shufps xmm3, xmm3, 0
shufps xmm4, xmm4, 0
mulps xmm3, xmm2
mulps xmm4, xmm0
addps xmm3, [edi + 32]
addps xmm4, [edi + 48]
movaps [edi+32], xmm3
movaps [edi+48], xmm4
movlps xmm3, [esi + 8]
movss xmm4, [esi + 12]
shufps xmm3, xmm3, 50h
shufps xmm4, xmm4, 0
mulps xmm3, xmm1
mulps xmm4, xmm2
addps xmm3, [edi + 64]
addps xmm4, [edi + 80]
movaps [edi+64], xmm3
movaps [edi+80], xmm4
add edi, 96
add esi, 16
dec ecx
jnz near mixloopMto51unrolled
mixloopMto51rolledstart:
mov ecx, ebp
and ecx, 3
%endif
test ecx, ecx
jz mixMto51done
mixloopMto51rolled:
movss xmm3, [esi + 0]
shufps xmm3, xmm3, 0
movups xmm4, [edi]
mulps xmm3, xmm0
addps xmm4, xmm3
movups [edi], xmm4
movlps xmm3, [esi + 0]
shufps xmm3, xmm3, 50h
movlps xmm4, [edi + 16]
mulps xmm3, xmm1
addps xmm4, xmm3
movlps [edi + 16], xmm4
add edi, 24
add esi, 4
dec ecx
jnz near mixloopMto51rolled
mixMto51done:
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
endproc
; =================================================================================================================================
; void FMOD_DSP_Connection_Mix5_1To5_1_SIMD(float *inbuffer, float *outbuffer, unsigned int length, float *volume0to3, float *volume4to1, float *volume2to5);
; =================================================================================================================================
proc FMOD_DSP_Connection_Mix5_1To5_1_SIMD
%$inbuffer arg
%$outbuffer arg
%$length arg
%$volume0to3 arg
%$volume4to1 arg
%$volume2to5 arg
push eax
push ebx
push ecx
push edx
push esi
push edi
mov esi, [ebp+%$inbuffer]
mov edi, [ebp+%$outbuffer]
; xmm0 = [l00 ][l10 ][l20 ][l30 ]
; xmm1 = [l40 ][l50 ][l00 ][l10 ]
; xmm2 = [l20 ][l30 ][l40 ][l50 ]
; xmm3 = [ ][ ][ ][ ]
; xmm4 = [ ][ ][ ][ ]
; xmm5 = [ ][ ][ ][ ]
; xmm6 = [ ][ ][ ][ ]
; xmm7 = [ ][ ][ ][ ]
mov edx, [ebp+%$length]
mov ecx, edx
mov eax, [ebp+%$volume0to3]
movups xmm0, [eax]
mov eax, [ebp+%$volume4to1]
movups xmm1, [eax]
mov eax, [ebp+%$volume2to5]
movups xmm2, [eax]
%if 1
shr ecx, 2
test ecx, ecx
jz near mixloop51to51rolledstart
mixloop51to51unrolled:
movaps xmm3, [esi + 0]
movaps xmm4, [esi + 16]
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi + 0]
addps xmm4, [edi + 16]
movaps [edi], xmm3
movaps [edi+16], xmm4
movaps xmm3, [esi + 32]
movaps xmm4, [esi + 48]
mulps xmm3, xmm2
mulps xmm4, xmm0
addps xmm3, [edi + 32]
addps xmm4, [edi + 48]
movaps [edi+32], xmm3
movaps [edi+48], xmm4
movaps xmm3, [esi + 64]
movaps xmm4, [esi + 80]
mulps xmm3, xmm1
mulps xmm4, xmm2
addps xmm3, [edi + 64]
addps xmm4, [edi + 80]
movaps [edi+64], xmm3
movaps [edi+80], xmm4
add edi, 96
add esi, 96
dec ecx
jnz near mixloop51to51unrolled
mixloop51to51rolledstart:
mov ecx, ebp
and ecx, 3
%endif
test ecx, ecx
jz mix51to51done
mixloop51to51rolled:
movups xmm3, [esi + 0]
movups xmm4, [edi + 0]
mulps xmm3, xmm0
addps xmm4, xmm3
movups [edi], xmm4
movlps xmm3, [esi + 16]
movlps xmm4, [edi + 16]
mulps xmm3, xmm1
addps xmm4, xmm3
movlps [edi+16], xmm4
add edi, 24
add esi, 24
dec ecx
jnz near mixloop51to51rolled
mix51to51done:
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
endproc
; =================================================================================================================================
; void FMOD_DSP_Connection_MixMonoTo7_1_SIMD(float *inbuffer, float *outbuffer, unsigned int length, float *volume0to3, float *volume4to7);
; =================================================================================================================================
proc FMOD_DSP_Connection_MixMonoTo7_1_SIMD
%$inbuffer arg
%$outbuffer arg
%$length arg
%$volume0to3 arg
%$volume4to7 arg
push eax
push ebx
push ecx
push edx
push esi
push edi
mov esi, [ebp+%$inbuffer]
mov edi, [ebp+%$outbuffer]
; xmm0 = [l00 ][l10 ][l20 ][l30 ]
; xmm1 = [l40 ][l50 ][l00 ][l10 ]
; xmm2 = [l20 ][l30 ][l40 ][l50 ]
; xmm3 = [ ][ ][ ][ ]
; xmm4 = [ ][ ][ ][ ]
; xmm5 = [ ][ ][ ][ ]
; xmm6 = [ ][ ][ ][ ]
; xmm7 = [ ][ ][ ][ ]
mov edx, [ebp+%$length]
mov ecx, edx
mov eax, [ebp+%$volume0to3]
movups xmm0, [eax]
mov eax, [ebp+%$volume4to7]
movups xmm1, [eax]
%if 1
shr ecx, 2
test ecx, ecx
jz near mixloopMto71rolledstart
mixloopMto71unrolled:
movss xmm3, [esi + 0]
shufps xmm3, xmm3, 0
movaps xmm4, xmm3
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi + 0]
addps xmm4, [edi + 16]
movaps [edi+0], xmm3
movaps [edi+16], xmm4
movss xmm3, [esi + 4]
shufps xmm3, xmm3, 0
movaps xmm4, xmm3
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi + 32]
addps xmm4, [edi + 48]
movaps [edi+32], xmm3
movaps [edi+48], xmm4
movss xmm3, [esi + 8]
shufps xmm3, xmm3, 0
movaps xmm4, xmm3
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi + 64]
addps xmm4, [edi + 80]
movaps [edi+64], xmm3
movaps [edi+80], xmm4
movss xmm3, [esi + 12]
shufps xmm3, xmm3, 0
movaps xmm4, xmm3
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi + 96]
addps xmm4, [edi + 112]
movaps [edi+96], xmm3
movaps [edi+112], xmm4
add edi, 128
add esi, 16
dec ecx
jnz near mixloopMto71unrolled
mixloopMto71rolledstart:
mov ecx, ebp
and ecx, 3
%endif
test ecx, ecx
jz mixMto71done
mixloopMto71rolled:
movss xmm3, [esi + 0]
shufps xmm3, xmm3, 0
movaps xmm4, xmm3
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi + 0]
addps xmm4, [edi + 16]
movaps [edi+0], xmm3
movaps [edi+16], xmm4
add edi, 32
add esi, 4
dec ecx
jnz near mixloopMto71rolled
mixMto71done:
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
endproc
; =================================================================================================================================
; void FMOD_DSP_Connection_Mix7_1To7_1_SIMD(float *inbuffer, float *outbuffer, unsigned int length, float *volume0to3, float *volume4to7);
; =================================================================================================================================
proc FMOD_DSP_Connection_Mix7_1To7_1_SIMD
%$inbuffer arg
%$outbuffer arg
%$length arg
%$volume0to3 arg
%$volume4to7 arg
push eax
push ebx
push ecx
push edx
push esi
push edi
mov esi, [ebp+%$inbuffer]
mov edi, [ebp+%$outbuffer]
; xmm0 = [l00 ][l10 ][l20 ][l30 ]
; xmm1 = [l40 ][l50 ][l00 ][l10 ]
; xmm2 = [l20 ][l30 ][l40 ][l50 ]
; xmm3 = [ ][ ][ ][ ]
; xmm4 = [ ][ ][ ][ ]
; xmm5 = [ ][ ][ ][ ]
; xmm6 = [ ][ ][ ][ ]
; xmm7 = [ ][ ][ ][ ]
mov edx, [ebp+%$length]
mov ecx, edx
mov eax, [ebp+%$volume0to3]
movups xmm0, [eax]
mov eax, [ebp+%$volume4to7]
movups xmm1, [eax]
%if 1
shr ecx, 2
test ecx, ecx
jz near mixloop71to71rolledstart
mixloop71to71unrolled:
movaps xmm3, [esi + 0]
movaps xmm4, [esi + 16]
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi + 0]
addps xmm4, [edi + 16]
movaps [edi], xmm3
movaps [edi+16], xmm4
movaps xmm3, [esi + 32]
movaps xmm4, [esi + 48]
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi + 32]
addps xmm4, [edi + 48]
movaps [edi+32], xmm3
movaps [edi+48], xmm4
movaps xmm3, [esi + 64]
movaps xmm4, [esi + 80]
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi + 64]
addps xmm4, [edi + 80]
movaps [edi+64], xmm3
movaps [edi+80], xmm4
movaps xmm3, [esi + 96]
movaps xmm4, [esi + 112]
mulps xmm3, xmm0
mulps xmm4, xmm1
addps xmm3, [edi + 96]
addps xmm4, [edi + 112]
movaps [edi+96], xmm3
movaps [edi+112], xmm4
add edi, 128
add esi, 128
dec ecx
jnz near mixloop71to71unrolled
mixloop71to71rolledstart:
mov ecx, ebp
and ecx, 3
%endif
test ecx, ecx
jz mix71to71done
mixloop71to71rolled:
movups xmm3, [esi + 0]
movups xmm4, [edi + 0]
mulps xmm3, xmm0
addps xmm4, xmm3
movups [edi], xmm4
movups xmm3, [esi + 16]
movups xmm4, [edi + 16]
mulps xmm3, xmm1
addps xmm4, xmm3
movups [edi+16], xmm4
add edi, 32
add esi, 32
dec ecx
jnz near mixloop71to71rolled
mix71to71done:
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
endproc

View file

@ -0,0 +1,148 @@
%include "./FMOD_static/win32/src/c32.mac"
; ==========================================================================================
; GLOBAL UNINITIALIZED DATA
; ==========================================================================================
[SEGMENT .bss use32 align=32]
; ==========================================================================================
; GLOBAL PREINITIALIZED DATA
; ==========================================================================================
section .text
align 16
negones dd -32768.0, -32768.0, -32768.0, -32768.0
ones dd 32767.0, 32767.0, 32767.0, 32767.0
; ==========================================================================================
; CODE
; ==========================================================================================
section .text
; =================================================================================================================================
; void FMOD_DSP_Convert_FloatToPCM16(short *outbuffer, float *inbuffer, unsigned int length, int destchannelstep, int srcchannelstep, float volume);
; =================================================================================================================================
proc FMOD_DSP_Convert_FloatToPCM16
%$outbuffer arg
%$inbuffer arg
%$length arg
%$destchannelstep arg
%$srcchannelstep arg
%$volume arg
push eax
push ebx
push ecx
push edx
push esi
push edi
; xmm0 = [ ][ ][ ][ ]
; xmm1 = [ ][ ][ ][ ]
; xmm2 = [ ][ ][ ][ ]
; xmm3 = [ ][ ][ ][ ]
; xmm4 = [ ][ ][ ][ ]
; xmm5 = [ ][ ][ ][ ]
; xmm6 = [ ][ ][ ][ ]
; xmm7 = [ ][ ][ ][ ]
mov esi, [ebp+%$inbuffer]
mov edi, [ebp+%$outbuffer]
mov eax, [ebp+%$srcchannelstep]
shl eax, 2
mov ebx, [ebp+%$destchannelstep]
shl ebx, 1
movss xmm4, [ebp+%$volume]
shufps xmm4, xmm4, 0
movaps xmm5, [negones]
movaps xmm6, [ones]
%if 1
mov ecx, [ebp+%$length]
shr ecx, 2
test ecx, ecx
jz near convertf2int16rolledstart
convertf2int16unrolled:
movss xmm0, [esi]
movss xmm1, [esi + eax]
lea esi, [esi + eax * 2]
movss xmm2, [esi]
movss xmm3, [esi + eax]
lea esi, [esi + eax * 2]
unpcklps xmm0, xmm1
unpcklps xmm2, xmm3
shufps xmm0, xmm2, 044h
mulps xmm0, xmm4 ; now from -1/+1 to -32768/+32767 (and may be outside of this range)
movhlps xmm1, xmm0
cvttps2pi mm0, xmm0
cvttps2pi mm1, xmm1
packssdw mm0, mm0 ; clamps to -32768 to 32767
packssdw mm1, mm1 ; clamps to -32768 to 32767
movd edx, mm0
mov [edi + 0], dl
mov [edi + 1], dh
shr edx, 16
mov [edi + ebx + 0], dl
mov [edi + ebx + 1], dh
lea edi, [edi + ebx * 2]
movd edx, mm1
mov [edi + 0], dl
mov [edi + 1], dh
shr edx, 16
mov [edi + ebx + 0], dl
mov [edi + ebx + 1], dh
lea edi, [edi + ebx * 2]
dec ecx
jnz near convertf2int16unrolled
convertf2int16rolledstart:
mov ecx, [ebp+%$length]
and ecx, 3
%endif
test ecx, ecx
jz near convertf2int16done
convertf2int16rolled:
movss xmm0, [esi]
mulps xmm0, xmm4 ; now from -1/+1 to -32768/+32767 (and may be outside of this range)
cvttps2pi mm0, xmm0
packssdw mm0, mm0 ; clamps to -32768 to 32767
movd edx, mm0
mov [edi + 0], dl
mov [edi + 1], dh
add edi, ebx
add esi, eax
dec ecx
jnz near convertf2int16rolled
convertf2int16done:
emms
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
endproc

View file

@ -0,0 +1,612 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_DISTORTION
#include "fmod.h"
#include "fmod_dspi.h"
#include "fmod_dsp_distortion.h"
#include "fmod_systemi.h"
#include "fmod_os_misc.h"
#include <stdio.h>
namespace FMOD
{
FMOD_DSP_DESCRIPTION_EX dspdistortion;
#ifdef PLUGIN_EXPORTS
#ifdef __cplusplus
extern "C" {
#endif
/*
FMODGetDSPDescription is mandantory for every fmod plugin. This is the symbol the registerplugin function searches for.
Must be declared with F_API to make it export as stdcall.
*/
F_DECLSPEC F_DLLEXPORT FMOD_DSP_DESCRIPTION_EX * F_API FMODGetDSPDescriptionEx()
{
return DSPDistortion::getDescriptionEx();
}
#ifdef __cplusplus
}
#endif
#endif /* PLUGIN_EXPORTS */
FMOD_DSP_PARAMETERDESC dspdistortion_param[1] =
{
{ 0.0f, 1.0f, 0.5, "Level", "", "Distortion value. 0.0 to 1.0. Default = 0.5." },
};
extern "C"
{
void FMOD_DSP_Distortion_SIMD(float * inbuffer, float * outbuffer, unsigned int length, int inchannels, int outchannels, float k);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_DSP_DESCRIPTION_EX *DSPDistortion::getDescriptionEx()
{
FMOD_memset(&dspdistortion, 0, sizeof(FMOD_DSP_DESCRIPTION_EX));
FMOD_strcpy(dspdistortion.name, "FMOD Distortion");
dspdistortion.version = 0x00010100;
dspdistortion.create = DSPDistortion::createCallback;
dspdistortion.release = DSPDistortion::releaseCallback;
dspdistortion.reset = DSPDistortion::resetCallback;
dspdistortion.read = DSPDistortion::readCallback;
dspdistortion.numparameters = sizeof(dspdistortion_param) / sizeof(dspdistortion_param[0]);
dspdistortion.paramdesc = dspdistortion_param;
dspdistortion.setparameter = DSPDistortion::setParameterCallback;
dspdistortion.getparameter = DSPDistortion::getParameterCallback;
#ifdef FMOD_SUPPORT_MEMORYTRACKER
dspdistortion.getmemoryused = &DSPDistortion::getMemoryUsedCallback;
#endif
dspdistortion.mType = FMOD_DSP_TYPE_DISTORTION;
dspdistortion.mCategory = FMOD_DSP_CATEGORY_FILTER;
dspdistortion.mSize = sizeof(DSPDistortion);
return &dspdistortion;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT DSPDistortion::createInternal()
{
int count;
init();
mSupportsSIMD = FMOD_OS_SupportsSIMD();
for (count = 0; count < mDescription.numparameters; count++)
{
FMOD_RESULT result;
result = setParameter(count, mDescription.paramdesc[count].defaultval);
if (result != FMOD_OK)
{
return result;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT DSPDistortion::releaseInternal()
{
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT DSPDistortion::resetInternal()
{
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT DSPDistortion::readInternal(float * inbuffer, float * outbuffer, unsigned int length, int inchannels, int outchannels)
{
float k;
float level = mLevel;
if (!inbuffer)
{
return FMOD_OK;
}
if (!(speakermask & ((1 << inchannels)-1)))
{
FMOD_memcpy(outbuffer, inbuffer, sizeof(float)*length*inchannels);
return FMOD_OK;
}
if (level < 1.0f)
{
k = 2.0f * level / (1.0f - level);
}
else
{
k = 2.0f * 0.9999f / (1.0f - 0.9999f);
}
if (mSupportsSIMD)
{
FMOD_DSP_Distortion_SIMD(inbuffer, outbuffer, length, inchannels, outchannels, k);
if (!((speakermask & ((1<<inchannels)-1)) == ((1<<inchannels)-1)))
{
unsigned int len;
int count, inc;
for (count = 0; count < inchannels; count++)
{
float *in = inbuffer + count;
float *out = outbuffer + count;
len = length >> 3;
inc = inchannels << 3;
int offset1, offset2, offset3, offset4, offset5, offset6, offset7;
offset1 = inchannels;
offset2 = inchannels * 2;
offset3 = inchannels * 3;
offset4 = inchannels * 4;
offset5 = inchannels * 5;
offset6 = inchannels * 6;
offset7 = inchannels * 7;
if (!((1 << count) & speakermask))
{
while (len)
{
out[0] = in[0];
out[offset1] = in[offset1];
out[offset2] = in[offset2];
out[offset3] = in[offset3];
out[offset4] = in[offset4];
out[offset5] = in[offset5];
out[offset6] = in[offset6];
out[offset7] = in[offset7];
in += inc;
out += inc;
len--;
}
len = length & 7;
while (len)
{
outbuffer[0] = inbuffer[0];
inbuffer += inchannels;
outbuffer += inchannels;
len--;
}
}
}
}
}
else
{
unsigned int len;
int count, inc;
int offset1, offset2, offset3, offset4, offset5, offset6, offset7;
inc = inchannels << 3;
offset1 = inchannels;
offset2 = inchannels * 2;
offset3 = inchannels * 3;
offset4 = inchannels * 4;
offset5 = inchannels * 5;
offset6 = inchannels * 6;
offset7 = inchannels * 7;
for (count = 0; count < inchannels; count++)
{
float *in = inbuffer + count;
float *out = outbuffer + count;
len = length >> 3;
if (!((1 << count) & speakermask))
{
while (len)
{
out[0] = in[0];
out[offset1] = in[offset1];
out[offset2] = in[offset2];
out[offset3] = in[offset3];
out[offset4] = in[offset4];
out[offset5] = in[offset5];
out[offset6] = in[offset6];
out[offset7] = in[offset7];
in += inc;
out += inc;
len--;
}
len = (length * inchannels) & 7;
while (len)
{
outbuffer[0] = inbuffer[0];
inbuffer+=inchannels;
outbuffer+=inchannels;
len--;
}
}
else
{
float kplus1 = 1.0f + k;
while (len)
{
out[0] = kplus1 * in[0] / (1.0f + k * FMOD_FABS(in[0]));
out[offset1] = kplus1 * in[offset1] / (1.0f + k * FMOD_FABS(in[offset1]));
out[offset2] = kplus1 * in[offset2] / (1.0f + k * FMOD_FABS(in[offset2]));
out[offset3] = kplus1 * in[offset3] / (1.0f + k * FMOD_FABS(in[offset3]));
out[offset4] = kplus1 * in[offset4] / (1.0f + k * FMOD_FABS(in[offset4]));
out[offset5] = kplus1 * in[offset5] / (1.0f + k * FMOD_FABS(in[offset5]));
out[offset6] = kplus1 * in[offset6] / (1.0f + k * FMOD_FABS(in[offset6]));
out[offset7] = kplus1 * in[offset7] / (1.0f + k * FMOD_FABS(in[offset7]));
in += inc;
out += inc;
len--;
}
len = (length * inchannels) & 7;
while (len)
{
outbuffer[0] = kplus1 * inbuffer[0] / (1.0f + k * FMOD_FABS(inbuffer[0]));
inbuffer+=inchannels;
outbuffer+=inchannels;
len--;
}
}
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT DSPDistortion::setParameterInternal(int index, float value)
{
mLevel = value;
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT DSPDistortion::getParameterInternal(int index, float *value, char *valuestr)
{
*value = mLevel;
sprintf(valuestr, "%.02f", mLevel);
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
#ifdef FMOD_SUPPORT_MEMORYTRACKER
FMOD_RESULT DSPDistortion::getMemoryUsedImpl(MemoryTracker *tracker)
{
// Size of this class is already accounted for (via description.mSize). Just add extra allocated memory here.
return FMOD_OK;
}
#endif
/*
==============================================================================================================
CALLBACK INTERFACE
==============================================================================================================
*/
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPDistortion::createCallback(FMOD_DSP_STATE *dsp)
{
DSPDistortion *distortion = (DSPDistortion *)dsp;
return distortion->createInternal();
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPDistortion::releaseCallback(FMOD_DSP_STATE *dsp)
{
DSPDistortion *distortion = (DSPDistortion *)dsp;
return distortion->releaseInternal();
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPDistortion::resetCallback(FMOD_DSP_STATE *dsp)
{
DSPDistortion *distortion = (DSPDistortion *)dsp;
return distortion->resetInternal();
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPDistortion::readCallback(FMOD_DSP_STATE *dsp, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels)
{
DSPDistortion *distortion = (DSPDistortion *)dsp;
return distortion->readInternal(inbuffer, outbuffer, length, inchannels, outchannels);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPDistortion::setParameterCallback(FMOD_DSP_STATE *dsp, int index, float value)
{
DSPDistortion *distortion = (DSPDistortion *)dsp;
return distortion->setParameterInternal(index, value);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPDistortion::getParameterCallback(FMOD_DSP_STATE *dsp, int index, float *value, char *valuestr)
{
DSPDistortion *distortion = (DSPDistortion *)dsp;
return distortion->getParameterInternal(index, value, valuestr);
}
#ifdef FMOD_SUPPORT_MEMORYTRACKER
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPDistortion::getMemoryUsedCallback(FMOD_DSP_STATE *dsp, MemoryTracker *tracker)
{
DSPDistortion *distortion = (DSPDistortion *)dsp;
return distortion->DSPDistortion::getMemoryUsed(tracker);
}
#endif
}
#endif

View file

@ -0,0 +1,128 @@
%include "./FMOD_static/win32/src/c32.mac"
; ==========================================================================================
; GLOBAL UNINITIALIZED DATA
; ==========================================================================================
[SEGMENT .data use32 align=32]
distortion_ones dd 1.0,1.0,1.0,1.0
distortion_fabsmask dd 7FFFFFFFh, 7FFFFFFFh, 7FFFFFFFh, 7FFFFFFFh
; ==========================================================================================
; CODE
; ==========================================================================================
[SEGMENT .text use32 align=32]
; =================================================================================================================================
; void FMOD_DSP_Distortion_SIMD(float * inbuffer, float * outbuffer, unsigned int length, int inchannels, int outchannels, float k);
; =================================================================================================================================
proc FMOD_DSP_Distortion_SIMD
%$inbuffer arg
%$outbuffer arg
%$length arg
%$inchannels arg
%$outchannels arg
%$k arg
push eax
push ebx
push ecx
push edx
push esi
push edi
mov esi, [ebp+%$inbuffer]
mov edi, [ebp+%$outbuffer]
; xmm0 = [0x7fffffff][0x7fffffff][0x7fffffff][0x7fffffff]
; xmm1 = [k ][k ][k ][k ]
; xmm2 = [k+1 ][k+1 ][k+1 ][k+1 ]
; xmm3 =
; xmm4 =
; xmm5 = [1.0f ][1.0f ][1.0f ][1.0f ]
; xmm6 =
; xmm7 =
movaps xmm0, [distortion_fabsmask]
movss xmm1, [ebp+%$k]
shufps xmm1, xmm1, 0x00
movaps xmm2, xmm1
movaps xmm5, [distortion_ones]
addps xmm2, xmm5
mov edx, [ebp+%$length]
imul edx, [ebp+%$inchannels]
mov ecx, edx
shr ecx, 3
test ecx, ecx
jz distortionlooprolledstart
distortionloopunrolled:
movups xmm3, [esi]
movups xmm4, xmm3
andps xmm3, xmm0
mulps xmm3, xmm1
addps xmm3, xmm5
rcpps xmm3, xmm3 ; <--- this is the reciprical calc.
mulps xmm4, xmm2 ; |
; divps xmm4, xmm3 ; |
mulps xmm4, xmm3 ; reciprical multiply instead of a div. Only 12bit accuracy but good enough for here. much faster.
movups [edi], xmm4
movups xmm6, [esi+16]
movups xmm7, xmm6
andps xmm6, xmm0
mulps xmm6, xmm1
addps xmm6, xmm5
rcpps xmm6, xmm6 ; <--- this is the reciprical calc.
mulps xmm7, xmm2 ; |
; divps xmm7, xmm6 ; |
mulps xmm7, xmm6 ; reciprical multiply instead of a div. Only 12bit accuracy but good enough for here. much faster.
movups [edi+16], xmm7
add edi, 32
add esi, 32
dec ecx
jnz near distortionloopunrolled
distortionlooprolledstart:
xorps xmm3, xmm3
mov ecx, edx
and ecx, 7
test ecx, ecx
jz distortiondone
distortionlooprolled:
movss xmm3, [esi]
movss xmm4, xmm3
andps xmm3, xmm0
mulss xmm3, xmm1
addss xmm3, xmm5
rcpss xmm3, xmm3 ; <--- this is the reciprical calc.
mulss xmm4, xmm2 ; |
; divss xmm4, xmm3 ; |
mulss xmm4, xmm3 ; reciprical multiply instead of a div. Only 12bit accuracy but good enough for here. much faster.
movss [edi], xmm4
add edi, 4
add esi, 4
dec ecx
jnz near distortionlooprolled
distortiondone:
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
endproc

View file

@ -0,0 +1,621 @@
#include "fmod_settings.h"
#include "fmod_dsp_resampler_linear.h"
#include "fmod_os_misc.h"
#define OO4GIG (1.0f / 4294967296.0f)
extern "C"
{
void FMOD_Resampler_Linear_PCM16_Mono(float *out, int outlength, void *src, FMOD_UINT64P *position, FMOD_SINT64P *speed);
void FMOD_Resampler_Linear_PCM16_Stereo(float *out, int outlength, void *src, FMOD_UINT64P *position, FMOD_SINT64P *speed);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
[SEE_ALSO]
]
*/
void FMOD_Resampler_Linear(float *out, int outlength, void *src, FMOD_SOUND_FORMAT srcformat, FMOD_UINT64P *position, FMOD_SINT64P *speed, int channels)
{
float scale = 1.0f;
bool supportssimd;
supportssimd = FMOD_OS_SupportsSIMD();
switch (srcformat)
{
/*
8 BIT
*/
case FMOD_SOUND_FORMAT_PCM8:
{
signed char *inptr = (signed char *)src;
scale /= (float)(1<<7);
if (channels == 1)
{
float f;
float a, b, r1,r2,r3,r4;
int len;
len = outlength >> 2;
while (len)
{
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r1 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r2 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r3 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r4 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
out[0] = r1;
out[1] = r2;
out[2] = r3;
out[3] = r4;
len--;
out+=4;
}
len = outlength & 3;
while (len)
{
f = position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r1 = (a * (1.0f - f)) + (b * f);
*out++ = r1;
position->mValue += speed->mValue;
len--;
}
}
else if (channels == 2)
{
float f;
float l_a,l_b, l_r1,l_r2,l_r3,l_r4;
float r_a,r_b, r_r1,r_r2,r_r3,r_r4;
int len;
len = outlength >> 2;
while (len)
{
f = (float)position->mLo * OO4GIG;
l_a = (float)inptr[position->mHi * 2 + 0] * scale;
l_b = (float)inptr[position->mHi * 2 + 2] * scale;
r_a = (float)inptr[position->mHi * 2 + 1] * scale;
r_b = (float)inptr[position->mHi * 2 + 3] * scale;
l_r1 = (l_a * (1.0f - f)) + (l_b * f);
r_r1 = (r_a * (1.0f - f)) + (r_b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
l_a = (float)inptr[position->mHi * 2 + 0] * scale;
l_b = (float)inptr[position->mHi * 2 + 2] * scale;
r_a = (float)inptr[position->mHi * 2 + 1] * scale;
r_b = (float)inptr[position->mHi * 2 + 3] * scale;
l_r2 = (l_a * (1.0f - f)) + (l_b * f);
r_r2 = (r_a * (1.0f - f)) + (r_b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
l_a = (float)inptr[position->mHi * 2 + 0] * scale;
l_b = (float)inptr[position->mHi * 2 + 2] * scale;
r_a = (float)inptr[position->mHi * 2 + 1] * scale;
r_b = (float)inptr[position->mHi * 2 + 3] * scale;
l_r3 = (l_a * (1.0f - f)) + (l_b * f);
r_r3 = (r_a * (1.0f - f)) + (r_b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
l_a = (float)inptr[position->mHi * 2 + 0] * scale;
l_b = (float)inptr[position->mHi * 2 + 2] * scale;
r_a = (float)inptr[position->mHi * 2 + 1] * scale;
r_b = (float)inptr[position->mHi * 2 + 3] * scale;
l_r4 = (l_a * (1.0f - f)) + (l_b * f);
r_r4 = (r_a * (1.0f - f)) + (r_b * f);
position->mValue += speed->mValue;
out[0] = l_r1;
out[1] = r_r1;
out[2] = l_r2;
out[3] = r_r2;
out[4] = l_r3;
out[5] = r_r3;
out[6] = l_r4;
out[7] = r_r4;
len--;
out+=8;
}
len = outlength & 3;
while (len)
{
f = position->mLo * OO4GIG;
l_a = (float)inptr[position->mHi * 2 + 0] * scale;
l_b = (float)inptr[position->mHi * 2 + 2] * scale;
r_a = (float)inptr[position->mHi * 2 + 1] * scale;
r_b = (float)inptr[position->mHi * 2 + 3] * scale;
l_r1 = (l_a * (1.0f - f)) + (l_b * f);
r_r1 = (r_a * (1.0f - f)) + (r_b * f);
*out++ = l_r1;
*out++ = r_r1;
position->mValue += speed->mValue;
len--;
}
}
else
{
while (outlength)
{
int count;
float f = position->mLo * OO4GIG;
for (count = 0; count < channels; count++)
{
float p0 = (float)inptr[((position->mHi + 0) * channels) + count] * scale;
float p1 = (float)inptr[((position->mHi + 1) * channels) + count] * scale;
float r;
r = (p0 * (1.0f - f)) + (p1 * f);
*out++ = r;
}
position->mValue += speed->mValue;
outlength--;
}
}
break;
}
/*
16 BIT
*/
case FMOD_SOUND_FORMAT_PCM16:
{
signed short *inptr = (signed short *)src;
if (channels == 1)
{
if (supportssimd)
{
FMOD_Resampler_Linear_PCM16_Mono(out, outlength, src, position, speed);
}
else
{
float f;
float a, b, r1,r2,r3,r4;
int len;
scale /= (float)(1<<15);
len = outlength >> 2;
while (len)
{
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r1 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r2 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r3 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r4 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
out[0] = r1;
out[1] = r2;
out[2] = r3;
out[3] = r4;
len--;
out+=4;
}
len = outlength & 3;
while (len)
{
f = position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r1 = (a * (1.0f - f)) + (b * f);
*out++ = r1;
position->mValue += speed->mValue;
len--;
}
}
}
else if (channels == 2)
{
if (supportssimd)
{
FMOD_Resampler_Linear_PCM16_Stereo(out, outlength, src, position, speed);
}
else
{
float f;
float l_a,l_b, l_r1,l_r2,l_r3,l_r4;
float r_a,r_b, r_r1,r_r2,r_r3,r_r4;
int len;
scale /= (float)(1<<15);
len = outlength >> 2;
while (len)
{
f = (float)position->mLo * OO4GIG;
l_a = (float)inptr[position->mHi * 2 + 0] * scale;
l_b = (float)inptr[position->mHi * 2 + 2] * scale;
r_a = (float)inptr[position->mHi * 2 + 1] * scale;
r_b = (float)inptr[position->mHi * 2 + 3] * scale;
l_r1 = (l_a * (1.0f - f)) + (l_b * f);
r_r1 = (r_a * (1.0f - f)) + (r_b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
l_a = (float)inptr[position->mHi * 2 + 0] * scale;
l_b = (float)inptr[position->mHi * 2 + 2] * scale;
r_a = (float)inptr[position->mHi * 2 + 1] * scale;
r_b = (float)inptr[position->mHi * 2 + 3] * scale;
l_r2 = (l_a * (1.0f - f)) + (l_b * f);
r_r2 = (r_a * (1.0f - f)) + (r_b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
l_a = (float)inptr[position->mHi * 2 + 0] * scale;
l_b = (float)inptr[position->mHi * 2 + 2] * scale;
r_a = (float)inptr[position->mHi * 2 + 1] * scale;
r_b = (float)inptr[position->mHi * 2 + 3] * scale;
l_r3 = (l_a * (1.0f - f)) + (l_b * f);
r_r3 = (r_a * (1.0f - f)) + (r_b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
l_a = (float)inptr[position->mHi * 2 + 0] * scale;
l_b = (float)inptr[position->mHi * 2 + 2] * scale;
r_a = (float)inptr[position->mHi * 2 + 1] * scale;
r_b = (float)inptr[position->mHi * 2 + 3] * scale;
l_r4 = (l_a * (1.0f - f)) + (l_b * f);
r_r4 = (r_a * (1.0f - f)) + (r_b * f);
position->mValue += speed->mValue;
out[0] = l_r1;
out[1] = r_r1;
out[2] = l_r2;
out[3] = r_r2;
out[4] = l_r3;
out[5] = r_r3;
out[6] = l_r4;
out[7] = r_r4;
len--;
out+=8;
}
len = outlength & 3;
while (len)
{
f = position->mLo * OO4GIG;
l_a = (float)inptr[position->mHi * 2 + 0] * scale;
l_b = (float)inptr[position->mHi * 2 + 2] * scale;
r_a = (float)inptr[position->mHi * 2 + 1] * scale;
r_b = (float)inptr[position->mHi * 2 + 3] * scale;
l_r1 = (l_a * (1.0f - f)) + (l_b * f);
r_r1 = (r_a * (1.0f - f)) + (r_b * f);
out[0] = l_r1;
out[1] = r_r1;
position->mValue += speed->mValue;
len--;
out+=2;
}
}
}
else
{
scale /= (float)(1<<15);
while (outlength)
{
int count;
float f = position->mLo * OO4GIG;
for (count = 0; count < channels; count++)
{
float p0 = (float)inptr[((position->mHi + 0) * channels) + count] * scale;
float p1 = (float)inptr[((position->mHi + 1) * channels) + count] * scale;
float r;
r = (p0 * (1.0f - f)) + (p1 * f);
*out++ = r;
}
position->mValue += speed->mValue;
outlength--;
}
}
break;
}
/*
24 BIT
*/
case FMOD_SOUND_FORMAT_PCM24:
{
FMOD_INT24 *inptr = (FMOD_INT24 *)src;
scale /= (float)(1<<23);
if (channels == 1)
{
while (outlength)
{
int count;
float r;
float f = position->mLo * OO4GIG;
for (count = 0; count < channels; count++)
{
FMOD_INT24 *s0 = &inptr[position->mHi + 0];
FMOD_INT24 *s1 = &inptr[position->mHi + 1];
float p0 = (float)((int)(((unsigned int)s0->val[0] << 8) | ((unsigned int)s0->val[1] << 16) | ((unsigned int)s0->val[2] << 24)) >> 8) * scale;
float p1 = (float)((int)(((unsigned int)s1->val[0] << 8) | ((unsigned int)s1->val[1] << 16) | ((unsigned int)s1->val[2] << 24)) >> 8) * scale;
r = (p0 * (1.0f - f)) + (p1 * f);
*out++ = r;
}
position->mValue += speed->mValue;
outlength--;
}
}
else
{
while (outlength)
{
int count;
float r;
float f = position->mLo * OO4GIG;
for (count = 0; count < channels; count++)
{
FMOD_INT24 *s0 = &inptr[((position->mHi + 0) * channels) + count];
FMOD_INT24 *s1 = &inptr[((position->mHi + 1) * channels) + count];
float p0 = (float)((int)(((unsigned int)s0->val[0] << 8) | ((unsigned int)s0->val[1] << 16) | ((unsigned int)s0->val[2] << 24)) >> 8) * scale;
float p1 = (float)((int)(((unsigned int)s1->val[0] << 8) | ((unsigned int)s1->val[1] << 16) | ((unsigned int)s1->val[2] << 24)) >> 8) * scale;
r = (p0 * (1.0f - f)) + (p1 * f);
*out++ = r;
}
position->mValue += speed->mValue;
outlength--;
}
}
break;
}
/*
32 BIT
*/
case FMOD_SOUND_FORMAT_PCM32:
{
signed int *inptr = (signed int *)src;
scale /= (float)(1<<31);
if (channels == 1)
{
float f;
float a, b, r1,r2,r3,r4;
int len;
len = outlength >> 2;
while (len)
{
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r1 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r2 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r3 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r4 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
out[0] = r1;
out[1] = r2;
out[2] = r3;
out[3] = r4;
len--;
out+=4;
}
len = outlength & 3;
while (len)
{
f = position->mLo * OO4GIG;
a = (float)inptr[position->mHi + 0] * scale;
b = (float)inptr[position->mHi + 1] * scale;
r1 = (a * (1.0f - f)) + (b * f);
*out++ = r1;
position->mValue += speed->mValue;
len--;
}
}
else
{
while (outlength)
{
int count;
float f = position->mLo * OO4GIG;
for (count = 0; count < channels; count++)
{
float p0 = (float)inptr[((position->mHi + 0) * channels) + count] * scale;
float p1 = (float)inptr[((position->mHi + 1) * channels) + count] * scale;
float r;
r = (p0 * (1.0f - f)) + (p1 * f);
*out++ = r;
}
position->mValue += speed->mValue;
outlength--;
}
}
break;
}
/*
FLOATING POINT.
*/
case FMOD_SOUND_FORMAT_PCMFLOAT:
{
float *inptr = (float *)src;
if (channels == 1)
{
float f;
float a, b, r1,r2,r3,r4;
int len;
len = outlength >> 2;
while (len)
{
f = (float)position->mLo * OO4GIG;
a = inptr[position->mHi + 0];
b = inptr[position->mHi + 1];
r1 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = inptr[position->mHi + 0];
b = inptr[position->mHi + 1];
r2 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = inptr[position->mHi + 0];
b = inptr[position->mHi + 1];
r3 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
f = (float)position->mLo * OO4GIG;
a = inptr[position->mHi + 0];
b = inptr[position->mHi + 1];
r4 = (a * (1.0f - f)) + (b * f);
position->mValue += speed->mValue;
out[0] = r1;
out[1] = r2;
out[2] = r3;
out[3] = r4;
len--;
out+=4;
}
len = outlength & 3;
while (len)
{
f = position->mLo * OO4GIG;
a = inptr[position->mHi + 0];
b = inptr[position->mHi + 1];
r1 = (a * (1.0f - f)) + (b * f);
*out++ = r1;
position->mValue += speed->mValue;
len--;
}
}
else
{
while (outlength)
{
int count;
float f = position->mLo * OO4GIG;
for (count = 0; count < channels; count++)
{
float p0 = inptr[((position->mHi + 0) * channels) + count];
float p1 = inptr[((position->mHi + 1) * channels) + count];
float r;
r = (p0 * (1.0f - f)) + (p1 * f);
*out++ = r;
}
position->mValue += speed->mValue;
outlength--;
}
}
break;
}
default:
{
break;
}
};
}

View file

@ -0,0 +1,440 @@
%include "./FMOD_static/win32/src/c32.mac"
; ==========================================================================================
; GLOBAL UNINITIALIZED DATA
; ==========================================================================================
section .bss
align 16
%define samples esp+0
%define samples_2 esp+10h
%define samplesplus1 esp+20h
%define samplesplus1_2 esp+30h
%define fracs esp+40h
%define fracs_2 esp+50h
; ==========================================================================================
; GLOBAL PREINITIALIZED DATA
; ==========================================================================================
section .text
align 16
ones_over_32768 dd 0.000030517578125, 0.000030517578125, 0.000030517578125, 0.000030517578125
ones_over_2gig dd 0.0000000004656612873077392578125, 0.0000000004656612873077392578125, 0.0000000004656612873077392578125, 0.0000000004656612873077392578125
ones dd 1.0, 1.0, 1.0, 1.0
; ==========================================================================================
; CODE
; ==========================================================================================
section .text
; =================================================================================================================================
; void FMOD_Resampler_Linear_PCM16_Mono(float *out, int outlength, void *src, FMOD_UINT64P *position, FMOD_SINT64P *speed);
; =================================================================================================================================
proc FMOD_Resampler_Linear_PCM16_Mono
%$out arg
%$outlength arg
%$src arg
%$position arg
%$speed arg
push eax
push ebx
push ecx
push edx
push esi
push edi
mov eax, [ebp + %$position]
mov eax, [eax]
mov esi, [ebp + %$src]
shr esi, 1
mov ebx, [ebp + %$position]
add esi, [ebx + 4] ; esi is now addr / 2 + offset. when accessing we use [esi*2]
mov edx, [ebp + %$speed]
mov edx, [edx + 4]
mov ebx, [ebp + %$speed]
mov ebx, [ebx]
mov edi, [ebp + %$out]
mov ecx, [ebp + %$outlength]
; eax = poslo
; ebx = speedlo
; ecx = count
; edx = speedhi
; esi = src + poshi
; edi = dest
; xmm0 = [ ][ ][ ][ ]
; xmm1 = [ ][ ][ ][ ]
; xmm2 = [ ][ ][ ][ ]
; xmm3 = [ ][ ][ ][ ]
; xmm4 = [ ][ ][ ][ ]
; xmm5 = [ ][ ][ ][ ]
; xmm6 = [ ][ ][ ][ ]
; xmm7 = [ ][ ][ ][ ]
push ebp
sub esp, 60h
xorps xmm0, xmm0
movups [samples], xmm0
movups [samples_2], xmm0
movups [samplesplus1], xmm0
movups [samplesplus1_2], xmm0
movups [fracs], xmm0
movups [fracs_2], xmm0
%if 1
shr ecx, 2
test ecx, ecx
jz near resample16Mrolledstart
resample16Munrolled:
movsx ebp, word [esi*2]
mov [samples + 0], ebp ; [ 1a][ ][ ][ ]
movsx ebp, word [esi*2+2]
mov [samplesplus1 + 0], ebp ; [ 1b][ ][ ][ ]
mov ebp, eax
shr ebp, 1
mov [fracs + 0], ebp ; [ 1f][ ][ ][ ]
add eax, ebx
adc esi, edx
movsx ebp, word [esi*2]
mov [samples_2 + 0], ebp ; [ 2a][ ][ ][ ]
movsx ebp, word [esi*2+2]
mov [samplesplus1_2 + 0], ebp ; [ 2b][ ][ ][ ]
mov ebp, eax
shr ebp, 1
mov [fracs_2 + 0], ebp ; [ 2f][ ][ ][ ]
add eax, ebx
adc esi, edx
movsx ebp, word [esi*2]
mov [samples + 4], ebp ; [ 1a][ 3a][ ][ ]
movsx ebp, word [esi*2+2]
mov [samplesplus1 + 4], ebp ; [ 1b][ 3b][ ][ ]
mov ebp, eax
shr ebp, 1
mov [fracs + 4], ebp ; [ 1f][ 3f][ ][ ]
add eax, ebx
adc esi, edx
movsx ebp, word [esi*2]
mov [samples_2 + 4], ebp ; [ 2a][ 4a][ ][ ]
movsx ebp, word [esi*2+2]
mov [samplesplus1_2 + 4], ebp ; [ 2b][ 4b][ ][ ]
mov ebp, eax
shr ebp, 1
mov [fracs_2 + 4], ebp ; [ 2f][ 4f][ ][ ]
add eax, ebx
adc esi, edx
cvtpi2ps xmm0, [samples]
cvtpi2ps xmm1, [samples_2]
cvtpi2ps xmm2, [samplesplus1]
cvtpi2ps xmm3, [samplesplus1_2]
cvtpi2ps xmm4, [fracs]
cvtpi2ps xmm5, [fracs_2]
unpcklps xmm0, xmm1 ; [ 1a][ 2a][ 3a][ 4a]
unpcklps xmm2, xmm3 ; [ 1b][ 2b][ 3b][ 4b]
unpcklps xmm4, xmm5 ; [ 1f][ 2f][ 3f][ 4f]
mulps xmm0, [ones_over_32768]
mulps xmm2, [ones_over_32768]
mulps xmm4, [ones_over_2gig]
movaps xmm6, [ones]
subps xmm6, xmm4 ; [ 1.0-1f][ 1.0-2f][ 1.0-3f][ 1.0-4f]
mulps xmm2, xmm4 ;
mulps xmm0, xmm6 ; [1a * 1.0-1f][2a *1.0-1f][3a *1.0-3f][4a * 1.0-4f]
addps xmm0, xmm2
movups [edi], xmm0
add edi, 16
dec ecx
jnz near resample16Munrolled
resample16Mrolledstart:
add esp, 60h
pop ebp
mov ecx, [ebp+%$outlength]
push ebp
sub esp, 60h
and ecx, 3
%endif
xorps xmm0, xmm0
xorps xmm2, xmm2
xorps xmm4, xmm4
test ecx, ecx
jz near resample16Mdone
resample16Mrolled:
movsx ebp, word [esi*2]
mov [samples + 0], ebp ; [ 1a][ ][ ][ ]
movsx ebp, word [esi*2+2]
mov [samplesplus1 + 0], ebp ; [ 1b][ ][ ][ ]
mov ebp, eax
shr ebp, 1
mov [fracs + 0], ebp ; [ 1f][ ][ ][ ]
add eax, ebx
adc esi, edx
cvtsi2ss xmm0, [samples]
cvtsi2ss xmm2, [samplesplus1]
cvtsi2ss xmm4, [fracs]
mulss xmm0, [ones_over_32768]
mulss xmm2, [ones_over_32768]
mulss xmm4, [ones_over_2gig]
movss xmm6, [ones]
subss xmm6, xmm4 ; [ 1.0-1f][ 1.0-2f][ 1.0-3f][ 1.0-4f]
mulss xmm2, xmm4 ;
mulss xmm0, xmm6 ; [1a * 1.0-1f][2a *1.0-1f][3a *1.0-3f][4a * 1.0-4f]
addss xmm0, xmm2
movss [edi], xmm0
add edi, 4
dec ecx
jnz near resample16Mrolled
resample16Mdone:
add esp, 60h
pop ebp
; restore position
mov ecx, [ebp + %$position]
mov [ecx + 0], eax
mov eax, [ebp + %$src]
shr eax, 1
sub esi, eax
mov ecx, [ebp + %$position]
mov [ecx + 4], esi
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
endproc
; =================================================================================================================================
; void FMOD_Resampler_Linear_PCM16_Stereo(float *out, int outlength, void *src, FMOD_UINT64P *position, FMOD_SINT64P *speed);
; =================================================================================================================================
proc FMOD_Resampler_Linear_PCM16_Stereo
%$out arg
%$outlength arg
%$src arg
%$position arg
%$speed arg
push eax
push ebx
push ecx
push edx
push esi
push edi
mov eax, [ebp + %$position]
mov eax, [eax]
mov esi, [ebp + %$src]
shr esi, 2
mov ebx, [ebp + %$position]
add esi, [ebx + 4] ; esi is now addr / 2 + offset. when accessing we use [esi*2]
mov edx, [ebp + %$speed]
mov edx, [edx + 4]
mov ebx, [ebp + %$speed]
mov ebx, [ebx]
mov edi, [ebp + %$out]
mov ecx, [ebp + %$outlength]
push ebp
sub esp, 60h
; eax = poslo
; ebx = speedlo
; ecx = count
; edx = speedhi
; esi = src + poshi
; edi = dest
; ebp = temp
; xmm0 = [ ][ ][ ][ ]
; xmm1 = [ ][ ][ ][ ]
; xmm2 = [ ][ ][ ][ ]
; xmm3 = [ ][ ][ ][ ]
; xmm4 = [ ][ ][ ][ ]
; xmm5 = [ ][ ][ ][ ]
; xmm6 = [ ][ ][ ][ ]
; xmm7 = [ ][ ][ ][ ]
xorps xmm0, xmm0
movups [samples], xmm0
movups [samples_2], xmm0
movups [samplesplus1], xmm0
movups [samplesplus1_2], xmm0
movups [fracs], xmm0
movups [fracs_2], xmm0
%if 1
shr ecx, 1
test ecx, ecx
jz near resample16Srolledstart
resample16Sunrolled:
movsx ebp, word [esi*4+0]
mov [samples + 0], ebp ; [ 1al][ ][ ][ ]
movsx ebp, word [esi*4+2]
mov [samples + 4], ebp ; [ 1al][ 1ar][ ][ ]
movsx ebp, word [esi*4+4]
mov [samplesplus1 + 0], ebp ; [ 1bl][ ][ ][ ]
movsx ebp, word [esi*4+6]
mov [samplesplus1 + 4], ebp ; [ 1bl][ 1br][ ][ ]
mov ebp, eax
shr ebp, 1
mov [fracs + 0], ebp ; [ 1f][ ][ ][ ]
mov [fracs + 4], ebp ; [ 1f][ 1f][ ][ ]
add eax, ebx
adc esi, edx
movsx ebp, word [esi*4+0]
mov [samples_2 + 0], ebp ; [ 2al][ ][ ][ ]
movsx ebp, word [esi*4+2]
mov [samples_2 + 4], ebp ; [ 2al][ 2ar][ ][ ]
movsx ebp, word [esi*4+4]
mov [samplesplus1_2 + 0], ebp ; [ 2bl][ ][ ][ ]
movsx ebp, word [esi*4+6]
mov [samplesplus1_2 + 4], ebp ; [ 2bl][ 2br][ ][ ]
mov ebp, eax
shr ebp, 1
mov [fracs_2 + 0], ebp ; [ 2f][ ][ ][ ]
mov [fracs_2 + 4], ebp ; [ 2f][ 2f][ ][ ]
add eax, ebx
adc esi, edx
cvtpi2ps xmm0, [samples]
cvtpi2ps xmm1, [samples_2]
cvtpi2ps xmm2, [samplesplus1]
cvtpi2ps xmm3, [samplesplus1_2]
cvtpi2ps xmm4, [fracs]
cvtpi2ps xmm5, [fracs_2]
shufps xmm0, xmm1, 44h
shufps xmm2, xmm3, 44h
shufps xmm4, xmm5, 44h
mulps xmm0, [ones_over_32768]
mulps xmm2, [ones_over_32768]
mulps xmm4, [ones_over_2gig]
movaps xmm6, [ones]
subps xmm6, xmm4 ; [ 1.0-1f][ 1.0-1f][ 1.0-2f][ 1.0-2f]
mulps xmm2, xmm4 ;
mulps xmm0, xmm6 ; [1al* 1.0-1f][1ar*1.0-1f][2al*1.0-2f][2ar* 1.0-2f]
addps xmm0, xmm2
movups [edi], xmm0
add edi, 16
dec ecx
jnz near resample16Sunrolled
resample16Srolledstart:
add esp, 60h
pop ebp
mov ecx, [ebp+%$outlength]
push ebp
sub esp, 60h
and ecx, 1
%endif
xorps xmm0, xmm0
xorps xmm2, xmm2
xorps xmm4, xmm4
test ecx, ecx
jz near resample16Sdone
resample16Srolled:
movsx ebp, word [esi*4]
mov [samples + 0], ebp ; [ 1al][ ][ ][ ]
movsx ebp, word [esi*4+2]
mov [samples + 4], ebp ; [ 1al][ 1ar][ ][ ]
movsx ebp, word [esi*4+4]
mov [samplesplus1 + 0], ebp ; [ 1bl][ ][ ][ ]
movsx ebp, word [esi*4+6]
mov [samplesplus1 + 4], ebp ; [ 1bl][ 1br][ ][ ]
mov ebp, eax
shr ebp, 1
mov [fracs + 0], ebp ; [ 1f][ ][ ][ ]
mov [fracs + 4], ebp ; [ 1f][ 1f][ ][ ]
add eax, ebx
adc esi, edx
cvtpi2ps xmm0, [samples]
cvtpi2ps xmm2, [samplesplus1]
cvtpi2ps xmm4, [fracs]
mulps xmm0, [ones_over_32768]
mulps xmm2, [ones_over_32768]
mulps xmm4, [ones_over_2gig]
movups xmm6, [ones]
subps xmm6, xmm4 ; [ 1.0-1f][ 1.0-1f][ ][ ]
mulps xmm2, xmm4 ;
mulps xmm0, xmm6 ; [1a * 1.0-1f][2a *1.0-1f][3a *1.0-3f][4a * 1.0-4f]
addps xmm0, xmm2
movlps [edi], xmm0
add edi, 8
dec ecx
jnz near resample16Srolled
resample16Sdone:
add esp, 60h
pop ebp
; restore position
mov ecx, [ebp + %$position]
mov [ecx + 0], eax
mov eax, [ebp + %$src]
shr eax, 2
sub esi, eax
mov ecx, [ebp + %$position]
mov [ecx + 4], esi
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
endproc

View file

@ -0,0 +1,487 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_WINAMPPLUGIN
#include "fmod.h"
#include "fmod_dsp_winampplugin.h"
#include "fmod_systemi.h"
#define BUFFERSIZE 256
namespace FMOD
{
FMOD_DSP_DESCRIPTION_EX dspwinampplugin;
#ifdef PLUGIN_EXPORTS
#ifdef __cplusplus
extern "C" {
#endif
/*
FMODGetDSPDescription is mandantory for every fmod plugin. This is the symbol the registerplugin function searches for.
Must be declared with F_API to make it export as stdcall.
*/
F_DECLSPEC F_DLLEXPORT FMOD_DSP_DESCRIPTION_EX * F_API FMODGetDSPDescriptionEx()
{
return DSPWinampPlugin::getDescriptionEx();
}
#ifdef __cplusplus
}
#endif
#endif /* PLUGIN_EXPORTS */
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_DSP_DESCRIPTION_EX *DSPWinampPlugin::getDescriptionEx()
{
FMOD_memset(&dspwinampplugin, 0, sizeof(FMOD_DSP_DESCRIPTION_EX));
// name and version is stamped in later.
dspwinampplugin.create = DSPWinampPlugin::createCallback;
dspwinampplugin.release = DSPWinampPlugin::releaseCallback;
dspwinampplugin.reset = DSPWinampPlugin::resetCallback;
dspwinampplugin.read = DSPWinampPlugin::readCallback;
dspwinampplugin.setparameter = DSPWinampPlugin::setParameterCallback;
dspwinampplugin.getparameter = DSPWinampPlugin::getParameterCallback;
dspwinampplugin.config = DSPWinampPlugin::configCallback;
dspwinampplugin.mType = FMOD_DSP_TYPE_WINAMPPLUGIN;
dspwinampplugin.mCategory = FMOD_DSP_CATEGORY_FILTER;
dspwinampplugin.mSize = sizeof(DSPWinampPlugin);
return &dspwinampplugin;
}
short *DSPWinampPlugin::mEffectBuffer = NULL;
int DSPWinampPlugin::mEffectBufferCount = 0;
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT DSPWinampPlugin::createInternal()
{
int result;
if (mEffectBufferCount == 0)
{
mEffectBuffer = (short *)FMOD_Memory_Alloc(sizeof(short) * BUFFERSIZE);
if (!mEffectBuffer)
{
return FMOD_ERR_MEMORY;
}
}
mEffectBufferCount++;
result = mEffect->Init(mEffect);
if (result)
{
return FMOD_ERR_PLUGIN;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT DSPWinampPlugin::releaseInternal()
{
mEffectBufferCount--;
if (mEffectBufferCount == 0)
{
FMOD_Memory_Free(mEffectBuffer);
mEffectBuffer = NULL;
}
mEffect->Quit(mEffect);
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT DSPWinampPlugin::resetInternal()
{
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT DSPWinampPlugin::readInternal(float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels)
{
int count;
int rate;
int remaining = length * outchannels;
mSystem->getSoftwareFormat(&rate, 0, 0, 0, 0, 0);
while(remaining > 0)
{
int size = remaining;
if (size > BUFFERSIZE)
{
size = BUFFERSIZE;
}
/*
Convert from float to short
*/
for (count = 0; count < size; count++)
{
float val = *inbuffer++;
mEffectBuffer[count] = (short)(val < -1.0f ? -32767 : val > 1.0f ? 32767 : val * 32767.0f);
}
mEffect->ModifySamples(mEffect, mEffectBuffer, size / outchannels, 16, outchannels, rate);
/*
Convert back to floating point data
*/
for (count = 0; count < size; count++)
{
*outbuffer++ = (float)mEffectBuffer[count] / 32767.0f;
}
remaining -= size;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT DSPWinampPlugin::setParameterInternal(int index, float value)
{
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT DSPWinampPlugin::getParameterInternal(int index, float *value, char *valuestr)
{
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT DSPWinampPlugin::showConfigDialogInternal(void *hwnd, int show)
{
mEffect->hwndParent = hwnd;
mEffect->Config(mEffect);
return FMOD_OK;
}
/*
==============================================================================================================
CALLBACK INTERFACE
==============================================================================================================
*/
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPWinampPlugin::createCallback(FMOD_DSP_STATE *dsp)
{
DSPWinampPlugin *winamp = (DSPWinampPlugin *)dsp;
return winamp->createInternal();
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPWinampPlugin::releaseCallback(FMOD_DSP_STATE *dsp)
{
DSPWinampPlugin *winamp = (DSPWinampPlugin *)dsp;
return winamp->releaseInternal();
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPWinampPlugin::resetCallback(FMOD_DSP_STATE *dsp)
{
DSPWinampPlugin *winamp = (DSPWinampPlugin *)dsp;
return winamp->resetInternal();
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPWinampPlugin::readCallback(FMOD_DSP_STATE *dsp, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels)
{
DSPWinampPlugin *winamp = (DSPWinampPlugin *)dsp;
return winamp->readInternal(inbuffer, outbuffer, length, inchannels, outchannels);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPWinampPlugin::setParameterCallback(FMOD_DSP_STATE *dsp, int index, float value)
{
DSPWinampPlugin *winamp = (DSPWinampPlugin *)dsp;
return winamp->setParameterInternal(index, value);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPWinampPlugin::getParameterCallback(FMOD_DSP_STATE *dsp, int index, float *value, char *valuestr)
{
DSPWinampPlugin *winamp = (DSPWinampPlugin *)dsp;
return winamp->getParameterInternal(index, value, valuestr);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32
[SEE_ALSO]
]
*/
FMOD_RESULT F_CALLBACK DSPWinampPlugin::configCallback(FMOD_DSP_STATE *dsp, void *hwnd, int show)
{
DSPWinampPlugin *winamp = (DSPWinampPlugin *)dsp;
return winamp->showConfigDialogInternal(hwnd, show);
}
}
#endif

View file

@ -0,0 +1,49 @@
#ifndef _FMOD_DSP_WINAMPPLUGIN_H
#define _FMOD_DSP_WINAMPPLUGIN_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_WINAMPPLUGIN
#include "fmod.h"
#include "fmod_dsp_filter.h"
#include "../lib/winamp/dsp.h"
namespace FMOD
{
class DSPWinampPlugin : public DSPFilter
{
private:
static short *mEffectBuffer;
static int mEffectBufferCount;
FMOD_RESULT createInternal();
FMOD_RESULT releaseInternal();
FMOD_RESULT resetInternal();
FMOD_RESULT readInternal(float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
FMOD_RESULT setParameterInternal(int index, float value);
FMOD_RESULT getParameterInternal(int index, float *value, char *valuestr);
FMOD_RESULT showConfigDialogInternal(void *hwnd, int show);
public:
winampDSPModule *mEffect;
static FMOD_DSP_DESCRIPTION_EX *getDescriptionEx();
static FMOD_RESULT F_CALLBACK createCallback(FMOD_DSP_STATE *dsp);
static FMOD_RESULT F_CALLBACK releaseCallback(FMOD_DSP_STATE *dsp);
static FMOD_RESULT F_CALLBACK resetCallback(FMOD_DSP_STATE *dsp);
static FMOD_RESULT F_CALLBACK readCallback(FMOD_DSP_STATE *dsp, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
static FMOD_RESULT F_CALLBACK setParameterCallback(FMOD_DSP_STATE *dsp, int index, float value);
static FMOD_RESULT F_CALLBACK getParameterCallback(FMOD_DSP_STATE *dsp, int index, float *value, char *valuestr);
static FMOD_RESULT F_CALLBACK configCallback(FMOD_DSP_STATE *dsp, void *hwnd, int show);
};
}
#endif
#endif

461
fmod/win32/src/fmod_eax2.h Executable file
View file

@ -0,0 +1,461 @@
/******************************************************************
*
* EAX.H - DirectSound3D Environmental Audio Extensions version 2.0
* Updated July 8, 1999
*
*******************************************************************
*/
#ifndef EAX_H_INCLUDED
#define EAX_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#ifndef OPENAL
#include <dxsdkver.h>
#if (_DXSDK_PRODUCT_MAJOR < 9 || (_DXSDK_PRODUCT_MAJOR == 9 && _DXSDK_PRODUCT_MINOR < 21))
#include <dplay.h> /* This defines DWORD_PTR for dsound.h to use. */
#endif
#include <dsound.h>
/*
* EAX Wrapper Interface (using Direct X 7) {4FF53B81-1CE0-11d3-AAB8-00A0C95949D5}
*/
DEFINE_GUID(CLSID_EAXDirectSound,
0x4ff53b81,
0x1ce0,
0x11d3,
0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5);
/*
* EAX Wrapper Interface (using Direct X 8) {CA503B60-B176-11d4-A094-D0C0BF3A560C}
*/
DEFINE_GUID(CLSID_EAXDirectSound8,
0xca503b60,
0xb176,
0x11d4,
0xa0, 0x94, 0xd0, 0xc0, 0xbf, 0x3a, 0x56, 0xc);
#ifdef DIRECTSOUND_VERSION
#if DIRECTSOUND_VERSION == 0x0800
__declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate8(GUID*, LPDIRECTSOUND8*, IUnknown FAR *);
typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE8)(GUID*, LPDIRECTSOUND8*, IUnknown FAR*);
#endif
#endif
__declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate(GUID*, LPDIRECTSOUND*, IUnknown FAR *);
typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE)(GUID*, LPDIRECTSOUND*, IUnknown FAR*);
#else
#include "../../lib/openal/include/al/al.h"
#ifndef GUID_DEFINED
#define GUID_DEFINED
typedef struct _GUID
{
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[8];
} GUID;
#endif // !GUID_DEFINED
#ifndef DEFINE_GUID
#ifndef INITGUID
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
extern const GUID FAR name
#else
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
extern const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#endif // INITGUID
#endif // DEFINE_GUID
/*
* EAX OpenAL Extension {4FF53B81-1CE0-11d3-AAB8-00A0C95949D5}
*/
typedef ALenum (*EAXSet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint);
typedef ALenum (*EAXGet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint);
#endif
#pragma pack(push, 4)
/*
* EAX 2.0 listener property set {0306A6A8-B224-11d2-99E5-0000E8D8C722}
*/
DEFINE_GUID(DSPROPSETID_EAX20_ListenerProperties,
0x306a6a8,
0xb224,
0x11d2,
0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22);
// For compatibility with future EAX versions:
#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX20_ListenerProperties
#define DSPROPSETID_EAX_SourceProperties DSPROPSETID_EAX20_BufferProperties
typedef enum
{
DSPROPERTY_EAXLISTENER_NONE,
DSPROPERTY_EAXLISTENER_ALLPARAMETERS,
DSPROPERTY_EAXLISTENER_ROOM,
DSPROPERTY_EAXLISTENER_ROOMHF,
DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR,
DSPROPERTY_EAXLISTENER_DECAYTIME,
DSPROPERTY_EAXLISTENER_DECAYHFRATIO,
DSPROPERTY_EAXLISTENER_REFLECTIONS,
DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY,
DSPROPERTY_EAXLISTENER_REVERB,
DSPROPERTY_EAXLISTENER_REVERBDELAY,
DSPROPERTY_EAXLISTENER_ENVIRONMENT,
DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE,
DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION,
DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF,
DSPROPERTY_EAXLISTENER_FLAGS
} DSPROPERTY_EAX_LISTENERPROPERTY;
// OR these flags with property id
#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately
#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later
#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \
DSPROPERTY_EAXLISTENER_IMMEDIATE)
// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS
// - all levels are hundredths of decibels
// - all times are in seconds
// - the reference for high frequency controls is 5 kHz
//
// NOTE: This structure may change in future EAX versions.
// It is recommended to initialize fields by name:
// myListener.lRoom = -1000;
// myListener.lRoomHF = -100;
// ...
// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ;
// instead of:
// myListener = { -1000, -100, ... , 0x00000009 };
// If you want to save and load presets in binary form, you
// should define your own structure to insure future compatibility.
//
typedef struct _EAXLISTENERPROPERTIES
{
long lRoom; // room effect level at low frequencies
long lRoomHF; // room effect high-frequency level re. low frequency level
float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect
float flDecayTime; // reverberation decay time at low frequencies
float flDecayHFRatio; // high-frequency to low-frequency decay time ratio
long lReflections; // early reflections level relative to room effect
float flReflectionsDelay; // initial reflection delay time
long lReverb; // late reverberation level relative to room effect
float flReverbDelay; // late reverberation delay time relative to initial reflection
unsigned long dwEnvironment; // sets all listener properties
float flEnvironmentSize; // environment size in meters
float flEnvironmentDiffusion; // environment diffusion
float flAirAbsorptionHF; // change in level per meter at 5 kHz
unsigned long dwFlags; // modifies the behavior of properties
} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES;
// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT
enum
{
EAX_ENVIRONMENT_GENERIC,
EAX_ENVIRONMENT_PADDEDCELL,
EAX_ENVIRONMENT_ROOM,
EAX_ENVIRONMENT_BATHROOM,
EAX_ENVIRONMENT_LIVINGROOM,
EAX_ENVIRONMENT_STONEROOM,
EAX_ENVIRONMENT_AUDITORIUM,
EAX_ENVIRONMENT_CONCERTHALL,
EAX_ENVIRONMENT_CAVE,
EAX_ENVIRONMENT_ARENA,
EAX_ENVIRONMENT_HANGAR,
EAX_ENVIRONMENT_CARPETEDHALLWAY,
EAX_ENVIRONMENT_HALLWAY,
EAX_ENVIRONMENT_STONECORRIDOR,
EAX_ENVIRONMENT_ALLEY,
EAX_ENVIRONMENT_FOREST,
EAX_ENVIRONMENT_CITY,
EAX_ENVIRONMENT_MOUNTAINS,
EAX_ENVIRONMENT_QUARRY,
EAX_ENVIRONMENT_PLAIN,
EAX_ENVIRONMENT_PARKINGLOT,
EAX_ENVIRONMENT_SEWERPIPE,
EAX_ENVIRONMENT_UNDERWATER,
EAX_ENVIRONMENT_DRUGGED,
EAX_ENVIRONMENT_DIZZY,
EAX_ENVIRONMENT_PSYCHOTIC,
EAX_ENVIRONMENT_COUNT
};
// Used by DSPROPERTY_EAXLISTENER_FLAGS
//
// Note: The number and order of flags may change in future EAX versions.
// It is recommended to use the flag defines as follows:
// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE;
// instead of:
// myFlags = 0x00000009;
//
// These flags determine what properties are affected by environment size.
#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time
#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level
#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time
#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level
#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time
// This flag limits high-frequency decay time according to air absorption.
#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020
#define EAXLISTENERFLAGS_RESERVED 0xFFFFFFC0 // reserved future use
// property ranges and defaults:
#define EAXLISTENER_MINROOM (-10000)
#define EAXLISTENER_MAXROOM 0
#define EAXLISTENER_DEFAULTROOM (-1000)
#define EAXLISTENER_MINROOMHF (-10000)
#define EAXLISTENER_MAXROOMHF 0
#define EAXLISTENER_DEFAULTROOMHF (-100)
#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f
#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f
#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f
#define EAXLISTENER_MINDECAYTIME 0.1f
#define EAXLISTENER_MAXDECAYTIME 20.0f
#define EAXLISTENER_DEFAULTDECAYTIME 1.49f
#define EAXLISTENER_MINDECAYHFRATIO 0.1f
#define EAXLISTENER_MAXDECAYHFRATIO 2.0f
#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f
#define EAXLISTENER_MINREFLECTIONS (-10000)
#define EAXLISTENER_MAXREFLECTIONS 1000
#define EAXLISTENER_DEFAULTREFLECTIONS (-2602)
#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f
#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f
#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f
#define EAXLISTENER_MINREVERB (-10000)
#define EAXLISTENER_MAXREVERB 2000
#define EAXLISTENER_DEFAULTREVERB 200
#define EAXLISTENER_MINREVERBDELAY 0.0f
#define EAXLISTENER_MAXREVERBDELAY 0.1f
#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f
#define EAXLISTENER_MINENVIRONMENT 0
#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT-1)
#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC
#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f
#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f
#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f
#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f
#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f
#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f
#define EAXLISTENER_MINAIRABSORPTIONHF (-100.0f)
#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f
#define EAXLISTENER_DEFAULTAIRABSORPTIONHF (-5.0f)
#define EAXLISTENER_DEFAULTFLAGS (EAXLISTENERFLAGS_DECAYTIMESCALE | \
EAXLISTENERFLAGS_REFLECTIONSSCALE | \
EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \
EAXLISTENERFLAGS_REVERBSCALE | \
EAXLISTENERFLAGS_REVERBDELAYSCALE | \
EAXLISTENERFLAGS_DECAYHFLIMIT)
/*
* EAX 2.0 buffer property set {0306A6A7-B224-11d2-99E5-0000E8D8C722}
*/
DEFINE_GUID(DSPROPSETID_EAX20_BufferProperties,
0x306a6a7,
0xb224,
0x11d2,
0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22);
// For compatibility with future EAX versions:
#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX20_BufferProperties
typedef enum
{
DSPROPERTY_EAXBUFFER_NONE,
DSPROPERTY_EAXBUFFER_ALLPARAMETERS,
DSPROPERTY_EAXBUFFER_DIRECT,
DSPROPERTY_EAXBUFFER_DIRECTHF,
DSPROPERTY_EAXBUFFER_ROOM,
DSPROPERTY_EAXBUFFER_ROOMHF,
DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR,
DSPROPERTY_EAXBUFFER_OBSTRUCTION,
DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO,
DSPROPERTY_EAXBUFFER_OCCLUSION,
DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO,
DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO,
DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF,
DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR,
DSPROPERTY_EAXBUFFER_FLAGS
} DSPROPERTY_EAX_BUFFERPROPERTY;
// OR these flags with property id
#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately
#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later
#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \
DSPROPERTY_EAXBUFFER_IMMEDIATE)
// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS
// - all levels are hundredths of decibels
//
// NOTE: This structure may change in future EAX versions.
// It is recommended to initialize fields by name:
// myBuffer.lDirect = 0;
// myBuffer.lDirectHF = -200;
// ...
// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ;
// instead of:
// myBuffer = { 0, -200, ... , 0x00000003 };
//
typedef struct _EAXBUFFERPROPERTIES
{
long lDirect; // direct path level
long lDirectHF; // direct path level at high frequencies
long lRoom; // room effect level
long lRoomHF; // room effect level at high frequencies
float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect
long lObstruction; // main obstruction control (attenuation at high frequencies)
float flObstructionLFRatio; // obstruction low-frequency level re. main control
long lOcclusion; // main occlusion control (attenuation at high frequencies)
float flOcclusionLFRatio; // occlusion low-frequency level re. main control
float flOcclusionRoomRatio; // occlusion room effect level re. main control
long lOutsideVolumeHF; // outside sound cone level at high frequencies
float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
unsigned long dwFlags; // modifies the behavior of properties
} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES;
// Used by DSPROPERTY_EAXBUFFER_FLAGS
// TRUE: value is computed automatically - property is an offset
// FALSE: value is used directly
//
// Note: The number and order of flags may change in future EAX versions.
// To insure future compatibility, use flag defines as follows:
// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO;
// instead of:
// myFlags = 0x00000003;
//
#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF
#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM
#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF
#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use
// property ranges and defaults:
#define EAXBUFFER_MINDIRECT (-10000)
#define EAXBUFFER_MAXDIRECT 1000
#define EAXBUFFER_DEFAULTDIRECT 0
#define EAXBUFFER_MINDIRECTHF (-10000)
#define EAXBUFFER_MAXDIRECTHF 0
#define EAXBUFFER_DEFAULTDIRECTHF 0
#define EAXBUFFER_MINROOM (-10000)
#define EAXBUFFER_MAXROOM 1000
#define EAXBUFFER_DEFAULTROOM 0
#define EAXBUFFER_MINROOMHF (-10000)
#define EAXBUFFER_MAXROOMHF 0
#define EAXBUFFER_DEFAULTROOMHF 0
#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f
#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f
#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f
#define EAXBUFFER_MINOBSTRUCTION (-10000)
#define EAXBUFFER_MAXOBSTRUCTION 0
#define EAXBUFFER_DEFAULTOBSTRUCTION 0
#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f
#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f
#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f
#define EAXBUFFER_MINOCCLUSION (-10000)
#define EAXBUFFER_MAXOCCLUSION 0
#define EAXBUFFER_DEFAULTOCCLUSION 0
#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f
#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f
#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f
#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f
#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f
#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 0.5f
#define EAXBUFFER_MINOUTSIDEVOLUMEHF (-10000)
#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0
#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0
#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f
#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f
#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f
#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | \
EAXBUFFERFLAGS_ROOMAUTO | \
EAXBUFFERFLAGS_ROOMHFAUTO)
// Material transmission presets
// 3 values in this order:
// 1: occlusion (or obstruction)
// 2: occlusion LF Ratio (or obstruction LF Ratio)
// 3: occlusion Room Ratio
// Single window material preset
#define EAX_MATERIAL_SINGLEWINDOW (-2800)
#define EAX_MATERIAL_SINGLEWINDOWLF 0.71f
#define EAX_MATERIAL_SINGLEWINDOWROOMRATIO 0.43f
// Double window material preset
#define EAX_MATERIAL_DOUBLEWINDOW (-5000)
#define EAX_MATERIAL_DOUBLEWINDOWHF 0.40f
#define EAX_MATERIAL_DOUBLEWINDOWROOMRATIO 0.24f
// Thin door material preset
#define EAX_MATERIAL_THINDOOR (-1800)
#define EAX_MATERIAL_THINDOORLF 0.66f
#define EAX_MATERIAL_THINDOORROOMRATIO 0.66f
// Thick door material preset
#define EAX_MATERIAL_THICKDOOR (-4400)
#define EAX_MATERIAL_THICKDOORLF 0.64f
#define EAX_MATERIAL_THICKDOORROOMRTATION 0.27f
// Wood wall material preset
#define EAX_MATERIAL_WOODWALL (-4000)
#define EAX_MATERIAL_WOODWALLLF 0.50f
#define EAX_MATERIAL_WOODWALLROOMRATIO 0.30f
// Brick wall material preset
#define EAX_MATERIAL_BRICKWALL (-5000)
#define EAX_MATERIAL_BRICKWALLLF 0.60f
#define EAX_MATERIAL_BRICKWALLROOMRATIO 0.24f
// Stone wall material preset
#define EAX_MATERIAL_STONEWALL (-6000)
#define EAX_MATERIAL_STONEWALLLF 0.68f
#define EAX_MATERIAL_STONEWALLROOMRATIO 0.20f
// Curtain material preset
#define EAX_MATERIAL_CURTAIN (-1200)
#define EAX_MATERIAL_CURTAINLF 0.15f
#define EAX_MATERIAL_CURTAINROOMRATIO 1.00f
#pragma pack(pop)
#ifdef __cplusplus
}
#endif // __cplusplus
#endif

536
fmod/win32/src/fmod_eax3.h Executable file
View file

@ -0,0 +1,536 @@
/*******************************************************************\
* *
* EAX.H - Environmental Audio Extensions version 3.0 *
* for OpenAL and DirectSound3D *
* *
********************************************************************/
#ifndef EAX3_H_INCLUDED
#define EAX3_H_INCLUDED
#include <dxsdkver.h>
#if (_DXSDK_PRODUCT_MAJOR < 9 || (_DXSDK_PRODUCT_MAJOR == 9 && _DXSDK_PRODUCT_MINOR < 21))
#include <dplay.h> /* This defines DWORD_PTR for dsound.h to use. */
#endif
#include <dsound.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#ifndef OPENAL
/*
* EAX Wrapper Interface (using Direct X 7) {4FF53B81-1CE0-11d3-AAB8-00A0C95949D5}
*/
DEFINE_GUID(CLSID_EAXDirectSound,
0x4ff53b81,
0x1ce0,
0x11d3,
0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5);
/*
* EAX Wrapper Interface (using Direct X 8) {CA503B60-B176-11d4-A094-D0C0BF3A560C}
*/
DEFINE_GUID(CLSID_EAXDirectSound8,
0xca503b60,
0xb176,
0x11d4,
0xa0, 0x94, 0xd0, 0xc0, 0xbf, 0x3a, 0x56, 0xc);
#ifdef DIRECTSOUND_VERSION
#if DIRECTSOUND_VERSION == 0x0800
__declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate8(GUID*, LPDIRECTSOUND8*, IUnknown FAR *);
typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE8)(GUID*, LPDIRECTSOUND8*, IUnknown FAR*);
#endif
#endif
__declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate(GUID*, LPDIRECTSOUND*, IUnknown FAR *);
typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE)(GUID*, LPDIRECTSOUND*, IUnknown FAR*);
#else // OPENAL
#include "../../lib/openal/include/al/al.h"
#ifndef GUID_DEFINED
#define GUID_DEFINED
typedef struct _GUID
{
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[8];
} GUID;
#endif // !GUID_DEFINED
#ifndef DEFINE_GUID
#ifndef INITGUID
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
extern const GUID /*FAR*/ name
#else
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
extern const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#endif // INITGUID
#endif // DEFINE_GUID
/*
* EAX OpenAL Extension
*/
typedef ALenum (*EAXSet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint);
typedef ALenum (*EAXGet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint);
#endif
#pragma pack(push, 4)
/*
* EAX 3.0 listener property set {A8FA6880-B476-11d3-BDB9-00C0F02DDF87}
*/
DEFINE_GUID(DSPROPSETID_EAX30_ListenerProperties,
0xa8fa6882,
0xb476,
0x11d3,
0xbd, 0xb9, 0x00, 0xc0, 0xf0, 0x2d, 0xdf, 0x87);
// For compatibility with future EAX versions:
#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX30_ListenerProperties
typedef enum
{
DSPROPERTY_EAXLISTENER_NONE,
DSPROPERTY_EAXLISTENER_ALLPARAMETERS,
DSPROPERTY_EAXLISTENER_ENVIRONMENT,
DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE,
DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION,
DSPROPERTY_EAXLISTENER_ROOM,
DSPROPERTY_EAXLISTENER_ROOMHF,
DSPROPERTY_EAXLISTENER_ROOMLF,
DSPROPERTY_EAXLISTENER_DECAYTIME,
DSPROPERTY_EAXLISTENER_DECAYHFRATIO,
DSPROPERTY_EAXLISTENER_DECAYLFRATIO,
DSPROPERTY_EAXLISTENER_REFLECTIONS,
DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY,
DSPROPERTY_EAXLISTENER_REFLECTIONSPAN,
DSPROPERTY_EAXLISTENER_REVERB,
DSPROPERTY_EAXLISTENER_REVERBDELAY,
DSPROPERTY_EAXLISTENER_REVERBPAN,
DSPROPERTY_EAXLISTENER_ECHOTIME,
DSPROPERTY_EAXLISTENER_ECHODEPTH,
DSPROPERTY_EAXLISTENER_MODULATIONTIME,
DSPROPERTY_EAXLISTENER_MODULATIONDEPTH,
DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF,
DSPROPERTY_EAXLISTENER_HFREFERENCE,
DSPROPERTY_EAXLISTENER_LFREFERENCE,
DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR,
DSPROPERTY_EAXLISTENER_FLAGS
} DSPROPERTY_EAX_LISTENERPROPERTY;
// OR these flags with property id
#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately
#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later
#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \
DSPROPERTY_EAXLISTENER_IMMEDIATE)
typedef struct _EAXVECTOR {
float x;
float y;
float z;
} EAXVECTOR;
// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS
// - all levels are hundredths of decibels
// - all times and delays are in seconds
//
// NOTE: This structure may change in future EAX versions.
// It is recommended to initialize fields by name:
// myListener.lRoom = -1000;
// myListener.lRoomHF = -100;
// ...
// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ;
// instead of:
// myListener = { -1000, -100, ... , 0x00000009 };
// If you want to save and load presets in binary form, you
// should define your own structure to insure future compatibility.
//
typedef struct _EAXLISTENERPROPERTIES
{
unsigned long ulEnvironment; // sets all listener properties
float flEnvironmentSize; // environment size in meters
float flEnvironmentDiffusion; // environment diffusion
long lRoom; // room effect level (at mid frequencies)
long lRoomHF; // relative room effect level at high frequencies
long lRoomLF; // relative room effect level at low frequencies
float flDecayTime; // reverberation decay time at mid frequencies
float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio
float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio
long lReflections; // early reflections level relative to room effect
float flReflectionsDelay; // initial reflection delay time
EAXVECTOR vReflectionsPan; // early reflections panning vector
long lReverb; // late reverberation level relative to room effect
float flReverbDelay; // late reverberation delay time relative to initial reflection
EAXVECTOR vReverbPan; // late reverberation panning vector
float flEchoTime; // echo time
float flEchoDepth; // echo depth
float flModulationTime; // modulation time
float flModulationDepth; // modulation depth
float flAirAbsorptionHF; // change in level per meter at high frequencies
float flHFReference; // reference high frequency
float flLFReference; // reference low frequency
float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect
unsigned long ulFlags; // modifies the behavior of properties
} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES;
// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT
enum
{
EAX_ENVIRONMENT_GENERIC,
EAX_ENVIRONMENT_PADDEDCELL,
EAX_ENVIRONMENT_ROOM,
EAX_ENVIRONMENT_BATHROOM,
EAX_ENVIRONMENT_LIVINGROOM,
EAX_ENVIRONMENT_STONEROOM,
EAX_ENVIRONMENT_AUDITORIUM,
EAX_ENVIRONMENT_CONCERTHALL,
EAX_ENVIRONMENT_CAVE,
EAX_ENVIRONMENT_ARENA,
EAX_ENVIRONMENT_HANGAR,
EAX_ENVIRONMENT_CARPETEDHALLWAY,
EAX_ENVIRONMENT_HALLWAY,
EAX_ENVIRONMENT_STONECORRIDOR,
EAX_ENVIRONMENT_ALLEY,
EAX_ENVIRONMENT_FOREST,
EAX_ENVIRONMENT_CITY,
EAX_ENVIRONMENT_MOUNTAINS,
EAX_ENVIRONMENT_QUARRY,
EAX_ENVIRONMENT_PLAIN,
EAX_ENVIRONMENT_PARKINGLOT,
EAX_ENVIRONMENT_SEWERPIPE,
EAX_ENVIRONMENT_UNDERWATER,
EAX_ENVIRONMENT_DRUGGED,
EAX_ENVIRONMENT_DIZZY,
EAX_ENVIRONMENT_PSYCHOTIC,
EAX_ENVIRONMENT_UNDEFINED,
EAX_ENVIRONMENT_COUNT
};
// Used by DSPROPERTY_EAXLISTENER_FLAGS
//
// Note: The number and order of flags may change in future EAX versions.
// It is recommended to use the flag defines as follows:
// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE;
// instead of:
// myFlags = 0x00000009;
//
// These flags determine what properties are affected by environment size.
#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time
#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level
#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time
#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level
#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time
#define EAXLISTENERFLAGS_ECHOTIMESCALE 0x00000040 // echo time
#define EAXLISTENERFLAGS_MODULATIONTIMESCALE 0x00000080 // modulation time
// This flag limits high-frequency decay time according to air absorption.
#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020
#define EAXLISTENERFLAGS_RESERVED 0xFFFFFF00 // reserved future use
// Property ranges and defaults:
#define EAXLISTENER_MINENVIRONMENT 0
#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT-1)
#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC
#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f
#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f
#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f
#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f
#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f
#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f
#define EAXLISTENER_MINROOM (-10000)
#define EAXLISTENER_MAXROOM 0
#define EAXLISTENER_DEFAULTROOM (-1000)
#define EAXLISTENER_MINROOMHF (-10000)
#define EAXLISTENER_MAXROOMHF 0
#define EAXLISTENER_DEFAULTROOMHF (-100)
#define EAXLISTENER_MINROOMLF (-10000)
#define EAXLISTENER_MAXROOMLF 0
#define EAXLISTENER_DEFAULTROOMLF 0
#define EAXLISTENER_MINDECAYTIME 0.1f
#define EAXLISTENER_MAXDECAYTIME 20.0f
#define EAXLISTENER_DEFAULTDECAYTIME 1.49f
#define EAXLISTENER_MINDECAYHFRATIO 0.1f
#define EAXLISTENER_MAXDECAYHFRATIO 2.0f
#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f
#define EAXLISTENER_MINDECAYLFRATIO 0.1f
#define EAXLISTENER_MAXDECAYLFRATIO 2.0f
#define EAXLISTENER_DEFAULTDECAYLFRATIO 1.00f
#define EAXLISTENER_MINREFLECTIONS (-10000)
#define EAXLISTENER_MAXREFLECTIONS 1000
#define EAXLISTENER_DEFAULTREFLECTIONS (-2602)
#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f
#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f
#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f
#define EAXLISTENER_MINREVERB (-10000)
#define EAXLISTENER_MAXREVERB 2000
#define EAXLISTENER_DEFAULTREVERB 200
#define EAXLISTENER_MINREVERBDELAY 0.0f
#define EAXLISTENER_MAXREVERBDELAY 0.1f
#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f
#define EAXLISTENER_MINECHOTIME 0.075f
#define EAXLISTENER_MAXECHOTIME 0.25f
#define EAXLISTENER_DEFAULTECHOTIME 0.25f
#define EAXLISTENER_MINECHODEPTH 0.0f
#define EAXLISTENER_MAXECHODEPTH 1.0f
#define EAXLISTENER_DEFAULTECHODEPTH 0.0f
#define EAXLISTENER_MINMODULATIONTIME 0.04f
#define EAXLISTENER_MAXMODULATIONTIME 4.0f
#define EAXLISTENER_DEFAULTMODULATIONTIME 0.25f
#define EAXLISTENER_MINMODULATIONDEPTH 0.0f
#define EAXLISTENER_MAXMODULATIONDEPTH 1.0f
#define EAXLISTENER_DEFAULTMODULATIONDEPTH 0.0f
#define EAXLISTENER_MINAIRABSORPTIONHF (-100.0f)
#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f
#define EAXLISTENER_DEFAULTAIRABSORPTIONHF (-5.0f)
#define EAXLISTENER_MINHFREFERENCE 1000.0f
#define EAXLISTENER_MAXHFREFERENCE 20000.0f
#define EAXLISTENER_DEFAULTHFREFERENCE 5000.0f
#define EAXLISTENER_MINLFREFERENCE 20.0f
#define EAXLISTENER_MAXLFREFERENCE 1000.0f
#define EAXLISTENER_DEFAULTLFREFERENCE 250.0f
#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f
#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f
#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f
#define EAXLISTENER_DEFAULTFLAGS (EAXLISTENERFLAGS_DECAYTIMESCALE | \
EAXLISTENERFLAGS_REFLECTIONSSCALE | \
EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \
EAXLISTENERFLAGS_REVERBSCALE | \
EAXLISTENERFLAGS_REVERBDELAYSCALE | \
EAXLISTENERFLAGS_DECAYHFLIMIT)
/*
* EAX 3.0 buffer property set {A8FA6881-B476-11d3-BDB9-00C0F02DDF87}
*/
DEFINE_GUID(DSPROPSETID_EAX30_BufferProperties,
0xa8fa6881,
0xb476,
0x11d3,
0xbd, 0xb9, 0x0, 0xc0, 0xf0, 0x2d, 0xdf, 0x87);
// For compatibility with future EAX versions:
#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX30_BufferProperties
#define DSPROPSETID_EAX_SourceProperties DSPROPSETID_EAX30_BufferProperties
typedef enum
{
DSPROPERTY_EAXBUFFER_NONE,
DSPROPERTY_EAXBUFFER_ALLPARAMETERS,
DSPROPERTY_EAXBUFFER_OBSTRUCTIONPARAMETERS,
DSPROPERTY_EAXBUFFER_OCCLUSIONPARAMETERS,
DSPROPERTY_EAXBUFFER_EXCLUSIONPARAMETERS,
DSPROPERTY_EAXBUFFER_DIRECT,
DSPROPERTY_EAXBUFFER_DIRECTHF,
DSPROPERTY_EAXBUFFER_ROOM,
DSPROPERTY_EAXBUFFER_ROOMHF,
DSPROPERTY_EAXBUFFER_OBSTRUCTION,
DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO,
DSPROPERTY_EAXBUFFER_OCCLUSION,
DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO,
DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO,
DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO,
DSPROPERTY_EAXBUFFER_EXCLUSION,
DSPROPERTY_EAXBUFFER_EXCLUSIONLFRATIO,
DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF,
DSPROPERTY_EAXBUFFER_DOPPLERFACTOR,
DSPROPERTY_EAXBUFFER_ROLLOFFFACTOR,
DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR,
DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR,
DSPROPERTY_EAXBUFFER_FLAGS
} DSPROPERTY_EAX_BUFFERPROPERTY;
// OR these flags with property id
#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately
#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later
#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \
DSPROPERTY_EAXBUFFER_IMMEDIATE)
// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS
// - all levels are hundredths of decibels
// - all delays are in seconds
//
// NOTE: This structure may change in future EAX versions.
// It is recommended to initialize fields by name:
// myBuffer.lDirect = 0;
// myBuffer.lDirectHF = -200;
// ...
// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ;
// instead of:
// myBuffer = { 0, -200, ... , 0x00000003 };
//
typedef struct _EAXBUFFERPROPERTIES
{
long lDirect; // direct path level (at low and mid frequencies)
long lDirectHF; // relative direct path level at high frequencies
long lRoom; // room effect level (at low and mid frequencies)
long lRoomHF; // relative room effect level at high frequencies
long lObstruction; // main obstruction control (attenuation at high frequencies)
float flObstructionLFRatio; // obstruction low-frequency level re. main control
long lOcclusion; // main occlusion control (attenuation at high frequencies)
float flOcclusionLFRatio; // occlusion low-frequency level re. main control
float flOcclusionRoomRatio; // relative occlusion control for room effect
float flOcclusionDirectRatio; // relative occlusion control for direct path
long lExclusion; // main exlusion control (attenuation at high frequencies)
float flExclusionLFRatio; // exclusion low-frequency level re. main control
long lOutsideVolumeHF; // outside sound cone level at high frequencies
float flDopplerFactor; // like DS3D flDopplerFactor but per source
float flRolloffFactor; // like DS3D flRolloffFactor but per source
float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect
float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
unsigned long ulFlags; // modifies the behavior of properties
} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES;
// Use this structure for DSPROPERTY_EAXBUFFER_OBSTRUCTION,
typedef struct _EAXOBSTRUCTIONPROPERTIES
{
long lObstruction;
float flObstructionLFRatio;
} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES;
// Use this structure for DSPROPERTY_EAXBUFFER_OCCLUSION
typedef struct _EAXOCCLUSIONPROPERTIES
{
long lOcclusion;
float flOcclusionLFRatio;
float flOcclusionRoomRatio;
float flOcclusionDirectRatio;
} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES;
// Use this structure for DSPROPERTY_EAXBUFFER_EXCLUSION
typedef struct _EAXEXCLUSIONPROPERTIES
{
long lExclusion;
float flExclusionLFRatio;
} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES;
// Used by DSPROPERTY_EAXBUFFER_FLAGS
// TRUE: value is computed automatically - property is an offset
// FALSE: value is used directly
//
// Note: The number and order of flags may change in future EAX versions.
// To insure future compatibility, use flag defines as follows:
// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO;
// instead of:
// myFlags = 0x00000003;
//
#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF
#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM
#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF
#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use
// Property ranges and defaults:
#define EAXBUFFER_MINDIRECT (-10000)
#define EAXBUFFER_MAXDIRECT 1000
#define EAXBUFFER_DEFAULTDIRECT 0
#define EAXBUFFER_MINDIRECTHF (-10000)
#define EAXBUFFER_MAXDIRECTHF 0
#define EAXBUFFER_DEFAULTDIRECTHF 0
#define EAXBUFFER_MINROOM (-10000)
#define EAXBUFFER_MAXROOM 1000
#define EAXBUFFER_DEFAULTROOM 0
#define EAXBUFFER_MINROOMHF (-10000)
#define EAXBUFFER_MAXROOMHF 0
#define EAXBUFFER_DEFAULTROOMHF 0
#define EAXBUFFER_MINOBSTRUCTION (-10000)
#define EAXBUFFER_MAXOBSTRUCTION 0
#define EAXBUFFER_DEFAULTOBSTRUCTION 0
#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f
#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f
#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f
#define EAXBUFFER_MINOCCLUSION (-10000)
#define EAXBUFFER_MAXOCCLUSION 0
#define EAXBUFFER_DEFAULTOCCLUSION 0
#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f
#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f
#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f
#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f
#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f
#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 1.5f
#define EAXBUFFER_MINOCCLUSIONDIRECTRATIO 0.0f
#define EAXBUFFER_MAXOCCLUSIONDIRECTRATIO 10.0f
#define EAXBUFFER_DEFAULTOCCLUSIONDIRECTRATIO 1.0f
#define EAXBUFFER_MINEXCLUSION (-10000)
#define EAXBUFFER_MAXEXCLUSION 0
#define EAXBUFFER_DEFAULTEXCLUSION 0
#define EAXBUFFER_MINEXCLUSIONLFRATIO 0.0f
#define EAXBUFFER_MAXEXCLUSIONLFRATIO 1.0f
#define EAXBUFFER_DEFAULTEXCLUSIONLFRATIO 1.0f
#define EAXBUFFER_MINOUTSIDEVOLUMEHF (-10000)
#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0
#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0
#define EAXBUFFER_MINDOPPLERFACTOR 0.0f
#define EAXBUFFER_MAXDOPPLERFACTOR 10.f
#define EAXBUFFER_DEFAULTDOPPLERFACTOR 0.0f
#define EAXBUFFER_MINROLLOFFFACTOR 0.0f
#define EAXBUFFER_MAXROLLOFFFACTOR 10.f
#define EAXBUFFER_DEFAULTROLLOFFFACTOR 0.0f
#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f
#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f
#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f
#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f
#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f
#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f
#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | \
EAXBUFFERFLAGS_ROOMAUTO | \
EAXBUFFERFLAGS_ROOMHFAUTO )
#pragma pack(pop)
#ifdef __cplusplus
}
#endif // __cplusplus
#endif

1535
fmod/win32/src/fmod_eax4.h Executable file

File diff suppressed because it is too large Load diff

2067
fmod/win32/src/fmod_eax5.h Executable file

File diff suppressed because it is too large Load diff

624
fmod/win32/src/fmod_file_cdda.cpp Executable file
View file

@ -0,0 +1,624 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_CDDA
#include "fmod_debug.h"
#include "fmod_file_cdda.h"
#include "fmod_os_cdda.h"
#include "fmod_string.h"
#include "fmod_time.h"
#include <stdio.h>
#include <string.h>
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
CddaFile::CddaFile()
{
mDevice = 0;
mLastTimeAccessed = 0;
mGotUserToc = false;
mJitterCorrection = false;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::init(bool force_aspi, bool jitter_correction)
{
mJitterCorrection = jitter_correction;
return FMOD_OS_CDDA_Init(force_aspi);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::shutDown()
{
return FMOD_OS_CDDA_Shutdown();
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::reallyOpen(const char *name_or_data, unsigned int *filesize)
{
int numtracks;
FMOD_RESULT result = FMOD_OK;
mReadBuf = 0;
mReadPtr = 0;
mReadSizebytes = 0;
mStartSector = 0;
mCurrentSector = 0;
mSectorsLeft = 0;
mSectorsInChunk = 26;
mJitterBuf = 0;
mJitterBufSectors = 7;
mJitterBufEmpty = true;
mGotUserToc = false;
result = FMOD_OS_CDDA_OpenDevice((char *)name_or_data, &mDevice);
if (result != FMOD_OK)
{
return result;
}
if (!FMOD_OS_CDDA_TestUnitReady(mDevice))
{
FMOD_OS_CDDA_DEBUGPRINT("CddaFile::reallyOpen: Device not ready (Make sure there's a CD/DVD in the drive!)");
return FMOD_ERR_CDDA_NODISC;
}
result = FMOD_OS_CDDA_ReadTocRaw(mDevice, &mDevice->toc);
if (result != FMOD_OK)
{
result = FMOD_OS_CDDA_ReadToc(mDevice, &mDevice->toc);
if (result != FMOD_OK)
{
return result;
}
}
#ifdef FMOD_OS_CDDA_DUMPTOC
{
unsigned int i;
for (i=0;i < mDevice->toc.num_tracks;i++)
{
unsigned int len = (((mDevice->toc.num_sectors[i] * SIZEOF_CDDA_SECTOR) >> 2) / 44100) * 1000;
FMOD_OS_CDDA_DEBUGPRINT("Track %d. 0x%08lx %d:%d (%d)\n", mDevice->toc.track_number[i], mDevice->toc.start_sector[i], len / 1000 / 60, len / 1000 % 60, *((unsigned char *)&mDevice->toc.flags[i]));
}
}
#endif
mReadBuf = (char *)FMOD_Memory_Alloc(mSectorsInChunk * SIZEOF_CDDA_SECTOR);
if (!mReadBuf)
{
reallyClose();
return FMOD_ERR_MEMORY;
}
FMOD_memset(mReadBuf, 0, mSectorsInChunk * SIZEOF_CDDA_SECTOR);
if (mJitterCorrection)
{
mJitterBuf = (char *)FMOD_Memory_Alloc(SIZEOF_CDDA_SECTOR);
if (!mJitterBuf)
{
reallyClose();
return FMOD_ERR_MEMORY;
}
FMOD_memset(mJitterBuf, 0, SIZEOF_CDDA_SECTOR);
mJitterBufEmpty = true;
}
result = getNumTracks(&numtracks);
if (result != FMOD_OK)
{
return result;
}
if (numtracks < 1)
{
FMOD_OS_CDDA_DEBUGPRINT("CddaFile::reallyOpen: No audio tracks! (Please insert a CD/DVD that contains one or more audio tracks)\n");
return FMOD_ERR_CDDA_NOAUDIO;
}
result = getTrackLength(0, filesize);
if (result != FMOD_OK)
{
return result;
}
*filesize <<= 3;
mDevice->usertoc.numtracks--;
FMOD_OS_CDDA_DEBUGPRINT("CddaFile::reallyOpen: ok\n");
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::reallyClose()
{
FMOD_RESULT result = FMOD_OK;
if (mDevice)
{
result = FMOD_OS_CDDA_CloseDevice(mDevice);
mDevice = 0;
}
if (mReadBuf)
{
FMOD_Memory_Free(mReadBuf);
mReadBuf = 0;
}
if (mJitterBuf)
{
FMOD_Memory_Free(mJitterBuf);
mJitterBuf = 0;
}
return result;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::reallyRead(void *buffer, unsigned int size, unsigned int *rd)
{
int bytestocopy, count;
unsigned int sectors_to_read = 0;
FMOD_RESULT result = FMOD_OK;
#ifdef FMOD_OS_CDDA_DEBUG
unsigned int starttime;
FMOD_OS_Time_GetMs(&starttime);
#endif
if (!mDevice)
{
return FMOD_ERR_INVALID_PARAM;
}
*rd = 0;
while (size)
{
if (!mReadSizebytes)
{
sectors_to_read = (mSectorsLeft < mSectorsInChunk) ? mSectorsLeft : mSectorsInChunk;
if (!sectors_to_read)
{
*rd = 0;
return FMOD_ERR_FILE_EOF;
}
for (count = 0; count < 10; count++)
{
result = FMOD_OS_CDDA_ReadSectors(mDevice, mReadBuf, mCurrentSector, sectors_to_read);
if (result == FMOD_OK)
{
break;
}
else
{
FMOD_OS_Time_Sleep(1);
}
}
FMOD_OS_Time_GetMs(&mLastTimeAccessed);
if (count >= 10)
{
return FMOD_ERR_CDDA_READ;
}
if (mJitterCorrection)
{
doJitterCorrection(sectors_to_read);
}
else
{
mCurrentSector += sectors_to_read;
mSectorsLeft -= sectors_to_read;
mReadPtr = mReadBuf;
mReadSizebytes = sectors_to_read * SIZEOF_CDDA_SECTOR;
}
#ifdef FMOD_OS_CDDA_DEBUG
{
unsigned int elapsed;
FMOD_OS_Time_GetMs(&elapsed);
elapsed -= starttime;
FMOD_OS_CDDA_AddProfileData((int)elapsed, mReadSizebytes);
}
#endif
}
bytestocopy = (mReadSizebytes < (unsigned int)size) ? mReadSizebytes : size;
FMOD_memcpy((char *)buffer, mReadPtr, bytestocopy);
*rd += bytestocopy;
mReadPtr += bytestocopy;
mReadSizebytes -= bytestocopy;
buffer = (void *)((char *)buffer + bytestocopy);
size -= bytestocopy;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::doJitterCorrection(unsigned int sectors_to_read)
{
if (!mJitterBufEmpty)
{
int offset, skip_bytes;
int compare_size = ((sectors_to_read < mJitterBufSectors ? sectors_to_read : mJitterBufSectors) - 1) * SIZEOF_CDDA_SECTOR;
int start_compare = compare_size >> 1;
char *ptr_forward, *ptr_back;
bool found = false;
if ((compare_size <= 0) || (sectors_to_read <= (mJitterBufSectors >> 1)))
{
FMOD_memset(mReadBuf, 0, sectors_to_read * SIZEOF_CDDA_SECTOR);
FMOD_memset(mJitterBuf, 0, SIZEOF_CDDA_SECTOR);
mCurrentSector += sectors_to_read;
mSectorsLeft -= sectors_to_read;
mReadPtr = mReadBuf;
mReadSizebytes = sectors_to_read * SIZEOF_CDDA_SECTOR;
return FMOD_OK;
}
ptr_forward = ptr_back = (mReadBuf + start_compare);
skip_bytes = start_compare;
for (offset=0;offset < start_compare;offset += 4, ptr_forward += 4, ptr_back -= 4)
{
if (!memcmp(ptr_forward, mJitterBuf, SIZEOF_CDDA_SECTOR))
{
skip_bytes = start_compare + offset + SIZEOF_CDDA_SECTOR;
found = true;
break;
}
if (!memcmp(ptr_back, mJitterBuf, SIZEOF_CDDA_SECTOR))
{
skip_bytes = start_compare - offset + SIZEOF_CDDA_SECTOR;
found = true;
break;
}
}
if (!found)
{
/*
Jitter error - couldn't match up this read to the last one - it's gonna sound bad...
*/
skip_bytes = 0;
}
if ((unsigned int)sectors_to_read == mSectorsLeft)
{
mCurrentSector += sectors_to_read;
mSectorsLeft -= sectors_to_read;
}
else
{
mCurrentSector += (sectors_to_read - (mJitterBufSectors >> 1) - 1);
mSectorsLeft -= (sectors_to_read - (mJitterBufSectors >> 1) - 1);
}
mReadPtr = mReadBuf + skip_bytes;
mReadSizebytes = (sectors_to_read * SIZEOF_CDDA_SECTOR) - skip_bytes;
}
else
{
mCurrentSector += sectors_to_read;
mSectorsLeft -= sectors_to_read;
mReadPtr = mReadBuf;
mReadSizebytes = sectors_to_read * SIZEOF_CDDA_SECTOR;
}
FMOD_memcpy(mJitterBuf, mReadBuf + ((sectors_to_read - 1) * SIZEOF_CDDA_SECTOR), SIZEOF_CDDA_SECTOR);
mJitterBufEmpty = false;
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::reallySeek(unsigned int pos)
{
unsigned int num_sectors;
pos /= SIZEOF_CDDA_SECTOR;
num_sectors = (mCurrentSector - mStartSector) + mSectorsLeft;
if (pos >= num_sectors)
{
return FMOD_ERR_INVALID_PARAM;
}
mCurrentSector = mStartSector + pos;
mSectorsLeft = num_sectors - pos;
FMOD_memset(mReadBuf, 0, mSectorsInChunk * SIZEOF_CDDA_SECTOR);
mReadPtr = 0;
mReadSizebytes = 0;
mJitterBufEmpty = true;
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::getNumTracks(int *numtracks)
{
if (!numtracks || !mDevice)
{
return FMOD_ERR_INVALID_PARAM;
}
*numtracks = mDevice->toc.num_tracks - 1;
if (*numtracks < 0)
{
*numtracks = 0;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::getTrackLength(unsigned int track, unsigned int *tracklength)
{
if (!tracklength || !mDevice || (track >= (mDevice->toc.num_tracks - 1)))
{
return FMOD_ERR_INVALID_PARAM;
}
*tracklength = mDevice->toc.num_sectors[track] * SIZEOF_CDDA_SECTOR;
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::openTrack(unsigned int track)
{
unsigned int starttime, thistime;
if (track >= (mDevice->toc.num_tracks - 1)) /* -1 for leadout track */
{
return FMOD_ERR_INVALID_PARAM;
}
mStartSector = mDevice->toc.start_sector[track];
mCurrentSector = mStartSector;
mSectorsLeft = mDevice->toc.num_sectors[track];
mLength = mSectorsLeft * SIZEOF_CDDA_SECTOR;
mReadPtr = 0;
mReadSizebytes = 0;
mJitterBufEmpty = true;
FMOD_memset(mReadBuf, 0, mSectorsInChunk * SIZEOF_CDDA_SECTOR);
FMOD_OS_Time_GetMs(&thistime);
if ((thistime - mLastTimeAccessed) > (FMOD_CDDA_SPINDOWN_TIME * 1000))
{
FMOD_OS_CDDA_SetSpeed(mDevice, 4);
FMOD_OS_Time_GetMs(&starttime);
for (;;)
{
FMOD_OS_Time_GetMs(&thistime);
if ((thistime - starttime) > (FMOD_CDDA_SPINUP_TIME * 1000))
{
break;
}
FMOD_OS_CDDA_ReadSectors(mDevice, mReadBuf, mStartSector, 1);
FMOD_OS_Time_Sleep(20);
}
FMOD_OS_Time_GetMs(&mLastTimeAccessed);
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT CddaFile::getMetadata(Metadata **metadata)
{
if (!mDevice || !metadata)
{
return FMOD_ERR_INVALID_PARAM;
}
if (mGotUserToc)
{
return FMOD_ERR_TAGNOTFOUND;
}
mMetadata.addTag(FMOD_TAGTYPE_FMOD, "CDTOC", &mDevice->usertoc, sizeof(FMOD_CDTOC), FMOD_TAGDATATYPE_CDTOC, true);
mGotUserToc = true;
*metadata = &mMetadata;
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
#ifdef FMOD_SUPPORT_MEMORYTRACKER
FMOD_RESULT CddaFile::getMemoryUsedImpl(MemoryTracker *tracker)
{
tracker->add(false, FMOD_MEMBITS_FILE, sizeof(CddaFile));
return File::getMemoryUsedImpl(tracker);
}
#endif
}
#endif

2809
fmod/win32/src/fmod_os_cdda.cpp Executable file

File diff suppressed because it is too large Load diff

829
fmod/win32/src/fmod_os_misc.cpp Executable file
View file

@ -0,0 +1,829 @@
#include "fmod_settings.h"
#include "fmod.h"
#include "fmod_os_misc.h"
#include "fmod_memory.h"
#include "MeteredSection.h"
#include <windows.h>
#include <stdio.h>
#include <process.h>
#define USEMETEREDSECTIONS
int gSizeofCriticalSection = sizeof(CRITICAL_SECTION);
#ifdef USEMETEREDSECTIONS
int gSizeofSemaphore = sizeof(METERED_SECTION);
#else
int gSizeofSemaphore = 0;
#endif
#if defined(FMOD_DEBUG) && !defined(PLATFORM_WINDOWS64)
#define MS_VC_EXCEPTION 0x406D1388
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
static void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = szThreadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
__try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (DWORD*)&info);
}
__except(EXCEPTION_CONTINUE_EXECUTION)
{
}
}
#endif
/*
[DESCRIPTION]
OS based memory alloc
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
void *FMOD_OS_Memory_Alloc(int size, FMOD_MEMORY_TYPE type)
{
return malloc(size);
}
/*
[DESCRIPTION]
OS based memory re-alloc.
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
void *FMOD_OS_Memory_Realloc(void *ptr, int size, FMOD_MEMORY_TYPE type)
{
return realloc(ptr, size);
}
/*
[DESCRIPTION]
OS based free
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
void FMOD_OS_Memory_Free(void *ptr, FMOD_MEMORY_TYPE type)
{
free(ptr);
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_File_DriveStatus()
{
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_File_Open(const char *name, char *mode, int unicode, unsigned int *filesize, void **handle)
{
if (unicode)
{
*handle = CreateFileW((WCHAR *)name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
else
{
*handle = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
if (*handle == INVALID_HANDLE_VALUE)
{
DWORD err = GetLastError();
if (err != ERROR_FILE_NOT_FOUND && err != ERROR_PATH_NOT_FOUND && err != ERROR_INVALID_NAME)
{
return FMOD_ERR_FILE_BAD;
}
return FMOD_ERR_FILE_NOTFOUND;
}
*filesize = GetFileSize(*handle, NULL);
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_File_Close(void *handle)
{
if (handle == INVALID_HANDLE_VALUE)
{
return FMOD_ERR_FILE_BAD;
}
CloseHandle(handle);
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_File_Cancel(void *handle)
{
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_File_Read(void *handle, void *buf, unsigned int count, unsigned int *read)
{
DWORD rd;
if (!ReadFile(handle, buf, count, &rd, NULL))
{
DWORD lasterr = GetLastError();
return FMOD_ERR_FILE_BAD;
}
*read = rd;
if (rd != count)
{
return FMOD_ERR_FILE_EOF;
}
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_File_Seek(void *handle, unsigned int offset)
{
DWORD retval;
retval = SetFilePointer(handle, offset, NULL, FILE_BEGIN);
if (retval == (unsigned int)-1)
{
return FMOD_ERR_FILE_BAD;
}
return FMOD_OK;
}
/*
[DESCRIPTION]
Debug to console function
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Debug_OutputStr(const char *s)
{
OutputDebugStringA(s);
return FMOD_OK;
}
/*
[DESCRIPTION]
Gets the current time in nanoseconds. (1000th of a millisecond)
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Time_GetNs(unsigned int *ns)
{
LARGE_INTEGER val,freq;
if (QueryPerformanceCounter(&val))
{
QueryPerformanceFrequency(&freq);
val.QuadPart *= 1000;
val.QuadPart *= 1000;
val.QuadPart /= freq.QuadPart;
*ns = val.LowPart;
}
else
{
*ns = timeGetTime() * 1000;
}
return FMOD_OK;
}
/*
[DESCRIPTION]
Gets the current time in milliseconds. (1000th of a second)
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Time_GetMs(unsigned int *ms)
{
*ms = timeGetTime();
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Time_Sleep(unsigned int ms)
{
Sleep(ms);
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Thread_GetCurrentID(FMOD_UINT_NATIVE *id)
{
*id = GetCurrentThreadId();
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
'priority' -1 to 2, -1 = low 0 = normal, 1 = high, 2 = critical
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Thread_Create(const char *name, THREAD_RETURNTYPE (THREAD_CALLCONV *func)(void *param), void *param, FMOD_THREAD_PRIORITY priority, void *stack, int stacksize, void **handle)
{
HRESULT hr;
unsigned int id;
if (!handle)
{
return FMOD_ERR_INVALID_PARAM;
}
*handle = (void *)_beginthreadex(NULL, stacksize, func, param,0, (unsigned int *)&id);
if (!*handle)
{
return FMOD_ERR_MEMORY;
}
switch (priority)
{
case FMOD_THREAD_PRIORITY_VERYLOW:
hr = SetThreadPriority(*handle, THREAD_PRIORITY_LOWEST);
break;
case FMOD_THREAD_PRIORITY_LOW:
hr = SetThreadPriority(*handle, THREAD_PRIORITY_BELOW_NORMAL);
break;
case FMOD_THREAD_PRIORITY_NORMAL:
hr = SetThreadPriority(*handle, THREAD_PRIORITY_NORMAL);
break;
case FMOD_THREAD_PRIORITY_HIGH:
hr = SetThreadPriority(*handle, THREAD_PRIORITY_ABOVE_NORMAL);
break;
case FMOD_THREAD_PRIORITY_VERYHIGH:
hr = SetThreadPriority(*handle, THREAD_PRIORITY_HIGHEST);
break;
case FMOD_THREAD_PRIORITY_CRITICAL:
hr = SetThreadPriority(*handle, THREAD_PRIORITY_TIME_CRITICAL);
break;
};
#if defined(FMOD_DEBUG) && !defined(PLATFORM_WINDOWS64)
SetThreadName(id, name);
#endif
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Thread_Destroy(void *handle)
{
CloseHandle(handle);
return FMOD_OK;
}
CRITICAL_SECTION gMemoryCrit;
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_CriticalSection_Create(FMOD_OS_CRITICALSECTION **crit, bool memorycrit)
{
FMOD_RESULT result = FMOD_OK;
if (!crit)
{
return FMOD_ERR_INVALID_PARAM;
}
if (memorycrit)
{
*crit = (FMOD_OS_CRITICALSECTION *)&gMemoryCrit; /* Can't use alloc on the critical section used in the memory system. */
}
else
{
*crit = (FMOD_OS_CRITICALSECTION *)FMOD_Memory_Alloc(sizeof(CRITICAL_SECTION));
if (!*crit)
{
return FMOD_ERR_MEMORY;
}
}
InitializeCriticalSection((CRITICAL_SECTION *)(*crit));
return result;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_CriticalSection_Free(FMOD_OS_CRITICALSECTION *crit, bool memorycrit)
{
if (!crit)
{
return FMOD_ERR_INVALID_PARAM;
}
DeleteCriticalSection((CRITICAL_SECTION *)crit);
if (memorycrit)
{
return FMOD_OK;
}
FMOD_Memory_Free(crit);
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_CriticalSection_Enter(FMOD_OS_CRITICALSECTION *crit)
{
if (!crit)
{
return FMOD_ERR_INVALID_PARAM;
}
EnterCriticalSection((CRITICAL_SECTION *)crit);
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_CriticalSection_Leave(FMOD_OS_CRITICALSECTION *crit)
{
if (!crit)
{
return FMOD_ERR_INVALID_PARAM;
}
LeaveCriticalSection((CRITICAL_SECTION *)crit);
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Semaphore_Create(FMOD_OS_SEMAPHORE **sema)
{
if (!sema)
{
return FMOD_ERR_INVALID_PARAM;
}
#ifdef USEMETEREDSECTIONS
*sema = (FMOD_OS_SEMAPHORE *)CreateMeteredSection(0, 0xffff, NULL);
if (!*sema)
{
return FMOD_ERR_MEMORY;
}
#else
*sema = (FMOD_OS_SEMAPHORE *)CreateSemaphore(NULL, 0, 0xffff, NULL);
#endif
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Semaphore_Free(FMOD_OS_SEMAPHORE *sema)
{
if (sema == INVALID_HANDLE_VALUE)
{
return FMOD_ERR_INVALID_PARAM;
}
#ifdef USEMETEREDSECTIONS
CloseMeteredSection((LPMETERED_SECTION)sema);
#else
CloseHandle((HANDLE)sema);
#endif
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Semaphore_Wait(FMOD_OS_SEMAPHORE *sema)
{
if (sema == INVALID_HANDLE_VALUE)
{
return FMOD_ERR_INVALID_PARAM;
}
#ifdef USEMETEREDSECTIONS
EnterMeteredSection((LPMETERED_SECTION)sema, INFINITE);
#else
WaitForSingleObject((HANDLE)sema, INFINITE);
#endif
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Semaphore_Signal(FMOD_OS_SEMAPHORE *sema, bool interrupt)
{
if (sema == INVALID_HANDLE_VALUE)
{
return FMOD_ERR_INVALID_PARAM;
}
#ifdef USEMETEREDSECTIONS
LeaveMeteredSection((LPMETERED_SECTION)sema, 1, NULL);
#else
ReleaseSemaphore((HANDLE)sema, 1, NULL);
#endif
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Library_Load(const char *dllname, FMOD_OS_LIBRARY **handle)
{
if (!dllname || !handle)
{
return FMOD_ERR_INVALID_PARAM;
}
*handle = (FMOD_OS_LIBRARY *)LoadLibraryA(dllname);
if (!*handle)
{
DWORD err = GetLastError();
return FMOD_ERR_FILE_NOTFOUND;
}
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Library_GetProcAddress(FMOD_OS_LIBRARY *handle, const char *procname, void **address)
{
if (!handle || !address)
{
return FMOD_ERR_INVALID_PARAM;
}
*address = (void *)GetProcAddress((HMODULE)handle, procname);
if (!*address)
{
return FMOD_ERR_FILE_BAD;
}
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Library_Free(FMOD_OS_LIBRARY *handle)
{
if (!handle)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!FreeLibrary((HMODULE)handle))
{
return FMOD_ERR_INVALID_PARAM;
}
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_CheckDriverList(bool *devicelistchanged)
{
static int lastNumDrivers = -1;
int numDrivers = -1;
numDrivers = waveOutGetNumDevs();
numDrivers += waveInGetNumDevs();
*devicelistchanged = (numDrivers != lastNumDrivers && lastNumDrivers != -1);
lastNumDrivers = numDrivers;
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
#ifdef FMOD_SUPPORT_MEMORYTRACKER
extern FMOD_OS_CRITICALSECTION *gResolveCrit;
int FMOD_OS_GetMemoryUsed()
{
int total = 0;
if (gResolveCrit)
{
total += gSizeofCriticalSection;
}
return total;
}
#endif

View file

@ -0,0 +1,41 @@
%include "./FMOD_static/win32/src/c32.mac"
; ==========================================================================================
; GLOBAL UNINITIALIZED DATA
; ==========================================================================================
[SEGMENT .data use32 align=32]
; ==========================================================================================
; CODE
; ==========================================================================================
[SEGMENT .text use32 align=32]
; =================================================================================================================================
; int FMOD_OS_SupportsSSE
; =================================================================================================================================
proc FMOD_OS_SupportsSSE
push ebx
push ecx
push edx
push esi
push edi
mov eax, 1
cpuid
test edx, 02000000h
jnz SSEFound
mov eax, 0
jmp SSETestEnd
SSEFound:
mov eax, 1
SSETestEnd:
pop edi
pop esi
pop edx
pop ecx
pop ebx
endproc

501
fmod/win32/src/fmod_os_net.cpp Executable file
View file

@ -0,0 +1,501 @@
#include "fmod_net.h"
#include "fmod_os_misc.h"
#include "fmod_time.h"
#include <windows.h>
static const int FMOD_NET_MAXADDRLEN = 46;
static int FMOD_OS_Net_Init_Count = 0;
FMOD_OS_CRITICALSECTION *gResolveCrit = 0;
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Net_Init()
{
FMOD_RESULT result;
if (FMOD_OS_Net_Init_Count == 0)
{
WSADATA wsadata;
WSAStartup(0x0002, &wsadata);
result = FMOD_OS_CriticalSection_Create(&gResolveCrit);
if (result != FMOD_OK)
{
WSACleanup();
return result;
}
FMOD_OS_Net_Init_Count++;
}
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Net_Shutdown()
{
if (FMOD_OS_Net_Init_Count > 0)
{
FMOD_OS_Net_Init_Count--;
if (FMOD_OS_Net_Init_Count == 0)
{
FMOD_OS_CriticalSection_Free(gResolveCrit);
gResolveCrit = 0;
WSACleanup();
}
}
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Net_Connect(const char *host, const unsigned short port, void **handle)
{
struct sockaddr_in server;
struct hostent *h;
FMOD_RESULT result;
SOCKET sock;
int rc;
struct timeval tv;
unsigned long nonblocking = 1;
fd_set writefd;
unsigned int thistime = 0, lasttime = 0, elapsedtime = 0;
unsigned int timeout = FMOD_Net_Timeout;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
return FMOD_ERR_MEMORY;
}
else
{
*handle = (void *)sock;
}
FMOD_memset(&server, 0, sizeof(struct sockaddr_in));
*((unsigned long *)&server.sin_addr) = inet_addr(host);
if (*((unsigned long *)&server.sin_addr) == INADDR_NONE)
{
char buf[MAXGETHOSTSTRUCT];
HANDLE handle;
result = FMOD_OS_CriticalSection_Enter(gResolveCrit);
if (result != FMOD_OK)
{
closesocket(sock);
return result;
}
FMOD_memset(buf, 0, MAXGETHOSTSTRUCT);
handle = WSAAsyncGetHostByName(NULL, NULL, host, buf, MAXGETHOSTSTRUCT);
h = (struct hostent *)buf;
FMOD_OS_Time_GetMs(&lasttime);
for (;;)
{
if (h->h_name)
{
break;
}
FMOD_OS_Time_GetMs(&thistime);
elapsedtime += (thistime - lasttime);
lasttime = thistime;
if (elapsedtime >= timeout)
{
WSACancelAsyncRequest(handle);
FMOD_OS_CriticalSection_Leave(gResolveCrit);
return FMOD_ERR_NET_URL;
}
FMOD_OS_Time_Sleep(10);
}
FMOD_memcpy(&server.sin_addr, (struct in_addr *)h->h_addr, sizeof(struct in_addr));
FMOD_OS_CriticalSection_Leave(gResolveCrit);
}
server.sin_family = AF_INET;
server.sin_port = htons(port);
FD_ZERO(&writefd);
FD_SET(sock, &writefd);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
ioctlsocket(sock, FIONBIO, &nonblocking);
rc = connect(sock, (struct sockaddr *)&server, sizeof(server));
if (rc == SOCKET_ERROR)
{
int rc = WSAGetLastError();
if (rc != WSAEWOULDBLOCK)
{
closesocket(sock);
return FMOD_ERR_NET_CONNECT;
}
}
/*
Select will block for timeout length, or return when connected
*/
rc = select(0, 0, &writefd, 0, &tv);
if (rc <= 0)
{
closesocket(sock);
return FMOD_ERR_NET_CONNECT;
}
nonblocking = 0;
ioctlsocket(sock, FIONBIO, &nonblocking);
return FMOD_OK;
}
/*
[DESCRIPTION]
Begin listening on the designated port, non-blocking
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Net_Listen(const unsigned short port, void **listenhandle)
{
SOCKET listensocket;
SOCKADDR_IN address;
u_long nonblocking = TRUE;
// Create the socket
listensocket = socket(AF_INET, SOCK_STREAM, 0);
if (listensocket == INVALID_SOCKET)
{
return FMOD_ERR_MEMORY;
}
// Set blocking mode
if (ioctlsocket(listensocket, FIONBIO, &nonblocking) == SOCKET_ERROR)
{
return FMOD_ERR_NET_SOCKET_ERROR;
}
// Set to listen from any IP on the defined port
FMOD_memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
// Bind the address to the socket
if (bind(listensocket, (struct sockaddr*)&address, sizeof(address)) == SOCKET_ERROR)
{
return FMOD_ERR_NET_SOCKET_ERROR;
}
// Start listening for connections
if (listen(listensocket, 3) == SOCKET_ERROR)
{
return FMOD_ERR_NET_SOCKET_ERROR;
}
*listenhandle = (void *)listensocket;
return FMOD_OK;
}
/*
[DESCRIPTION]
Accept a pending connection from the queue
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Net_Accept(const void *listenhandle, void **clienthandle)
{
SOCKET listensocket = (SOCKET)listenhandle;
SOCKET clientsocket = NULL;
if (listenhandle == (void *)-1)
{
return FMOD_ERR_NET_SOCKET_ERROR;
}
// Accept a waiting connection
clientsocket = accept(listensocket, NULL, NULL);
if(clientsocket == INVALID_SOCKET)
{
int errorcode = WSAGetLastError();
if(errorcode == WSAEWOULDBLOCK)
{
return FMOD_ERR_NET_WOULD_BLOCK;
}
else
{
return FMOD_ERR_NET_SOCKET_ERROR;
}
}
*clienthandle = (void *)clientsocket;
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Net_Close(const void *handle)
{
SOCKET sock = (SOCKET)handle;
if (sock != -1)
{
closesocket(sock);
}
return FMOD_OK;
}
/*
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
*/
FMOD_RESULT FMOD_OS_Net_Write(const void *handle, const char *buf, const unsigned int len, unsigned int *byteswritten)
{
SOCKET sock = (SOCKET)handle;
int written, bytestowrite = len;
if (handle == (void *)-1)
{
return FMOD_ERR_NET_SOCKET_ERROR;
}
*byteswritten = 0;
while (bytestowrite)
{
written = send(sock, buf, bytestowrite, 0);
if (written == SOCKET_ERROR)
{
int errorcode = WSAGetLastError();
if(errorcode == WSAEWOULDBLOCK)
{
return FMOD_ERR_NET_WOULD_BLOCK;
}
else
{
return FMOD_ERR_NET_SOCKET_ERROR;
}
}
*byteswritten += written;
bytestowrite -= written;
buf += written;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT FMOD_OS_Net_Read(const void *handle, char *buf, const unsigned int len, unsigned int *bytesread)
{
SOCKET sock = (SOCKET)handle;
int read, bytestoread = len;
if (handle == (void *)-1)
{
return FMOD_ERR_NET_SOCKET_ERROR;
}
if (!buf || (len <= 0))
{
return FMOD_ERR_INVALID_PARAM;
}
*bytesread = 0;
while (bytestoread)
{
read = recv(sock, buf, bytestoread, 0);
if (read == SOCKET_ERROR)
{
int errorcode = WSAGetLastError();
if(errorcode == WSAEWOULDBLOCK)
{
return FMOD_ERR_NET_WOULD_BLOCK;
}
else
{
return FMOD_ERR_NET_SOCKET_ERROR;
}
}
else if (read == 0)
{
/*
Connection closed gracefully
*/
return FMOD_ERR_FILE_EOF;
}
else
{
*bytesread += read;
bytestoread -= read;
buf += read;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT FMOD_OS_Net_ReadLine(const void *handle, char *buf, const unsigned int len)
{
unsigned int pos, read;
char c = 0;
buf[0] = 0;
if (handle == (void *)-1)
{
return FMOD_ERR_NET_SOCKET_ERROR;
}
if (!buf || (len <= 0))
{
return FMOD_ERR_INVALID_PARAM;
}
pos = 0;
while (pos < len)
{
FMOD_RESULT result = FMOD_OS_Net_Read(handle, &c, 1, &read);
if (result == FMOD_ERR_NET_WOULD_BLOCK)
{
return FMOD_ERR_NET_WOULD_BLOCK;
}
if (read == 1)
{
if (c == '\n')
{
break;
}
else if (c != '\r')
{
buf[pos++] = c;
}
}
else
{
break;
}
}
if (pos >= len)
{
pos = len - 1;
}
buf[pos] = 0;
return FMOD_OK;
}

112
fmod/win32/src/fmod_os_output.cpp Executable file
View file

@ -0,0 +1,112 @@
#include "fmod_settings.h"
#include "fmod.h"
#include "fmod_memory.h"
#include "fmod_output.h"
#include "fmod_output_asio.h"
#include "fmod_output_wasapi.h"
#include "fmod_output_dsound.h"
#include "fmod_output_winmm.h"
#include "fmod_output_openal.h"
#include "fmod_pluginfactory.h"
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT FMOD_OS_Output_Register(FMOD::PluginFactory *pluginfactory)
{
#ifdef FMOD_USE_PLUGINS
CHECK_RESULT(pluginfactory->tryLoadPlugin("output_dsound"));
CHECK_RESULT(pluginfactory->tryLoadPlugin("output_winmm"));
CHECK_RESULT(pluginfactory->tryLoadPlugin("output_wasapi"));
CHECK_RESULT(pluginfactory->tryLoadPlugin("output_asio"));
#else
#ifdef FMOD_SUPPORT_DSOUND
CHECK_RESULT(pluginfactory->registerOutput(FMOD::OutputDSound::getDescriptionEx()));
#endif
#ifdef FMOD_SUPPORT_WINMM
CHECK_RESULT(pluginfactory->registerOutput(FMOD::OutputWinMM::getDescriptionEx()));
#endif
#ifdef FMOD_SUPPORT_WASAPI
CHECK_RESULT(pluginfactory->registerOutput(FMOD::OutputWASAPI::getDescriptionEx()));
#endif
#ifdef FMOD_SUPPORT_ASIO
CHECK_RESULT(pluginfactory->registerOutput(FMOD::OutputASIO::getDescriptionEx()));
#endif
#ifdef FMOD_SUPPORT_OPENAL
CHECK_RESULT(pluginfactory->registerOutput(FMOD::OutputOpenAL::getDescriptionEx()));
#endif
#endif
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT FMOD_OS_Output_GetDefault(FMOD_OUTPUTTYPE *outputtype)
{
if (!outputtype)
{
return FMOD_ERR_INVALID_PARAM;
}
*outputtype = FMOD_OUTPUTTYPE_DSOUND;
#ifdef FMOD_SUPPORT_WASAPI
/*
Check COM support for WASAPI, override default output mode if supported
*/
{
IMMDeviceEnumerator *enumerator = NULL;
HRESULT hResult = S_OK;
hResult = CoInitialize(NULL);
if (SUCCEEDED(CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&enumerator)))
{
*outputtype = FMOD_OUTPUTTYPE_WASAPI;
enumerator->Release();
}
if (hResult == S_OK || hResult == S_FALSE)
{
CoUninitialize();
}
}
#endif
return FMOD_OK;
}

File diff suppressed because it is too large Load diff

101
fmod/win32/src/fmod_output_asio.h Executable file
View file

@ -0,0 +1,101 @@
#ifndef _FMOD_OUTPUT_ASIO_H
#define _FMOD_OUTPUT_ASIO_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_ASIO
#include "fmod_outputi.h"
#include "asio\asiosys.h"
#include "asio\asio.h"
#include "asio\asiodrivers.h"
namespace FMOD
{
class OutputASIO : public Output
{
private:
AsioDrivers *mHandle;
long mInputChannels;
long mOutputChannels;
long mBufferMinSize;
long mBufferMaxSize;
long mBufferPreferredSize;
long mBufferGranularity;
bool mPostOutput;
float *mInterleavedBuffer;
#ifdef FMOD_SUPPORT_RECORDING
float *mInterleavedRecordBuffer;
unsigned int mInterleavedRecordBufferPos;
bool mRecordLoop;
SoundI *mRecordSound;
FMOD_SOUND_FORMAT mRecordFormat;
unsigned int mRecordBufferLength;
#endif
ASIOCallbacks mCallbacks;
ASIOBufferInfo *mBufferInfo;
ASIOChannelInfo *mChannelInfo;
static void bufferSwitch(long index, ASIOBool processNow);
static ASIOTime * bufferSwitchTimeInfo(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess);
static void sampleRateDidChange(ASIOSampleRate sRate);
static long asioMessage(long selector, long value, void* message, double* opt);
#ifdef FMOD_SUPPORT_SOFTWARE
FMOD_RESULT updateMixer(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess);
#endif
public:
static FMOD_OUTPUT_DESCRIPTION_EX *getDescriptionEx();
FMOD_RESULT enumerate();
FMOD_RESULT getNumDrivers(int *numdrivers);
FMOD_RESULT getDriverName(int id, char *name, int namelen);
FMOD_RESULT getDriverCaps(int id, FMOD_CAPS *caps);
FMOD_RESULT init(int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int dspnumbuffers, void *extradriverdata);
FMOD_RESULT close();
FMOD_RESULT getHandle(void **handle);
FMOD_RESULT start();
FMOD_RESULT stop();
#ifdef FMOD_SUPPORT_RECORDING
FMOD_RESULT recordEnumerate();
FMOD_RESULT recordGetNumDrivers(int *numdrivers);
FMOD_RESULT recordGetDriverInfo(int id, char *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT recordStart (FMOD_RECORDING_INFO *recordinfo, Sound *sound, bool loop);
FMOD_RESULT recordStop (FMOD_RECORDING_INFO *recordinfo);
FMOD_RESULT recordGetPosition (FMOD_RECORDING_INFO *recordinfo, unsigned int *pcm);
FMOD_RESULT recordLock (FMOD_RECORDING_INFO *recordinfo, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
FMOD_RESULT recordUnlock (FMOD_RECORDING_INFO *recordinfo, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
#endif
static FMOD_RESULT F_CALLBACK getNumDriversCallback (FMOD_OUTPUT_STATE *output, int *numdrivers);
static FMOD_RESULT F_CALLBACK getDriverNameCallback (FMOD_OUTPUT_STATE *output, int id, char *name, int namelen);
static FMOD_RESULT F_CALLBACK getDriverCapsCallback (FMOD_OUTPUT_STATE *output, int id, FMOD_CAPS *caps);
static FMOD_RESULT F_CALLBACK initCallback (FMOD_OUTPUT_STATE *output, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int dspnumbuffers, void *extradriverdata);
static FMOD_RESULT F_CALLBACK closeCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK startCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK stopCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK getHandleCallback (FMOD_OUTPUT_STATE *output, void **handle);
#ifdef FMOD_SUPPORT_RECORDING
static FMOD_RESULT F_CALLBACK recordGetNumDriversCallback(FMOD_OUTPUT_STATE *output, int *numdrivers);
static FMOD_RESULT F_CALLBACK recordGetDriverInfoCallback(FMOD_OUTPUT_STATE *output, int id, char *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK recordStartCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, FMOD_SOUND *sound, int loop);
static FMOD_RESULT F_CALLBACK recordStopCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo);
static FMOD_RESULT F_CALLBACK recordGetPositionCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, unsigned int *pcm);
static FMOD_RESULT F_CALLBACK recordLockCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
static FMOD_RESULT F_CALLBACK recordUnlockCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
#endif
};
}
#endif /* #ifdef FMOD_SUPPORT_ASIO */
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,252 @@
#ifndef _FMOD_OUTPUT_DSOUND_H
#define _FMOD_OUTPUT_DSOUND_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_DSOUND
//#define FMOD_OUTPUT_DSOUND_USETIMER
#ifdef FMOD_OUTPUT_DSOUND_USETIMER
#include "fmod_output_timer.h"
#else
#include "fmod_output_polled.h"
#endif
#include "fmod_os_misc.h"
#ifdef PLATFORM_32BIT
typedef unsigned long DWORD;
typedef DWORD DWORD_PTR;
#endif
#include <dsound.h>
#ifndef _FMOD_MEMORYTRACKER_H
#include "fmod_memorytracker.h"
#endif
/*
Directsound function pointers definitions.
*/
typedef HRESULT (WINAPI * PFN_DSCREATE) (LPGUID lpguid, LPDIRECTSOUND * ppDS, IUnknown FAR * pUnkOuter);
typedef BOOL (WINAPI * PFN_DSENUMERATE) (LPDSENUMCALLBACKW lpDSEnumCallback, LPVOID lpContext);
typedef HRESULT (WINAPI * PFN_DSCREATE8) (LPCGUID lpcGuidDevice, LPDIRECTSOUND8 * ppDS8, LPUNKNOWN pUnkOuter);
typedef HRESULT (WINAPI * PFN_DSCCREATE) (LPGUID lpGUID, LPDIRECTSOUNDCAPTURE *lplpDSC,LPUNKNOWN pUnkOuter);
typedef BOOL (WINAPI * PFN_DSCENUMERATE) (LPDSENUMCALLBACKW lpDSEnumCallback,LPVOID lpContext);
typedef HRESULT (WINAPI * PFN_DSCCREATE8) (LPCGUID lpcGUID, LPDIRECTSOUNDCAPTURE8 *lplpDSC, LPUNKNOWN pUnkOuter);
static const FMOD_GUID FMOD_DSPROPSETID_I3DL2_ListenerProperties = { 0xDA0F0520, 0x300A, 0x11D3, { 0x8A, 0x2B, 0x00, 0x60, 0x97, 0x0D, 0xB0, 0x11 } };
static const FMOD_GUID FMOD_DSPROPSETID_I3DL2_BufferProperties = { 0xDA0F0521, 0x300A, 0x11D3, { 0x8A, 0x2B, 0x00, 0x60, 0x97, 0x0D, 0xB0, 0x11 } };
static const FMOD_GUID FMOD_DSPROPSETID_EAX20_BufferProperties = { 0x306a6a7, 0xb224, 0x11d2, { 0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22 } };
static const FMOD_GUID FMOD_DSPROPSETID_EAX20_ListenerProperties = { 0x306a6a8, 0xb224, 0x11d2, { 0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22 } };
static const FMOD_GUID FMOD_DSPROPSETID_EAX30_ListenerProperties = { 0xa8fa6882, 0xb476, 0x11d3, { 0xbd, 0xb9, 0x00, 0xc0, 0xf0, 0x2d, 0xdf, 0x87 } };
static const FMOD_GUID FMOD_DSPROPSETID_EAX30_BufferProperties = { 0xa8fa6881, 0xb476, 0x11d3, { 0xbd, 0xb9, 0x0, 0xc0, 0xf0, 0x2d, 0xdf, 0x87 } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX40_Context = { 0x1d4870ad, 0xdef, 0x43c0, { 0xa4, 0xc, 0x52, 0x36, 0x32, 0x29, 0x63, 0x42 } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX40_Source = { 0x1b86b823, 0x22df, 0x4eae, { 0x8b, 0x3c, 0x12, 0x78, 0xce, 0x54, 0x42, 0x27 } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX40_FXSlot0 = { 0xc4d79f1e, 0xf1ac, 0x436b, { 0xa8, 0x1d, 0xa7, 0x38, 0xe7, 0x4, 0x54, 0x69 } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX40_FXSlot1 = { 0x8c00e96, 0x74be, 0x4491, { 0x93, 0xaa, 0xe8, 0xad, 0x35, 0xa4, 0x91, 0x17 } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX40_FXSlot2 = { 0x1d433b88, 0xf0f6, 0x4637, { 0x91, 0x9f, 0x60, 0xe7, 0xe0, 0x6b, 0x5e, 0xdd } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX40_FXSlot3 = { 0xefff08ea, 0xc7d8, 0x44ab, { 0x93, 0xad, 0x6d, 0xbd, 0x5f, 0x91, 0x0, 0x64 } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX50_Context = { 0x57e13437, 0xb932, 0x4ab2, { 0xb8, 0xbd, 0x52, 0x66, 0xc1, 0xa8, 0x87, 0xee } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX50_Source = { 0x5edf82f0, 0x24a7, 0x4f38, { 0x8e, 0x64, 0x2f, 0x09, 0xca, 0x05, 0xde, 0xe1 } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX50_FXSlot0 = { 0x91f9590f, 0xc388, 0x407a, { 0x84, 0xb0, 0x1b, 0xae, 0x0e, 0xf7, 0x1a, 0xbc } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX50_FXSlot1 = { 0x8f5f7aca, 0x9608, 0x4965, { 0x81, 0x37, 0x82, 0x13, 0xc7, 0xb9, 0xd9, 0xde } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX50_FXSlot2 = { 0x3c0f5252, 0x9834, 0x46f0, { 0xa1, 0xd8, 0x5b, 0x95, 0xc4, 0xa0, 0x0a, 0x30 } };
static const FMOD_GUID FMOD_EAXPROPERTYID_EAX50_FXSlot3 = { 0xe2eb0eaa, 0xe806, 0x45e7, { 0x9f, 0x86, 0x06, 0xc1, 0x57, 0x1a, 0x6f, 0xa3 } };
static const FMOD_GUID FMOD_EAX_NULL_GUID = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
static const FMOD_GUID FMOD_EAX_REVERB_EFFECT = { 0xcf95c8f, 0xa3cc, 0x4849, { 0xb0, 0xb6, 0x83, 0x2e, 0xcc, 0x18, 0x22, 0xdf } };
static const FMOD_GUID FMOD_IID_IKsPropertySet = { 0x31efac30, 0x515c, 0x11d0, { 0xa9, 0xaa, 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93 } };
namespace FMOD
{
class ChannelDSound;
class SampleDSound;
class Sound;
typedef enum
{
REVERB_VERSION_NONE,
REVERB_VERSION_EAX5,
REVERB_VERSION_EAX4,
REVERB_VERSION_EAX3,
REVERB_VERSION_EAX2,
REVERB_VERSION_I3DL2
} REVERB_VERSION;
typedef struct FMOD_DSoundRecordMembers
{
IDirectSoundCapture8 *mDirectSoundCapture;
IDirectSoundCaptureBuffer *mDirectSoundCaptureBuffer;
} FMOD_DSoundRecordMembers;
#ifdef FMOD_OUTPUT_DSOUND_USETIMER
class OutputDSound : public OutputTimer
#else
class OutputDSound : public OutputPolled
#endif
{
DECLARE_MEMORYTRACKER_NONVIRTUAL
friend class SampleDSound;
friend class ChannelDSound;
friend class ChannelDSoundEAX2;
friend class ChannelDSoundEAX3;
friend class ChannelDSoundEAX4;
friend class ChannelDSoundI3DL2;
private:
bool mDLLInitialized;
bool mCoInitialized;
bool mGlobalFocus;
bool mNeedToCommit;
FMOD_INITFLAGS mInitFlags;
int mDirectXVersion;
HMODULE mDSoundModule;
HMODULE mDSound3DModule;
PFN_DSCREATE8 mDirectSoundCreate;
PFN_DSENUMERATE mDirectSoundEnumerate;
IDirectSound8 *mDirectSound;
IDirectSound3DListener *mDirectSoundListener;
PFN_DSCENUMERATE mDirectSoundCaptureEnumerate;
PFN_DSCCREATE8 mDirectSoundCaptureCreate;
REVERB_VERSION mReverbVersion;
unsigned int mFeaturesReverb;
IKsPropertySet *mBufferReverb;
SampleDSound *mSampleReverb;
bool mUseSoftware2DBuffers;
bool mUseSoftware3DBuffers;
float mMinFrequency;
float mMaxFrequency;
unsigned int mBufferLength;
unsigned int mNumBuffers;
float mLastDopplerScale;
float mLastDistancerScale;
float mLastRolloffrScale;
FMOD_SPEAKERMODE mSpeakerMode;
ChannelDSound *mChannel2D;
ChannelDSound *mChannel3D;
Sample *mSample;
unsigned int mBufferMemoryCurrent;
unsigned int mBufferMemoryMax;
FMOD_RESULT registerDLL();
bool initI3DL2();
FMOD_RESULT closeI3DL2();
FMOD_RESULT setPropertiesI3DL2(const FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT getPropertiesI3DL2(FMOD_REVERB_PROPERTIES *prop);
bool querySupportI3DL2(unsigned int ulQuery);
bool initEAX2();
FMOD_RESULT closeEAX2();
FMOD_RESULT setPropertiesEAX2(const FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT getPropertiesEAX2(FMOD_REVERB_PROPERTIES *prop);
bool querySupportEAX2(unsigned int ulQuery);
bool initEAX3();
FMOD_RESULT closeEAX3();
FMOD_RESULT setPropertiesEAX3(const FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT getPropertiesEAX3(FMOD_REVERB_PROPERTIES *prop);
bool querySupportEAX3(unsigned int ulQuery);
bool initEAX4();
FMOD_RESULT closeEAX4();
FMOD_RESULT setPropertiesEAX4(const FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT getPropertiesEAX4(FMOD_REVERB_PROPERTIES *prop);
bool querySupportEAX4(FMOD_GUID guid, unsigned long ulProperty);
public:
int mNumDrivers; /* Public for C callback access */
short *mDriverName[FMOD_OUTPUT_MAXDRIVERS]; /* Public for C callback access */
GUID mGUID[FMOD_OUTPUT_MAXDRIVERS];
static FMOD_OUTPUT_DESCRIPTION_EX *getDescriptionEx();
FMOD_RESULT enumerate();
FMOD_RESULT getNumDrivers(int *numdrivers);
FMOD_RESULT getDriverInfo(int id, char *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT getDriverInfoW(int id, short *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT getDriverCapsEx(int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency, FMOD_SPEAKERMODE *controlpanelspeakermode, int *num2dchannels, int *num3dchannels, int *totalchannels);
FMOD_RESULT init(int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, FMOD_SPEAKERMODE *speakermode, int dspbufferlength, int dspnumbuffers, int max2dchannels, int max3dchannels, void *extradriverdata);
FMOD_RESULT close();
FMOD_RESULT getHandle(void **handle);
FMOD_RESULT update();
FMOD_RESULT createSample(FMOD_MODE mode, FMOD_CODEC_WAVEFORMAT *waveformat, Sample **sample);
FMOD_RESULT getSoundRAM(int *currentalloced, int *maxalloced, int *total);
FMOD_RESULT setReverbProperties(const FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT getReverbProperties(FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT start();
FMOD_RESULT stop();
FMOD_RESULT getPosition(unsigned int *pcm);
FMOD_RESULT lock(unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
FMOD_RESULT unlock(void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
int getSampleMaxChannels(FMOD_MODE mode, FMOD_SOUND_FORMAT format);
#ifdef FMOD_SUPPORT_RECORDING
int mRecordNumDrivers; /* Public for C callback access */
short *mRecordDriverName[FMOD_OUTPUT_MAXDRIVERS]; /* Public for C callback access */
GUID mRecordGUID[FMOD_OUTPUT_MAXDRIVERS];
FMOD_RESULT recordEnumerate();
FMOD_RESULT recordGetNumDrivers(int *numdrivers);
FMOD_RESULT recordGetDriverInfo(int id, char *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT recordGetDriverInfoW(int id, short *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT recordStart (FMOD_RECORDING_INFO *recordinfo, Sound *sound, bool loop);
FMOD_RESULT recordStop (FMOD_RECORDING_INFO *recordinfo);
FMOD_RESULT recordGetPosition (FMOD_RECORDING_INFO *recordinfo, unsigned int *pcm);
FMOD_RESULT recordLock (FMOD_RECORDING_INFO *recordinfo, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
FMOD_RESULT recordUnlock (FMOD_RECORDING_INFO *recordinfo, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
#endif
static FMOD_RESULT F_CALLBACK getNumDriversCallback (FMOD_OUTPUT_STATE *output, int *numdrivers);
static FMOD_RESULT F_CALLBACK getDriverInfoCallback (FMOD_OUTPUT_STATE *output, int id, char *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK getDriverInfoWCallback (FMOD_OUTPUT_STATE *output, int id, short *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK getDriverCapsExCallback (FMOD_OUTPUT_STATE *output, int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency, FMOD_SPEAKERMODE *controlpanelspeakermode, int *num2dchannels, int *num3dchannels, int *totalchannels);
static FMOD_RESULT F_CALLBACK initExCallback (FMOD_OUTPUT_STATE *output, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, FMOD_SPEAKERMODE *speakermode, int dspbufferlength, int dspnumbuffers, int max2dchannels, int max3dchannels, void *extradriverdata);
static FMOD_RESULT F_CALLBACK closeCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK startCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK stopCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK updateCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK getHandleCallback (FMOD_OUTPUT_STATE *output, void **handle);
static FMOD_RESULT F_CALLBACK getPositionCallback (FMOD_OUTPUT_STATE *output, unsigned int *pcm);
static FMOD_RESULT F_CALLBACK lockCallback (FMOD_OUTPUT_STATE *output, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
static FMOD_RESULT F_CALLBACK unlockCallback (FMOD_OUTPUT_STATE *output, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
static FMOD_RESULT F_CALLBACK createSampleCallback (FMOD_OUTPUT_STATE *output, FMOD_MODE mode, FMOD_CODEC_WAVEFORMAT *waveformat, Sample **sample);
static FMOD_RESULT F_CALLBACK getSoundRAMCallback (FMOD_OUTPUT_STATE *output, int *currentalloced, int *maxalloced, int *total);
static FMOD_RESULT F_CALLBACK setReverbPropertiesCallback (FMOD_OUTPUT_STATE *output, const FMOD_REVERB_PROPERTIES *prop);
static int F_CALLBACK getSampleMaxChannelsCallback (FMOD_OUTPUT_STATE *output, FMOD_MODE mode, FMOD_SOUND_FORMAT format);
#ifdef FMOD_SUPPORT_RECORDING
static FMOD_RESULT F_CALLBACK recordGetNumDriversCallback (FMOD_OUTPUT_STATE *output, int *numdrivers);
static FMOD_RESULT F_CALLBACK recordGetDriverInfoCallback (FMOD_OUTPUT_STATE *output, int id, char *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK recordGetDriverInfoWCallback (FMOD_OUTPUT_STATE *output, int id, short *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK recordStartCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, FMOD_SOUND *sound, int loop);
static FMOD_RESULT F_CALLBACK recordStopCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo);
static FMOD_RESULT F_CALLBACK recordGetPositionCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, unsigned int *pcm);
static FMOD_RESULT F_CALLBACK recordLockCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
static FMOD_RESULT F_CALLBACK recordUnlockCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
#endif
#ifdef FMOD_SUPPORT_MEMORYTRACKER
static FMOD_RESULT F_CALLBACK getMemoryUsedCallback (FMOD_OUTPUT_STATE *output, MemoryTracker *tracker);
#endif
};
}
#endif /* FMOD_SUPPORT_DSOUND */
#endif

View file

@ -0,0 +1,353 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_EAX
#include "fmod_output_dsound.h"
#include "fmod_eax2.h"
#include "fmod_localcriticalsection.h"
#include "fmod_sample_dsound.h"
#include "fmod_systemi.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
bool OutputDSound::querySupportEAX2(unsigned int ulQuery)
{
unsigned long ulSupport = 0;
HRESULT hr;
GUID guid;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX2", "check properties %08X\n", ulQuery));
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX20_ListenerProperties, sizeof(GUID));
hr = mBufferReverb->QuerySupport(guid, ulQuery, &ulSupport);
if ( FAILED(hr) )
{
return false;
}
if ( (ulSupport&(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET)) ==
(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET) )
{
mFeaturesReverb |= (DWORD)(1 << ulQuery);
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX2", "success.\n"));
return true;
}
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX2", "failed.\n"));
return false;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
bool OutputDSound::initEAX2()
{
FMOD_RESULT result;
ULONG support = 0;
HRESULT hr = DS_OK;
GUID guid;
FMOD_CODEC_WAVEFORMAT waveformat;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX2", "Querying EAX2\n"));
if (mBufferReverb)
{
mBufferReverb->Release();
mBufferReverb = 0;
}
/*
Create EAX sample
*/
FMOD_memset(&waveformat, 0, sizeof(FMOD_CODEC_WAVEFORMAT));
waveformat.frequency = 44100;
waveformat.lengthpcm = 1024;
waveformat.channels = 1;
waveformat.format = FMOD_SOUND_FORMAT_PCM16;
result = createSample(FMOD_3D | FMOD_UNIQUE, &waveformat, (Sample **)&mSampleReverb);
if (result != FMOD_OK)
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX2", "could not create hardware sample.\n"));
return false;
}
mSampleReverb->mSystem = mSystem;
/*
OBTAIN EAX INTERFACE TO BUFFER
*/
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
if(mSampleReverb->mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb) != DS_OK)
{
mBufferReverb = 0;
return false;
}
/*
QUERY FOR EAX support
*/
support = querySupportEAX2(DSPROPERTY_EAXLISTENER_NONE);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_ALLPARAMETERS);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_ENVIRONMENT);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_ROOM);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_ROOMHF);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_DECAYTIME);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_DECAYHFRATIO);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_REFLECTIONS);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_REVERB);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_REVERBDELAY);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR);
if (support) support = querySupportEAX2(DSPROPERTY_EAXLISTENER_FLAGS);
if (!mFeaturesReverb)
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX2", "failed EAX check, releasing reverb interface\n"));
return false;
}
/*
Turn down reverb to start with.
*/
if ((mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ROOM))
{
DWORD Room = EAXLISTENER_MINROOM;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX2", "setting reverb environment to OFF\n"));
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX20_ListenerProperties, sizeof(GUID));
mBufferReverb->Set(guid, DSPROPERTY_EAXLISTENER_ROOM, 0, 0, &Room, sizeof(DWORD));
}
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX2", "found!\n"));
return true;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::closeEAX2()
{
if (mBufferReverb)
{
/*
Turn down reverb again
*/
if ((mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ROOM))
{
GUID guid;
DWORD Room = EAXLISTENER_MINROOM;
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX20_ListenerProperties, sizeof(GUID));
mBufferReverb->Set(guid, DSPROPERTY_EAXLISTENER_ROOM, 0, 0, &Room, sizeof(DWORD));
}
mBufferReverb->Release();
mBufferReverb = NULL;
}
if (mSampleReverb)
{
mSampleReverb->release();
mSampleReverb = NULL;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::setPropertiesEAX2(const FMOD_REVERB_PROPERTIES *prop)
{
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesEAX2", "Entering \n"));
if ( !(mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ALLPARAMETERS) )
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesEAX2", "failed - apparently DSPROPERTY_EAXLISTENER_ALLPARAMETERS isnt supported\n"));
return FMOD_ERR_UNSUPPORTED;
}
if (mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ALLPARAMETERS)
{
HRESULT hr;
EAXLISTENERPROPERTIES dsprop = {0};
GUID guid;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesEAX2", "setting listener properties\n"));
dsprop.flEnvironmentSize = prop->EnvSize;
dsprop.dwEnvironment = prop->Environment < 0 ? 0 : prop->Environment;
dsprop.flEnvironmentDiffusion = prop->EnvDiffusion;
dsprop.lRoom = prop->Room;
dsprop.lRoomHF = prop->RoomHF;
dsprop.flDecayTime = prop->DecayTime;
dsprop.flDecayHFRatio = prop->DecayHFRatio;
dsprop.lReflections = prop->Reflections;
dsprop.flReflectionsDelay = prop->ReflectionsDelay;
dsprop.lReverb = prop->Reverb;
dsprop.flReverbDelay = prop->ReverbDelay;
dsprop.flAirAbsorptionHF = prop->AirAbsorptionHF;
dsprop.flRoomRolloffFactor = prop->RoomRolloffFactor;
dsprop.dwFlags = prop->Flags & 0xFF;
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX20_ListenerProperties, sizeof(GUID));
hr = mBufferReverb->Set(guid, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, 0, 0, &dsprop, sizeof(EAXLISTENERPROPERTIES));
if (FAILED(hr))
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesEAX2", "setting listener properties FAILED\n"));
return FMOD_ERR_INVALID_PARAM;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::getPropertiesEAX2(FMOD_REVERB_PROPERTIES *prop)
{
ULONG ulReceived;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if ( !(mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ALLPARAMETERS) )
{
return FMOD_ERR_UNSUPPORTED;
}
if ((mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ALLPARAMETERS))
{
GUID guid;
HRESULT hr;
EAXLISTENERPROPERTIES dsprop = {0};
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX20_ListenerProperties, sizeof(GUID));
hr = mBufferReverb->Get(guid, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, 0, 0, &dsprop, sizeof(EAXLISTENERPROPERTIES), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_UNSUPPORTED;
}
prop->Environment = dsprop.dwEnvironment;
prop->EnvSize = dsprop.flEnvironmentSize ;
prop->EnvDiffusion = dsprop.flEnvironmentDiffusion ;
prop->Room = dsprop.lRoom ;
prop->RoomHF = dsprop.lRoomHF ;
prop->RoomLF = 0;
prop->DecayTime = dsprop.flDecayTime ;
prop->DecayHFRatio = dsprop.flDecayHFRatio ;
prop->DecayLFRatio = 0;
prop->Reflections = dsprop.lReflections ;
prop->ReflectionsDelay = dsprop.flReflectionsDelay ;
prop->ReflectionsPan[0] = 0;
prop->ReflectionsPan[1] = 0;
prop->ReflectionsPan[2] = 0;
prop->Reverb = dsprop.lReverb ;
prop->ReverbDelay = dsprop.flReverbDelay ;
prop->ReverbPan[0] = 0;
prop->ReverbPan[1] = 0;
prop->ReverbPan[2] = 0;
prop->EchoTime = 0;
prop->EchoDepth = 0;
prop->ModulationTime = 0;
prop->ModulationDepth = 0;
prop->AirAbsorptionHF = dsprop.flAirAbsorptionHF ;
prop->HFReference = 0;
prop->LFReference = 0;
prop->RoomRolloffFactor = dsprop.flRoomRolloffFactor ;
prop->Flags = dsprop.dwFlags ;
}
return FMOD_OK;
}
}
#endif /* FMOD_SUPPORT_EAX */

View file

@ -0,0 +1,381 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_EAX
#include "fmod_output_dsound.h"
#include "fmod_eax3.h"
#include "fmod_localcriticalsection.h"
#include "fmod_sample_dsound.h"
#include "fmod_systemi.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
bool OutputDSound::querySupportEAX3(unsigned int ulQuery)
{
unsigned long ulSupport = 0;
HRESULT hr;
GUID guid;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX3", "check properties %08X\n", ulQuery));
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX30_ListenerProperties, sizeof(GUID));
hr = mBufferReverb->QuerySupport(guid, ulQuery, &ulSupport);
if ( FAILED(hr) )
{
return false;
}
if ( (ulSupport&(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET)) ==
(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET) )
{
mFeaturesReverb |= (DWORD)(1 << ulQuery);
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX3", "success\n"));
return true;
}
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX3", "failed.\n"));
return false;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
bool OutputDSound::initEAX3()
{
FMOD_RESULT result;
ULONG support = 0;
HRESULT hr = DS_OK;
GUID guid;
FMOD_CODEC_WAVEFORMAT waveformat;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "Querying EAX3\n"));
if (mBufferReverb)
{
mBufferReverb->Release();
mBufferReverb = NULL;
}
/*
Create EAX sample
*/
FMOD_memset(&waveformat, 0, sizeof(FMOD_CODEC_WAVEFORMAT));
waveformat.frequency = 44100;
waveformat.lengthpcm = 1024;
waveformat.channels = 1;
waveformat.format = FMOD_SOUND_FORMAT_PCM16;
result = createSample(FMOD_3D | FMOD_UNIQUE, &waveformat, (Sample **)&mSampleReverb);
if (result != FMOD_OK)
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX3", "could not create hardware sample.\n"));
return false;
}
mSampleReverb->mSystem = mSystem;
/*
OBTAIN EAX INTERFACE TO BUFFER
*/
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
if(mSampleReverb->mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb) != DS_OK)
{
mBufferReverb = NULL;
return false;
}
/*
QUERY FOR EAX support
*/
support = querySupportEAX3(DSPROPERTY_EAXLISTENER_NONE);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_ALLPARAMETERS);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_ENVIRONMENT);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_ROOM);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_ROOMHF);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_ROOMLF);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_DECAYTIME);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_DECAYHFRATIO);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_DECAYLFRATIO);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_REFLECTIONS);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_REFLECTIONSPAN);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_REVERB);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_REVERBDELAY);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_REVERBPAN);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_ECHOTIME);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_ECHODEPTH);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_MODULATIONTIME);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_MODULATIONDEPTH);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_HFREFERENCE);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_LFREFERENCE);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR);
if (support) support = querySupportEAX3(DSPROPERTY_EAXLISTENER_FLAGS);
if (!mFeaturesReverb)
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX3", "failed EAX check, releasing reverb interface\n"));
return false;
}
/*
Turn down reverb to start with.
*/
if ((mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ROOM))
{
DWORD Room = EAXLISTENER_MINROOM;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX3", "setting reverb environment to OFF\n"));
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX30_ListenerProperties, sizeof(GUID));
mBufferReverb->Set(guid, DSPROPERTY_EAXLISTENER_ROOM, NULL, 0, &Room, sizeof(DWORD));
}
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX3", "found!\n"));
return true;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::closeEAX3()
{
if (mBufferReverb)
{
/*
Turn down reverb again
*/
if ((mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ROOM))
{
GUID guid;
DWORD Room = EAXLISTENER_MINROOM;
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX30_ListenerProperties, sizeof(GUID));
mBufferReverb->Set(guid, DSPROPERTY_EAXLISTENER_ROOM, NULL, 0, &Room, sizeof(DWORD));
}
mBufferReverb->Release();
mBufferReverb = NULL;
}
if (mSampleReverb)
{
mSampleReverb->release();
mSampleReverb = NULL;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::setPropertiesEAX3(const FMOD_REVERB_PROPERTIES *prop)
{
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
// FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesEAX3", "Entering \n"));
if ( !(mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ALLPARAMETERS) )
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesEAX3", "failed - apparently DSPROPERTY_EAXLISTENER_ALLPARAMETERS isnt supported\n"));
return FMOD_ERR_UNSUPPORTED;
}
if (mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ALLPARAMETERS)
{
HRESULT hr;
EAXLISTENERPROPERTIES dsprop = {0};
GUID guid;
// FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesEAX3", "setting listener properties\n"));
dsprop.ulEnvironment = prop->Environment < 0 ? 0 : prop->Environment;
dsprop.flEnvironmentSize = prop->EnvSize;
dsprop.flEnvironmentDiffusion = prop->EnvDiffusion;
dsprop.lRoom = prop->Room;
dsprop.lRoomHF = prop->RoomHF;
dsprop.lRoomLF = prop->RoomLF;
dsprop.flDecayTime = prop->DecayTime;
dsprop.flDecayHFRatio = prop->DecayHFRatio;
dsprop.flDecayLFRatio = prop->DecayLFRatio;
dsprop.lReflections = prop->Reflections;
dsprop.flReflectionsDelay = prop->ReflectionsDelay;
dsprop.vReflectionsPan.x = prop->ReflectionsPan[0];
dsprop.vReflectionsPan.y = prop->ReflectionsPan[1];
dsprop.vReflectionsPan.z = prop->ReflectionsPan[2];
dsprop.lReverb = prop->Reverb;
dsprop.flReverbDelay = prop->ReverbDelay;
dsprop.vReverbPan.x = prop->ReverbPan[0];
dsprop.vReverbPan.y = prop->ReverbPan[1];
dsprop.vReverbPan.z = prop->ReverbPan[2];
dsprop.flEchoTime = prop->EchoTime;
dsprop.flEchoDepth = prop->EchoDepth;
dsprop.flModulationTime = prop->ModulationTime;
dsprop.flModulationDepth = prop->ModulationDepth;
dsprop.flAirAbsorptionHF = prop->AirAbsorptionHF;
dsprop.flHFReference = prop->HFReference;
dsprop.flLFReference = prop->LFReference;
dsprop.flRoomRolloffFactor = prop->RoomRolloffFactor;
dsprop.ulFlags = prop->Flags & 0xFF;
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX30_ListenerProperties, sizeof(GUID));
hr = mBufferReverb->Set(guid, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, NULL, 0, &dsprop, sizeof(EAXLISTENERPROPERTIES));
if (FAILED(hr))
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesEAX3", "setting listener properties FAILED\n"));
return FMOD_ERR_INVALID_PARAM;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::getPropertiesEAX3(FMOD_REVERB_PROPERTIES *prop)
{
ULONG ulReceived;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if ( !(mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ALLPARAMETERS) )
{
return FMOD_ERR_UNSUPPORTED;
}
if ((mFeaturesReverb & (DWORD)1 << DSPROPERTY_EAXLISTENER_ALLPARAMETERS))
{
GUID guid;
HRESULT hr;
EAXLISTENERPROPERTIES dsprop = {0};
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_EAX30_ListenerProperties, sizeof(GUID));
hr = mBufferReverb->Get(guid, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, NULL, 0, &dsprop, sizeof(EAXLISTENERPROPERTIES), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_UNSUPPORTED;
}
prop->Environment = dsprop.ulEnvironment ;
prop->EnvSize = dsprop.flEnvironmentSize ;
prop->EnvDiffusion = dsprop.flEnvironmentDiffusion ;
prop->Room = dsprop.lRoom ;
prop->RoomHF = dsprop.lRoomHF ;
prop->RoomLF = dsprop.lRoomLF ;
prop->DecayTime = dsprop.flDecayTime ;
prop->DecayHFRatio = dsprop.flDecayHFRatio ;
prop->DecayLFRatio = dsprop.flDecayLFRatio ;
prop->Reflections = dsprop.lReflections ;
prop->ReflectionsDelay = dsprop.flReflectionsDelay ;
prop->ReflectionsPan[0] = dsprop.vReflectionsPan.x ;
prop->ReflectionsPan[1] = dsprop.vReflectionsPan.y ;
prop->ReflectionsPan[2] = dsprop.vReflectionsPan.z ;
prop->Reverb = dsprop.lReverb ;
prop->ReverbDelay = dsprop.flReverbDelay ;
prop->ReverbPan[0] = dsprop.vReverbPan.x ;
prop->ReverbPan[1] = dsprop.vReverbPan.y ;
prop->ReverbPan[2] = dsprop.vReverbPan.z ;
prop->EchoTime = dsprop.flEchoTime ;
prop->EchoDepth = dsprop.flEchoDepth ;
prop->ModulationTime = dsprop.flModulationTime ;
prop->ModulationDepth = dsprop.flModulationDepth ;
prop->AirAbsorptionHF = dsprop.flAirAbsorptionHF ;
prop->HFReference = dsprop.flHFReference ;
prop->LFReference = dsprop.flLFReference ;
prop->RoomRolloffFactor = dsprop.flRoomRolloffFactor ;
prop->Flags = dsprop.ulFlags ;
}
return FMOD_OK;
}
}
#endif /* FMOD_SUPPORT_EAX */

View file

@ -0,0 +1,440 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_EAX
#include "fmod_output_dsound.h"
#include "fmod_eax4.h"
#include "fmod_localcriticalsection.h"
#include "fmod_sample_dsound.h"
#include "fmod_systemi.h"
#include <stdio.h>
namespace FMOD
{
bool gFXslot2set = false;
bool gFXslot3set = false;
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
bool OutputDSound::querySupportEAX4(FMOD_GUID guid, unsigned long ulProperty)
{
HRESULT hr;
unsigned long ulSupport;
GUID g;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX4", "check properties %08X\n", ulProperty));
FMOD_memcpy(&g, &guid, sizeof(GUID));
hr = mBufferReverb->QuerySupport(g, ulProperty, &ulSupport);
if ( FAILED(hr) )
{
return false;
}
if ( (ulSupport&(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET)) ==
(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET) )
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX4", "success.\n"));
return true;
}
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportEAX4", "failed.\n"));
return false;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
bool OutputDSound::initEAX4()
{
FMOD_RESULT result;
ULONG support = 0;
HRESULT hr = DS_OK;
GUID guid;
FMOD_CODEC_WAVEFORMAT waveformat;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "Querying EAX4\n"));
if (mBufferReverb)
{
mBufferReverb->Release();
mBufferReverb = NULL;
}
/*
Create EAX sample
*/
FMOD_memset(&waveformat, 0, sizeof(FMOD_CODEC_WAVEFORMAT));
waveformat.frequency = 44100;
waveformat.lengthpcm = 1024;
waveformat.channels = 1;
waveformat.format = FMOD_SOUND_FORMAT_PCM16;
result = createSample(FMOD_3D | FMOD_UNIQUE, &waveformat, (Sample **)&mSampleReverb);
if (result != FMOD_OK)
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "could not create hardware sample.\n"));
return false;
}
mSampleReverb->mSystem = mSystem;
/*
OBTAIN EAX INTERFACE TO BUFFER
*/
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
if(mSampleReverb->mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb) != DS_OK)
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "failed (1).\n"));
mBufferReverb = NULL;
return false;
}
/*
QUERY FOR EAX support
*/
support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_Context, EAXCONTEXT_ALLPARAMETERS);
if (support) support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_FXSlot0, EAXFXSLOT_ALLPARAMETERS);
if (support) support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_FXSlot1, EAXFXSLOT_ALLPARAMETERS);
if (support) support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_FXSlot2, EAXFXSLOT_ALLPARAMETERS);
if (support) support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_FXSlot3, EAXFXSLOT_ALLPARAMETERS);
if (support) support = querySupportEAX4(FMOD_EAXPROPERTYID_EAX40_Source, EAXSOURCE_ALLPARAMETERS);
if (support)
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "EAX 4.0 - success\n"));
}
else
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "failed (2).\n"));
return false;
}
/*
Turn down reverb to start with
*/
{
long room = EAXREVERB_MINROOM;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "setting reverb environment to OFF\n"));
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
hr = mBufferReverb->Set(guid, EAXREVERB_ROOM, 0, 0, &room, sizeof(long));
if (FAILED(hr))
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "failed (3).\n"));
return false;
}
}
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initEAX4", "found!\n"));
return true;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::closeEAX4()
{
GUID guid;
long lock = EAXFXSLOT_UNLOCKED;
if (mBufferReverb)
{
/*
Unlock FX slots
*/
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
mBufferReverb->Set(guid, EAXFXSLOT_LOCKED, 0, 0, &lock, sizeof(long));
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
mBufferReverb->Set(guid, EAXFXSLOT_LOCKED, 0, 0, &lock, sizeof(long));
mBufferReverb->Release();
mBufferReverb = NULL;
}
if (mSampleReverb)
{
mSampleReverb->release();
mSampleReverb = NULL;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::setPropertiesEAX4(const FMOD_REVERB_PROPERTIES *prop)
{
HRESULT hr;
EAXREVERBPROPERTIES eaxprop = {0};
EAXFXSLOTPROPERTIES fxslot;
GUID guid;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
switch(prop->Instance)
{
case 1:
{
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
if (!gFXslot2set)
{
FMOD_memcpy(&fxslot.guidLoadEffect, &FMOD_EAX_REVERB_EFFECT, sizeof(GUID));
fxslot.lLock = EAXFXSLOT_LOCKED;
fxslot.lVolume = 0;
fxslot.ulFlags = EAXFXSLOTFLAGS_ENVIRONMENT;
hr = mBufferReverb->Set(guid, EAXFXSLOT_ALLPARAMETERS, NULL, 0, &fxslot, sizeof(EAXFXSLOTPROPERTIES));
if (FAILED(hr))
{
ULONG ulReceived;
GUID effect;
/*
Check if the slot contains a reverb. If so, we can still use that slot.
*/
hr = mBufferReverb->Get(guid, EAXFXSLOT_LOADEFFECT, NULL, 0, &effect, sizeof(GUID), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_REVERB_INSTANCE;
}
if (memcmp(&effect, &fxslot.guidLoadEffect, sizeof(GUID)))
{
return FMOD_ERR_REVERB_INSTANCE;
}
}
gFXslot2set = true;
}
break;
}
case 2:
{
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
if (!gFXslot3set)
{
FMOD_memcpy(&fxslot.guidLoadEffect, &FMOD_EAX_REVERB_EFFECT, sizeof(GUID));
fxslot.lLock = EAXFXSLOT_LOCKED;
fxslot.lVolume = 0;
fxslot.ulFlags = EAXFXSLOTFLAGS_ENVIRONMENT;
hr = mBufferReverb->Set(guid, EAXFXSLOT_ALLPARAMETERS, NULL, 0, &fxslot, sizeof(EAXFXSLOTPROPERTIES));
if (FAILED(hr))
{
ULONG ulReceived;
GUID effect;
/*
Check if the slot contains a reverb. If so, we can still use that slot.
*/
hr = mBufferReverb->Get(guid, EAXFXSLOT_LOADEFFECT, NULL, 0, &effect, sizeof(GUID), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_REVERB_INSTANCE;
}
if (memcmp(&effect, &fxslot.guidLoadEffect, sizeof(GUID)))
{
return FMOD_ERR_REVERB_INSTANCE;
}
}
gFXslot3set = true;
}
break;
}
default:
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
break;
}
eaxprop.ulEnvironment = prop->Environment < 0 ? 0 : prop->Environment;
eaxprop.flEnvironmentSize = prop->EnvSize;
eaxprop.flEnvironmentDiffusion = prop->EnvDiffusion;
eaxprop.lRoom = prop->Room;
eaxprop.lRoomHF = prop->RoomHF;
eaxprop.lRoomLF = prop->RoomLF;
eaxprop.flDecayTime = prop->DecayTime;
eaxprop.flDecayHFRatio = prop->DecayHFRatio;
eaxprop.flDecayLFRatio = prop->DecayLFRatio;
eaxprop.lReflections = prop->Reflections;
eaxprop.flReflectionsDelay = prop->ReflectionsDelay;
eaxprop.vReflectionsPan.x = prop->ReflectionsPan[0];
eaxprop.vReflectionsPan.y = prop->ReflectionsPan[1];
eaxprop.vReflectionsPan.z = prop->ReflectionsPan[2];
eaxprop.lReverb = prop->Reverb;
eaxprop.flReverbDelay = prop->ReverbDelay;
eaxprop.vReverbPan.x = prop->ReverbPan[0];
eaxprop.vReverbPan.y = prop->ReverbPan[1];
eaxprop.vReverbPan.z = prop->ReverbPan[2];
eaxprop.flEchoTime = prop->EchoTime;
eaxprop.flEchoDepth = prop->EchoDepth;
eaxprop.flModulationTime = prop->ModulationTime;
eaxprop.flModulationDepth = prop->ModulationDepth;
eaxprop.flAirAbsorptionHF = prop->AirAbsorptionHF;
eaxprop.flHFReference = prop->HFReference;
eaxprop.flLFReference = prop->LFReference;
eaxprop.flRoomRolloffFactor = prop->RoomRolloffFactor;
eaxprop.ulFlags = prop->Flags & 0xFF;
hr = mBufferReverb->Set(guid, EAXREVERB_ALLPARAMETERS, NULL, 0, &eaxprop, sizeof(EAXREVERBPROPERTIES));
if (FAILED(hr))
{
return FMOD_ERR_INVALID_PARAM;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::getPropertiesEAX4(FMOD_REVERB_PROPERTIES *prop)
{
HRESULT hr;
EAXREVERBPROPERTIES eaxprop;
ULONG ulReceived;
GUID guid;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
switch(prop->Instance)
{
case 1:
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
break;
case 2:
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
break;
default:
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
break;
}
hr = mBufferReverb->Get(guid, EAXREVERB_ALLPARAMETERS, NULL, 0, &eaxprop, sizeof(EAXREVERBPROPERTIES), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_UNSUPPORTED;
}
prop->Environment = eaxprop.ulEnvironment ;
prop->EnvSize = eaxprop.flEnvironmentSize ;
prop->EnvDiffusion = eaxprop.flEnvironmentDiffusion ;
prop->Room = eaxprop.lRoom ;
prop->RoomHF = eaxprop.lRoomHF ;
prop->RoomLF = eaxprop.lRoomLF ;
prop->DecayTime = eaxprop.flDecayTime ;
prop->DecayHFRatio = eaxprop.flDecayHFRatio ;
prop->DecayLFRatio = eaxprop.flDecayLFRatio ;
prop->Reflections = eaxprop.lReflections ;
prop->ReflectionsDelay = eaxprop.flReflectionsDelay ;
prop->ReflectionsPan[0] = eaxprop.vReflectionsPan.x ;
prop->ReflectionsPan[1] = eaxprop.vReflectionsPan.y ;
prop->ReflectionsPan[2] = eaxprop.vReflectionsPan.z ;
prop->Reverb = eaxprop.lReverb ;
prop->ReverbDelay = eaxprop.flReverbDelay ;
prop->ReverbPan[0] = eaxprop.vReverbPan.x ;
prop->ReverbPan[1] = eaxprop.vReverbPan.y ;
prop->ReverbPan[2] = eaxprop.vReverbPan.z ;
prop->EchoTime = eaxprop.flEchoTime ;
prop->EchoDepth = eaxprop.flEchoDepth ;
prop->ModulationTime = eaxprop.flModulationTime ;
prop->ModulationDepth = eaxprop.flModulationDepth ;
prop->AirAbsorptionHF = eaxprop.flAirAbsorptionHF ;
prop->HFReference = eaxprop.flHFReference ;
prop->LFReference = eaxprop.flLFReference ;
prop->RoomRolloffFactor = eaxprop.flRoomRolloffFactor ;
prop->Flags = eaxprop.ulFlags ;
return FMOD_OK;
}
}
#endif /* FMOD_SUPPORT_EAX */

View file

@ -0,0 +1,348 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_I3DL2
#include "fmod.h"
#include "fmod_3dl2.h"
#include "fmod_localcriticalsection.h"
#include "fmod_output_dsound.h"
#include "fmod_sample_dsound.h"
#include "fmod_systemi.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
bool OutputDSound::querySupportI3DL2(unsigned int ulQuery)
{
unsigned long ulSupport = 0;
HRESULT hr;
GUID guid;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportI3DL2", "check properties %08X\n", ulQuery));
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_I3DL2_ListenerProperties, sizeof(GUID));
hr = mBufferReverb->QuerySupport(guid, ulQuery, &ulSupport);
if ( FAILED(hr) )
{
return false;
}
if ( (ulSupport&(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET)) ==
(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET) )
{
mFeaturesReverb |= (DWORD)(1 << ulQuery);
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::querySupportI3DL2", "success\n"));
return true;
}
return false;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
bool OutputDSound::initI3DL2()
{
FMOD_RESULT result;
ULONG support = 0;
HRESULT hr = DS_OK;
GUID guid;
FMOD_CODEC_WAVEFORMAT waveformat;
if (mBufferReverb)
{
mBufferReverb->Release();
mBufferReverb = 0;
}
/*
Create I3DL2 sample
*/
FMOD_memset(&waveformat, 0, sizeof(FMOD_CODEC_WAVEFORMAT));
waveformat.frequency = 44100;
waveformat.lengthpcm = 1024;
waveformat.channels = 1;
waveformat.format = FMOD_SOUND_FORMAT_PCM16;
result = createSample(FMOD_3D | FMOD_UNIQUE, &waveformat, (Sample **)&mSampleReverb);
if (result != FMOD_OK)
{
return false;
}
/*
OBTAIN I3DL2 INTERFACE TO BUFFER
*/
FMOD_memcpy(&guid, &FMOD_IID_IKsPropertySet, sizeof(GUID));
if(mSampleReverb->mBuffer3D->QueryInterface(guid, (void **)&mBufferReverb) != DS_OK)
{
mBufferReverb = 0;
return false;
}
/*
QUERY FOR I3DL2 support
*/
support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_ALL);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_ROOM);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_ROOMHF);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_ROOMROLLOFFFACTOR);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_DECAYTIME);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_DECAYHFRATIO);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_REFLECTIONS);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_REFLECTIONSDELAY);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_REVERB);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_REVERBDELAY);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_DIFFUSION);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_DENSITY);
if (support) support = querySupportI3DL2(DSPROPERTY_I3DL2LISTENER_HFREFERENCE);
if (support)
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initI3DL2", "I3DL2 - success\n"));
}
else
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initI3DL2", "I3DL2 - FAIL\n"));
}
if (!mFeaturesReverb)
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::initI3DL2", "failed I3DL2 check, releasing reverb interface\n"));
return false;
}
/*
Turn down reverb to start with.
*/
if ((mFeaturesReverb & (DWORD)1 << DSPROPERTY_I3DL2LISTENER_ROOM))
{
DWORD Room = I3DL2LISTENER_MINROOM;
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_I3DL2_ListenerProperties, sizeof(GUID));
hr = mBufferReverb->Set(guid, DSPROPERTY_I3DL2LISTENER_ROOM, 0, 0, &Room, sizeof(DWORD));
}
return true;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::closeI3DL2()
{
if (mBufferReverb)
{
/*
Turn down reverb again
*/
if ((mFeaturesReverb & (DWORD)1 << DSPROPERTY_I3DL2LISTENER_ROOM))
{
GUID guid;
DWORD Room = I3DL2LISTENER_MINROOM;
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_I3DL2_ListenerProperties, sizeof(GUID));
mBufferReverb->Set(guid, DSPROPERTY_I3DL2LISTENER_ROOM, 0, 0, &Room, sizeof(DWORD));
}
mBufferReverb->Release();
mBufferReverb = 0;
}
if (mSampleReverb)
{
mSampleReverb->release();
mSampleReverb = 0;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::setPropertiesI3DL2(const FMOD_REVERB_PROPERTIES *prop)
{
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesI3DL2", "Entering \n"));
if ( !(mFeaturesReverb & (DWORD)1 << DSPROPERTY_I3DL2LISTENER_ALL) )
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesI3DL2", "failed - apparently DSPROPERTY_I3DL2LISTENER_ALL isnt supported\n"));
return FMOD_ERR_UNSUPPORTED;
}
if (mFeaturesReverb & (DWORD)1 << DSPROPERTY_I3DL2LISTENER_ALL)
{
HRESULT hr;
I3DL2_LISTENERPROPERTIES dsprop = {0};
GUID guid;
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesI3DL2", "setting listener properties\n"));
dsprop.lRoom = prop->Room;
dsprop.lRoomHF = prop->RoomHF;
dsprop.flRoomRolloffFactor = prop->RoomRolloffFactor;
dsprop.flDecayTime = prop->DecayTime;
dsprop.flDecayHFRatio = prop->DecayHFRatio;
dsprop.lReflections = prop->Reflections;
dsprop.flReflectionsDelay = prop->ReflectionsDelay;
dsprop.lReverb = prop->Reverb;
dsprop.flReverbDelay = prop->ReverbDelay;
dsprop.flDiffusion = prop->Diffusion;
dsprop.flDensity = prop->Density;
dsprop.flHFReference = prop->HFReference;
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_I3DL2_ListenerProperties, sizeof(GUID));
hr = mBufferReverb->Set(guid, DSPROPERTY_I3DL2LISTENER_ALL, 0, 0, &dsprop, sizeof(I3DL2_LISTENERPROPERTIES));
if (FAILED(hr))
{
FLOG((FMOD_DEBUG_LEVEL_ALL, __FILE__, __LINE__, "OutputDSound::setPropertiesEAX2", "setting listener properties FAILED\n"));
return FMOD_ERR_INVALID_PARAM;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::getPropertiesI3DL2(FMOD_REVERB_PROPERTIES *prop)
{
ULONG ulReceived;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
if ( !(mFeaturesReverb & (DWORD)1 << DSPROPERTY_I3DL2LISTENER_ALL) )
{
return FMOD_ERR_UNSUPPORTED;
}
if ((mFeaturesReverb & (DWORD)1 << DSPROPERTY_I3DL2LISTENER_ALL))
{
GUID guid;
HRESULT hr;
I3DL2_LISTENERPROPERTIES dsprop = {0};
FMOD_memcpy(&guid, &FMOD_DSPROPSETID_I3DL2_ListenerProperties, sizeof(GUID));
hr = mBufferReverb->Get(guid, DSPROPERTY_I3DL2LISTENER_ALL, 0, 0, &dsprop, sizeof(I3DL2_LISTENERPROPERTIES), &ulReceived);
if (FAILED(hr))
{
return FMOD_ERR_UNSUPPORTED;
}
prop->Environment = 0;
prop->EnvSize = 0;
prop->EnvDiffusion = 0;
prop->Room = dsprop.lRoom;
prop->RoomHF = dsprop.lRoomHF;
prop->RoomLF = 0;
prop->DecayTime = dsprop.flDecayTime;
prop->DecayHFRatio = dsprop.flDecayHFRatio;
prop->DecayLFRatio = 0;
prop->Reflections = dsprop.lReflections;
prop->ReflectionsDelay = dsprop.flReflectionsDelay;
prop->ReflectionsPan[0] = 0;
prop->ReflectionsPan[1] = 0;
prop->ReflectionsPan[2] = 0;
prop->Reverb = dsprop.lReverb;
prop->ReverbDelay = dsprop.flReverbDelay;
prop->ReverbPan[0] = 0;
prop->ReverbPan[1] = 0;
prop->ReverbPan[2] = 0;
prop->EchoTime = 0;
prop->EchoDepth = 0;
prop->ModulationTime = 0;
prop->ModulationDepth = 0;
prop->AirAbsorptionHF = 0;
prop->HFReference = dsprop.flHFReference;
prop->LFReference = 0;
prop->RoomRolloffFactor = dsprop.flRoomRolloffFactor;
prop->Flags = 0;
prop->Density = dsprop.flDensity;
prop->Diffusion = dsprop.flDiffusion;
}
return FMOD_OK;
}
}
#endif /* FMOD_SUPPORT_I3DL2 */

View file

@ -0,0 +1,546 @@
#include "fmod_settings.h"
#if defined(FMOD_SUPPORT_DSOUND) && defined(FMOD_SUPPORT_RECORDING)
#include "fmod.hpp"
#include "fmod_output_dsound.h"
#include "fmod_soundi.h"
#include "fmod_stringw.h"
#include "fmod_codec_wav.h"
#include <dxsdkver.h>
#if (_DXSDK_PRODUCT_MAJOR < 9 || (_DXSDK_PRODUCT_MAJOR == 9 && _DXSDK_PRODUCT_MINOR < 21))
#include <dplay.h> /* This defines DWORD_PTR for dsound.h to use. */
#endif
#include <dsound.h>
namespace FMOD
{
static const FMOD_GUID KSDATAFORMAT_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010, { 0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71} };
static const FMOD_GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010, { 0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71} };
/*
[
[DESCRIPTION]
Callback to enumerate each found input driver
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
The first enumerated driver is skipped as it has no GUID, (it's a duplicate
anyway), the next driver enumerated is always the default, therefore it will be
in element 0 of FMODs driver list as required.
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
BOOL CALLBACK FMOD_Output_DSound_RecordEnumProc(LPGUID lpGUID, LPCWSTR lpszDesc, LPCWSTR lpszDrvName, LPVOID lpContext)
{
FMOD::OutputDSound *outputdsound = (FMOD::OutputDSound *)lpContext;
// Don't allow more drivers than the maximum number of drivers
if (outputdsound->mRecordNumDrivers < FMOD_OUTPUT_MAXDRIVERS)
{
// Don't add pseudo driver "Primary..." (no GUID), it is just a dupe anyway
if (lpGUID)
{
outputdsound->mRecordDriverName[outputdsound->mRecordNumDrivers] = (short *)FMOD_Memory_Calloc((FMOD_strlenW((short *)lpszDesc) + 1) * sizeof(short));
if (outputdsound->mRecordDriverName[outputdsound->mRecordNumDrivers])
{
FMOD_strncpyW(outputdsound->mRecordDriverName[outputdsound->mRecordNumDrivers], (short *)lpszDesc, FMOD_strlenW((short *)lpszDesc));
}
FMOD_memcpy(&outputdsound->mRecordGUID[outputdsound->mRecordNumDrivers], lpGUID, sizeof(GUID));
{
short driverName[FMOD_STRING_MAXNAMELEN] = {0};
FMOD_strncpyW(driverName, (short *)lpszDesc, FMOD_STRING_MAXNAMELEN);
FMOD_wtoa(driverName);
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "FMOD_Output_DSound_RecordEnumProc", "Enumerating \"%s\"\n", driverName));
}
outputdsound->mRecordNumDrivers++;
}
}
return TRUE;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::recordEnumerate()
{
FMOD_RESULT result;
if (mRecordEnumerated)
{
return FMOD_OK;
}
result = registerDLL();
if (result != FMOD_OK)
{
return result;
}
for (int i = 0; i < mRecordNumDrivers; i++)
{
if (mRecordDriverName[i])
{
FMOD_Memory_Free(mRecordDriverName[i]);
mRecordDriverName[i] = NULL;
}
}
mRecordNumDrivers = 0;
if (mDirectSoundCaptureEnumerate)
{
(*mDirectSoundCaptureEnumerate)((LPDSENUMCALLBACKW)FMOD_Output_DSound_RecordEnumProc, (void *)this);
}
mRecordEnumerated = true;
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::recordGetNumDrivers(int *numdrivers)
{
if (!numdrivers)
{
return FMOD_ERR_INVALID_PARAM;
}
if (!mRecordEnumerated)
{
FMOD_RESULT result;
result = recordEnumerate();
if (result != FMOD_OK)
{
return result;
}
}
*numdrivers = mRecordNumDrivers;
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::recordGetDriverInfo(int id, char *name, int namelen, FMOD_GUID *guid)
{
if (!mRecordEnumerated)
{
FMOD_RESULT result;
result = recordEnumerate();
if (result != FMOD_OK)
{
return result;
}
}
if (id < 0 || id >= mRecordNumDrivers)
{
return FMOD_ERR_INVALID_PARAM;
}
if (name && namelen >= 1)
{
short driverName[FMOD_STRING_MAXNAMELEN] = {0};
FMOD_strncpyW(driverName, mRecordDriverName[id], FMOD_STRING_MAXNAMELEN - 1);
FMOD_wtoa(driverName);
FMOD_strncpy(name, (char *)driverName, namelen - 1);
name[namelen - 1] = 0;
}
if (guid)
{
FMOD_memcpy(guid, &mRecordGUID[id], sizeof(FMOD_GUID));
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::recordGetDriverInfoW(int id, short *name, int namelen, FMOD_GUID *guid)
{
if (!mRecordEnumerated)
{
FMOD_RESULT result;
result = recordEnumerate();
if (result != FMOD_OK)
{
return result;
}
}
if (id < 0 || id >= mRecordNumDrivers)
{
return FMOD_ERR_INVALID_PARAM;
}
if (name && namelen >= 1)
{
FMOD_strncpyW(name, mRecordDriverName[id], namelen - 1);
name[namelen - 1] = 0;
}
if (guid)
{
FMOD_memcpy(guid, &mRecordGUID[id], sizeof(FMOD_GUID));
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::recordStart(FMOD_RECORDING_INFO *recordinfo, Sound *sound, bool loop)
{
FMOD_RESULT result;
DSCBUFFERDESC dscbd;
WAVE_FORMATEXTENSIBLE wfx;
SoundI *soundi;
int bits;
HRESULT hr;
FMOD_DSoundRecordMembers *recordMembers = NULL;
soundi = (SoundI *)sound;
if (!soundi)
{
return FMOD_ERR_INVALID_PARAM;
}
result = registerDLL();
if (result != FMOD_OK)
{
return result;
}
if (!mDirectSoundCaptureCreate)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
recordinfo->mRecordPlatformSpecific = recordMembers = (FMOD_DSoundRecordMembers *)FMOD_Object_Calloc(FMOD_DSoundRecordMembers);
if (recordMembers == NULL)
{
return FMOD_ERR_MEMORY;
}
// ========================================================================================================
// CREATE CAPTURE SYSTEM
// ========================================================================================================
hr = (*mDirectSoundCaptureCreate)(&mRecordGUID[recordinfo->mRecordId], &recordMembers->mDirectSoundCapture, 0);
if (hr != DS_OK)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
// ========================================================================================================
// CREATE AND START CAPTURE BUFFER
// ========================================================================================================
recordinfo->mRecordFormat = soundi->mFormat;
recordinfo->mRecordChannels = soundi->mChannels;
recordinfo->mRecordBufferLength = soundi->mLength;
recordinfo->mRecordRate = (int)soundi->mDefaultFrequency;
SoundI::getBitsFromFormat(recordinfo->mRecordFormat, &bits);
FMOD_memset(&wfx, 0, sizeof(WAVE_FORMATEXTENSIBLE));
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wfx.Format.nChannels = recordinfo->mRecordChannels;
wfx.Format.wBitsPerSample = bits;
wfx.Format.nBlockAlign = wfx.Format.nChannels * wfx.Format.wBitsPerSample / 8;
wfx.Format.nSamplesPerSec = recordinfo->mRecordRate;
wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
wfx.Format.cbSize = 22; // Designates extra data
wfx.Samples.wValidBitsPerSample = bits;
FMOD_memcpy(&wfx.SubFormat, (soundi->mFormat == FMOD_SOUND_FORMAT_PCMFLOAT ? &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT : &KSDATAFORMAT_SUBTYPE_PCM), sizeof(GUID));
dscbd.dwSize = sizeof(DSCBUFFERDESC);
dscbd.dwFlags = 0;
dscbd.dwBufferBytes = recordinfo->mRecordBufferLength * wfx.Format.nBlockAlign;
dscbd.dwReserved = 0;
dscbd.lpwfxFormat = (WAVEFORMATEX*)&wfx;
dscbd.dwFXCount = 0;
dscbd.lpDSCFXDesc = 0;
hr = recordMembers->mDirectSoundCapture->CreateCaptureBuffer(&dscbd, &recordMembers->mDirectSoundCaptureBuffer, 0);
if (hr != DS_OK)
{
return FMOD_ERR_FORMAT;
}
hr = recordMembers->mDirectSoundCaptureBuffer->Start(loop);
if (hr != DS_OK)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::recordStop(FMOD_RECORDING_INFO *recordinfo)
{
FMOD_DSoundRecordMembers *recordMembers = (FMOD_DSoundRecordMembers *)recordinfo->mRecordPlatformSpecific;
if (recordinfo)
{
if (recordMembers->mDirectSoundCaptureBuffer)
{
recordMembers->mDirectSoundCaptureBuffer->Stop();
recordMembers->mDirectSoundCaptureBuffer->Release();
recordMembers->mDirectSoundCaptureBuffer = 0;
}
if (recordMembers->mDirectSoundCapture)
{
recordMembers->mDirectSoundCapture->Release();
recordMembers->mDirectSoundCapture = 0;
}
FMOD_Memory_Free(recordinfo->mRecordPlatformSpecific);
recordinfo->mRecordPlatformSpecific = 0;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::recordGetPosition(FMOD_RECORDING_INFO *recordinfo, unsigned int *pcm)
{
FMOD_RESULT result;
HRESULT hr = DS_OK;
unsigned int position = 0, lengthbytes;
FMOD_SOUND_FORMAT format;
int bits, channels;
FMOD_DSoundRecordMembers *recordMembers = (FMOD_DSoundRecordMembers *)recordinfo->mRecordPlatformSpecific;
if (!recordMembers->mDirectSoundCaptureBuffer)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
hr = recordMembers->mDirectSoundCaptureBuffer->GetCurrentPosition(0, (LPDWORD)&position);
if (hr != DS_OK)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
result = recordinfo->mRecordSound->getLength(&lengthbytes, FMOD_TIMEUNIT_PCMBYTES);
if (result != FMOD_OK)
{
return result;
}
result = recordinfo->mRecordSound->getFormat(0, &format, &channels, &bits);
if (result != FMOD_OK)
{
return result;
}
if (position >= lengthbytes)
{
*pcm = 0;
return FMOD_ERR_OUTPUT_DRIVERCALL;;
}
position *= 8;
position /= bits;
position /= channels;
if (pcm)
{
*pcm = position;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::recordLock(FMOD_RECORDING_INFO *recordinfo, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2)
{
FMOD_DSoundRecordMembers *recordMembers = (FMOD_DSoundRecordMembers *)recordinfo->mRecordPlatformSpecific;
recordMembers->mDirectSoundCaptureBuffer->Lock(offset, length, ptr1, (DWORD *)len1, ptr2, (DWORD *)len2, 0);
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputDSound::recordUnlock(FMOD_RECORDING_INFO *recordinfo, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2)
{
FMOD_DSoundRecordMembers *recordMembers = (FMOD_DSoundRecordMembers *)recordinfo->mRecordPlatformSpecific;
recordMembers->mDirectSoundCaptureBuffer->Unlock(ptr1, len1, ptr2, len2);
return FMOD_OK;
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,132 @@
#ifndef _FMOD_OUTPUT_OPENAL_H
#define _FMOD_OUTPUT_OPENAL_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#include "fmod_systemi.h"
#include "fmod_output_timer.h"
#include "fmod_output_dsound.h"
#include "../../lib/openal/utils/LoadOAL.h"
namespace FMOD
{
typedef ALenum (*EAXSet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint);
typedef ALenum (*EAXGet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint);
typedef ALboolean (*EAXSetBufferMode)(ALsizei n, ALuint *buffers, ALint value);
typedef ALenum (*EAXGetBufferMode)(ALuint buffer, ALint *value);
typedef struct
{
bool used;
ALuint sid;
ALuint *bid;
} SourceOpenAL;
class OutputOpenAL : public OutputTimer
{
friend class SampleOpenAL;
friend class ChannelOpenAL;
friend class ChannelOpenALEAX2;
friend class ChannelOpenALEAX3;
friend class ChannelOpenALEAX4;
friend class ChannelOpenALEAX5;
private:
OPENALFNTABLE mOALFnTable;
bool mSetupOnce;
bool mInitialised;
bool mDLLInitialised;
ALCdevice *mDevice;
ALCcontext *mContext;
int mNumDrivers;
char *mDriverNames[FMOD_OUTPUT_MAXDRIVERS];
int mNumBuffers;
unsigned int mBufferLength;
unsigned int mBufferLengthBytes;
unsigned int mPcmBase;
char *mBufferData;
int mNumChannels;
ChannelOpenAL *mChannels;
int mNumSources;
SourceOpenAL *mSources;
unsigned int mMixerSourceOffset;
int mRate;
FMOD_SOUND_FORMAT mFormat;
ALuint mFormatOAL;
int mNumHwChannels;
int mOutputChannels;
REVERB_VERSION mReverbVersion;
bool mMixerReverbDisabled;
EAXSet mEAXSet;
EAXGet mEAXGet;
EAXSetBufferMode mEAXSetBufferMode;
EAXGetBufferMode mEAXGetBufferMode;
// Private methods
FMOD_RESULT registerDLL ();
FMOD_RESULT enumerate ();
FMOD_RESULT initEAX ();
FMOD_RESULT setupSessionEAX5 ();
FMOD_RESULT getSpeakerModeEAX5 (FMOD_SPEAKERMODE *speakerMode);
FMOD_RESULT lockSlotEAX4 (GUID &slotGUID);
FMOD_RESULT lockSlotEAX5 (GUID &slotGUID);
FMOD_RESULT setPropertiesEAX2 (const FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT setPropertiesEAX3 (const FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT setPropertiesEAX4 (const FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT setPropertiesEAX5 (const FMOD_REVERB_PROPERTIES *prop);
public:
OutputOpenAL();
static FMOD_OUTPUT_DESCRIPTION_EX *getDescriptionEx();
// Public methods
FMOD_RESULT getFreeChannel (FMOD_MODE mode, ChannelReal **realchannel, int numchannels, int numsoundchannels, int *found);
FMOD_RESULT getNumDrivers (int *numdrivers);
FMOD_RESULT getDriverName (int id, char *name, int namelen);
FMOD_RESULT getDriverCapsEx (int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency, FMOD_SPEAKERMODE *controlpanelspeakermode, int *num2dchannels, int *num3dchannels, int *totalchannels);
FMOD_RESULT init (int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int dspnumbuffers, void *extradriverdata);
FMOD_RESULT close ();
FMOD_RESULT start ();
FMOD_RESULT stop ();
FMOD_RESULT getHandle (void **handle);
FMOD_RESULT update ();
FMOD_RESULT postMix ();
FMOD_RESULT getPosition (unsigned int *pcm);
FMOD_RESULT lock (unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
FMOD_RESULT unlock (void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
FMOD_RESULT createSample (FMOD_MODE mode, FMOD_CODEC_WAVEFORMAT *waveformat, Sample **sample);
FMOD_RESULT setReverbProperties (const FMOD_REVERB_PROPERTIES *prop);
int getSampleMaxChannels (FMOD_MODE mode, FMOD_SOUND_FORMAT format);
// Public callbacks
static FMOD_RESULT F_CALLBACK getNumDriversCallback (FMOD_OUTPUT_STATE *output, int *numdrivers);
static FMOD_RESULT F_CALLBACK getDriverNameCallback (FMOD_OUTPUT_STATE *output, int id, char *name, int namelen);
static FMOD_RESULT F_CALLBACK getDriverCapsExCallback (FMOD_OUTPUT_STATE *output, int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency, FMOD_SPEAKERMODE *controlpanelspeakermode, int *num2dchannels, int *num3dchannels, int *totalchannels);
static FMOD_RESULT F_CALLBACK initCallback (FMOD_OUTPUT_STATE *output, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int dspnumbuffers, void *extradriverdata);
static FMOD_RESULT F_CALLBACK closeCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK startCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK stopCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK getHandleCallback (FMOD_OUTPUT_STATE *output, void **handle);
static FMOD_RESULT F_CALLBACK updateCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK postMixCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK getPositionCallback (FMOD_OUTPUT_STATE *output, unsigned int *pcm);
static FMOD_RESULT F_CALLBACK lockCallback (FMOD_OUTPUT_STATE *output, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
static FMOD_RESULT F_CALLBACK unlockCallback (FMOD_OUTPUT_STATE *output, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
static FMOD_RESULT F_CALLBACK createSampleCallback (FMOD_OUTPUT_STATE *output, FMOD_MODE mode, FMOD_CODEC_WAVEFORMAT *waveformat, Sample **sample);
static FMOD_RESULT F_CALLBACK setReverbPropertiesCallback (FMOD_OUTPUT_STATE *output, const FMOD_REVERB_PROPERTIES *prop);
static int F_CALLBACK getSampleMaxChannelsCallback (FMOD_OUTPUT_STATE *output, FMOD_MODE mode, FMOD_SOUND_FORMAT format);
};
}
#endif /* #ifdef FMOD_SUPPORT_OPENAL */
#endif /* #ifndef _FMOD_OUTPUT_OPENAL_H */

View file

@ -0,0 +1,95 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_output_openal.h"
#include "fmod_eax2.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
Set properties for EAX2
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputOpenAL::setPropertiesEAX2(const FMOD_REVERB_PROPERTIES *prop)
{
GUID bufferGUID;
GUID listenerGUID;
EAXLISTENERPROPERTIES eaxProperties;
int room;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "OutputOpenAL::setPropertiesEAX2", "Setting reverb properties\n"));
/*
Make sure all reverb effects are disabled on the mixer sources
*/
if (!mMixerReverbDisabled)
{
room = -10000;
FMOD_memcpy(&bufferGUID, &FMOD_DSPROPSETID_EAX20_BufferProperties, sizeof(GUID));
// Only the first mixer source is technically used (multichannel source), but set all anyway
for (int i = mMixerSourceOffset; i < mNumSources; i++)
{
mEAXSet(&bufferGUID, DSPROPERTY_EAXBUFFER_ROOM, mSources[i].sid, &room, sizeof(int));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_INTERNAL;
}
}
mMixerReverbDisabled = true;
}
FMOD_memcpy(&listenerGUID, &FMOD_DSPROPSETID_EAX20_ListenerProperties, sizeof(GUID));
eaxProperties.flEnvironmentSize = prop->EnvSize;
eaxProperties.dwEnvironment = prop->Environment < 0 ? 0 : prop->Environment;
eaxProperties.flEnvironmentDiffusion = prop->EnvDiffusion;
eaxProperties.lRoom = prop->Room;
eaxProperties.lRoomHF = prop->RoomHF;
eaxProperties.flDecayTime = prop->DecayTime;
eaxProperties.flDecayHFRatio = prop->DecayHFRatio;
eaxProperties.lReflections = prop->Reflections;
eaxProperties.flReflectionsDelay = prop->ReflectionsDelay;
eaxProperties.lReverb = prop->Reverb;
eaxProperties.flReverbDelay = prop->ReverbDelay;
eaxProperties.flAirAbsorptionHF = prop->AirAbsorptionHF;
eaxProperties.flRoomRolloffFactor = prop->RoomRolloffFactor;
eaxProperties.dwFlags = prop->Flags & 0xFF; // Mask out FMOD specific flags, leaving only EAX flags
mEAXSet(&listenerGUID, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, 0, &eaxProperties, sizeof(EAXLISTENERPROPERTIES));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
FLOG((FMOD_DEBUG_LEVEL_ERROR, __FILE__, __LINE__, "OutputOpenAL::setPropertiesEAX2", "Error setting reverb properties\n"));
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
return FMOD_OK;
}
} /* namespace FMOD */
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */

View file

@ -0,0 +1,109 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_output_openal.h"
#include "fmod_eax3.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
Set properties for EAX3
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputOpenAL::setPropertiesEAX3(const FMOD_REVERB_PROPERTIES *prop)
{
GUID bufferGUID;
GUID listenerGUID;
EAXLISTENERPROPERTIES eaxProperties;
int room;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "OutputOpenAL::setPropertiesEAX3", "Setting reverb properties\n"));
/*
Make sure all reverb effects are disabled on the mixer sources
*/
if (!mMixerReverbDisabled)
{
room = -10000;
FMOD_memcpy(&bufferGUID, &FMOD_DSPROPSETID_EAX30_BufferProperties, sizeof(GUID));
// Only the first mixer source is technically used (multichannel source), but set all anyway
for (int i = mMixerSourceOffset; i < mNumSources; i++)
{
mEAXSet(&bufferGUID, DSPROPERTY_EAXBUFFER_ROOM, mSources[i].sid, &room, sizeof(int));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_INTERNAL;
}
}
mMixerReverbDisabled = true;
}
FMOD_memcpy(&listenerGUID, &FMOD_DSPROPSETID_EAX30_ListenerProperties, sizeof(GUID));
eaxProperties.ulEnvironment = prop->Environment < 0 ? 0 : prop->Environment;
eaxProperties.flEnvironmentSize = prop->EnvSize;
eaxProperties.flEnvironmentDiffusion = prop->EnvDiffusion;
eaxProperties.lRoom = prop->Room;
eaxProperties.lRoomHF = prop->RoomHF;
eaxProperties.lRoomLF = prop->RoomLF;
eaxProperties.flDecayTime = prop->DecayTime;
eaxProperties.flDecayHFRatio = prop->DecayHFRatio;
eaxProperties.flDecayLFRatio = prop->DecayLFRatio;
eaxProperties.lReflections = prop->Reflections;
eaxProperties.flReflectionsDelay = prop->ReflectionsDelay;
eaxProperties.vReflectionsPan.x = prop->ReflectionsPan[0];
eaxProperties.vReflectionsPan.y = prop->ReflectionsPan[1];
eaxProperties.vReflectionsPan.z = prop->ReflectionsPan[2];
eaxProperties.lReverb = prop->Reverb;
eaxProperties.flReverbDelay = prop->ReverbDelay;
eaxProperties.vReverbPan.x = prop->ReverbPan[0];
eaxProperties.vReverbPan.y = prop->ReverbPan[1];
eaxProperties.vReverbPan.z = prop->ReverbPan[2];
eaxProperties.flEchoTime = prop->EchoTime;
eaxProperties.flEchoDepth = prop->EchoDepth;
eaxProperties.flModulationTime = prop->ModulationTime;
eaxProperties.flModulationDepth = prop->ModulationDepth;
eaxProperties.flAirAbsorptionHF = prop->AirAbsorptionHF;
eaxProperties.flHFReference = prop->HFReference;
eaxProperties.flLFReference = prop->LFReference;
eaxProperties.flRoomRolloffFactor = prop->RoomRolloffFactor;
eaxProperties.ulFlags = prop->Flags & 0xFF; // Mask out FMOD specific flags, leaving only EAX flags
mEAXSet(&listenerGUID, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, 0, &eaxProperties, sizeof(EAXLISTENERPROPERTIES));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
FLOG((FMOD_DEBUG_LEVEL_ERROR, __FILE__, __LINE__, "OutputOpenAL::setPropertiesEAX3", "Error setting reverb properties\n"));
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
return FMOD_OK;
}
} /* namespace FMOD */
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */

View file

@ -0,0 +1,225 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_output_openal.h"
#include "fmod_eax4.h"
namespace FMOD
{
bool gEAX4LockedOALFxSlot2 = false;
bool gEAX4LockedOALFxSlot3 = false;
/*
[
[DESCRIPTION]
Attempt to lock an EAX slot
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputOpenAL::lockSlotEAX4(GUID &slotGUID)
{
int slotIsLocked;
EAXFXSLOTPROPERTIES fxSlot;
FMOD_memcpy(&fxSlot.guidLoadEffect, &FMOD_EAX_REVERB_EFFECT, sizeof(GUID));
/*
Check if this slot is locked
*/
mEAXGet(&slotGUID, EAXFXSLOT_LOCK, 0, &slotIsLocked, sizeof(int));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_REVERB_INSTANCE;
}
if (slotIsLocked)
{
GUID effect;
// Find out what type of effect is in the locked slot
mEAXGet(&slotGUID, EAXFXSLOT_LOADEFFECT, 0, &effect, sizeof(GUID));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_REVERB_INSTANCE;
}
// Check if the slot contains a reverb, if so we can still use that slot
if (memcmp(&effect, &fxSlot.guidLoadEffect, sizeof(GUID)))
{
return FMOD_ERR_REVERB_INSTANCE;
}
}
else // Slot isn't locked
{
fxSlot.lLock = EAXFXSLOT_LOCKED;
fxSlot.lVolume = EAXFXSLOT_DEFAULTVOLUME;
fxSlot.ulFlags = EAXFXSLOT_DEFAULTFLAGS;
// Lock the slot
mEAXSet(&slotGUID, EAXFXSLOT_ALLPARAMETERS, 0, &fxSlot, sizeof(EAXFXSLOTPROPERTIES));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_REVERB_INSTANCE;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Set properties for EAX4
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
With EAX4 the first slot is locked as reverb so we can still use it,
the second slot is locked as chorus, so it is no use to us, slots
3 and 4 are free to be tasked as reverb
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputOpenAL::setPropertiesEAX4(const FMOD_REVERB_PROPERTIES *prop)
{
GUID slotGUID;
GUID sourceGUID;
EAXREVERBPROPERTIES eaxProperties;
FMOD_RESULT result;
int room;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "OutputOpenAL::setPropertiesEAX4", "Setting reverb properties for instance: %d\n", prop->Instance));
/*
Make sure all reverb effects are disabled on the mixer sources
*/
if (!mMixerReverbDisabled)
{
room = -10000;
FMOD_memcpy(&sourceGUID, &FMOD_EAXPROPERTYID_EAX40_Source, sizeof(GUID));
// Only the first mixer source is technically used (multichannel source), but set all anyway
for (int i = mMixerSourceOffset; i < mNumSources; i++)
{
mEAXSet(&sourceGUID, EAXSOURCE_ROOM, mSources[i].sid, &room, sizeof(int));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_INTERNAL;
}
}
mMixerReverbDisabled = true;
}
/*
Each reverb instance is equivalent to a hardware effect slot,
attempt to lock that slot for use by FMOD
*/
switch (prop->Instance)
{
case 1:
{
FMOD_memcpy(&slotGUID, &FMOD_EAXPROPERTYID_EAX40_FXSlot2, sizeof(GUID));
if (!gEAX4LockedOALFxSlot2)
{
result = lockSlotEAX4(slotGUID);
if (result != FMOD_OK)
{
return result;
}
gEAX4LockedOALFxSlot2 = true;
}
break;
}
case 2:
{
FMOD_memcpy(&slotGUID, &FMOD_EAXPROPERTYID_EAX40_FXSlot3, sizeof(GUID));
if (!gEAX4LockedOALFxSlot3)
{
result = lockSlotEAX4(slotGUID);
if (result != FMOD_OK)
{
return result;
}
gEAX4LockedOALFxSlot3 = true;
}
break;
}
default:
{
FMOD_memcpy(&slotGUID, &FMOD_EAXPROPERTYID_EAX40_FXSlot0, sizeof(GUID));
}
}
eaxProperties.ulEnvironment = prop->Environment < 0 ? 0 : prop->Environment;
eaxProperties.flEnvironmentSize = prop->EnvSize;
eaxProperties.flEnvironmentDiffusion = prop->EnvDiffusion;
eaxProperties.lRoom = prop->Room;
eaxProperties.lRoomHF = prop->RoomHF;
eaxProperties.lRoomLF = prop->RoomLF;
eaxProperties.flDecayTime = prop->DecayTime;
eaxProperties.flDecayHFRatio = prop->DecayHFRatio;
eaxProperties.flDecayLFRatio = prop->DecayLFRatio;
eaxProperties.lReflections = prop->Reflections;
eaxProperties.flReflectionsDelay = prop->ReflectionsDelay;
eaxProperties.vReflectionsPan.x = prop->ReflectionsPan[0];
eaxProperties.vReflectionsPan.y = prop->ReflectionsPan[1];
eaxProperties.vReflectionsPan.z = prop->ReflectionsPan[2];
eaxProperties.lReverb = prop->Reverb;
eaxProperties.flReverbDelay = prop->ReverbDelay;
eaxProperties.vReverbPan.x = prop->ReverbPan[0];
eaxProperties.vReverbPan.y = prop->ReverbPan[1];
eaxProperties.vReverbPan.z = prop->ReverbPan[2];
eaxProperties.flEchoTime = prop->EchoTime;
eaxProperties.flEchoDepth = prop->EchoDepth;
eaxProperties.flModulationTime = prop->ModulationTime;
eaxProperties.flModulationDepth = prop->ModulationDepth;
eaxProperties.flAirAbsorptionHF = prop->AirAbsorptionHF;
eaxProperties.flHFReference = prop->HFReference;
eaxProperties.flLFReference = prop->LFReference;
eaxProperties.flRoomRolloffFactor = prop->RoomRolloffFactor;
eaxProperties.ulFlags = prop->Flags & 0xFF; // Mask out FMOD specific flags, leaving only EAX flags
mEAXSet(&slotGUID, EAXREVERB_ALLPARAMETERS, 0, &eaxProperties, sizeof(EAXREVERBPROPERTIES));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
FLOG((FMOD_DEBUG_LEVEL_ERROR, __FILE__, __LINE__, "OutputOpenAL::setPropertiesEAX4", "Error setting reverb properties\n"));
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
return FMOD_OK;
}
} /* namespace FMOD */
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */

View file

@ -0,0 +1,386 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#ifdef FMOD_SUPPORT_EAX
#include "fmod_output_openal.h"
#include "fmod_eax5.h"
namespace FMOD
{
bool gEAX5LockedOALFxSlot0 = false;
bool gEAX5LockedOALFxSlot1 = false;
bool gEAX5LockedOALFxSlot2 = false;
bool gEAX5LockedOALFxSlot3 = false;
/*
[
[DESCRIPTION]
Create an EAX5 session
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
A session must be created before using EAX5
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputOpenAL::setupSessionEAX5()
{
GUID guid;
EAXSESSIONPROPERTIES eaxSession;
eaxSession.ulEAXVersion = EAX_50;
eaxSession.ulMaxActiveSends = 2;
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX50_Context, sizeof(GUID));
mEAXSet(&guid, EAXCONTEXT_EAXSESSION, 0, &eaxSession, sizeof(EAXSESSIONPROPERTIES));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_INTERNAL;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Get the current speaker mode
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
This is called from getCaps, before the main device has been initialised
so we need to do EAX5 specific initialisation here for the temporary
device
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputOpenAL::getSpeakerModeEAX5(FMOD_SPEAKERMODE *speakerMode)
{
EAXGet eaxGet = NULL;
EAXSet eaxSet = NULL;
long oalSpeakerMode = 0;
GUID guid;
EAXSESSIONPROPERTIES eaxSession;
/*
Get the EAX function pointers
*/
eaxGet = (EAXGet)mOALFnTable.alGetProcAddress("EAXGet");
eaxSet = (EAXSet)mOALFnTable.alGetProcAddress("EAXSet");
if (!eaxGet || !eaxSet)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
/*
Create an EAX5 session here for the getCaps temporary OAL context
*/
eaxSession.ulEAXVersion = EAX_50;
eaxSession.ulMaxActiveSends = 2;
FMOD_memcpy(&guid, &FMOD_EAXPROPERTYID_EAX50_Context, sizeof(GUID));
eaxSet(&guid, EAXCONTEXT_EAXSESSION, 0, &eaxSession, sizeof(EAXSESSIONPROPERTIES));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
/*
Determine the speaker mode
*/
eaxGet(&guid, EAXCONTEXT_SPEAKERCONFIG, 0, &oalSpeakerMode, sizeof(long));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
switch (oalSpeakerMode)
{
case HEADPHONES:
case SPEAKERS_2:
{
*speakerMode = FMOD_SPEAKERMODE_STEREO;
break;
}
case SPEAKERS_4:
{
*speakerMode = FMOD_SPEAKERMODE_QUAD;
break;
}
case SPEAKERS_5:
{
*speakerMode = FMOD_SPEAKERMODE_5POINT1;
break;
}
case SPEAKERS_6:
{
*speakerMode = FMOD_SPEAKERMODE_RAW;
break;
}
case SPEAKERS_7:
{
*speakerMode = FMOD_SPEAKERMODE_7POINT1;
break;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Attempt to lock an EAX slot
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputOpenAL::lockSlotEAX5(GUID &slotGUID)
{
int slotIsLocked;
EAXFXSLOTPROPERTIES fxSlot;
FMOD_memcpy(&fxSlot.guidLoadEffect, &FMOD_EAX_REVERB_EFFECT, sizeof(GUID));
/*
Check if this slot is locked
*/
mEAXGet(&slotGUID, EAXFXSLOT_LOCK, 0, &slotIsLocked, sizeof(int));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_REVERB_INSTANCE;
}
if (slotIsLocked)
{
GUID effect;
// Find out what type of effect is in the locked slot
mEAXGet(&slotGUID, EAXFXSLOT_LOADEFFECT, 0, &effect, sizeof(GUID));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_REVERB_INSTANCE;
}
// Check if the slot contains a reverb, if so we can still use that slot
if (memcmp(&effect, &fxSlot.guidLoadEffect, sizeof(GUID)))
{
return FMOD_ERR_REVERB_INSTANCE;
}
}
else // Slot isn't locked
{
fxSlot.lLock = EAXFXSLOT_LOCKED;
fxSlot.lVolume = EAXFXSLOT_DEFAULTVOLUME;
fxSlot.ulFlags = EAXFXSLOT_DEFAULTFLAGS;
fxSlot.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION;
fxSlot.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO;
// Lock the slot
mEAXSet(&slotGUID, EAXFXSLOT_ALLPARAMETERS, 0, &fxSlot, sizeof(EAXFXSLOTPROPERTIES));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_REVERB_INSTANCE;
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
Set properties for EAX5
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
With EAX5 all four slots can be locked with reverb
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT OutputOpenAL::setPropertiesEAX5(const FMOD_REVERB_PROPERTIES *prop)
{
GUID slotGUID;
GUID sourceGUID;
EAXREVERBPROPERTIES eaxProperties;
FMOD_RESULT result;
int room;
if (!prop)
{
return FMOD_ERR_INVALID_PARAM;
}
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "OutputOpenAL::setPropertiesEAX5", "Setting reverb properties for instance: %d\n", prop->Instance));
/*
Make sure all reverb effects are disabled on the mixer sources
*/
if (!mMixerReverbDisabled)
{
room = -10000;
FMOD_memcpy(&sourceGUID, &FMOD_EAXPROPERTYID_EAX50_Source, sizeof(GUID));
// Only the first mixer source is technically used (multichannel source), but set all anyway
for (int i = mMixerSourceOffset; i < mNumSources; i++)
{
mEAXSet(&sourceGUID, EAXSOURCE_ROOM, mSources[i].sid, &room, sizeof(int));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
return FMOD_ERR_INTERNAL;
}
}
mMixerReverbDisabled = true;
}
/*
Each reverb instance is equivalent to a hardware effect slot,
attempt to lock that slot for use by FMOD
*/
switch (prop->Instance)
{
case 1:
{
FMOD_memcpy(&slotGUID, &FMOD_EAXPROPERTYID_EAX50_FXSlot1, sizeof(GUID));
if (!gEAX5LockedOALFxSlot1)
{
result = lockSlotEAX5(slotGUID);
if (result != FMOD_OK)
{
return result;
}
gEAX5LockedOALFxSlot1 = true;
}
break;
}
case 2:
{
FMOD_memcpy(&slotGUID, &FMOD_EAXPROPERTYID_EAX50_FXSlot2, sizeof(GUID));
if (!gEAX5LockedOALFxSlot2)
{
result = lockSlotEAX5(slotGUID);
if (result != FMOD_OK)
{
return result;
}
gEAX5LockedOALFxSlot2 = true;
}
break;
}
case 3:
{
FMOD_memcpy(&slotGUID, &FMOD_EAXPROPERTYID_EAX50_FXSlot3, sizeof(GUID));
if (!gEAX5LockedOALFxSlot3)
{
result = lockSlotEAX5(slotGUID);
if (result != FMOD_OK)
{
return result;
}
gEAX5LockedOALFxSlot3 = true;
}
break;
}
default:
{
FMOD_memcpy(&slotGUID, &FMOD_EAXPROPERTYID_EAX50_FXSlot0, sizeof(GUID));
if (!gEAX5LockedOALFxSlot0)
{
result = lockSlotEAX5(slotGUID);
if (result != FMOD_OK)
{
return result;
}
gEAX5LockedOALFxSlot0 = true;
}
}
}
FMOD_memset(&eaxProperties, 0, sizeof(EAXREVERBPROPERTIES));
eaxProperties.ulEnvironment = prop->Environment < 0 ? 0 : prop->Environment;
eaxProperties.flEnvironmentSize = prop->EnvSize;
eaxProperties.flEnvironmentDiffusion = prop->EnvDiffusion;
eaxProperties.lRoom = prop->Room;
eaxProperties.lRoomHF = prop->RoomHF;
eaxProperties.lRoomLF = prop->RoomLF;
eaxProperties.flDecayTime = prop->DecayTime;
eaxProperties.flDecayHFRatio = prop->DecayHFRatio;
eaxProperties.flDecayLFRatio = prop->DecayLFRatio;
eaxProperties.lReflections = prop->Reflections;
eaxProperties.flReflectionsDelay = prop->ReflectionsDelay;
eaxProperties.vReflectionsPan.x = prop->ReflectionsPan[0];
eaxProperties.vReflectionsPan.y = prop->ReflectionsPan[1];
eaxProperties.vReflectionsPan.z = prop->ReflectionsPan[2];
eaxProperties.lReverb = prop->Reverb;
eaxProperties.flReverbDelay = prop->ReverbDelay;
eaxProperties.vReverbPan.x = prop->ReverbPan[0];
eaxProperties.vReverbPan.y = prop->ReverbPan[1];
eaxProperties.vReverbPan.z = prop->ReverbPan[2];
eaxProperties.flEchoTime = prop->EchoTime;
eaxProperties.flEchoDepth = prop->EchoDepth;
eaxProperties.flModulationTime = prop->ModulationTime;
eaxProperties.flModulationDepth = prop->ModulationDepth;
eaxProperties.flAirAbsorptionHF = prop->AirAbsorptionHF;
eaxProperties.flHFReference = prop->HFReference;
eaxProperties.flLFReference = prop->LFReference;
eaxProperties.flRoomRolloffFactor = prop->RoomRolloffFactor;
eaxProperties.ulFlags = prop->Flags & 0xFF; // Mask out FMOD specific flags, leaving only EAX flags
mEAXSet(&slotGUID, EAXREVERB_ALLPARAMETERS, 0, &eaxProperties, sizeof(EAXREVERBPROPERTIES));
if (mOALFnTable.alGetError() != AL_NO_ERROR)
{
FLOG((FMOD_DEBUG_LEVEL_ERROR, __FILE__, __LINE__, "OutputOpenAL::setPropertiesEAX5", "Error setting reverb properties\n"));
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
return FMOD_OK;
}
} /* namespace FMOD */
#endif /* FMOD_SUPPORT_EAX */
#endif /* FMOD_SUPPORT_OPENAL */

View file

@ -0,0 +1,329 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_SOFTWARE
#include "fmod_output_timer.h"
#include "fmod_systemi.h"
// #define DUMPMIXERTODISK
#ifdef DUMPMIXERTODISK
#include <stdio.h>
static FILE *fp = 0;
#endif
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputTimer::timerFunc()
{
FMOD_RESULT result = FMOD_OK;
unsigned int playPosition = 0;
unsigned int blockSize = 0;
int numBlocks = 0;
FMOD_SOUND_FORMAT outputFormat = FMOD_SOUND_FORMAT_NONE;
int outputChannels = 0;
// Playing has stopped
if (!mPlaying)
{
return FMOD_OK;
}
// Attempt to apply a pro-audio thread characteristic to reduce stuttering
if (!mThreadElevated)
{
HANDLE (WINAPI *SetThreadTask)(LPCTSTR, LPDWORD);
FMOD_OS_LIBRARY *avrtHandle = NULL;
DWORD taskIndex = 0;
result = FMOD_OS_Library_Load("avrt.dll", &avrtHandle);
if (result == FMOD_OK) // If this fails, OS does not support setting thread characteristics
{
result = FMOD_OS_Library_GetProcAddress(avrtHandle, "AvSetMmThreadCharacteristicsA", (void **)&SetThreadTask);
if (result == FMOD_OK)
{
SetThreadTask("Pro Audio", &taskIndex);
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "OutputTimer::timerFunc", "Mixer thread set to 'Pro Audio' characteristic\n"));
FMOD_OS_Library_Free(avrtHandle);
}
}
mThreadElevated = true; // This will prevent reattempting to elevate if already elevated and if the OS doesn't support it
}
mSystem->mDSPTimeStamp.stampIn();
result = mSystem->getDSPBufferSize(&blockSize, &numBlocks);
if (result != FMOD_OK)
{
return result;
}
result = mSystem->getSoftwareFormat(0, &outputFormat, &outputChannels, 0, 0, 0);
if (result != FMOD_OK)
{
return result;
}
if (mDescription.getposition)
{
result = mDescription.getposition(this, &playPosition);
if (result != FMOD_OK)
{
return result;
}
}
// Determine which block is currently playing
playPosition /= blockSize;
playPosition %= numBlocks;
FLOG((FMOD_DEBUG_TYPE_THREAD, __FILE__, __LINE__, "OutputTimer::timerFunc", "Play block %8d, Fill block %8d\n", playPosition, mFillBlock));
while (mFillBlock != (int)playPosition)
{
void *ptr1 = NULL;
void *ptr2 = NULL;
unsigned int len1 = 0;
unsigned int len2 = 0;
unsigned int writePositionBytes = 0;
unsigned int blockSizeBytes = 0;
unsigned int samplesLocked = 0;
result = SoundI::getBytesFromSamples(blockSize, &blockSizeBytes, outputChannels, outputFormat);
if (result != FMOD_OK)
{
return result;
}
result = SoundI::getBytesFromSamples(mFillBlock * blockSize, &writePositionBytes, outputChannels, outputFormat);
if (result != FMOD_OK)
{
return result;
}
if (mDescription.lock)
{
result = mDescription.lock(this, writePositionBytes, blockSizeBytes, &ptr1, &ptr2, &len1, &len2);
if (result != FMOD_OK)
{
return result;
}
}
result = SoundI::getSamplesFromBytes(len1, &samplesLocked, outputChannels, outputFormat);
if (result != FMOD_OK)
{
return result;
}
result = mix(ptr1, samplesLocked);
if (result != FMOD_OK)
{
return result;
}
#ifdef DUMPMIXERTODISK
if (fp)
{
fwrite(ptr1, len1, 1, fp);
}
#endif
/*
ptr2 and len2 should never be non 0. All updates are block aligned.
*/
if (mDescription.unlock)
{
result = mDescription.unlock(this, ptr1, ptr2, len1, len2);
if (result != FMOD_OK)
{
return result;
}
}
mFillBlock++;
if (mFillBlock >= numBlocks)
{
mFillBlock = 0;
}
}
mSystem->mDSPTimeStamp.stampOut(95);
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputTimer::start()
{
FMOD_RESULT result = FMOD_OK;
unsigned int blockSize = 0;
int sampleRate = 0;
/*
Calculate the callback time for the mixer
*/
result = mSystem->getDSPBufferSize(&blockSize, NULL);
if (result != FMOD_OK)
{
return result;
}
result = mSystem->getSoftwareFormat(&sampleRate, NULL, NULL, NULL, NULL, NULL);
if (result != FMOD_OK)
{
return result;
}
mMixerTimerPeriod = (float)blockSize * 1000.0f / (float)sampleRate;
if (mMixerTimerPeriod < 20)
{
mMixerTimerPeriod /= 3;
if (mMixerTimerPeriod < 1)
{
mMixerTimerPeriod = 1;
}
}
else
{
mMixerTimerPeriod = 10;
}
FLOG((FMOD_DEBUG_TYPE_THREAD, __FILE__, __LINE__, "OutputTimer::start", "Starting timer callback that triggers every %d ms\n", (int)mMixerTimerPeriod));
mPlaying = true;
// Mixer update callback critical section
result = FMOD_OS_CriticalSection_Create(&mMixerCrit);
if (result != FMOD_OK)
{
return result;
}
// Setup the timed callback event
mThreadElevated = false;
mMixerTimerID = timeSetEvent((unsigned int)mMixerTimerPeriod, 0, (LPTIMECALLBACK)timerFuncCallback, (UINT_PTR)this, TIME_PERIODIC);
if (!mMixerTimerID)
{
FLOG((FMOD_DEBUG_LEVEL_ERROR, __FILE__, __LINE__, "OutputTimer::start", "timeSetEvent failed! Something is really wrong with your PC. timer period = %d ms\n", (int)mMixerTimerPeriod));
return FMOD_ERR_OUTPUT_INIT;
}
#ifdef DUMPMIXERTODISK
fp = fopen("/media/fmod4output.raw", "wb");
#endif
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT OutputTimer::stop()
{
FMOD_RESULT fResult = FMOD_OK;
HRESULT hResult = S_OK;
// Stop mixer callbacks
timeKillEvent(mMixerTimerID);
mMixerTimerID = 0;
// If timer still ticks a few times ensure the callback will do nothing
mPlaying = false;
// Ensure that the mixer is finish before returning (wont re-enter because of mPlaying)
FMOD_OS_CriticalSection_Enter(mMixerCrit);
#ifdef DUMPMIXERTODISK
if (fp)
{
fclose(fp);
fp = 0;
}
#endif
FMOD_OS_CriticalSection_Leave(mMixerCrit);
FMOD_OS_CriticalSection_Free(mMixerCrit);
mMixerCrit = NULL;
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
void CALLBACK OutputTimer::timerFuncCallback(UINT uTimerID, UINT uMsg, UINT_PTR dwUser, UINT_PTR dw1, UINT_PTR dw2)
{
OutputTimer *outputTimer = (OutputTimer *)dwUser;
FMOD_OS_CriticalSection_Enter(outputTimer->mMixerCrit);
outputTimer->timerFunc();
FMOD_OS_CriticalSection_Leave(outputTimer->mMixerCrit);
}
}
#endif

View file

@ -0,0 +1,37 @@
#ifndef _FMOD_OUTPUT_TIMER_H
#define _FMOD_OUTPUT_TIMER_H
#include "fmod_settings.h"
#include "fmod_outputi.h"
#include "fmod_codec_wav.h"
namespace FMOD
{
class OutputTimer : public Output
{
private:
float mMixerTimerPeriod;
unsigned int mMixerTimerID;
bool mPlaying;
bool mThreadElevated;
FMOD_OS_CRITICALSECTION *mMixerCrit;
FMOD_RESULT timerFunc();
static void CALLBACK timerFuncCallback(UINT uTimerID, UINT uMsg, UINT_PTR dwUser, UINT_PTR dw1, UINT_PTR dw2);
protected:
int mFillBlock;
public:
FMOD_RESULT start();
FMOD_RESULT stop();
};
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,171 @@
#ifndef _FMOD_OUTPUT_WASAPI_H
#define _FMOD_OUTPUT_WASAPI_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_WASAPI
#include "fmod_systemi.h"
#include "fmod_outputi.h"
#include "fmod_memorytracker.h"
#include "fmod_stringw.h"
// 0x0600 is Vista (safe since WASAPI output mode is only available on Vista)
#define _WIN32_WINNT 0x0601
#include <Windows.h>
#include "wasapi\fmod_audioclient.h"
#include "wasapi\fmod_mmdeviceapi.h"
namespace FMOD
{
typedef struct FMOD_WASAPIDriver
{
LPWSTR id;
short *name;
} FMOD_WASAPIDriver;
typedef struct FMOD_WASAPIRecordMembers
{
bool mRecordStereoToMono;
IAudioClient *mCaptureAudioClient;
IAudioCaptureClient *mCaptureClient;
UINT mCaptureBufferLength;
BYTE *mRecordBuffer;
int mRecordBlockAlign;
int mRecordWritePosition;
} FMOD_WASAPIRecordMembers;
class OutputWASAPI : public Output
{
DECLARE_MEMORYTRACKER_NONVIRTUAL
private:
/*
General variables
*/
bool mCoInitialized;
bool mInitialised;
bool mExclusiveMode;
/*
Render variables
*/
int mNumRenderDrivers;
FMOD_WASAPIDriver mRenderDrivers[FMOD_OUTPUT_MAXDRIVERS];
IAudioClient *mRenderAudioClient;
IAudioRenderClient *mRenderClient;
UINT mRenderBufferLength;
int mRenderBlockAlign;
FMOD_SOUND_FORMAT mRenderFormat;
int mRenderChannels;
HANDLE mFeederEventHandle;
bool mFeederThreadElevated;
Thread mFeederThread;
unsigned int mFeederTimeout;
Thread mMixerThread;
BYTE *mMixerBuffer;
int mMixerBufferLength;
UINT mMixerBufferBlockSize;
int mMixerBufferNumBlocks;
int mMixerReadPosition;
int mMixerWritePosition;
DSPResampler *mMixerResamplerDSP;
float *mMixerFormatConversionBuffer;
unsigned int mMixerFormatConversionBufferSizeBytes;
float *mMixerChannelConversionBuffer;
unsigned int mMixerChannelConversionBufferSizeBytes;
/*
Capture variables
*/
int mNumCaptureDrivers;
FMOD_WASAPIDriver mCaptureDrivers[FMOD_OUTPUT_MAXDRIVERS];
#ifdef FMOD_SUPPORT_RECORDING
HANDLE mRecordEventHandle;
bool mRecordThreadElevated;
Thread mRecordThread;
bool mRecordInitialised;
#endif
/*
Private methods
*/
FMOD_RESULT enumerateDefaultDevices (IMMDeviceEnumerator *pEnumerator);
FMOD_RESULT enumerate ();
FMOD_RESULT parseUUIDString (WCHAR *srcString, FMOD_GUID *destGUID);
FMOD_RESULT feederUpdate ();
FMOD_RESULT mixerUpdate ();
FMOD_RESULT channelConvert (float *outbuffer, float *inbuffer, int outchannels, int inchannels, int length);
FMOD_RESULT cleanUpEnumeration ();
#ifdef FMOD_SUPPORT_RECORDING
FMOD_RESULT recordUpdate ();
#endif
static void feederThreadCallback (void *userdata);
static void mixerThreadCallback (void *userdata);
#ifdef FMOD_SUPPORT_RECORDING
static void recordThreadCallback (void *userdata);
#endif
public:
static FMOD_OUTPUT_DESCRIPTION_EX *getDescriptionEx();
FMOD_RESULT getNumDrivers (int *numdrivers);
FMOD_RESULT getDriverInfo (int id, char *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT getDriverInfoW (int id, short *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT getDriverCapsEx (int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency, FMOD_SPEAKERMODE *controlpanelspeakermode);
FMOD_RESULT initEx (int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, FMOD_SPEAKERMODE *speakermode, int dspbufferlength, int dspnumbuffers, int max2dchannels, int max3dchannels, void *extradriverdata);
FMOD_RESULT close ();
FMOD_RESULT getHandle (void **handle);
FMOD_RESULT start ();
FMOD_RESULT stop ();
FMOD_RESULT mixerResampleRead (float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
#ifdef FMOD_SUPPORT_RECORDING
FMOD_RESULT recordGetNumDrivers (int *numdrivers);
FMOD_RESULT recordGetDriverInfo (int id, char *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT recordGetDriverInfoW (int id, short *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT recordGetDriverCaps (int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency);
FMOD_RESULT recordStart (FMOD_RECORDING_INFO *recordinfo, Sound *sound, bool loop);
FMOD_RESULT recordStop (FMOD_RECORDING_INFO *recordinfo);
FMOD_RESULT recordGetPosition (FMOD_RECORDING_INFO *recordinfo, unsigned int *pcm);
FMOD_RESULT recordLock (FMOD_RECORDING_INFO *recordinfo, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
#endif
static FMOD_RESULT F_CALLBACK getNumDriversCallback (FMOD_OUTPUT_STATE *output, int *numdrivers);
static FMOD_RESULT F_CALLBACK getDriverInfoCallback (FMOD_OUTPUT_STATE *output, int id, char *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK getDriverInfoWCallback (FMOD_OUTPUT_STATE *output, int id, short *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK getDriverCapsExCallback (FMOD_OUTPUT_STATE *output, int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency, FMOD_SPEAKERMODE *controlpanelspeakermode);
static FMOD_RESULT F_CALLBACK initExCallback (FMOD_OUTPUT_STATE *output, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, FMOD_SPEAKERMODE *speakermode, int dspbufferlength, int dspnumbuffers, int max2dchannels, int max3dchannels, void *extradriverdata);
static FMOD_RESULT F_CALLBACK closeCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK startCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK stopCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK getHandleCallback (FMOD_OUTPUT_STATE *output, void **handle);
static FMOD_RESULT F_CALLBACK mixerResampleReadCallback (FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
#ifdef FMOD_SUPPORT_RECORDING
static FMOD_RESULT F_CALLBACK recordGetNumDriversCallback (FMOD_OUTPUT_STATE *output, int *numdrivers);
static FMOD_RESULT F_CALLBACK recordGetDriverInfoCallback (FMOD_OUTPUT_STATE *output, int id, char *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK recordGetDriverInfoWCallback (FMOD_OUTPUT_STATE *output, int id, short *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK recordGetDriverCapsCallback (FMOD_OUTPUT_STATE *output, int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency);
static FMOD_RESULT F_CALLBACK recordStartCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, FMOD_SOUND *sound, int loop);
static FMOD_RESULT F_CALLBACK recordStopCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo);
static FMOD_RESULT F_CALLBACK recordGetPositionCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, unsigned int *pcm);
static FMOD_RESULT F_CALLBACK recordLockCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
#endif
#ifdef FMOD_SUPPORT_MEMORYTRACKER
static FMOD_RESULT F_CALLBACK getMemoryUsedCallback (FMOD_OUTPUT_STATE *output, MemoryTracker *tracker);
#endif
};
}
#endif /* FMOD_SUPPORT_WASAPI */
#endif /* _FMOD_OUTPUT_WASAPI_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,116 @@
#ifndef _FMOD_OUTPUT_WINMM_H
#define _FMOD_OUTPUT_WINMM_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_WINMM
#include "fmod_output_polled.h"
#include <windows.h>
#include <mmsystem.h>
namespace FMOD
{
const int PLAY_MAXBLOCKS = 1; /* number of buffers */
const int RECORD_MAXBLOCKS = 100; /* number of buffers */
const int RECORD_BLOCKLENMS = 5; /* size of each buffer - 100 * 5 = 500ms with 5ms granularity */
typedef struct
{
WAVEHDR wavehdr;
char *data;
} SoundBlock;
class OutputWinMM : public OutputPolled
{
private:
bool mCoInitialized;
/*
Playback information.
*/
HWAVEOUT mHandle;
bool mRunning;
char *mBuffer;
SoundBlock mBlock[PLAY_MAXBLOCKS];
int mNumBlocks;
unsigned int mBlockLengthBytes;
/*
Record information.
*/
#ifdef FMOD_SUPPORT_RECORDING
HWAVEIN mRecordHandle;
Thread mRecordThread;
bool mRecording;
int mRecordCurrentBlock;
int mRecordNextBlock;
SoundBlock mRecordBlock[RECORD_MAXBLOCKS];
char *mRecordData;
unsigned int mRecordBlockLenBytes;
int mRecordBlockAlign;
static void CALLBACK recordCallback(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
static void recordThreadCallback(void *userdata);
FMOD_RESULT recordThread();
#endif
FMOD_RESULT testFormat(int id, FMOD_SOUND_FORMAT format, int channels);
public:
static FMOD_OUTPUT_DESCRIPTION_EX *getDescriptionEx();
FMOD_RESULT enumerate();
FMOD_RESULT getNumDrivers(int *numdrivers);
FMOD_RESULT getDriverInfo(int id, char *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT getDriverInfoW(int id, short *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT getDriverCaps(int id, FMOD_CAPS *caps);
FMOD_RESULT init(int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, int dspbuffersize, int dspnumbuffers, void *extradriverdata);
FMOD_RESULT close();
FMOD_RESULT getHandle(void **handle);
FMOD_RESULT start();
FMOD_RESULT stop();
FMOD_RESULT getPosition(unsigned int *pcm);
FMOD_RESULT lock(unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
FMOD_RESULT unlock(void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
#ifdef FMOD_SUPPORT_RECORDING
FMOD_RESULT recordGetNumDrivers(int *numdrivers);
FMOD_RESULT recordGetDriverInfo(int id, char *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT recordGetDriverInfoW(int id, short *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT recordStart (FMOD_RECORDING_INFO *recordinfo, Sound *sound, bool loop);
FMOD_RESULT recordStop (FMOD_RECORDING_INFO *recordinfo);
FMOD_RESULT recordGetPosition (FMOD_RECORDING_INFO *recordinfo, unsigned int *pcm);
FMOD_RESULT recordLock (FMOD_RECORDING_INFO *recordinfo, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
#endif
static FMOD_RESULT F_CALLBACK getNumDriversCallback (FMOD_OUTPUT_STATE *output, int *numdrivers);
static FMOD_RESULT F_CALLBACK getDriverInfoCallback (FMOD_OUTPUT_STATE *output, int id, char *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK getDriverInfoWCallback (FMOD_OUTPUT_STATE *output, int id, short *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK getDriverCapsCallback (FMOD_OUTPUT_STATE *output, int id, FMOD_CAPS *caps);
static FMOD_RESULT F_CALLBACK initCallback (FMOD_OUTPUT_STATE *output, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int dspnumbuffers, void *extradriverdata);
static FMOD_RESULT F_CALLBACK closeCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK startCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK stopCallback (FMOD_OUTPUT_STATE *output);
static FMOD_RESULT F_CALLBACK getHandleCallback (FMOD_OUTPUT_STATE *output, void **handle);
static FMOD_RESULT F_CALLBACK getPositionCallback (FMOD_OUTPUT_STATE *output, unsigned int *pcm);
static FMOD_RESULT F_CALLBACK lockCallback (FMOD_OUTPUT_STATE *output, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
static FMOD_RESULT F_CALLBACK unlockCallback (FMOD_OUTPUT_STATE *output, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
#ifdef FMOD_SUPPORT_RECORDING
static FMOD_RESULT F_CALLBACK recordGetNumDriversCallback (FMOD_OUTPUT_STATE *output, int *numdrivers);
static FMOD_RESULT F_CALLBACK recordGetDriverInfoCallback (FMOD_OUTPUT_STATE *output, int id, char *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK recordGetDriverInfoWCallback (FMOD_OUTPUT_STATE *output, int id, short *name, int namelen, FMOD_GUID *guid);
static FMOD_RESULT F_CALLBACK recordStartCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, FMOD_SOUND *sound, int loop);
static FMOD_RESULT F_CALLBACK recordStopCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo);
static FMOD_RESULT F_CALLBACK recordGetPositionCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, unsigned int *pcm);
static FMOD_RESULT F_CALLBACK recordLockCallback (FMOD_OUTPUT_STATE *output, FMOD_RECORDING_INFO *recordinfo, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
#endif
};
}
#endif /* #ifdef FMOD_SUPPORT_WINMM */
#endif

View file

@ -0,0 +1,256 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_DSOUND
#include "fmod.h"
#include "fmod_output_dsound.h"
#include "fmod_sample_dsound.h"
#include "fmod_systemi.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
SampleDSound::SampleDSound()
{
mBuffer = 0;
mBuffer3D = 0;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT SampleDSound::release(bool freethis)
{
FMOD_RESULT result;
if (!mSystem)
{
return FMOD_ERR_UNINITIALIZED;
}
if (mFlags & FMOD_SOUND_FLAG_PRELOADEDFSB)
{
return FMOD_ERR_PRELOADED;
}
if (mFlags & FMOD_SOUND_FLAG_PROGRAMMERSOUND)
{
return FMOD_ERR_PROGRAMMERSOUND;
}
while (mOpenState != FMOD_OPENSTATE_READY && mOpenState != FMOD_OPENSTATE_ERROR)
{
FMOD_OS_Time_Sleep(2);
}
result = mSystem->stopSound(this);
if (result != FMOD_OK)
{
return result;
}
/*
Free sample's secondary buffer
*/
if (mBuffer)
{
if (mOutput)
{
mOutput->mBufferMemoryCurrent -= mLengthBytes;
}
mBuffer->Release();
mBuffer = 0;
}
if(mBuffer3D)
{
mBuffer3D->Release();
mBuffer3D = 0;
}
return Sample::release(freethis);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT SampleDSound::lockInternal(unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2)
{
HRESULT hr;
if (!mBuffer)
{
return FMOD_ERR_INVALID_PARAM;
}
hr = mBuffer->Lock(offset, length, ptr1, (DWORD *)len1, ptr2, (DWORD *)len2, 0); /* not DSBLOCK_FROMWRITECURSOR OR DSBLOCK_ENTIREBUFFER */
if (hr == E_INVALIDARG)
{
return FMOD_ERR_INVALID_PARAM;
}
else if (hr == DSBSTATUS_BUFFERLOST)
{
DWORD locflags = 0;
if (!(mMode & FMOD_UNIQUE))
{
if (mLOCSoftware)
{
locflags |= DSBPLAY_LOCSOFTWARE;
}
else
{
locflags |= DSBPLAY_LOCHARDWARE;
}
}
mBuffer->Restore();
mBuffer->Play(0, 0, locflags | DSBPLAY_LOOPING);
}
else if (hr != DS_OK)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
FMOD_OK
[REMARKS]
[PLATFORMS]
Win32, Win64
[SEE_ALSO]
]
*/
FMOD_RESULT SampleDSound::unlockInternal(void *ptr1, void *ptr2, unsigned int len1, unsigned int len2)
{
HRESULT hr;
if (!mBuffer)
{
return FMOD_ERR_INVALID_PARAM;
}
if (mFormat == FMOD_SOUND_FORMAT_PCM8)
{
if (ptr1 && len1)
{
unsigned int count;
unsigned char *destptr = (unsigned char *)ptr1;
for (count = 0; count < len1; count++)
{
*destptr++ ^= 128;
}
}
if (ptr2 && len2)
{
unsigned int count;
unsigned char *destptr = (unsigned char *)ptr2;
for (count = 0; count < len2; count++)
{
*destptr++ ^= 128;
}
}
}
hr = mBuffer->Unlock(ptr1, len1, ptr2, len2);
if (hr != DS_OK)
{
return FMOD_ERR_OUTPUT_DRIVERCALL;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
#ifdef FMOD_SUPPORT_MEMORYTRACKER
FMOD_RESULT SampleDSound::getMemoryUsedImpl(MemoryTracker *tracker)
{
tracker->add(false, FMOD_MEMBITS_SOUND, sizeof(SampleDSound) - sizeof(Sample)); // only the SampleDSound members...
return Sample::getMemoryUsedImpl(tracker); // all the base class members
}
#endif
}
#endif /* FMOD_SUPPORT_DSOUND */

View file

@ -0,0 +1,52 @@
#ifndef _FMOD_SAMPLE_DSOUND_H
#define _FMOD_SAMPLE_DSOUND_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_DSOUND
#include "fmod_memory.h"
#include "fmod_soundi.h"
#include "fmod_sound_sample.h"
#ifndef _FMOD_MEMORYTRACKER_H
#include "fmod_memorytracker.h"
#endif
struct IDirectSoundBuffer8;
struct IDirectSound3DBuffer;
struct OutputDSound;
namespace FMOD
{
class SampleDSound : public Sample
{
DECLARE_MEMORYTRACKER
friend class ChannelDSound;
friend class OutputDSound;
#ifdef FMOD_SUPPORT_OPENAL
friend class OutputOpenAL;
#endif
private:
IDirectSoundBuffer8 *mBuffer;
IDirectSound3DBuffer *mBuffer3D;
OutputDSound *mOutput;
bool mLOCSoftware;
public:
SampleDSound();
FMOD_RESULT release(bool freethis = true);
FMOD_RESULT lockInternal(unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
FMOD_RESULT unlockInternal(void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
};
}
#endif /* FMOD_SUPPORT_DSOUND */
#endif

View file

@ -0,0 +1,503 @@
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#include "fmod_memory.h"
#include "fmod_output.h"
#include "fmod_output_software.h"
#include "fmod_sample_openal.h"
#include "fmod_systemi.h"
namespace FMOD
{
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
SampleOpenAL::SampleOpenAL()
{
mBuffer = 0;
mBufferMemory = 0;
mDataEndCopied = false;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT SampleOpenAL::release(bool freethis)
{
FMOD_RESULT result;
if (!mSystem)
{
return FMOD_ERR_UNINITIALIZED;
}
if (mFlags & FMOD_SOUND_FLAG_PRELOADEDFSB)
{
return FMOD_ERR_PRELOADED;
}
if (mFlags & FMOD_SOUND_FLAG_PROGRAMMERSOUND)
{
return FMOD_ERR_PROGRAMMERSOUND;
}
while (mOpenState != FMOD_OPENSTATE_READY && mOpenState != FMOD_OPENSTATE_ERROR)
{
FMOD_OS_Time_Sleep(2);
}
result = mSystem->stopSound(this);
if (result != FMOD_OK)
{
return result;
}
if (mBufferMemory)
{
FMOD_Memory_Free(mBufferMemory);
mBufferMemory = 0;
}
if (mLoopPointDataEnd && mLoopPointDataEnd != mLoopPointDataEndMemory)
{
FMOD_Memory_Free(mLoopPointDataEnd);
mLoopPointDataEnd = 0;
}
mBuffer = 0;
return Sample::release(freethis);
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT SampleOpenAL::setMode(FMOD_MODE mode)
{
FMOD_RESULT result;
result = Sample::setMode(mode);
if (result != FMOD_OK)
{
return result;
}
result = setLoopPointData();
if (result != FMOD_OK)
{
return result;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT SampleOpenAL::lockInternal(unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2)
{
FMOD_RESULT result;
char *src = 0;
unsigned int overflowbytes, pointB;
/*
If we're locking part of the sample that has been modified by the loop point stuff, restore the old data first.
*/
result = getBytesFromSamples(FMOD_DSP_RESAMPLER_OVERFLOWLENGTH, &overflowbytes);
if (result != FMOD_OK)
{
return result;
}
result = getBytesFromSamples(mLoopStart + mLoopLength, &pointB);
if (result != FMOD_OK)
{
return result;
}
if (offset >= pointB && offset < pointB + overflowbytes)
{
result = restoreLoopPointData();
if (result != FMOD_OK)
{
return result;
}
}
src = (char *)mBuffer;
if (offset >= mLengthBytes || offset < 0 || length < 0)
{
*ptr1 = 0;
if (ptr2)
{
*ptr2 = 0;
}
*len1 = 0;
if (len2)
{
*len2 = 0;
}
return FMOD_ERR_INVALID_PARAM;
}
if (offset + length <= mLengthBytes)
{
*ptr1 = src + offset;
*len1 = length;
if (ptr2)
{
*ptr2 = 0;
}
if (len2)
{
*len2 = 0;
}
}
/*
Otherwise return wrapped pointers in pt1 and ptr2
*/
else
{
*ptr1 = src + offset;
*len1 = mLengthBytes - offset;
*ptr2 = src;
*len2 = length - (mLengthBytes - offset);
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT SampleOpenAL::unlockInternal(void *ptr1, void *ptr2, unsigned int len1, unsigned int len2)
{
FMOD_RESULT result;
result = setLoopPointData();
if (result != FMOD_OK)
{
return result;
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT SampleOpenAL::setBufferData(void *data)
{
mBuffer = data;
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT SampleOpenAL::setLoopPoints(unsigned int loopstart, unsigned int looplength)
{
if (loopstart >= mLength || loopstart + looplength > mLength)
{
return FMOD_ERR_INVALID_PARAM;
}
restoreLoopPointData();
mLoopStart = loopstart;
mLoopLength = looplength;
setLoopPointData();
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT SampleOpenAL::setLoopPointData()
{
FMOD_RESULT result;
unsigned int overflowbytes, pointA, pointB;
if ((mFormat != FMOD_SOUND_FORMAT_PCM8 &&
mFormat != FMOD_SOUND_FORMAT_PCM16 &&
mFormat != FMOD_SOUND_FORMAT_PCM24 &&
mFormat != FMOD_SOUND_FORMAT_PCM32 &&
mFormat != FMOD_SOUND_FORMAT_PCMFLOAT) || !mLoopPointDataEnd)
{
return FMOD_OK;
}
result = getBytesFromSamples(FMOD_DSP_RESAMPLER_OVERFLOWLENGTH, &overflowbytes);
if (result != FMOD_OK)
{
return result;
}
result = getBytesFromSamples(mLoopStart, &pointA);
if (result != FMOD_OK)
{
return result;
}
result = getBytesFromSamples(mLoopStart + mLoopLength, &pointB);
if (result != FMOD_OK)
{
return result;
}
if (mMode & FMOD_LOOP_BIDI)
{
int count;
FMOD_memcpy(mLoopPointDataEnd, (char *)mBuffer + pointB, overflowbytes); /* backup the data first */
mDataEndCopied = true;
switch (mFormat)
{
case FMOD_SOUND_FORMAT_PCM8:
{
char *srcptr, *destptr;
srcptr = destptr = (char *)mBuffer + pointB;
srcptr -= mChannels;
for (count=0; count < FMOD_DSP_RESAMPLER_OVERFLOWLENGTH * mChannels; count++)
{
*destptr = *srcptr;
destptr++;
srcptr--;
}
break;
}
case FMOD_SOUND_FORMAT_PCM16:
{
short *srcptr, *destptr;
srcptr = destptr = (short *)((char *)mBuffer + pointB);
srcptr -= mChannels;
for (count=0; count < FMOD_DSP_RESAMPLER_OVERFLOWLENGTH * mChannels; count++)
{
*destptr = *srcptr;
destptr++;
srcptr--;
}
break;
}
case FMOD_SOUND_FORMAT_PCM24:
{
char *srcptr, *destptr;
srcptr = destptr = (char *)mBuffer + pointB;
srcptr -= (mChannels * 3);
for (count=0; count < FMOD_DSP_RESAMPLER_OVERFLOWLENGTH * mChannels; count++)
{
destptr[0] = srcptr[0];
destptr[1] = srcptr[1];
destptr[2] = srcptr[2];
destptr += 3;
srcptr -= 3;
}
break;
}
case FMOD_SOUND_FORMAT_PCM32:
case FMOD_SOUND_FORMAT_PCMFLOAT:
{
int *srcptr, *destptr;
srcptr = destptr = (int *)((char *)mBuffer + pointB);
srcptr -= mChannels;
for (count=0; count < FMOD_DSP_RESAMPLER_OVERFLOWLENGTH * mChannels; count++)
{
*destptr = *srcptr;
destptr++;
srcptr--;
}
break;
}
default:
{
break;
}
}
}
else if (mMode & FMOD_LOOP_NORMAL)
{
FMOD_memcpy(mLoopPointDataEnd, (char *)mBuffer + pointB, overflowbytes);
mDataEndCopied = true;
FMOD_memcpy((char *)mBuffer + pointB, (char *)mBuffer + pointA, overflowbytes);
}
else if (mMode & FMOD_LOOP_OFF)
{
if(mDataEndCopied)
{
FMOD_memcpy((char *)mBuffer + pointB, mLoopPointDataEnd,overflowbytes);
}
}
return FMOD_OK;
}
/*
[
[DESCRIPTION]
[PARAMETERS]
[RETURN_VALUE]
[REMARKS]
[PLATFORMS]
[SEE_ALSO]
]
*/
FMOD_RESULT SampleOpenAL::restoreLoopPointData()
{
FMOD_RESULT result;
unsigned int overflowbytes, pointA, pointB;
if ((mFormat != FMOD_SOUND_FORMAT_PCM8 &&
mFormat != FMOD_SOUND_FORMAT_PCM16 &&
mFormat != FMOD_SOUND_FORMAT_PCM24 &&
mFormat != FMOD_SOUND_FORMAT_PCM32 &&
mFormat != FMOD_SOUND_FORMAT_PCMFLOAT) || !mLoopPointDataEnd)
{
return FMOD_OK;
}
result = getBytesFromSamples(FMOD_DSP_RESAMPLER_OVERFLOWLENGTH, &overflowbytes);
if (result != FMOD_OK)
{
return result;
}
result = getBytesFromSamples(mLoopStart, &pointA);
if (result != FMOD_OK)
{
return result;
}
result = getBytesFromSamples(mLoopStart + mLoopLength, &pointB);
if (result != FMOD_OK)
{
return result;
}
if(mDataEndCopied)
{
FMOD_memcpy((char *)mBuffer + pointB, mLoopPointDataEnd,overflowbytes);
}
return FMOD_OK;
}
}
#endif /* FMOD_SUPPORT_OPENAL */

View file

@ -0,0 +1,45 @@
#ifndef _FMOD_SAMPLE_OPENAL_H
#define _FMOD_SAMPLE_OPENAL_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_OPENAL
#include "fmod_dsp_resampler.h"
#include "fmod_sound_sample.h"
namespace FMOD
{
class SampleOpenAL : public Sample
{
friend class OutputOpenAL;
friend class ChannelOpenAL;
friend class DSPWaveTable;
private:
void *mBuffer;
void *mBufferMemory;
char *mLoopPointDataEnd;
char mLoopPointDataEndMemory[8];
bool mDataEndCopied;
public:
SampleOpenAL();
FMOD_RESULT release(bool freethis = true);
FMOD_RESULT lockInternal(unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
FMOD_RESULT unlockInternal(void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
FMOD_RESULT setBufferData(void *data);
FMOD_RESULT setLoopPoints(unsigned int loopstart, unsigned int looplength);
FMOD_RESULT setLoopPointData();
FMOD_RESULT restoreLoopPointData();
FMOD_RESULT setMode(FMOD_MODE mode);
};
}
#endif /* FMOD_SUPPORT_OPENAL */
#endif

15
fmod/win32/src/resource.h Executable file
View file

@ -0,0 +1,15 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by fmod.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View file

@ -0,0 +1,109 @@
#ifndef _FMOD_AUDIOCLIENT_H
#define _FMOD_AUDIOCLIENT_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_WASAPI
#include "fmod_codec_wav.h"
// GUIDs
static const GUID IID_IAudioClock = { 0xcd63314f, 0x3fba, 0x4a1b, { 0x81, 0x2c, 0xef, 0x96, 0x35, 0x87, 0x28, 0xe7 } };
static const GUID IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } };
static const GUID IID_IAudioRenderClient = { 0xf294acfc, 0x3146, 0x4483, { 0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2 } };
static const GUID IID_IAudioCaptureClient = { 0xc8adbd64, 0xe71e, 0x48a0, { 0xa4, 0xde, 0x18, 0x5c, 0x39, 0x5c, 0xd3, 0x17 } };
static const GUID KSDATAFORMAT_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
static const GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
// Helper defines
typedef LONGLONG REFERENCE_TIME;
typedef const FMOD_GUID* LPCFMOD_GUID;
typedef enum
{
AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_SHAREMODE_EXCLUSIVE
} AUDCLNT_SHAREMODE;
// Error defines
#define FACILITY_AUDCLNT 0x889
#define AUDCLNT_ERR(n) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_AUDCLNT, n)
#define AUDCLNT_SUCCESS(n) MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_AUDCLNT, n)
#define AUDCLNT_E_NOT_INITIALIZED AUDCLNT_ERR(0x001)
#define AUDCLNT_E_ALREADY_INITIALIZED AUDCLNT_ERR(0x002)
#define AUDCLNT_E_WRONG_ENDPOINT_TYPE AUDCLNT_ERR(0x003)
#define AUDCLNT_E_DEVICE_INVALIDATED AUDCLNT_ERR(0x004)
#define AUDCLNT_E_NOT_STOPPED AUDCLNT_ERR(0x005)
#define AUDCLNT_E_BUFFER_TOO_LARGE AUDCLNT_ERR(0x006)
#define AUDCLNT_E_OUT_OF_ORDER AUDCLNT_ERR(0x007)
#define AUDCLNT_E_UNSUPPORTED_FORMAT AUDCLNT_ERR(0x008)
#define AUDCLNT_E_INVALID_SIZE AUDCLNT_ERR(0x009)
#define AUDCLNT_E_DEVICE_IN_USE AUDCLNT_ERR(0x00a)
#define AUDCLNT_E_BUFFER_OPERATION_PENDING AUDCLNT_ERR(0x00b)
#define AUDCLNT_E_THREAD_NOT_REGISTERED AUDCLNT_ERR(0x00c)
#define AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED AUDCLNT_ERR(0x00e)
#define AUDCLNT_E_ENDPOINT_CREATE_FAILED AUDCLNT_ERR(0x00f)
#define AUDCLNT_E_SERVICE_NOT_RUNNING AUDCLNT_ERR(0x010)
#define AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED AUDCLNT_ERR(0x011)
#define AUDCLNT_E_EXCLUSIVE_MODE_ONLY AUDCLNT_ERR(0x012)
#define AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL AUDCLNT_ERR(0x013)
#define AUDCLNT_E_EVENTHANDLE_NOT_SET AUDCLNT_ERR(0x014)
#define AUDCLNT_E_INCORRECT_BUFFER_SIZE AUDCLNT_ERR(0x015)
#define AUDCLNT_E_BUFFER_SIZE_ERROR AUDCLNT_ERR(0x016)
#define AUDCLNT_E_CPUUSAGE_EXCEEDED AUDCLNT_ERR(0x017)
#define AUDCLNT_S_BUFFER_EMPTY AUDCLNT_SUCCESS(0x001)
#define AUDCLNT_S_THREAD_ALREADY_REGISTERED AUDCLNT_SUCCESS(0x002)
#define AUDCLNT_S_POSITION_STALLED AUDCLNT_SUCCESS(0x003)
// AudioClient stream flags
#define AUDCLNT_STREAMFLAGS_CROSSPROCESS 0x00010000
#define AUDCLNT_STREAMFLAGS_LOOPBACK 0x00020000
#define AUDCLNT_STREAMFLAGS_EVENTCALLBACK 0x00040000
#define AUDCLNT_STREAMFLAGS_NOPERSIST 0x00080000
// Used to create and initialize a connection to the audio engine
struct IAudioClient : public IUnknown
{
public:
virtual HRESULT F_STDCALL Initialize (AUDCLNT_SHAREMODE ShareMode, DWORD StreamFlags, REFERENCE_TIME hnsBufferDuration, REFERENCE_TIME hnsPeriodicity, const FMOD::WAVE_FORMATEX *pFormat, LPCFMOD_GUID AudioSessionGuid) = 0;
virtual HRESULT F_STDCALL GetBufferSize (UINT32 *pNumBufferFrames) = 0;
virtual HRESULT F_STDCALL GetStreamLatency (REFERENCE_TIME *phnsLatency) = 0;
virtual HRESULT F_STDCALL GetCurrentPadding (UINT32 *pNumPaddingFrames) = 0;
virtual HRESULT F_STDCALL IsFormatSupported (AUDCLNT_SHAREMODE ShareMode, const FMOD::WAVE_FORMATEX *pFormat, FMOD::WAVE_FORMATEX **ppClosestMatch) = 0;
virtual HRESULT F_STDCALL GetMixFormat (FMOD::WAVE_FORMATEX **ppDeviceFormat) = 0;
virtual HRESULT F_STDCALL GetDevicePeriod (REFERENCE_TIME *phnsDefaultDevicePeriod, REFERENCE_TIME *phnsMinimumDevicePeriod) = 0;
virtual HRESULT F_STDCALL Start (void) = 0;
virtual HRESULT F_STDCALL Stop (void) = 0;
virtual HRESULT F_STDCALL Reset (void) = 0;
virtual HRESULT F_STDCALL SetEventHandle (HANDLE eventHandle) = 0;
virtual HRESULT F_STDCALL GetService (REFIID riid, void **ppv) = 0;
};
// Used for monitoring the stream data rate and stream position
struct IAudioClock : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetFrequency (UINT64 *pu64Frequency) = 0;
virtual HRESULT STDMETHODCALLTYPE GetPosition (UINT64 *pu64Position, UINT64 *pu64QPCPosition) = 0;
virtual HRESULT STDMETHODCALLTYPE GetCharacteristics (DWORD *pdwCharacteristics) = 0;
};
// Used by audio-rendering applications to stream their output data to a rendering endpoint device
struct IAudioRenderClient : public IUnknown
{
public:
virtual HRESULT F_STDCALL GetBuffer (UINT32 NumFramesRequested, BYTE **ppData) = 0;
virtual HRESULT F_STDCALL ReleaseBuffer (UINT32 NumFramesWritten, DWORD dwFlags) = 0;
};
// Used by a capture application to read capture data from a capture endpoint buffer
struct IAudioCaptureClient : public IUnknown
{
public:
virtual HRESULT F_STDCALL GetBuffer (BYTE **ppData, UINT32 *pNumFramesToRead, DWORD *pdwFlags, UINT64 *pu64DevicePosition, UINT64 *pu64QPCPosition) = 0;
virtual HRESULT F_STDCALL ReleaseBuffer (UINT32 NumFramesRead) = 0;
virtual HRESULT F_STDCALL GetNextPacketSize (UINT32 *pNumFramesInNextPacket) = 0;
};
#endif /* FMOD_SUPPORT_WASAPI */
#endif /* _FMOD_AUDIOCLIENT_H */

View file

@ -0,0 +1,125 @@
#ifndef _FMOD_MMDEVICEAPI_H
#define _FMOD_MMDEVICEAPI_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_WASAPI
// Audio data flow direction
typedef enum
{
eRender,
eCapture,
eAll,
EDataFlow_enum_count
} EDataFlow;
// Role assigned to an audio endpoint
typedef enum
{
eConsole,
eMultimedia,
eCommunications,
ERole_enum_count
} ERole;
// Identifier for a property
#ifndef PROPERTYKEY_DEFINED
#define PROPERTYKEY_DEFINED
typedef struct
{
FMOD_GUID category;
DWORD propertyID;
} PROPERTYKEY;
#endif
// GUIDs
static const GUID CLSID_MMDeviceEnumerator = { 0xbcde0395, 0xe52f, 0x467c, { 0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e }};
static const GUID IID_IMMDeviceEnumerator = { 0xa95664d2, 0x9614, 0x4f35, { 0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6 }};
static const GUID IID_IMMEndpoint = { 0x1be09788, 0x6894, 0x4089, { 0x85, 0x86, 0x9a, 0x2a, 0x6c, 0x26, 0x5a, 0xc5 }};
// Property keys
static const PROPERTYKEY PKEY_Device_DeviceDesc = { { 0xa45c254e, 0xdf1c, 0x4efd, { 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0 } }, 2 };
static const PROPERTYKEY PKEY_DeviceInterface_FriendlyName = { { 0x026e516e, 0xb814, 0x414b, { 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22 } }, 2 };
// Helper defines
#define REFPROPERTYKEY const PROPERTYKEY &
#define REFPROPVARIANT const PROPVARIANT &
// Error defines
#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND)
#define E_UNSUPPORTED_TYPE HRESULT_FROM_WIN32(ERROR_UNSUPPORTED_TYPE)
// Device states
#define DEVICE_STATE_ACTIVE 0x00000001
#define DEVICE_STATE_DISABLED 0x00000002
#define DEVICE_STATE_NOTPRESENT 0x00000004
#define DEVICE_STATE_UNPLUGGED 0x00000008
#define DEVICE_STATEMASK_ALL 0x0000000f
// Property variant management
#define PropVariantInit(pvar) FMOD_memset((pvar), 0, sizeof(PROPVARIANT))
WINOLEAPI PropVariantClear ( PROPVARIANT * pvar );
// Provides methods for enumerating, getting, and setting property values
struct IPropertyStore : public IUnknown
{
public:
virtual HRESULT F_STDCALL GetCount (DWORD *cProps) = 0;
virtual HRESULT F_STDCALL GetAt (DWORD iProp, PROPERTYKEY *pkey) = 0;
virtual HRESULT F_STDCALL GetValue (REFPROPERTYKEY key, PROPVARIANT *pv) = 0;
virtual HRESULT F_STDCALL SetValue (REFPROPERTYKEY key, REFPROPVARIANT propvar) = 0;
virtual HRESULT F_STDCALL Commit (void) = 0;
};
// Provices notification when an endpoint state has changed
struct IMMNotificationClient : public IUnknown
{
public:
virtual HRESULT F_STDCALL OnDeviceStateChanged (LPCWSTR pwstrDeviceId, DWORD dwNewState) = 0;
virtual HRESULT F_STDCALL OnDeviceAdded (LPCWSTR pwstrDeviceId) = 0;
virtual HRESULT F_STDCALL OnDeviceRemoved (LPCWSTR pwstrDeviceId) = 0;
virtual HRESULT F_STDCALL OnDefaultDeviceChanged (EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) = 0;
virtual HRESULT F_STDCALL OnPropertyValueChanged (LPCWSTR pwstrDeviceId, const PROPERTYKEY key) = 0;
};
// Encapsulate the generic features of a multimedia device resource
struct IMMDevice : public IUnknown
{
public:
virtual HRESULT F_STDCALL Activate (REFIID iid, DWORD dwClsCtx, PROPVARIANT *pActivationParams, void **ppInterface) = 0;
virtual HRESULT F_STDCALL OpenPropertyStore (DWORD stgmAccess, IPropertyStore **ppProperties) = 0;
virtual HRESULT F_STDCALL GetId (LPWSTR *ppstrId) = 0;
virtual HRESULT F_STDCALL GetState (DWORD *pdwState) = 0;
};
// An audio endpoint device
struct IMMEndpoint : public IUnknown
{
public:
virtual HRESULT F_STDCALL GetDataFlow (EDataFlow *pDataFlow) = 0;
};
// A collection of multimedia device resources
struct IMMDeviceCollection : public IUnknown
{
public:
virtual HRESULT F_STDCALL GetCount (UINT *pcDevices) = 0;
virtual HRESULT F_STDCALL Item (UINT nDevice, IMMDevice **ppDevice) = 0;
};
// Provides methods for enumerating multimedia device resources
struct IMMDeviceEnumerator : public IUnknown
{
public:
virtual HRESULT F_STDCALL EnumAudioEndpoints (EDataFlow dataFlow, DWORD dwStateMask, IMMDeviceCollection **ppDevices) = 0;
virtual HRESULT F_STDCALL GetDefaultAudioEndpoint (EDataFlow dataFlow, ERole role, IMMDevice **ppEndpoint) = 0;
virtual HRESULT F_STDCALL GetDevice (LPCWSTR pwstrId, IMMDevice **ppDevice) = 0;
virtual HRESULT F_STDCALL RegisterEndpointNotificationCallback (IMMNotificationClient *pClient) = 0;
virtual HRESULT F_STDCALL UnregisterEndpointNotificationCallback (IMMNotificationClient *pClient) = 0;
};
#endif /* FMOD_SUPPORT_WASAPI */
#endif /* _FMOD_MMDEVICEAPI_H */