mirror of
https://gitlab.com/shinovon/re3-symbian.git
synced 2026-05-23 01:57:21 +03:00
Initial commit
This commit is contained in:
commit
77cdaaf97e
827 changed files with 418745 additions and 0 deletions
291
src/audio/oal/aldlist.cpp
Normal file
291
src/audio/oal/aldlist.cpp
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* Copyright (c) 2006, Creative Labs Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
||||
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
|
||||
* promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "aldlist.h"
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
/*
|
||||
* Init call
|
||||
*/
|
||||
ALDeviceList::ALDeviceList()
|
||||
{
|
||||
char *devices;
|
||||
int index;
|
||||
const char *defaultDeviceName;
|
||||
const char *actualDeviceName;
|
||||
|
||||
// DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support
|
||||
nNumOfDevices = 0;
|
||||
|
||||
defaultDeviceIndex = 0;
|
||||
|
||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT")) {
|
||||
devices = (char *)alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
||||
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
|
||||
|
||||
index = 0;
|
||||
// go through device list (each device terminated with a single NULL, list terminated with double NULL)
|
||||
while (*devices != '\0') {
|
||||
if (strcmp(defaultDeviceName, devices) == 0) {
|
||||
defaultDeviceIndex = index;
|
||||
}
|
||||
ALCdevice *device = alcOpenDevice(devices);
|
||||
if (device) {
|
||||
ALCcontext *context = alcCreateContext(device, NULL);
|
||||
if (context) {
|
||||
alcMakeContextCurrent(context);
|
||||
// if new actual device name isn't already in the list, then add it...
|
||||
actualDeviceName = alcGetString(device, ALC_ALL_DEVICES_SPECIFIER);
|
||||
if ((actualDeviceName != NULL) && (strlen(actualDeviceName) > 0)) {
|
||||
ALDEVICEINFO &ALDeviceInfo = aDeviceInfo[nNumOfDevices++];
|
||||
ALDeviceInfo.bSelected = true;
|
||||
ALDeviceInfo.SetName(actualDeviceName);
|
||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(int), &ALDeviceInfo.iMajorVersion);
|
||||
alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(int), &ALDeviceInfo.iMinorVersion);
|
||||
|
||||
// Check for ALC Extensions
|
||||
if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE)
|
||||
ALDeviceInfo.Extensions |= ADEXT_EXT_CAPTURE;
|
||||
if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE)
|
||||
ALDeviceInfo.Extensions |= ADEXT_EXT_EFX;
|
||||
|
||||
// Check for AL Extensions
|
||||
if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE)
|
||||
ALDeviceInfo.Extensions |= ADEXT_EXT_OFFSET;
|
||||
|
||||
if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE)
|
||||
ALDeviceInfo.Extensions |= ADEXT_EXT_LINEAR_DISTANCE;
|
||||
if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
|
||||
ALDeviceInfo.Extensions |= ADEXT_EXT_EXPONENT_DISTANCE;
|
||||
|
||||
if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
|
||||
ALDeviceInfo.Extensions |= ADEXT_EAX2;
|
||||
if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
|
||||
ALDeviceInfo.Extensions |= ADEXT_EAX3;
|
||||
if (alIsExtensionPresent("EAX4.0") == AL_TRUE)
|
||||
ALDeviceInfo.Extensions |= ADEXT_EAX4;
|
||||
if (alIsExtensionPresent("EAX5.0") == AL_TRUE)
|
||||
ALDeviceInfo.Extensions |= ADEXT_EAX5;
|
||||
|
||||
if (alIsExtensionPresent("EAX-RAM") == AL_TRUE)
|
||||
ALDeviceInfo.Extensions |= ADEXT_EAX_RAM;
|
||||
|
||||
// Get Source Count
|
||||
ALDeviceInfo.uiSourceCount = GetMaxNumSources();
|
||||
}
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(context);
|
||||
}
|
||||
alcCloseDevice(device);
|
||||
}
|
||||
devices += strlen(devices) + 1;
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
ResetFilters();
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit call
|
||||
*/
|
||||
ALDeviceList::~ALDeviceList()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of devices in the complete device list
|
||||
*/
|
||||
unsigned int ALDeviceList::GetNumDevices()
|
||||
{
|
||||
return nNumOfDevices;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the device name at an index in the complete device list
|
||||
*/
|
||||
const char * ALDeviceList::GetDeviceName(unsigned int index)
|
||||
{
|
||||
if (index < GetNumDevices())
|
||||
return aDeviceInfo[index].strDeviceName;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the major and minor version numbers for a device at a specified index in the complete list
|
||||
*/
|
||||
void ALDeviceList::GetDeviceVersion(unsigned int index, int *major, int *minor)
|
||||
{
|
||||
if (index < GetNumDevices()) {
|
||||
if (major)
|
||||
*major = aDeviceInfo[index].iMajorVersion;
|
||||
if (minor)
|
||||
*minor = aDeviceInfo[index].iMinorVersion;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the maximum number of Sources that can be generate on the given device
|
||||
*/
|
||||
unsigned int ALDeviceList::GetMaxNumSources(unsigned int index)
|
||||
{
|
||||
if (index < GetNumDevices())
|
||||
return aDeviceInfo[index].uiSourceCount;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the extension is supported on the given device
|
||||
*/
|
||||
bool ALDeviceList::IsExtensionSupported(int index, unsigned short ext)
|
||||
{
|
||||
return !!(aDeviceInfo[index].Extensions & ext);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the index of the default device in the complete device list
|
||||
*/
|
||||
int ALDeviceList::GetDefaultDevice()
|
||||
{
|
||||
return defaultDeviceIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deselects devices which don't have the specified minimum version
|
||||
*/
|
||||
void ALDeviceList::FilterDevicesMinVer(int major, int minor)
|
||||
{
|
||||
int dMajor, dMinor;
|
||||
for (unsigned int i = 0; i < nNumOfDevices; i++) {
|
||||
GetDeviceVersion(i, &dMajor, &dMinor);
|
||||
if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {
|
||||
aDeviceInfo[i].bSelected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deselects devices which don't have the specified maximum version
|
||||
*/
|
||||
void ALDeviceList::FilterDevicesMaxVer(int major, int minor)
|
||||
{
|
||||
int dMajor, dMinor;
|
||||
for (unsigned int i = 0; i < nNumOfDevices; i++) {
|
||||
GetDeviceVersion(i, &dMajor, &dMinor);
|
||||
if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {
|
||||
aDeviceInfo[i].bSelected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deselects device which don't support the given extension name
|
||||
*/
|
||||
void
|
||||
ALDeviceList::FilterDevicesExtension(unsigned short ext)
|
||||
{
|
||||
for (unsigned int i = 0; i < nNumOfDevices; i++) {
|
||||
if (!IsExtensionSupported(i, ext))
|
||||
aDeviceInfo[i].bSelected = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Resets all filtering, such that all devices are in the list
|
||||
*/
|
||||
void ALDeviceList::ResetFilters()
|
||||
{
|
||||
for (unsigned int i = 0; i < GetNumDevices(); i++) {
|
||||
aDeviceInfo[i].bSelected = true;
|
||||
}
|
||||
filterIndex = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets index of first filtered device
|
||||
*/
|
||||
int ALDeviceList::GetFirstFilteredDevice()
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < GetNumDevices(); i++) {
|
||||
if (aDeviceInfo[i].bSelected == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
filterIndex = i + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets index of next filtered device
|
||||
*/
|
||||
int ALDeviceList::GetNextFilteredDevice()
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = filterIndex; i < GetNumDevices(); i++) {
|
||||
if (aDeviceInfo[i].bSelected == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
filterIndex = i + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function to detemine max number of Sources that can be generated
|
||||
*/
|
||||
unsigned int ALDeviceList::GetMaxNumSources()
|
||||
{
|
||||
ALuint uiSources[256];
|
||||
unsigned int iSourceCount = 0;
|
||||
|
||||
// Clear AL Error Code
|
||||
alGetError();
|
||||
|
||||
// Generate up to 256 Sources, checking for any errors
|
||||
for (iSourceCount = 0; iSourceCount < 256; iSourceCount++)
|
||||
{
|
||||
alGenSources(1, &uiSources[iSourceCount]);
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
break;
|
||||
}
|
||||
|
||||
// Release the Sources
|
||||
alDeleteSources(iSourceCount, uiSources);
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
for (unsigned int i = 0; i < 256; i++)
|
||||
{
|
||||
alDeleteSources(1, &uiSources[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return iSourceCount;
|
||||
}
|
||||
#endif
|
||||
82
src/audio/oal/aldlist.h
Normal file
82
src/audio/oal/aldlist.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
#ifndef ALDEVICELIST_H
|
||||
#define ALDEVICELIST_H
|
||||
|
||||
#include "oal_utils.h"
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
#pragma warning(disable: 4786) //disable warning "identifier was truncated to '255' characters in the browser information"
|
||||
|
||||
enum
|
||||
{
|
||||
ADEXT_EXT_CAPTURE = (1 << 0),
|
||||
ADEXT_EXT_EFX = (1 << 1),
|
||||
ADEXT_EXT_OFFSET = (1 << 2),
|
||||
ADEXT_EXT_LINEAR_DISTANCE = (1 << 3),
|
||||
ADEXT_EXT_EXPONENT_DISTANCE = (1 << 4),
|
||||
ADEXT_EAX2 = (1 << 5),
|
||||
ADEXT_EAX3 = (1 << 6),
|
||||
ADEXT_EAX4 = (1 << 7),
|
||||
ADEXT_EAX5 = (1 << 8),
|
||||
ADEXT_EAX_RAM = (1 << 9),
|
||||
};
|
||||
|
||||
struct ALDEVICEINFO {
|
||||
char *strDeviceName;
|
||||
int iMajorVersion;
|
||||
int iMinorVersion;
|
||||
unsigned int uiSourceCount;
|
||||
unsigned short Extensions;
|
||||
bool bSelected;
|
||||
|
||||
ALDEVICEINFO() : iMajorVersion(0), iMinorVersion(0), uiSourceCount(0), bSelected(false)
|
||||
{
|
||||
strDeviceName = NULL;
|
||||
Extensions = 0;
|
||||
}
|
||||
|
||||
~ALDEVICEINFO()
|
||||
{
|
||||
delete[] strDeviceName;
|
||||
strDeviceName = NULL;
|
||||
}
|
||||
|
||||
void SetName(const char *name)
|
||||
{
|
||||
if(strDeviceName) delete[] strDeviceName;
|
||||
strDeviceName = new char[strlen(name) + 1];
|
||||
strcpy(strDeviceName, name);
|
||||
}
|
||||
};
|
||||
|
||||
typedef ALDEVICEINFO *LPALDEVICEINFO;
|
||||
|
||||
class ALDeviceList
|
||||
{
|
||||
private:
|
||||
ALDEVICEINFO aDeviceInfo[64];
|
||||
unsigned int nNumOfDevices;
|
||||
int defaultDeviceIndex;
|
||||
int filterIndex;
|
||||
|
||||
public:
|
||||
ALDeviceList ();
|
||||
~ALDeviceList ();
|
||||
unsigned int GetNumDevices();
|
||||
const char *GetDeviceName(unsigned int index);
|
||||
void GetDeviceVersion(unsigned int index, int *major, int *minor);
|
||||
unsigned int GetMaxNumSources(unsigned int index);
|
||||
bool IsExtensionSupported(int index, unsigned short ext);
|
||||
int GetDefaultDevice();
|
||||
void FilterDevicesMinVer(int major, int minor);
|
||||
void FilterDevicesMaxVer(int major, int minor);
|
||||
void FilterDevicesExtension(unsigned short ext);
|
||||
void ResetFilters();
|
||||
int GetFirstFilteredDevice();
|
||||
int GetNextFilteredDevice();
|
||||
|
||||
private:
|
||||
unsigned int GetMaxNumSources();
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // ALDEVICELIST_H
|
||||
295
src/audio/oal/channel.cpp
Normal file
295
src/audio/oal/channel.cpp
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
#include "common.h"
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
#include "channel.h"
|
||||
#include "sampman.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <float.h>
|
||||
#endif
|
||||
|
||||
extern bool IsFXSupported();
|
||||
|
||||
ALuint alSources[NUM_CHANNELS];
|
||||
ALuint alFilters[NUM_CHANNELS];
|
||||
ALuint alBuffers[NUM_CHANNELS];
|
||||
bool bChannelsCreated = false;
|
||||
|
||||
int32 CChannel::channelsThatNeedService = 0;
|
||||
|
||||
uint8 tempStereoBuffer[PED_BLOCKSIZE * 2];
|
||||
|
||||
void
|
||||
CChannel::InitChannels()
|
||||
{
|
||||
alGenSources(NUM_CHANNELS, alSources);
|
||||
alGenBuffers(NUM_CHANNELS, alBuffers);
|
||||
if (IsFXSupported())
|
||||
alGenFilters(NUM_CHANNELS, alFilters);
|
||||
bChannelsCreated = true;
|
||||
}
|
||||
|
||||
void
|
||||
CChannel::DestroyChannels()
|
||||
{
|
||||
if (bChannelsCreated)
|
||||
{
|
||||
alDeleteSources(NUM_CHANNELS, alSources);
|
||||
memset(alSources, 0, sizeof(alSources));
|
||||
alDeleteBuffers(NUM_CHANNELS, alBuffers);
|
||||
memset(alBuffers, 0, sizeof(alBuffers));
|
||||
if (IsFXSupported())
|
||||
{
|
||||
alDeleteFilters(NUM_CHANNELS, alFilters);
|
||||
memset(alFilters, 0, sizeof(alFilters));
|
||||
}
|
||||
bChannelsCreated = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CChannel::CChannel()
|
||||
{
|
||||
Data = nil;
|
||||
DataSize = 0;
|
||||
bIs2D = false;
|
||||
SetDefault();
|
||||
}
|
||||
|
||||
void CChannel::SetDefault()
|
||||
{
|
||||
Pitch = 1.0f;
|
||||
Gain = 1.0f;
|
||||
Mix = 0.0f;
|
||||
|
||||
Position[0] = 0.0f; Position[1] = 0.0f; Position[2] = 0.0f;
|
||||
Distances[0] = 0.0f; Distances[1] = FLT_MAX;
|
||||
|
||||
LoopCount = 1;
|
||||
LastProcessedOffset = UINT32_MAX;
|
||||
LoopPoints[0] = 0; LoopPoints[1] = -1;
|
||||
|
||||
Frequency = MAX_FREQ;
|
||||
}
|
||||
|
||||
void CChannel::Reset()
|
||||
{
|
||||
// Here is safe because ctor don't call this
|
||||
if (LoopCount > 1)
|
||||
channelsThatNeedService--;
|
||||
|
||||
ClearBuffer();
|
||||
SetDefault();
|
||||
}
|
||||
|
||||
void CChannel::Init(uint32 _id, bool Is2D)
|
||||
{
|
||||
id = _id;
|
||||
if ( HasSource() )
|
||||
{
|
||||
alSourcei(alSources[id], AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
if ( IsFXSupported() )
|
||||
alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
|
||||
|
||||
if ( Is2D )
|
||||
{
|
||||
bIs2D = true;
|
||||
alSource3f(alSources[id], AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
alSourcef(alSources[id], AL_GAIN, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CChannel::Term()
|
||||
{
|
||||
Stop();
|
||||
if ( HasSource() )
|
||||
{
|
||||
if ( IsFXSupported() )
|
||||
{
|
||||
alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CChannel::Start()
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
if ( !Data ) return;
|
||||
|
||||
if ( bIs2D )
|
||||
{
|
||||
// convert mono data to stereo
|
||||
int16 *monoData = (int16*)Data;
|
||||
int16 *stereoData = (int16*)tempStereoBuffer;
|
||||
for (size_t i = 0; i < DataSize / 2; i++)
|
||||
{
|
||||
*(stereoData++) = *monoData;
|
||||
*(stereoData++) = *(monoData++);
|
||||
}
|
||||
alBufferData(alBuffers[id], AL_FORMAT_STEREO16, tempStereoBuffer, DataSize * 2, Frequency);
|
||||
}
|
||||
else
|
||||
alBufferData(alBuffers[id], AL_FORMAT_MONO16, Data, DataSize, Frequency);
|
||||
if ( LoopPoints[0] != 0 && LoopPoints[0] != -1 )
|
||||
alBufferiv(alBuffers[id], AL_LOOP_POINTS_SOFT, LoopPoints);
|
||||
alSourcei(alSources[id], AL_BUFFER, alBuffers[id]);
|
||||
alSourcePlay(alSources[id]);
|
||||
}
|
||||
|
||||
void CChannel::Stop()
|
||||
{
|
||||
if ( HasSource() )
|
||||
alSourceStop(alSources[id]);
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool CChannel::HasSource()
|
||||
{
|
||||
return alSources[id] != AL_NONE;
|
||||
}
|
||||
|
||||
bool CChannel::IsUsed()
|
||||
{
|
||||
if ( HasSource() )
|
||||
{
|
||||
ALint sourceState;
|
||||
alGetSourcei(alSources[id], AL_SOURCE_STATE, &sourceState);
|
||||
return sourceState == AL_PLAYING;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CChannel::SetPitch(float pitch)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSourcef(alSources[id], AL_PITCH, pitch);
|
||||
}
|
||||
|
||||
void CChannel::SetGain(float gain)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSourcef(alSources[id], AL_GAIN, gain);
|
||||
}
|
||||
|
||||
void CChannel::SetVolume(int32 vol)
|
||||
{
|
||||
SetGain(ALfloat(vol) / MAX_VOLUME);
|
||||
}
|
||||
|
||||
void CChannel::SetSampleData(void *_data, size_t _DataSize, int32 freq)
|
||||
{
|
||||
Data = _data;
|
||||
DataSize = _DataSize;
|
||||
Frequency = freq;
|
||||
}
|
||||
|
||||
void CChannel::SetCurrentFreq(uint32 freq)
|
||||
{
|
||||
SetPitch(ALfloat(freq) / Frequency);
|
||||
}
|
||||
|
||||
void CChannel::SetLoopCount(int32 count)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
|
||||
// 0: loop indefinitely, 1: play one time, 2: play two times etc...
|
||||
// only > 1 needs manual processing
|
||||
|
||||
if (LoopCount > 1 && count < 2)
|
||||
channelsThatNeedService--;
|
||||
else if (LoopCount < 2 && count > 1)
|
||||
channelsThatNeedService++;
|
||||
|
||||
alSourcei(alSources[id], AL_LOOPING, count == 1 ? AL_FALSE : AL_TRUE);
|
||||
LoopCount = count;
|
||||
}
|
||||
|
||||
bool CChannel::Update()
|
||||
{
|
||||
if (!HasSource()) return false;
|
||||
if (LoopCount < 2) return false;
|
||||
|
||||
ALint state;
|
||||
alGetSourcei(alSources[id], AL_SOURCE_STATE, &state);
|
||||
if (state == AL_STOPPED) {
|
||||
debug("Looping channels(%d in this case) shouldn't report AL_STOPPED, but nvm\n", id);
|
||||
SetLoopCount(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(channelsThatNeedService > 0 && "Ref counting is broken");
|
||||
|
||||
ALint offset;
|
||||
alGetSourcei(alSources[id], AL_SAMPLE_OFFSET, &offset);
|
||||
|
||||
// Rewound
|
||||
if (offset < LastProcessedOffset) {
|
||||
LoopCount--;
|
||||
if (LoopCount == 1) {
|
||||
// Playing last tune...
|
||||
channelsThatNeedService--;
|
||||
alSourcei(alSources[id], AL_LOOPING, AL_FALSE);
|
||||
}
|
||||
}
|
||||
LastProcessedOffset = offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CChannel::SetLoopPoints(ALint start, ALint end)
|
||||
{
|
||||
LoopPoints[0] = start;
|
||||
LoopPoints[1] = end;
|
||||
}
|
||||
|
||||
void CChannel::SetPosition(float x, float y, float z)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSource3f(alSources[id], AL_POSITION, x, y, z);
|
||||
}
|
||||
|
||||
void CChannel::SetDistances(float max, float min)
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSourcef (alSources[id], AL_MAX_DISTANCE, max);
|
||||
alSourcef (alSources[id], AL_REFERENCE_DISTANCE, min);
|
||||
alSourcef (alSources[id], AL_MAX_GAIN, 1.0f);
|
||||
alSourcef (alSources[id], AL_ROLLOFF_FACTOR, 1.0f);
|
||||
}
|
||||
|
||||
void CChannel::SetPan(int32 pan)
|
||||
{
|
||||
SetPosition((pan-63)/64.0f, 0.0f, Sqrt(1.0f-SQR((pan-63)/64.0f)));
|
||||
}
|
||||
|
||||
void CChannel::ClearBuffer()
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
alSourcei(alSources[id], AL_LOOPING, AL_FALSE);
|
||||
alSourcei(alSources[id], AL_BUFFER, AL_NONE);
|
||||
Data = nil;
|
||||
DataSize = 0;
|
||||
}
|
||||
|
||||
void CChannel::SetReverbMix(ALuint slot, float mix)
|
||||
{
|
||||
if ( !IsFXSupported() ) return;
|
||||
if ( !HasSource() ) return;
|
||||
if ( alFilters[id] == AL_FILTER_NULL ) return;
|
||||
|
||||
Mix = mix;
|
||||
EAX3_SetReverbMix(alFilters[id], mix);
|
||||
alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, slot, 0, alFilters[id]);
|
||||
}
|
||||
|
||||
void CChannel::UpdateReverb(ALuint slot)
|
||||
{
|
||||
if ( !IsFXSupported() ) return;
|
||||
if ( !HasSource() ) return;
|
||||
if ( alFilters[id] == AL_FILTER_NULL ) return;
|
||||
EAX3_SetReverbMix(alFilters[id], Mix);
|
||||
alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, slot, 0, alFilters[id]);
|
||||
}
|
||||
|
||||
#endif
|
||||
55
src/audio/oal/channel.h
Normal file
55
src/audio/oal/channel.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
#include "oal/oal_utils.h"
|
||||
#include <AL/al.h>
|
||||
#include <AL/alext.h>
|
||||
#include <AL/efx.h>
|
||||
|
||||
|
||||
class CChannel
|
||||
{
|
||||
uint32 id;
|
||||
float Pitch, Gain;
|
||||
float Mix;
|
||||
void *Data;
|
||||
size_t DataSize;
|
||||
int32 Frequency;
|
||||
float Position[3];
|
||||
float Distances[2];
|
||||
int32 LoopCount;
|
||||
ALint LoopPoints[2];
|
||||
ALint LastProcessedOffset;
|
||||
bool bIs2D;
|
||||
public:
|
||||
static int32 channelsThatNeedService;
|
||||
|
||||
static void InitChannels();
|
||||
static void DestroyChannels();
|
||||
|
||||
CChannel();
|
||||
void SetDefault();
|
||||
void Reset();
|
||||
void Init(uint32 _id, bool Is2D = false);
|
||||
void Term();
|
||||
void Start();
|
||||
void Stop();
|
||||
bool HasSource();
|
||||
bool IsUsed();
|
||||
void SetPitch(float pitch);
|
||||
void SetGain(float gain);
|
||||
void SetVolume(int32 vol);
|
||||
void SetSampleData(void *_data, size_t _DataSize, int32 freq);
|
||||
void SetCurrentFreq(uint32 freq);
|
||||
void SetLoopCount(int32 count);
|
||||
void SetLoopPoints(ALint start, ALint end);
|
||||
void SetPosition(float x, float y, float z);
|
||||
void SetDistances(float max, float min);
|
||||
void SetPan(int32 pan);
|
||||
void ClearBuffer();
|
||||
void SetReverbMix(ALuint slot, float mix);
|
||||
void UpdateReverb(ALuint slot);
|
||||
bool Update();
|
||||
};
|
||||
|
||||
#endif
|
||||
181
src/audio/oal/oal_utils.cpp
Normal file
181
src/audio/oal/oal_utils.cpp
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
#include "common.h"
|
||||
#include "oal_utils.h"
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
|
||||
/*
|
||||
* When linking to a static openal-soft library,
|
||||
* the extension function inside the openal library conflict with the variables here.
|
||||
* Therefore declare these re3 owned symbols in a private namespace.
|
||||
*/
|
||||
|
||||
namespace re3_openal {
|
||||
|
||||
LPALGENEFFECTS alGenEffects;
|
||||
LPALDELETEEFFECTS alDeleteEffects;
|
||||
LPALISEFFECT alIsEffect;
|
||||
LPALEFFECTI alEffecti;
|
||||
LPALEFFECTIV alEffectiv;
|
||||
LPALEFFECTF alEffectf;
|
||||
LPALEFFECTFV alEffectfv;
|
||||
LPALGETEFFECTI alGetEffecti;
|
||||
LPALGETEFFECTIV alGetEffectiv;
|
||||
LPALGETEFFECTF alGetEffectf;
|
||||
LPALGETEFFECTFV alGetEffectfv;
|
||||
LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
|
||||
LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
|
||||
LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
|
||||
LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
|
||||
LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
|
||||
LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
|
||||
LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
|
||||
LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
|
||||
LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
|
||||
LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
|
||||
LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
|
||||
LPALGENFILTERS alGenFilters;
|
||||
LPALDELETEFILTERS alDeleteFilters;
|
||||
LPALISFILTER alIsFilter;
|
||||
LPALFILTERI alFilteri;
|
||||
LPALFILTERIV alFilteriv;
|
||||
LPALFILTERF alFilterf;
|
||||
LPALFILTERFV alFilterfv;
|
||||
LPALGETFILTERI alGetFilteri;
|
||||
LPALGETFILTERIV alGetFilteriv;
|
||||
LPALGETFILTERF alGetFilterf;
|
||||
LPALGETFILTERFV alGetFilterfv;
|
||||
|
||||
}
|
||||
|
||||
using namespace re3_openal;
|
||||
|
||||
void EFXInit()
|
||||
{
|
||||
/* Define a macro to help load the function pointers. */
|
||||
#define LOAD_PROC(T, x) ((x) = (T)alGetProcAddress(#x))
|
||||
LOAD_PROC(LPALGENEFFECTS, alGenEffects);
|
||||
LOAD_PROC(LPALDELETEEFFECTS, alDeleteEffects);
|
||||
LOAD_PROC(LPALISEFFECT, alIsEffect);
|
||||
LOAD_PROC(LPALEFFECTI, alEffecti);
|
||||
LOAD_PROC(LPALEFFECTIV, alEffectiv);
|
||||
LOAD_PROC(LPALEFFECTF, alEffectf);
|
||||
LOAD_PROC(LPALEFFECTFV, alEffectfv);
|
||||
LOAD_PROC(LPALGETEFFECTI, alGetEffecti);
|
||||
LOAD_PROC(LPALGETEFFECTIV, alGetEffectiv);
|
||||
LOAD_PROC(LPALGETEFFECTF, alGetEffectf);
|
||||
LOAD_PROC(LPALGETEFFECTFV, alGetEffectfv);
|
||||
|
||||
LOAD_PROC(LPALGENFILTERS, alGenFilters);
|
||||
LOAD_PROC(LPALDELETEFILTERS, alDeleteFilters);
|
||||
LOAD_PROC(LPALISFILTER, alIsFilter);
|
||||
LOAD_PROC(LPALFILTERI, alFilteri);
|
||||
LOAD_PROC(LPALFILTERIV, alFilteriv);
|
||||
LOAD_PROC(LPALFILTERF, alFilterf);
|
||||
LOAD_PROC(LPALFILTERFV, alFilterfv);
|
||||
LOAD_PROC(LPALGETFILTERI, alGetFilteri);
|
||||
LOAD_PROC(LPALGETFILTERIV, alGetFilteriv);
|
||||
LOAD_PROC(LPALGETFILTERF, alGetFilterf);
|
||||
LOAD_PROC(LPALGETFILTERFV, alGetFilterfv);
|
||||
|
||||
LOAD_PROC(LPALGENAUXILIARYEFFECTSLOTS, alGenAuxiliaryEffectSlots);
|
||||
LOAD_PROC(LPALDELETEAUXILIARYEFFECTSLOTS, alDeleteAuxiliaryEffectSlots);
|
||||
LOAD_PROC(LPALISAUXILIARYEFFECTSLOT, alIsAuxiliaryEffectSlot);
|
||||
LOAD_PROC(LPALAUXILIARYEFFECTSLOTI, alAuxiliaryEffectSloti);
|
||||
LOAD_PROC(LPALAUXILIARYEFFECTSLOTIV, alAuxiliaryEffectSlotiv);
|
||||
LOAD_PROC(LPALAUXILIARYEFFECTSLOTF, alAuxiliaryEffectSlotf);
|
||||
LOAD_PROC(LPALAUXILIARYEFFECTSLOTFV, alAuxiliaryEffectSlotfv);
|
||||
LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTI, alGetAuxiliaryEffectSloti);
|
||||
LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTIV, alGetAuxiliaryEffectSlotiv);
|
||||
LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTF, alGetAuxiliaryEffectSlotf);
|
||||
LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTFV, alGetAuxiliaryEffectSlotfv);
|
||||
#undef LOAD_PROC
|
||||
}
|
||||
|
||||
void SetEffectsLevel(ALuint uiFilter, float level)
|
||||
{
|
||||
alFilteri(uiFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
|
||||
alFilterf(uiFilter, AL_LOWPASS_GAIN, 1.0f);
|
||||
alFilterf(uiFilter, AL_LOWPASS_GAINHF, level);
|
||||
}
|
||||
|
||||
static inline float gain_to_mB(float gain)
|
||||
{
|
||||
return (gain > 1e-5f) ? (float)(log10f(gain) * 2000.0f) : -10000l;
|
||||
}
|
||||
|
||||
static inline float mB_to_gain(float millibels)
|
||||
{
|
||||
return (millibels > -10000.0f) ? powf(10.0f, millibels/2000.0f) : 0.0f;
|
||||
}
|
||||
|
||||
static inline float clampF(float val, float minval, float maxval)
|
||||
{
|
||||
if(val >= maxval) return maxval;
|
||||
if(val <= minval) return minval;
|
||||
return val;
|
||||
}
|
||||
|
||||
void EAX3_Set(ALuint effect, const EAXLISTENERPROPERTIES *props)
|
||||
{
|
||||
alEffecti (effect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
|
||||
alEffectf (effect, AL_EAXREVERB_DENSITY, clampF(powf(props->flEnvironmentSize, 3.0f) / 16.0f, 0.0f, 1.0f));
|
||||
alEffectf (effect, AL_EAXREVERB_DIFFUSION, props->flEnvironmentDiffusion);
|
||||
alEffectf (effect, AL_EAXREVERB_GAIN, mB_to_gain((float)props->lRoom));
|
||||
alEffectf (effect, AL_EAXREVERB_GAINHF, mB_to_gain((float)props->lRoomHF));
|
||||
alEffectf (effect, AL_EAXREVERB_GAINLF, mB_to_gain((float)props->lRoomLF));
|
||||
alEffectf (effect, AL_EAXREVERB_DECAY_TIME, props->flDecayTime);
|
||||
alEffectf (effect, AL_EAXREVERB_DECAY_HFRATIO, props->flDecayHFRatio);
|
||||
alEffectf (effect, AL_EAXREVERB_DECAY_LFRATIO, props->flDecayLFRatio);
|
||||
alEffectf (effect, AL_EAXREVERB_REFLECTIONS_GAIN, clampF(mB_to_gain((float)props->lReflections), AL_EAXREVERB_MIN_REFLECTIONS_GAIN, AL_EAXREVERB_MAX_REFLECTIONS_GAIN));
|
||||
alEffectf (effect, AL_EAXREVERB_REFLECTIONS_DELAY, props->flReflectionsDelay);
|
||||
alEffectfv(effect, AL_EAXREVERB_REFLECTIONS_PAN, &props->vReflectionsPan.x);
|
||||
alEffectf (effect, AL_EAXREVERB_LATE_REVERB_GAIN, clampF(mB_to_gain((float)props->lReverb), AL_EAXREVERB_MIN_LATE_REVERB_GAIN, AL_EAXREVERB_MAX_LATE_REVERB_GAIN));
|
||||
alEffectf (effect, AL_EAXREVERB_LATE_REVERB_DELAY, props->flReverbDelay);
|
||||
alEffectfv(effect, AL_EAXREVERB_LATE_REVERB_PAN, &props->vReverbPan.x);
|
||||
alEffectf (effect, AL_EAXREVERB_ECHO_TIME, props->flEchoTime);
|
||||
alEffectf (effect, AL_EAXREVERB_ECHO_DEPTH, props->flEchoDepth);
|
||||
alEffectf (effect, AL_EAXREVERB_MODULATION_TIME, props->flModulationTime);
|
||||
alEffectf (effect, AL_EAXREVERB_MODULATION_DEPTH, props->flModulationDepth);
|
||||
alEffectf (effect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, clampF(mB_to_gain(props->flAirAbsorptionHF), AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF, AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF));
|
||||
alEffectf (effect, AL_EAXREVERB_HFREFERENCE, props->flHFReference);
|
||||
alEffectf (effect, AL_EAXREVERB_LFREFERENCE, props->flLFReference);
|
||||
alEffectf (effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, props->flRoomRolloffFactor);
|
||||
alEffecti (effect, AL_EAXREVERB_DECAY_HFLIMIT, (props->ulFlags&EAXLISTENERFLAGS_DECAYHFLIMIT) ? AL_TRUE : AL_FALSE);
|
||||
}
|
||||
|
||||
void EFX_Set(ALuint effect, const EAXLISTENERPROPERTIES *props)
|
||||
{
|
||||
alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
|
||||
|
||||
alEffectf(effect, AL_REVERB_DENSITY, clampF(powf(props->flEnvironmentSize, 3.0f) / 16.0f, 0.0f, 1.0f));
|
||||
alEffectf(effect, AL_REVERB_DIFFUSION, props->flEnvironmentDiffusion);
|
||||
alEffectf(effect, AL_REVERB_GAIN, mB_to_gain((float)props->lRoom));
|
||||
alEffectf(effect, AL_REVERB_GAINHF, mB_to_gain((float)props->lRoomHF));
|
||||
alEffectf(effect, AL_REVERB_DECAY_TIME, props->flDecayTime);
|
||||
alEffectf(effect, AL_REVERB_DECAY_HFRATIO, props->flDecayHFRatio);
|
||||
alEffectf(effect, AL_REVERB_REFLECTIONS_GAIN, clampF(mB_to_gain((float)props->lReflections), AL_EAXREVERB_MIN_REFLECTIONS_GAIN, AL_EAXREVERB_MAX_REFLECTIONS_GAIN));
|
||||
alEffectf(effect, AL_REVERB_REFLECTIONS_DELAY, props->flReflectionsDelay);
|
||||
alEffectf(effect, AL_REVERB_LATE_REVERB_GAIN, clampF(mB_to_gain((float)props->lReverb), AL_EAXREVERB_MIN_LATE_REVERB_GAIN, AL_EAXREVERB_MAX_LATE_REVERB_GAIN));
|
||||
alEffectf(effect, AL_REVERB_LATE_REVERB_DELAY, props->flReverbDelay);
|
||||
alEffectf(effect, AL_REVERB_AIR_ABSORPTION_GAINHF, clampF(mB_to_gain(props->flAirAbsorptionHF), AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF, AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF));
|
||||
alEffectf(effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, props->flRoomRolloffFactor);
|
||||
alEffecti(effect, AL_REVERB_DECAY_HFLIMIT, (props->ulFlags&EAXLISTENERFLAGS_DECAYHFLIMIT) ? AL_TRUE : AL_FALSE);
|
||||
}
|
||||
|
||||
void EAX3_SetReverbMix(ALuint filter, float mix)
|
||||
{
|
||||
//long vol=(long)linear_to_dB(mix);
|
||||
//DSPROPERTY_EAXBUFFER_ROOMHF,
|
||||
//DSPROPERTY_EAXBUFFER_ROOM,
|
||||
//DSPROPERTY_EAXBUFFER_REVERBMIX,
|
||||
|
||||
long mbvol = gain_to_mB(mix);
|
||||
float mb = mbvol;
|
||||
float mbhf = mbvol;
|
||||
|
||||
alFilteri(filter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
|
||||
alFilterf(filter, AL_LOWPASS_GAIN, mB_to_gain(Min(mb, 0.0f)));
|
||||
alFilterf(filter, AL_LOWPASS_GAINHF, mB_to_gain(mbhf));
|
||||
}
|
||||
|
||||
#endif
|
||||
54
src/audio/oal/oal_utils.h
Normal file
54
src/audio/oal/oal_utils.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
#include "eax.h"
|
||||
#include "AL/efx.h"
|
||||
|
||||
|
||||
void EFXInit();
|
||||
void EAX3_Set(ALuint effect, const EAXLISTENERPROPERTIES *props);
|
||||
void EFX_Set(ALuint effect, const EAXLISTENERPROPERTIES *props);
|
||||
void EAX3_SetReverbMix(ALuint filter, float mix);
|
||||
void SetEffectsLevel(ALuint uiFilter, float level);
|
||||
|
||||
namespace re3_openal {
|
||||
|
||||
extern LPALGENEFFECTS alGenEffects;
|
||||
extern LPALDELETEEFFECTS alDeleteEffects;
|
||||
extern LPALISEFFECT alIsEffect;
|
||||
extern LPALEFFECTI alEffecti;
|
||||
extern LPALEFFECTIV alEffectiv;
|
||||
extern LPALEFFECTF alEffectf;
|
||||
extern LPALEFFECTFV alEffectfv;
|
||||
extern LPALGETEFFECTI alGetEffecti;
|
||||
extern LPALGETEFFECTIV alGetEffectiv;
|
||||
extern LPALGETEFFECTF alGetEffectf;
|
||||
extern LPALGETEFFECTFV alGetEffectfv;
|
||||
extern LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
|
||||
extern LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
|
||||
extern LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
|
||||
extern LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
|
||||
extern LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
|
||||
extern LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
|
||||
extern LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
|
||||
extern LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
|
||||
extern LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
|
||||
extern LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
|
||||
extern LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
|
||||
extern LPALGENFILTERS alGenFilters;
|
||||
extern LPALDELETEFILTERS alDeleteFilters;
|
||||
extern LPALISFILTER alIsFilter;
|
||||
extern LPALFILTERI alFilteri;
|
||||
extern LPALFILTERIV alFilteriv;
|
||||
extern LPALFILTERF alFilterf;
|
||||
extern LPALFILTERFV alFilterfv;
|
||||
extern LPALGETFILTERI alGetFilteri;
|
||||
extern LPALGETFILTERIV alGetFilteriv;
|
||||
extern LPALGETFILTERF alGetFilterf;
|
||||
extern LPALGETFILTERFV alGetFilterfv;
|
||||
|
||||
}
|
||||
|
||||
using namespace re3_openal;
|
||||
|
||||
#endif
|
||||
1759
src/audio/oal/stream.cpp
Normal file
1759
src/audio/oal/stream.cpp
Normal file
File diff suppressed because it is too large
Load diff
192
src/audio/oal/stream.h
Normal file
192
src/audio/oal/stream.h
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
#include <AL/al.h>
|
||||
|
||||
#define NUM_STREAMBUFFERS 8
|
||||
|
||||
class IDecoder
|
||||
{
|
||||
public:
|
||||
virtual ~IDecoder() { }
|
||||
|
||||
virtual bool IsOpened() = 0;
|
||||
virtual void FileOpen() = 0;
|
||||
|
||||
virtual uint32 GetSampleSize() = 0;
|
||||
virtual uint32 GetSampleCount() = 0;
|
||||
virtual uint32 GetSampleRate() = 0;
|
||||
virtual uint32 GetChannels() = 0;
|
||||
|
||||
uint32 GetAvgSamplesPerSec()
|
||||
{
|
||||
return GetChannels() * GetSampleRate();
|
||||
}
|
||||
|
||||
uint32 ms2samples(uint32 ms)
|
||||
{
|
||||
return float(ms) / 1000.0f * float(GetSampleRate());
|
||||
}
|
||||
|
||||
uint32 samples2ms(uint32 sm)
|
||||
{
|
||||
return float(sm) * 1000.0f / float(GetSampleRate());
|
||||
}
|
||||
|
||||
uint32 GetBufferSamples()
|
||||
{
|
||||
//return (GetAvgSamplesPerSec() >> 2) - (GetSampleCount() % GetChannels());
|
||||
return (GetAvgSamplesPerSec() / 4); // 250ms
|
||||
}
|
||||
|
||||
uint32 GetBufferSize()
|
||||
{
|
||||
return GetBufferSamples() * GetSampleSize();
|
||||
}
|
||||
|
||||
virtual void Seek(uint32 milliseconds) = 0;
|
||||
virtual uint32 Tell() = 0;
|
||||
|
||||
uint32 GetLength()
|
||||
{
|
||||
FileOpen(); // abort deferred init, we need length now - game has to cache audio file sizes
|
||||
return float(GetSampleCount()) * 1000.0f / float(GetSampleRate());
|
||||
}
|
||||
|
||||
virtual uint32 Decode(void *buffer) = 0;
|
||||
};
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
template <typename T> class tsQueue
|
||||
{
|
||||
public:
|
||||
tsQueue() : count(0) { }
|
||||
|
||||
void push(const T &value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_queue.push(value);
|
||||
count++;
|
||||
}
|
||||
|
||||
bool peekPop(T *retVal)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (count == 0)
|
||||
return false;
|
||||
|
||||
*retVal = m_queue.front();
|
||||
m_queue.pop();
|
||||
count--;
|
||||
return true;
|
||||
}
|
||||
|
||||
void swapNts(tsQueue<T> &replaceWith)
|
||||
{
|
||||
m_queue.swap(replaceWith.m_queue);
|
||||
replaceWith.count = count;
|
||||
}
|
||||
|
||||
/*
|
||||
void swapTs(tsQueue<T> &replaceWith)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock2(replaceWith.m_mutex);
|
||||
swapNts(replaceWith);
|
||||
}
|
||||
*/
|
||||
|
||||
bool emptyNts()
|
||||
{
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
bool emptyTs()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return emptyNts();
|
||||
}
|
||||
*/
|
||||
|
||||
std::queue<T> m_queue;
|
||||
int count;
|
||||
mutable std::mutex m_mutex;
|
||||
};
|
||||
#endif
|
||||
class CStream
|
||||
{
|
||||
char m_aFilename[128];
|
||||
ALuint *m_pAlSources;
|
||||
ALuint (&m_alBuffers)[NUM_STREAMBUFFERS];
|
||||
|
||||
bool m_bPaused;
|
||||
bool m_bActive;
|
||||
|
||||
public:
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::mutex m_mutex;
|
||||
std::queue<std::pair<ALuint, ALuint>> m_fillBuffers; // left and right buffer
|
||||
tsQueue<std::pair<ALuint, ALuint>> m_queueBuffers;
|
||||
// std::condition_variable m_closeCv;
|
||||
bool m_bDoSeek;
|
||||
uint32 m_SeekPos;
|
||||
bool m_bIExist;
|
||||
#endif
|
||||
|
||||
void *m_pBuffer;
|
||||
|
||||
bool m_bReset;
|
||||
uint32 m_nVolume;
|
||||
uint8 m_nPan;
|
||||
uint32 m_nPosBeforeReset;
|
||||
int32 m_nLoopCount;
|
||||
|
||||
IDecoder *m_pSoundFile;
|
||||
|
||||
void BuffersShouldBeFilled(); // all
|
||||
bool BufferShouldBeFilledAndQueued(std::pair<ALuint, ALuint>*); // two (left-right)
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
void FlagAsToBeProcessed(bool close = false);
|
||||
bool QueueBuffers();
|
||||
#endif
|
||||
|
||||
bool HasSource();
|
||||
void SetPosition(int i, float x, float y, float z);
|
||||
void SetPitch(float pitch);
|
||||
void SetGain(float gain);
|
||||
void Pause();
|
||||
void SetPlay(bool state);
|
||||
|
||||
bool FillBuffer(ALuint *alBuffer);
|
||||
int32 FillBuffers();
|
||||
void ClearBuffers();
|
||||
//public:
|
||||
static void Initialise();
|
||||
static void Terminate();
|
||||
|
||||
CStream(ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS]);
|
||||
~CStream();
|
||||
void Delete();
|
||||
bool Open(const char *filename, uint32 overrideSampleRate = 32000);
|
||||
void Close();
|
||||
|
||||
bool IsOpened();
|
||||
bool IsPlaying();
|
||||
void SetPause (bool bPause);
|
||||
void SetVolume(uint32 nVol);
|
||||
void SetPan (uint8 nPan);
|
||||
void SetPosMS (uint32 nPos);
|
||||
uint32 GetPosMS();
|
||||
uint32 GetLengthMS();
|
||||
|
||||
bool Setup(bool imSureQueueIsEmpty = false, bool lock = true);
|
||||
void Start();
|
||||
void Stop();
|
||||
void Update(void);
|
||||
void SetLoopCount(int32);
|
||||
|
||||
void ProviderInit();
|
||||
void ProviderTerm();
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue