mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
b=815643 Add Blink's HRTFDatabase and HRTFDatabaseLoader to the build r=ehsan
--HG-- extra : rebase_source : e7aa0ce1ca436bbb429cb1f6051b3b8210bf767a
This commit is contained in:
parent
76ae42715c
commit
296268450d
@ -26,15 +26,9 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "HRTFDatabase.h"
|
||||
|
||||
#if ENABLE(WEB_AUDIO)
|
||||
|
||||
#include "core/platform/audio/HRTFDatabase.h"
|
||||
|
||||
#include "core/platform/PlatformMemoryInstrumentation.h"
|
||||
#include "core/platform/audio/HRTFElevation.h"
|
||||
#include <wtf/MemoryInstrumentationVector.h>
|
||||
#include "HRTFElevation.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -47,24 +41,24 @@ const unsigned HRTFDatabase::NumberOfRawElevations = 10; // -45 -> +90 (each 15
|
||||
const unsigned HRTFDatabase::InterpolationFactor = 1;
|
||||
const unsigned HRTFDatabase::NumberOfTotalElevations = NumberOfRawElevations * InterpolationFactor;
|
||||
|
||||
PassOwnPtr<HRTFDatabase> HRTFDatabase::create(float sampleRate)
|
||||
nsReturnRef<HRTFDatabase> HRTFDatabase::create(float sampleRate)
|
||||
{
|
||||
OwnPtr<HRTFDatabase> hrtfDatabase = adoptPtr(new HRTFDatabase(sampleRate));
|
||||
return hrtfDatabase.release();
|
||||
return nsReturnRef<HRTFDatabase>(new HRTFDatabase(sampleRate));
|
||||
}
|
||||
|
||||
HRTFDatabase::HRTFDatabase(float sampleRate)
|
||||
: m_elevations(NumberOfTotalElevations)
|
||||
, m_sampleRate(sampleRate)
|
||||
: m_sampleRate(sampleRate)
|
||||
{
|
||||
m_elevations.SetLength(NumberOfTotalElevations);
|
||||
|
||||
unsigned elevationIndex = 0;
|
||||
for (int elevation = MinElevation; elevation <= MaxElevation; elevation += RawElevationAngleSpacing) {
|
||||
OwnPtr<HRTFElevation> hrtfElevation = HRTFElevation::createForSubject("Composite", elevation, sampleRate);
|
||||
ASSERT(hrtfElevation.get());
|
||||
nsAutoRef<HRTFElevation> hrtfElevation(HRTFElevation::createBuiltin(elevation, sampleRate));
|
||||
MOZ_ASSERT(hrtfElevation.get());
|
||||
if (!hrtfElevation.get())
|
||||
return;
|
||||
|
||||
m_elevations[elevationIndex] = hrtfElevation.release();
|
||||
m_elevations[elevationIndex] = hrtfElevation.out();
|
||||
elevationIndex += InterpolationFactor;
|
||||
}
|
||||
|
||||
@ -79,7 +73,7 @@ HRTFDatabase::HRTFDatabase(float sampleRate)
|
||||
for (unsigned jj = 1; jj < InterpolationFactor; ++jj) {
|
||||
float x = static_cast<float>(jj) / static_cast<float>(InterpolationFactor);
|
||||
m_elevations[i + jj] = HRTFElevation::createByInterpolatingSlices(m_elevations[i].get(), m_elevations[j].get(), x, sampleRate);
|
||||
ASSERT(m_elevations[i + jj].get());
|
||||
MOZ_ASSERT(m_elevations[i + jj].get());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,19 +83,19 @@ void HRTFDatabase::getKernelsFromAzimuthElevation(double azimuthBlend, unsigned
|
||||
double& frameDelayL, double& frameDelayR)
|
||||
{
|
||||
unsigned elevationIndex = indexFromElevationAngle(elevationAngle);
|
||||
ASSERT_WITH_SECURITY_IMPLICATION(elevationIndex < m_elevations.size() && m_elevations.size() > 0);
|
||||
MOZ_ASSERT(elevationIndex < m_elevations.Length() && m_elevations.Length() > 0);
|
||||
|
||||
if (!m_elevations.size()) {
|
||||
if (!m_elevations.Length()) {
|
||||
kernelL = 0;
|
||||
kernelR = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (elevationIndex > m_elevations.size() - 1)
|
||||
elevationIndex = m_elevations.size() - 1;
|
||||
if (elevationIndex > m_elevations.Length() - 1)
|
||||
elevationIndex = m_elevations.Length() - 1;
|
||||
|
||||
HRTFElevation* hrtfElevation = m_elevations[elevationIndex].get();
|
||||
ASSERT(hrtfElevation);
|
||||
MOZ_ASSERT(hrtfElevation);
|
||||
if (!hrtfElevation) {
|
||||
kernelL = 0;
|
||||
kernelR = 0;
|
||||
@ -114,19 +108,12 @@ void HRTFDatabase::getKernelsFromAzimuthElevation(double azimuthBlend, unsigned
|
||||
unsigned HRTFDatabase::indexFromElevationAngle(double elevationAngle)
|
||||
{
|
||||
// Clamp to allowed range.
|
||||
elevationAngle = max(static_cast<double>(MinElevation), elevationAngle);
|
||||
elevationAngle = min(static_cast<double>(MaxElevation), elevationAngle);
|
||||
elevationAngle = mozilla::clamped(elevationAngle,
|
||||
static_cast<double>(MinElevation),
|
||||
static_cast<double>(MaxElevation));
|
||||
|
||||
unsigned elevationIndex = static_cast<int>(InterpolationFactor * (elevationAngle - MinElevation) / RawElevationAngleSpacing);
|
||||
return elevationIndex;
|
||||
}
|
||||
|
||||
void HRTFDatabase::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
|
||||
{
|
||||
MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::AudioSharedData);
|
||||
info.addMember(m_elevations, "elevations");
|
||||
}
|
||||
|
||||
} // namespace WebCore
|
||||
|
||||
#endif // ENABLE(WEB_AUDIO)
|
||||
|
@ -29,21 +29,17 @@
|
||||
#ifndef HRTFDatabase_h
|
||||
#define HRTFDatabase_h
|
||||
|
||||
#include "core/platform/audio/HRTFElevation.h"
|
||||
#include <wtf/Forward.h>
|
||||
#include <wtf/Noncopyable.h>
|
||||
#include <wtf/OwnPtr.h>
|
||||
#include <wtf/PassRefPtr.h>
|
||||
#include <wtf/Vector.h>
|
||||
#include "HRTFElevation.h"
|
||||
#include "nsAutoRef.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace WebCore {
|
||||
|
||||
class HRTFKernel;
|
||||
|
||||
class HRTFDatabase {
|
||||
WTF_MAKE_NONCOPYABLE(HRTFDatabase);
|
||||
public:
|
||||
static PassOwnPtr<HRTFDatabase> create(float sampleRate);
|
||||
static nsReturnRef<HRTFDatabase> create(float sampleRate);
|
||||
|
||||
// getKernelsFromAzimuthElevation() returns a left and right ear kernel, and an interpolated left and right frame delay for the given azimuth and elevation.
|
||||
// azimuthBlend must be in the range 0 -> 1.
|
||||
@ -59,9 +55,10 @@ public:
|
||||
// Number of elevations loaded from resource.
|
||||
static const unsigned NumberOfRawElevations;
|
||||
|
||||
void reportMemoryUsage(MemoryObjectInfo*) const;
|
||||
|
||||
private:
|
||||
HRTFDatabase(const HRTFDatabase& other) MOZ_DELETE;
|
||||
void operator=(const HRTFDatabase& other) MOZ_DELETE;
|
||||
|
||||
explicit HRTFDatabase(float sampleRate);
|
||||
|
||||
// Minimum and maximum elevation angles (inclusive) for a HRTFDatabase.
|
||||
@ -78,10 +75,17 @@ private:
|
||||
// Returns the index for the correct HRTFElevation given the elevation angle.
|
||||
static unsigned indexFromElevationAngle(double);
|
||||
|
||||
Vector<OwnPtr<HRTFElevation> > m_elevations;
|
||||
nsTArray<nsAutoRef<HRTFElevation> > m_elevations;
|
||||
float m_sampleRate;
|
||||
};
|
||||
|
||||
} // namespace WebCore
|
||||
|
||||
template <>
|
||||
class nsAutoRefTraits<WebCore::HRTFDatabase> :
|
||||
public nsPointerRefTraits<WebCore::HRTFDatabase> {
|
||||
public:
|
||||
static void Release(WebCore::HRTFDatabase* ptr) { delete(ptr); }
|
||||
};
|
||||
|
||||
#endif // HRTFDatabase_h
|
||||
|
@ -26,39 +26,38 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "HRTFDatabaseLoader.h"
|
||||
|
||||
#if ENABLE(WEB_AUDIO)
|
||||
#include "HRTFDatabase.h"
|
||||
|
||||
#include "core/platform/audio/HRTFDatabaseLoader.h"
|
||||
|
||||
#include "core/platform/PlatformMemoryInstrumentation.h"
|
||||
#include "core/platform/audio/HRTFDatabase.h"
|
||||
#include "wtf/MainThread.h"
|
||||
#include "wtf/MemoryInstrumentationHashMap.h"
|
||||
using namespace mozilla;
|
||||
|
||||
namespace WebCore {
|
||||
|
||||
// Singleton
|
||||
HRTFDatabaseLoader::LoaderMap* HRTFDatabaseLoader::s_loaderMap = 0;
|
||||
nsTHashtable<HRTFDatabaseLoader::LoaderByRateEntry>*
|
||||
HRTFDatabaseLoader::s_loaderMap = nullptr;
|
||||
|
||||
PassRefPtr<HRTFDatabaseLoader> HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(float sampleRate)
|
||||
TemporaryRef<HRTFDatabaseLoader> HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(float sampleRate)
|
||||
{
|
||||
ASSERT(isMainThread());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<HRTFDatabaseLoader> loader;
|
||||
|
||||
if (!s_loaderMap)
|
||||
s_loaderMap = adoptPtr(new LoaderMap()).leakPtr();
|
||||
if (!s_loaderMap) {
|
||||
s_loaderMap = new nsTHashtable<LoaderByRateEntry>();
|
||||
s_loaderMap->Init();
|
||||
}
|
||||
|
||||
loader = s_loaderMap->get(sampleRate);
|
||||
if (loader) {
|
||||
ASSERT(sampleRate == loader->databaseSampleRate());
|
||||
LoaderByRateEntry* entry = s_loaderMap->PutEntry(sampleRate);
|
||||
loader = entry->mLoader;
|
||||
if (loader) { // existing entry
|
||||
MOZ_ASSERT(sampleRate == loader->databaseSampleRate());
|
||||
return loader;
|
||||
}
|
||||
|
||||
loader = adoptRef(new HRTFDatabaseLoader(sampleRate));
|
||||
s_loaderMap->add(sampleRate, loader.get());
|
||||
loader = new HRTFDatabaseLoader(sampleRate);
|
||||
entry->mLoader = loader;
|
||||
|
||||
loader->loadAsynchronously();
|
||||
|
||||
@ -66,35 +65,41 @@ PassRefPtr<HRTFDatabaseLoader> HRTFDatabaseLoader::createAndLoadAsynchronouslyIf
|
||||
}
|
||||
|
||||
HRTFDatabaseLoader::HRTFDatabaseLoader(float sampleRate)
|
||||
: m_databaseLoaderThread(0)
|
||||
: m_threadLock("HRTFDatabaseLoader")
|
||||
, m_databaseLoaderThread(nullptr)
|
||||
, m_databaseSampleRate(sampleRate)
|
||||
{
|
||||
ASSERT(isMainThread());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
HRTFDatabaseLoader::~HRTFDatabaseLoader()
|
||||
{
|
||||
ASSERT(isMainThread());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
waitForLoaderThreadCompletion();
|
||||
m_hrtfDatabase.clear();
|
||||
m_hrtfDatabase.reset();
|
||||
|
||||
// Remove ourself from the map.
|
||||
if (s_loaderMap)
|
||||
s_loaderMap->remove(m_databaseSampleRate);
|
||||
s_loaderMap->RemoveEntry(m_databaseSampleRate);
|
||||
if (s_loaderMap->Count() == 0) {
|
||||
delete s_loaderMap;
|
||||
s_loaderMap = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Asynchronously load the database in this thread.
|
||||
static void databaseLoaderEntry(void* threadData)
|
||||
{
|
||||
PR_SetCurrentThreadName("HRTFDatabaseLdr");
|
||||
|
||||
HRTFDatabaseLoader* loader = reinterpret_cast<HRTFDatabaseLoader*>(threadData);
|
||||
ASSERT(loader);
|
||||
MOZ_ASSERT(loader);
|
||||
loader->load();
|
||||
}
|
||||
|
||||
void HRTFDatabaseLoader::load()
|
||||
{
|
||||
ASSERT(!isMainThread());
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
if (!m_hrtfDatabase.get()) {
|
||||
// Load the default HRTF database.
|
||||
m_hrtfDatabase = HRTFDatabase::create(m_databaseSampleRate);
|
||||
@ -103,13 +108,16 @@ void HRTFDatabaseLoader::load()
|
||||
|
||||
void HRTFDatabaseLoader::loadAsynchronously()
|
||||
{
|
||||
ASSERT(isMainThread());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
MutexLocker locker(m_threadLock);
|
||||
MutexAutoLock locker(m_threadLock);
|
||||
|
||||
if (!m_hrtfDatabase.get() && !m_databaseLoaderThread) {
|
||||
// Start the asynchronous database loading process.
|
||||
m_databaseLoaderThread = createThread(databaseLoaderEntry, this, "HRTF database loader");
|
||||
m_databaseLoaderThread =
|
||||
PR_CreateThread(PR_USER_THREAD, databaseLoaderEntry, this,
|
||||
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
|
||||
PR_JOINABLE_THREAD, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,21 +128,14 @@ bool HRTFDatabaseLoader::isLoaded() const
|
||||
|
||||
void HRTFDatabaseLoader::waitForLoaderThreadCompletion()
|
||||
{
|
||||
MutexLocker locker(m_threadLock);
|
||||
MutexAutoLock locker(m_threadLock);
|
||||
|
||||
// waitForThreadCompletion() should not be called twice for the same thread.
|
||||
if (m_databaseLoaderThread)
|
||||
waitForThreadCompletion(m_databaseLoaderThread);
|
||||
m_databaseLoaderThread = 0;
|
||||
}
|
||||
|
||||
void HRTFDatabaseLoader::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
|
||||
{
|
||||
MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::AudioSharedData);
|
||||
info.addMember(m_hrtfDatabase, "hrtfDatabase");
|
||||
info.addMember(s_loaderMap, "loaderMap", WTF::RetainingPointer);
|
||||
if (m_databaseLoaderThread) {
|
||||
DebugOnly<PRStatus> status = PR_JoinThread(m_databaseLoaderThread);
|
||||
MOZ_ASSERT(status == PR_SUCCESS, "PR_JoinThread failed");
|
||||
}
|
||||
m_databaseLoaderThread = nullptr;
|
||||
}
|
||||
|
||||
} // namespace WebCore
|
||||
|
||||
#endif // ENABLE(WEB_AUDIO)
|
||||
|
@ -29,24 +29,23 @@
|
||||
#ifndef HRTFDatabaseLoader_h
|
||||
#define HRTFDatabaseLoader_h
|
||||
|
||||
#include "core/platform/audio/HRTFDatabase.h"
|
||||
#include "wtf/HashMap.h"
|
||||
#include "wtf/PassRefPtr.h"
|
||||
#include "wtf/RefCounted.h"
|
||||
#include "wtf/RefPtr.h"
|
||||
#include "wtf/Threading.h"
|
||||
#include "HRTFDatabase.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsIThread.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
namespace WebCore {
|
||||
|
||||
// HRTFDatabaseLoader will asynchronously load the default HRTFDatabase in a new thread.
|
||||
|
||||
class HRTFDatabaseLoader : public RefCounted<HRTFDatabaseLoader> {
|
||||
class HRTFDatabaseLoader : public mozilla::RefCounted<HRTFDatabaseLoader> {
|
||||
public:
|
||||
// Lazily creates a HRTFDatabaseLoader (if not already created) for the given sample-rate
|
||||
// and starts loading asynchronously (when created the first time).
|
||||
// Returns the HRTFDatabaseLoader.
|
||||
// Must be called from the main thread.
|
||||
static PassRefPtr<HRTFDatabaseLoader> createAndLoadAsynchronouslyIfNecessary(float sampleRate);
|
||||
static mozilla::TemporaryRef<HRTFDatabaseLoader> createAndLoadAsynchronouslyIfNecessary(float sampleRate);
|
||||
|
||||
// Both constructor and destructor must be called from the main thread.
|
||||
~HRTFDatabaseLoader();
|
||||
@ -54,7 +53,8 @@ public:
|
||||
// Returns true once the default database has been completely loaded.
|
||||
bool isLoaded() const;
|
||||
|
||||
// waitForLoaderThreadCompletion() may be called more than once and is thread-safe.
|
||||
// waitForLoaderThreadCompletion() may be called more than once,
|
||||
// on any thread except m_databaseLoaderThread.
|
||||
void waitForLoaderThreadCompletion();
|
||||
|
||||
HRTFDatabase* database() { return m_hrtfDatabase.get(); }
|
||||
@ -64,8 +64,6 @@ public:
|
||||
// Called in asynchronous loading thread.
|
||||
void load();
|
||||
|
||||
void reportMemoryUsage(MemoryObjectInfo*) const;
|
||||
|
||||
private:
|
||||
// Both constructor and destructor must be called from the main thread.
|
||||
explicit HRTFDatabaseLoader(float sampleRate);
|
||||
@ -75,16 +73,23 @@ private:
|
||||
void loadAsynchronously();
|
||||
|
||||
// Map from sample-rate to loader.
|
||||
typedef HashMap<double, HRTFDatabaseLoader*> LoaderMap;
|
||||
|
||||
class LoaderByRateEntry : public nsFloatHashKey {
|
||||
public:
|
||||
LoaderByRateEntry(KeyTypePointer aKey)
|
||||
: nsFloatHashKey(aKey)
|
||||
, mLoader() // so PutEntry() will zero-initialize
|
||||
{
|
||||
}
|
||||
HRTFDatabaseLoader* mLoader;
|
||||
};
|
||||
// Keeps track of loaders on a per-sample-rate basis.
|
||||
static LoaderMap* s_loaderMap; // singleton
|
||||
static nsTHashtable<LoaderByRateEntry> *s_loaderMap; // singleton
|
||||
|
||||
OwnPtr<HRTFDatabase> m_hrtfDatabase;
|
||||
nsAutoRef<HRTFDatabase> m_hrtfDatabase;
|
||||
|
||||
// Holding a m_threadLock is required when accessing m_databaseLoaderThread.
|
||||
Mutex m_threadLock;
|
||||
ThreadIdentifier m_databaseLoaderThread;
|
||||
mozilla::Mutex m_threadLock;
|
||||
PRThread* m_databaseLoaderThread;
|
||||
|
||||
float m_databaseSampleRate;
|
||||
};
|
||||
|
@ -12,6 +12,8 @@ CPP_SOURCES += [
|
||||
'DynamicsCompressor.cpp',
|
||||
'DynamicsCompressorKernel.cpp',
|
||||
'FFTConvolver.cpp',
|
||||
'HRTFDatabase.cpp',
|
||||
'HRTFDatabaseLoader.cpp',
|
||||
'HRTFElevation.cpp',
|
||||
'HRTFKernel.cpp',
|
||||
'Reverb.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user