rtphone/src/engine/audio/Audio_Helper.cpp

151 lines
3.0 KiB
C++

/* Copyright(C) 2007-2014 VoIP objects (voipobjects.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef TARGET_WIN
# include <WinSock2.h>
#endif
#include <assert.h>
#include "Audio_Helper.h"
#include "../helper/HL_Exception.h"
using namespace Audio;
// --- QPCSource
TimeSource::TimeSource(int quantTime, int nrOfQuants)
{
#ifdef TARGET_WIN
mCounter.QuadPart = 0;
#endif
#if defined(TARGET_OSX) || defined(TARGET_IOS)
mach_timebase_info(&mTimebase);
mRatio = ((double)mTimebase.numer / (double)mTimebase.denom) / 1000000;
#endif
mQuantTime = quantTime;
mDepthTime = quantTime * nrOfQuants;
mTailTime = 0;
}
void TimeSource::start()
{
#ifdef TARGET_WIN
if (!QueryPerformanceFrequency(&mFreq))
throw Exception(ERR_QPC, GetLastError());
if (!QueryPerformanceCounter(&mCounter))
throw Exception(ERR_QPC, GetLastError());
#endif
}
void TimeSource::stop()
{
}
unsigned TimeSource::time()
{
#ifdef TARGET_WIN
LARGE_INTEGER c;
if (!QueryPerformanceCounter(&c))
throw Exception(ERR_QPC, GetLastError());
//find the f
double f = (double)mFreq.QuadPart / 1000.0;
//find the difference
unsigned __int64 diff = c.QuadPart - mCounter.QuadPart;
mCounter.QuadPart = c.QuadPart;
diff = (unsigned __int64)((double)diff / f + 0.5); //get ms
diff += mTailTime;
if (diff > mDepthTime)
{
mTailTime = 0;
return mDepthTime;
}
else
{
mTailTime = (unsigned )(diff % (unsigned __int64)mQuantTime);
unsigned int t = (unsigned )(diff / (unsigned __int64)mQuantTime);
return t * mQuantTime;
}
#endif
#if defined(TARGET_OSX) || defined(TARGET_IOS)
uint64_t t = mach_absolute_time();
uint64_t c = uint64_t((double)t * mRatio + 0.5);
uint64_t diff = c - this->mTime + mTailTime;
mTime = c;
if (diff > mDepthTime)
{
mTailTime = 0;
return mDepthTime;
}
else
{
mTailTime = diff % mQuantTime;
uint64_t t = diff / mQuantTime;
return t * mQuantTime;
}
#endif
#if defined(TARGET_LINUX)
assert(0);
#endif
#if defined(TARGET_ANDROID)
assert(0);
#endif
return 0;
}
// --- StubTimer ---
StubTimer::StubTimer(int bufferTime, int bufferCount)
:mBufferTime(bufferTime), mBufferCount(bufferCount), mTimeSource(bufferTime, bufferCount), mActive(false), mCurrentTime(0)
{
#ifdef TARGET_WIN
mStubSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
#endif
}
StubTimer::~StubTimer()
{
#ifdef TARGET_WIN
::CloseHandle(mStubSignal);
#endif
}
void StubTimer::start()
{
mTimeSource.start();
mCurrentTime = mTimeSource.time();
mActive = true;
}
void StubTimer::stop()
{
mTimeSource.stop();
mActive = false;
}
void StubTimer::waitForBuffer()
{
if (!mActive)
start();
unsigned t = mTimeSource.time();
while (!t)
{
#ifdef TARGET_WIN
::WaitForSingleObject(mStubSignal, mBufferTime);
#endif
#if defined(TARGET_OSX) || defined(TARGET_IOS)
usleep(100);
#endif
t = mTimeSource.time();
}
}