mirror of
https://github.com/darlinghq/darling-openal.git
synced 2024-11-23 04:09:42 +00:00
196 lines
7.0 KiB
C++
196 lines
7.0 KiB
C++
/**********************************************************************************************************************************
|
|
*
|
|
* OpenAL cross platform audio library
|
|
* Copyright (c) 2004, Apple Computer, Inc., Copyright (c) 2012, Apple 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:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
* 2. 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.
|
|
* 3. Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS
|
|
* 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.
|
|
*
|
|
**********************************************************************************************************************************/
|
|
|
|
#ifndef __OAL_DEVICE__
|
|
#define __OAL_DEVICE__
|
|
|
|
#include <Carbon/Carbon.h>
|
|
#include <CoreAudio/AudioHardware.h>
|
|
#include <AudioToolbox/AudioToolbox.h>
|
|
#include <AudioUnit/AudioUnit.h>
|
|
#include <libkern/OSAtomic.h>
|
|
#include <map>
|
|
|
|
#include "oalImp.h"
|
|
|
|
#include "CAStreamBasicDescription.h"
|
|
|
|
|
|
class OALContext; // forward declaration
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Some build flags for gathering performance and data flow information
|
|
|
|
#if USE_AU_TRACER
|
|
#include "AUTracer.h"
|
|
#endif
|
|
|
|
#if DEBUG
|
|
#define AUHAL_LOG_OUTPUT 0
|
|
#endif
|
|
|
|
#if AUHAL_LOG_OUTPUT
|
|
#include "AudioLogger.h"
|
|
#endif
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Device Constants
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
// Default Mixer Output Sample Rate Setting:
|
|
#define kDefaultMixerRate 44100.0
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// OALDevices
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
#pragma mark _____OALDevice_____
|
|
class OALDevice
|
|
{
|
|
public:
|
|
|
|
OALDevice(const char* inDeviceName, uintptr_t inSelfToken, UInt32 inRenderChannelSetting);
|
|
~OALDevice();
|
|
|
|
void ConnectContext (OALContext* inContext);
|
|
void DisconnectContext (OALContext* inContext);
|
|
void RemoveContext (OALContext* inContext);
|
|
void StopGraph();
|
|
|
|
// thread safety
|
|
volatile int32_t IsInUse() { return mInUseFlag; }
|
|
void SetInUseFlag() { OSAtomicIncrement32Barrier(&mInUseFlag); }
|
|
void ClearInUseFlag() { OSAtomicDecrement32Barrier(&mInUseFlag); }
|
|
|
|
// set info
|
|
void SetRenderChannelSetting (UInt32 inRenderChannelSetting);
|
|
void SetError(ALenum errorCode);
|
|
|
|
// get info
|
|
uintptr_t GetDeviceToken () const { return mSelfToken; }
|
|
Float64 GetDeviceSampleRate () const { return mDeviceSampleRate; }
|
|
UInt32 GetRenderChannelSetting() { return mRenderChannelSetting; }
|
|
ALenum GetError();
|
|
UInt32 GetFramesPerSlice() { return mFramesPerSlice;}
|
|
AUGraph GetGraph () {return mAUGraph;}
|
|
AudioUnit GetOutputAU(){return mOutputUnit;}
|
|
OSStatus UpdateDeviceChannelLayout();
|
|
UInt32 GetDesiredRenderChannelCount ();
|
|
|
|
// misc.
|
|
bool IsValidRenderQuality (UInt32 inRenderQuality);
|
|
static void GraphFormatPropertyListener ( void *inRefCon,
|
|
AudioUnit ci,
|
|
AudioUnitPropertyID inID,
|
|
AudioUnitScope inScope,
|
|
AudioUnitElement inElement);
|
|
|
|
bool IsGraphStillRunning ()
|
|
{
|
|
Boolean running;
|
|
OSStatus result = AUGraphIsRunning (mAUGraph, &running);
|
|
THROW_RESULT
|
|
return bool(running);
|
|
}
|
|
|
|
void Print () const
|
|
{
|
|
#if DEBUG || CoreAudio_Debug
|
|
CAShow (mAUGraph);
|
|
#endif
|
|
}
|
|
|
|
private:
|
|
uintptr_t mSelfToken;
|
|
ALenum mCurrentError;
|
|
AudioDeviceID mHALDevice; // the HAL device used to render audio to the user
|
|
bool mDistanceScalingRequired;
|
|
bool mGraphInitialized;
|
|
AUGraph mAUGraph;
|
|
AUNode mOutputNode;
|
|
AudioUnit mOutputUnit;
|
|
AUNode mMixerNode;
|
|
AudioChannelLayoutTag mChannelLayoutTag;
|
|
OALContext* mConnectedContext;
|
|
Float64 mDeviceSampleRate;
|
|
UInt32 mRenderChannelCount;
|
|
UInt32 mRenderChannelSetting; // currently either stereo or multichannel
|
|
UInt32 mFramesPerSlice;
|
|
volatile int32_t mInUseFlag; // flag to indicate if the device is currently being edited by one or more threads
|
|
#if AUHAL_LOG_OUTPUT
|
|
AudioLogger mLogger;
|
|
#endif
|
|
#if USE_AU_TRACER
|
|
AUTracer mAUTracer;
|
|
#endif
|
|
|
|
void InitializeGraph (const char* inDeviceName);
|
|
void TeardownGraph();
|
|
void ResetRenderChannelSettings();
|
|
AudioChannelLayoutTag GetLayoutTagForLayout(AudioChannelLayout *inLayout, UInt32 inNumChannels);
|
|
UInt32 GetChannelLayoutTag();
|
|
};
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
#pragma mark _____OALDeviceMap_____
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
class OALDeviceMap : std::multimap<uintptr_t, OALDevice*, std::less<uintptr_t> > {
|
|
public:
|
|
|
|
void Add (const uintptr_t inDeviceToken, OALDevice **inDevice) {
|
|
iterator it = upper_bound(inDeviceToken);
|
|
insert(it, value_type (inDeviceToken, *inDevice));
|
|
}
|
|
|
|
OALDevice* Get(uintptr_t inDeviceToken) {
|
|
iterator it = find(inDeviceToken);
|
|
if (it != end())
|
|
return ((*it).second);
|
|
return (NULL);
|
|
}
|
|
|
|
OALDevice* GetDeviceByIndex(UInt32 inIndex, uintptr_t &outDeviceToken) {
|
|
iterator it = begin();
|
|
std::advance(it, inIndex);
|
|
if (it != end())
|
|
{
|
|
outDeviceToken = (*it).first;
|
|
return (*it).second;
|
|
}
|
|
return (NULL);
|
|
}
|
|
|
|
void Remove (const uintptr_t inDeviceToken) {
|
|
iterator it = find(inDeviceToken);
|
|
if (it != end())
|
|
erase(it);
|
|
}
|
|
|
|
UInt32 Size () const { return size(); }
|
|
bool Empty () const { return empty(); }
|
|
};
|
|
|
|
#endif
|