2020-06-04 15:28:45 +00:00
|
|
|
|
#include "AudioCapture.h"
|
|
|
|
|
#include "Debuger.h"
|
|
|
|
|
PaStream *gStreamOut = nullptr;
|
|
|
|
|
|
|
|
|
|
CaptureAudio::CaptureAudio(uint16_t rate, uint8_t channel) {
|
|
|
|
|
this->mChanel = channel;
|
|
|
|
|
this->mSampleRate = rate;
|
|
|
|
|
this->mSize = 0;
|
|
|
|
|
this->mStatus = FAIL;
|
|
|
|
|
this->observer = nullptr;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CaptureAudio::SetObserver(CaptureAudioObserver* ob) {
|
|
|
|
|
if (nullptr == ob) return -1;
|
|
|
|
|
this->observer = ob;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int paOutStreamBkss(const void* input, void* output, unsigned long frameCount,
|
|
|
|
|
const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void * userData)
|
|
|
|
|
{
|
|
|
|
|
CaptureAudio *pCap;
|
|
|
|
|
Debuger::Debug(L"%d\r\n", frameCount);
|
|
|
|
|
if (userData != nullptr) {
|
|
|
|
|
pCap = (CaptureAudio *)userData;
|
|
|
|
|
pCap->OnCallBack(input,output,frameCount);
|
|
|
|
|
}
|
|
|
|
|
pCap->AddCnt(4 * frameCount);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CaptureAudio::OnCallBack(const void* input, void* output, unsigned long frameCount) {
|
|
|
|
|
if(nullptr != this->observer)
|
|
|
|
|
this->observer->OnAudioData(input, frameCount);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CaptureAudio::~CaptureAudio() {
|
|
|
|
|
if(mInStream != nullptr)
|
|
|
|
|
Pa_CloseStream(mInStream);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CaptureAudio::StartCapture()
|
|
|
|
|
{
|
|
|
|
|
PaError err = paNoError;
|
|
|
|
|
if (this->mStatus == RUNNING) {
|
|
|
|
|
err = Pa_StartStream(mInStream);
|
|
|
|
|
if (err != paNoError) {
|
|
|
|
|
this->mStatus = FAIL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector<CaptureAudio::MICInfo> CaptureAudio::EnumSpeakers()
|
|
|
|
|
{
|
|
|
|
|
vector<CaptureAudio::MICInfo> ret;
|
|
|
|
|
PaError err = Pa_Initialize();
|
|
|
|
|
if (err != paNoError) {
|
|
|
|
|
Debuger::Debug(L"init stream error\r\n");
|
|
|
|
|
mStatus = FAIL;
|
|
|
|
|
}
|
|
|
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD>豸<EFBFBD><E8B1B8><EFBFBD><EFBFBD>
|
|
|
|
|
PaDeviceIndex iNumDevices = Pa_GetDeviceCount();
|
|
|
|
|
if (iNumDevices <= 0)
|
|
|
|
|
{
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < iNumDevices; i++)
|
|
|
|
|
{
|
|
|
|
|
MICInfo ins;
|
|
|
|
|
ins.index = i;
|
|
|
|
|
const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i);
|
|
|
|
|
if (nullptr != deviceInfo)
|
|
|
|
|
if (deviceInfo->maxInputChannels > 0) {
|
|
|
|
|
ins.name = deviceInfo->name;
|
|
|
|
|
ret.push_back(ins);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CaptureAudio::InitCapture(int index,uint16_t rate, uint8_t channel) {
|
|
|
|
|
PaStreamParameters intputParameters;
|
|
|
|
|
PaError err = paNoError;
|
|
|
|
|
err = Pa_Initialize();
|
|
|
|
|
if (err != paNoError) goto error;
|
|
|
|
|
if (index < 0)
|
|
|
|
|
{
|
|
|
|
|
index = Pa_GetDefaultInputDevice();
|
|
|
|
|
}
|
|
|
|
|
if (paNoDevice == index) {
|
|
|
|
|
mStatus = FAIL;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
intputParameters.device = index;
|
|
|
|
|
intputParameters.channelCount = 2;
|
|
|
|
|
intputParameters.sampleFormat = paInt16;
|
|
|
|
|
intputParameters.suggestedLatency = Pa_GetDeviceInfo(intputParameters.device)->defaultLowInputLatency;
|
|
|
|
|
intputParameters.hostApiSpecificStreamInfo = NULL;
|
|
|
|
|
|
|
|
|
|
err = Pa_OpenStream(&mInStream, &intputParameters, NULL, 44100, 1024,
|
|
|
|
|
paFramesPerBufferUnspecified, paOutStreamBkss, this);
|
|
|
|
|
if (err != paNoError) {
|
|
|
|
|
this->mStatus = FAIL;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
this->mStatus = RUNNING;
|
|
|
|
|
return 0;
|
|
|
|
|
error:
|
|
|
|
|
Pa_Terminate();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CaptureAudio::StopCapture()
|
|
|
|
|
{
|
|
|
|
|
if (this->mStatus == RUNNING) {
|
|
|
|
|
Pa_StopStream(mInStream);
|
|
|
|
|
this->mStatus = STOP;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-06-19 17:10:03 +00:00
|
|
|
|
std::string WString2String(const std::wstring& ws)
|
|
|
|
|
{
|
|
|
|
|
std::string strLocale = setlocale(LC_ALL, "");
|
|
|
|
|
const wchar_t* wchSrc = ws.c_str();
|
|
|
|
|
size_t nDestSize = wcstombs(NULL, wchSrc, 0) + 1;
|
|
|
|
|
char *chDest = new char[nDestSize];
|
|
|
|
|
memset(chDest, 0, nDestSize);
|
|
|
|
|
wcstombs(chDest, wchSrc, nDestSize);
|
|
|
|
|
std::string strResult = chDest;
|
|
|
|
|
delete[]chDest;
|
|
|
|
|
setlocale(LC_ALL, strLocale.c_str());
|
|
|
|
|
return strResult;
|
|
|
|
|
}
|
|
|
|
|
vector<CaptureAudioFfmpeg::MICInfo> CaptureAudioFfmpeg::EnumSpeakers()
|
2020-06-19 09:30:29 +00:00
|
|
|
|
{
|
2020-06-19 17:10:03 +00:00
|
|
|
|
vector<CaptureAudioFfmpeg::MICInfo> ret;
|
|
|
|
|
std::vector<std::wstring> names;
|
|
|
|
|
IEnumMoniker *pEnum = nullptr;
|
|
|
|
|
// Create the System Device Enumerator.
|
|
|
|
|
ICreateDevEnum *pDevEnum;
|
|
|
|
|
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr,
|
|
|
|
|
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
{
|
|
|
|
|
// Create an enumerator for the category.
|
|
|
|
|
hr = pDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEnum, 0);
|
|
|
|
|
if (hr == S_FALSE)
|
|
|
|
|
{
|
|
|
|
|
hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error.
|
|
|
|
|
}
|
|
|
|
|
pDevEnum->Release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!SUCCEEDED(hr))
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
IMoniker *pMoniker = nullptr;
|
|
|
|
|
while (pEnum->Next(1, &pMoniker, nullptr) == S_OK)
|
|
|
|
|
{
|
|
|
|
|
IPropertyBag *pPropBag;
|
|
|
|
|
IBindCtx* bindCtx = nullptr;
|
|
|
|
|
LPOLESTR str = nullptr;
|
|
|
|
|
VARIANT var;
|
|
|
|
|
VariantInit(&var);
|
|
|
|
|
|
|
|
|
|
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
|
|
|
|
|
if (FAILED(hr))
|
|
|
|
|
{
|
|
|
|
|
pMoniker->Release();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-06-19 09:30:29 +00:00
|
|
|
|
|
2020-06-19 17:10:03 +00:00
|
|
|
|
// Get description or friendly name.
|
|
|
|
|
hr = pPropBag->Read(L"Description", &var, 0);
|
|
|
|
|
if (FAILED(hr))
|
|
|
|
|
{
|
|
|
|
|
hr = pPropBag->Read(L"FriendlyName", &var, 0);
|
|
|
|
|
}
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
{
|
|
|
|
|
names.push_back(var.bstrVal);
|
|
|
|
|
std::string x = WString2String(var.bstrVal);
|
|
|
|
|
CaptureAudioFfmpeg::MICInfo ele;
|
|
|
|
|
ele.name = x;
|
|
|
|
|
ret.push_back(ele);
|
|
|
|
|
VariantClear(&var);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pPropBag->Release();
|
|
|
|
|
pMoniker->Release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pEnum->Release();
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CaptureAudioFfmpeg::CaptureAudioFfmpeg(uint16_t rate, uint8_t channel)
|
|
|
|
|
{
|
2020-06-19 09:30:29 +00:00
|
|
|
|
|
|
|
|
|
}
|