#ifndef __KINECTAUDIOSTREAM_H__
#define __KINECTAUDIOSTREAM_H__
#pragma once
#include <dmo.h>
#include <mmreg.h>
#include <avrt.h>
#include <stack>
#include <queue>
static const WORD AudioFormat = WAVE_FORMAT_PCM;
static const WORD AudioChannels = 1;
static const DWORD AudioSamplesPerSecond = 16000;
static const DWORD AudioAverageBytesPerSecond = 32000;
static const WORD AudioBlockAlign = 2;
static const WORD AudioBitsPerSample = 16;
class CStaticMediaBuffer : public IMediaBuffer
{
public:
CStaticMediaBuffer() : m_dataLength(0) {}
STDMETHODIMP_(ULONG) AddRef() { return 2; }
STDMETHODIMP_(ULONG) Release() { return 1; }
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
if (riid == IID_IUnknown)
{
AddRef();
*ppv = (IUnknown*)this;
return NOERROR;
}
else if (riid == IID_IMediaBuffer)
{
AddRef();
*ppv = (IMediaBuffer*)this;
return NOERROR;
}
else
{
return E_NOINTERFACE;
}
}
STDMETHODIMP SetLength(DWORD
length) {m_dataLength =
length;
return NOERROR;}
STDMETHODIMP GetMaxLength(DWORD *pMaxLength) {*pMaxLength = sizeof(m_pData); return NOERROR;}
STDMETHODIMP GetBufferAndLength(
BYTE **ppBuffer, DWORD *pLength)
{
if (ppBuffer)
{
*ppBuffer = m_pData;
}
if (pLength)
{
*pLength = m_dataLength;
}
return NOERROR;
}
void Init(ULONG ulData)
{
m_dataLength = ulData;
}
protected:
BYTE m_pData[AudioSamplesPerSecond * AudioBlockAlign];
ULONG m_dataLength;
};
class KinectAudioStream : public IStream
{
public:
KinectAudioStream(IMediaObject *pKinectDmo);
virtual ~KinectAudioStream();
HRESULT StartCapture();
HRESULT StopCapture();
STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&m_cRef); }
STDMETHODIMP_(ULONG) Release()
{
UINT ref = InterlockedDecrement(&m_cRef);
if (ref == 0)
{
delete this;
}
return ref;
}
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
if (riid == IID_IUnknown)
{
AddRef();
*ppv = (IUnknown*)this;
return S_OK;
}
else if (riid == IID_IStream)
{
AddRef();
*ppv = (IStream*)this;
return S_OK;
}
else
{
return E_NOINTERFACE;
}
}
STDMETHODIMP Read(void *,ULONG,ULONG *);
STDMETHODIMP Write(const void *,ULONG,ULONG *);
STDMETHODIMP Seek(LARGE_INTEGER,DWORD,ULARGE_INTEGER *);
STDMETHODIMP SetSize(ULARGE_INTEGER);
STDMETHODIMP CopyTo(IStream *,ULARGE_INTEGER,ULARGE_INTEGER *,ULARGE_INTEGER *);
STDMETHODIMP Commit(DWORD);
STDMETHODIMP Revert();
STDMETHODIMP LockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD);
STDMETHODIMP UnlockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD);
STDMETHODIMP Stat(STATSTG *,DWORD);
STDMETHODIMP Clone(IStream **);
private:
static const UINT NumBuffers = 20;
typedef std::stack<CStaticMediaBuffer*> BufferPool;
typedef std::queue<CStaticMediaBuffer*> CircularBufferQueue;
UINT m_cRef;
IMediaObject* m_pKinectDmo;
HANDLE m_hStopEvent;
HANDLE m_hDataReady;
HANDLE m_hCaptureThread;
BufferPool m_BufferPool;
CircularBufferQueue m_ReadBufferQueue;
CStaticMediaBuffer* m_CurrentWriteBuffer;
CStaticMediaBuffer* m_CurrentReadBuffer;
ULONG m_CurrentReadBufferIndex;
ULONG m_BytesRead;
CRITICAL_SECTION m_Lock;
CStaticMediaBuffer* GetWriteBuffer();
void ReleaseBuffer(CStaticMediaBuffer* pBuffer);
void ReleaseAllBuffers();
void QueueCapturedData(
BYTE *pData, UINT cbData);
void QueueCapturedBuffer(CStaticMediaBuffer *pBuffer);
void ReadOneBuffer(
BYTE **ppbData, ULONG* pcbData);
static DWORD WINAPI CaptureThread(LPVOID pParam);
DWORD WINAPI CaptureThread();
BOOL IsCapturing()
{
return (m_hStopEvent !=
NULL) && (WaitForSingleObject(m_hStopEvent,0) != WAIT_OBJECT_0);
}
};
#endif