Files
2026-11-07 13:30:45 +07:00

295 lines
6.7 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#include <process.h>
#include "BandiVideoSound_NULL.h"
CBandiVideoSound_NULL::CBandiVideoSound_NULL() : m_ref_count(0)
{
m_init_count = 0;
m_start_time = 0;
memset(&m_crit_sec, NULL, sizeof(m_crit_sec));
m_crit_sec_inited = FALSE;
m_playing = FALSE;
m_hevent = NULL;
m_hthread = NULL;
m_thread_id = 0;
m_callback = NULL;
// Performance Frequency ±¸Çϱâ
LARGE_INTEGER freq = {0, 0};
QueryPerformanceFrequency(&freq);
m_freq_units = freq.QuadPart;
}
CBandiVideoSound_NULL::~CBandiVideoSound_NULL()
{
Close();
}
STDMETHODIMP_(ULONG) CBandiVideoSound_NULL::AddRef()
{
LONG lRef = InterlockedIncrement( &m_ref_count );
ASSERT(lRef >= 0);
return m_ref_count;
}
STDMETHODIMP_(ULONG) CBandiVideoSound_NULL::Release()
{
LONG lRef = InterlockedDecrement( &m_ref_count );
ASSERT(lRef >= 0);
if(lRef == 0)
{
delete this;
return ULONG(0);
}
return m_ref_count;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Open sound device.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::Open(INT channels, INT samplerate, IBandiVideoSoundCB *callback)
{
InitializeCriticalSection(&m_crit_sec);
m_crit_sec_inited = TRUE;
// Create an event object for periodical processing
m_hevent = CreateEvent(NULL, FALSE, FALSE, NULL); // auto reset event
if(m_hevent == NULL)
goto error;
// Create thread for playback
m_hthread = (HANDLE)_beginthreadex(NULL, 0, InitialThreadProc, this, CREATE_SUSPENDED, &m_thread_id);
if(m_hthread == NULL)
goto error;
m_callback = callback;
SetThreadPriority(m_hthread, THREAD_PRIORITY_TIME_CRITICAL);
ResumeThread(m_hthread);
return S_OK;
error:
Close();
return E_FAIL;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Close sound device.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
void CBandiVideoSound_NULL::Close()
{
HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hthread, 0);
if(hThread)
{
if(m_hevent) SetEvent(m_hevent);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
if(m_hevent)
{
CloseHandle(m_hevent);
m_hevent = NULL;
}
if(m_crit_sec_inited)
{
DeleteCriticalSection(&m_crit_sec);
m_crit_sec_inited = FALSE;
}
m_init_count = 0;
m_start_time = 0;
}
static LONGLONG GetPerformanceCounter()
{
LARGE_INTEGER count;
::QueryPerformanceCounter(&count);
return count.QuadPart;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Start
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::Start()
{
EnterCriticalSection(&m_crit_sec);
{
m_init_count = GetPerformanceCounter();
m_start_time = 0;
m_playing = TRUE;
}
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Stop
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::Stop()
{
EnterCriticalSection(&m_crit_sec);
{
m_start_time = 0;
m_playing = FALSE;
}
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Stop
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::Pause(BOOL pause)
{
EnterCriticalSection(&m_crit_sec);
{
if(pause)
{
m_start_time = CalcTime();
m_playing = FALSE;
}
else
{
m_init_count = GetPerformanceCounter();
m_playing = TRUE;
}
}
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Get play time (100nsec units)
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::GetTime(INT64 &time)
{
EnterCriticalSection(&m_crit_sec);
{
time = CalcTime();
}
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Set sound volume
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::SetVolume(INT volume)
{
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// ThreadProc
///
////////////////////////////////////////////////////////////////////////////////////////////////////
UINT CBandiVideoSound_NULL::ThreadProc()
{
BOOL bWorking = FALSE;
while(m_hthread)
{
EnterCriticalSection(&m_crit_sec);
{
if(m_playing)
PlayNULL();
}
LeaveCriticalSection(&m_crit_sec);
WaitForSingleObject(m_hevent, 10);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Play NullSound
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::PlayNULL()
{
if(m_callback)
{
INT16 buf[1024*2];
m_callback->GetPcmData(buf, 1024);
}
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Calculate current time
///
////////////////////////////////////////////////////////////////////////////////////////////////////
LONGLONG CBandiVideoSound_NULL::CalcTime()
{
LONGLONG ret;
LONGLONG delta_time = 0;
EnterCriticalSection(&m_crit_sec);
{
if(m_playing && m_freq_units)
delta_time = LONGLONG(double(GetPerformanceCounter() - m_init_count)/(double)m_freq_units*10000000.0);
ret = m_start_time + delta_time;
}
LeaveCriticalSection(&m_crit_sec);
return ret;
}