JACKAudioSource::JACKAudioSource(UINT inputSamplesPerSec) { bool bFloat = true; UINT inputChannels = 2; UINT inputBitsPerSample = sizeof(float)*8; UINT inputBlockSize = sizeof(float) * inputChannels; sampleFrameCount = inputSamplesPerSec/100; sampleSegmentSize = inputBlockSize*sampleFrameCount; outputBuffer.SetSize(sampleSegmentSize); sampleBuffer = jack_ringbuffer_create(sampleSegmentSize * 5); assert(!jack_ringbuffer_mlock(sampleBuffer)); InitAudioData(bFloat, inputChannels, inputSamplesPerSec, inputBitsPerSample, inputBlockSize, 0); API->AddAudioSource(this); }
bool PipeAudioSource::Initialize(PipeVideo *parent, const AudioParam& param) { m_iLastPts = 0; m_iBlockSize = 0; Times = 0; LimitGetData = 0; m_PipeVideo = parent; if (!hAudioMutex) { hAudioMutex = OSCreateMutex(); } bool bFloat = false; UINT inputChannels; UINT inputSamplesPerSec; UINT inputBitsPerSample; DWORD inputChannelMask; inputBitsPerSample = param.bitsPerSample; // 16; inputChannelMask = 0; inputChannels = param.channels; // 1; inputSamplesPerSec = param.samplesPerSec; // 8000; m_iBlockSize = inputChannels * inputBitsPerSample / 8; sampleFrameCount = inputSamplesPerSec / 100; sampleSegmentSize = m_iBlockSize * sampleFrameCount; Param = param; m_isFirstDiffTimeWithAPI = true; m_lTimeDiffWithAPI = 0; m_iLastTimeStamp = 0; outputBuffer.SetSize(sampleSegmentSize); InitAudioData(bFloat, inputChannels, inputSamplesPerSec, inputBitsPerSample, m_iBlockSize, inputChannelMask); if (m_pAudioWaveOut) { m_pAudioWaveOut->Uninitialize(); } String strReanderName = GetDirectorMonitorDevices(); if (NULL == m_pAudioWaveOut) { if (!strReanderName.Compare(TEXT("停用")) && !m_pAudioWaveOut) { m_pAudioWaveOut = new AudioWaveOut; } } else { if ((strReanderName.Compare(TEXT("Disable")) || strReanderName.Compare(TEXT("停用")))) { delete m_pAudioWaveOut; m_pAudioWaveOut = NULL; } } if (NULL != m_pAudioWaveOut) { m_pAudioWaveOut->Initialize(strReanderName.Array(), 2, inputSamplesPerSec, inputBitsPerSample); } String SecRenderName = GetSecMonitorDevices(); if (m_pSecWaveOut) { m_pSecWaveOut->Uninitialize(); } if (SecRenderName.CompareI(strReanderName.Array()) && (!SecRenderName.Compare(TEXT("Disable")) || !SecRenderName.Compare(TEXT("停用")))) { bSameDevice = true; } else if (!SecRenderName.Compare(TEXT("停用")) && !m_pSecWaveOut) { m_pSecWaveOut = new AudioWaveOut; } else if (m_pSecWaveOut) { if ((SecRenderName.Compare(TEXT("Disable")) || SecRenderName.Compare(TEXT("停用")))) { delete m_pSecWaveOut; m_pSecWaveOut = NULL; } } if (m_pSecWaveOut) { m_pSecWaveOut->Initialize(SecRenderName.Array(), 2, inputSamplesPerSec, inputBitsPerSample); } return true; }
bool MMDeviceAudioSource::Initialize(bool bMic, CTSTR lpID) { const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); const IID IID_IAudioClient = __uuidof(IAudioClient); const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient); HRESULT err; err = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&mmEnumerator); if(FAILED(err)) { AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not create IMMDeviceEnumerator = %08lX"), (BOOL)bMic, err); return false; } bIsMic = bMic; if (bIsMic) { BOOL bMicSyncFixHack = GlobalConfig->GetInt(TEXT("Audio"), TEXT("UseMicSyncFixHack")); angerThreshold = bMicSyncFixHack ? 40 : 1000; } if (scmpi(lpID, TEXT("Default")) == 0) err = mmEnumerator->GetDefaultAudioEndpoint(bMic ? eCapture : eRender, bMic ? eCommunications : eConsole, &mmDevice); else err = mmEnumerator->GetDevice(lpID, &mmDevice); if(FAILED(err)) { AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not create IMMDevice = %08lX"), (BOOL)bMic, err); return false; } err = mmDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&mmClient); if(FAILED(err)) { AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not create IAudioClient = %08lX"), (BOOL)bMic, err); return false; } //----------------------------------------------------------------- // get name IPropertyStore *store; if(SUCCEEDED(mmDevice->OpenPropertyStore(STGM_READ, &store))) { PROPVARIANT varName; PropVariantInit(&varName); if(SUCCEEDED(store->GetValue(PKEY_Device_FriendlyName, &varName))) { CWSTR wstrName = varName.pwszVal; strDeviceName = wstrName; } store->Release(); } if(bMic) { Log(TEXT("------------------------------------------")); Log(TEXT("Using auxilary audio input: %s"), GetDeviceName()); bUseQPC = GlobalConfig->GetInt(TEXT("Audio"), TEXT("UseMicQPC")) != 0; if (bUseQPC) Log(TEXT("Using Mic QPC timestamps")); } else { Log(TEXT("------------------------------------------")); Log(TEXT("Using desktop audio input: %s"), GetDeviceName()); bUseVideoTime = AppConfig->GetInt(TEXT("Audio"), TEXT("SyncToVideoTime")) != 0; SetTimeOffset(GlobalConfig->GetInt(TEXT("Audio"), TEXT("GlobalAudioTimeAdjust"))); } //----------------------------------------------------------------- // get format WAVEFORMATEX *pwfx; err = mmClient->GetMixFormat(&pwfx); if(FAILED(err)) { AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not get mix format from audio client = %08lX"), (BOOL)bMic, err); return false; } bool bFloat; UINT inputChannels; UINT inputSamplesPerSec; UINT inputBitsPerSample; UINT inputBlockSize; DWORD inputChannelMask = 0; WAVEFORMATEXTENSIBLE *wfext = NULL; //the internal audio engine should always use floats (or so I read), but I suppose just to be safe better check if(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) { wfext = (WAVEFORMATEXTENSIBLE*)pwfx; inputChannelMask = wfext->dwChannelMask; if(wfext->SubFormat != KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) { AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Unsupported wave format"), (BOOL)bMic); return false; } } else if(pwfx->wFormatTag != WAVE_FORMAT_IEEE_FLOAT) { AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Unsupported wave format"), (BOOL)bMic); return false; } bFloat = true; inputChannels = pwfx->nChannels; inputBitsPerSample = 32; inputBlockSize = pwfx->nBlockAlign; inputSamplesPerSec = pwfx->nSamplesPerSec; sampleWindowSize = (inputSamplesPerSec/100); DWORD flags = bMic ? 0 : AUDCLNT_STREAMFLAGS_LOOPBACK; err = mmClient->Initialize(AUDCLNT_SHAREMODE_SHARED, flags, ConvertMSTo100NanoSec(5000), 0, pwfx, NULL); //err = AUDCLNT_E_UNSUPPORTED_FORMAT; if (err == AUDCLNT_E_UNSUPPORTED_FORMAT) { //workaround for razer kraken headset (bad drivers) pwfx->nBlockAlign = 2*pwfx->nChannels; pwfx->nAvgBytesPerSec = inputSamplesPerSec*pwfx->nBlockAlign; pwfx->wBitsPerSample = 16; wfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wfext->Samples.wValidBitsPerSample = 16; bConvert = true; err = mmClient->Initialize(AUDCLNT_SHAREMODE_SHARED, flags, ConvertMSTo100NanoSec(5000), 0, pwfx, NULL); } if(FAILED(err)) { AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not initialize audio client, result = %08lX"), (BOOL)bMic, err); return false; } //----------------------------------------------------------------- // acquire services err = mmClient->GetService(IID_IAudioCaptureClient, (void**)&mmCapture); if(FAILED(err)) { AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not get audio capture client, result = %08lX"), (BOOL)bMic, err); return false; } err = mmClient->GetService(__uuidof(IAudioClock), (void**)&mmClock); if(FAILED(err)) { AppWarning(TEXT("MMDeviceAudioSource::Initialize(%d): Could not get audio capture clock, result = %08lX"), (BOOL)bMic, err); return false; } CoTaskMemFree(pwfx); //----------------------------------------------------------------- InitAudioData(bFloat, inputChannels, inputSamplesPerSec, inputBitsPerSample, inputBlockSize, inputChannelMask); return true; }
/************************************************** 重置音频参数函数 参数: sAudioParam :设置音频参数,采样率,采样位,声道 ***************************************************/ void CDemandMediaAudio::ResetAudioParam(const AudioParam & sAudioParam) { Log::writeMessage(LOG_RTSPSERV, 1, "%s invoke begin!",__FUNCTION__); EnterCriticalSection(&sampleBufferLock); m_sAudioParam = sAudioParam; m_bisFloat = false; bSameDevice = false; m_uBlockSize = sAudioParam.iChannel * sAudioParam.iBitPerSample / 8; if (m_pAudioWaveOut) { m_pAudioWaveOut->Uninitialize(); } String strReanderName = GetDirectorMonitorDevices(); if (NULL == m_pAudioWaveOut) { if (!strReanderName.Compare(TEXT("停用")) && !m_pAudioWaveOut) { m_pAudioWaveOut = new AudioWaveOut; } } else { if ((strReanderName.Compare(TEXT("Disable")) || strReanderName.Compare(TEXT("停用")))) { delete m_pAudioWaveOut; m_pAudioWaveOut = NULL; } } if (NULL != m_pAudioWaveOut) { if (sAudioParam.iChannel > 2) { m_bisFloat = true; m_pAudioWaveOut->Initialize(strReanderName.Array(), 2, sAudioParam.iSamplesPerSec, sAudioParam.iBitPerSample * 2); } else { m_pAudioWaveOut->Initialize(strReanderName.Array(), 2, sAudioParam.iSamplesPerSec, sAudioParam.iBitPerSample); } } String SecRenderName = GetSecMonitorDevices(); if (m_pSecWaveOut) { m_pSecWaveOut->Uninitialize(); } if (SecRenderName.CompareI(strReanderName.Array()) && (!SecRenderName.Compare(TEXT("Disable")) || !SecRenderName.Compare(TEXT("停用")))) { bSameDevice = true; } else if (!SecRenderName.Compare(TEXT("停用")) && !m_pSecWaveOut) { m_pSecWaveOut = new AudioWaveOut; } else if (m_pSecWaveOut) { if ((SecRenderName.Compare(TEXT("Disable")) || SecRenderName.Compare(TEXT("停用")))) { delete m_pSecWaveOut; m_pSecWaveOut = NULL; } } if (m_pSecWaveOut) { if (sAudioParam.iChannel > 2) { m_bisFloat = true; m_pSecWaveOut->Initialize(SecRenderName.Array(), 2, sAudioParam.iSamplesPerSec, sAudioParam.iBitPerSample * 2); } else { m_pSecWaveOut->Initialize(SecRenderName.Array(), 2, sAudioParam.iSamplesPerSec, sAudioParam.iBitPerSample); } } sampleFrameCount = m_sAudioParam.iSamplesPerSec / 100; if (m_bisFloat) { InitAudioData(m_bisFloat, 2, m_sAudioParam.iSamplesPerSec, m_sAudioParam.iBitPerSample * 2, m_uBlockSize, m_uchannelMask); sampleSegmentSize = 4 * sampleFrameCount * sizeof(float) * 8 / m_sAudioParam.iBitPerSample;//4 又声道的BlockSize,2为转为short转float后扩大2倍 } else { InitAudioData(m_bisFloat, m_sAudioParam.iChannel, m_sAudioParam.iSamplesPerSec, m_sAudioParam.iBitPerSample, m_uBlockSize, m_uchannelMask); sampleSegmentSize = this->m_uBlockSize * sampleFrameCount; } outputBuffer.SetSize(sampleSegmentSize); if (!sampleSegmentSize) { sampleBuffer.RemoveRange(0, sampleBuffer.Num()); } LeaveCriticalSection(&sampleBufferLock); Log::writeMessage(LOG_RTSPSERV, 1, "%s invoke end!",__FUNCTION__); }
bool DeviceAudioSource::Initialize(DeviceSource *parent) { m_timeStart = 0; device = parent; if (!hAudioMutex) hAudioMutex = OSCreateMutex(); m_bErrorLog = false; lastTimestamp = 0; //--------------------------------- bool bFloat = false; UINT inputChannels; UINT inputSamplesPerSec; UINT inputBitsPerSample; //UINT inputBlockSize; DWORD inputChannelMask; //--------------------------------- if(device->audioFormat.wFormatTag == WAVE_FORMAT_EXTENSIBLE) { WAVEFORMATEXTENSIBLE *wfext = (WAVEFORMATEXTENSIBLE*)&device->audioFormat; if(wfext->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) bFloat = true; } else if(device->audioFormat.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) bFloat = true; inputBitsPerSample = device->audioFormat.wBitsPerSample; inputBlockSize = device->audioFormat.nBlockAlign; inputChannelMask = 0; inputChannels = device->audioFormat.nChannels; inputSamplesPerSec = device->audioFormat.nSamplesPerSec; sampleFrameCount = inputSamplesPerSec/100; sampleSegmentSize = inputBlockSize*sampleFrameCount; outputBuffer.SetSize(sampleSegmentSize); InitAudioData(bFloat, inputChannels, inputSamplesPerSec, inputBitsPerSample, inputBlockSize, inputChannelMask); if (m_pAudioWaveOut) { m_pAudioWaveOut->Uninitialize(); } String strReanderName = GetDirectorMonitorDevices(); if (NULL == m_pAudioWaveOut) { if (!strReanderName.Compare(TEXT("禁用")) && !m_pAudioWaveOut) { m_pAudioWaveOut = new AudioWaveOut; } } else { if ((strReanderName.Compare(TEXT("Disable")) || strReanderName.Compare(TEXT("禁用")))) { delete m_pAudioWaveOut; m_pAudioWaveOut = NULL; } } if (NULL != m_pAudioWaveOut) { m_pAudioWaveOut->Initialize(strReanderName.Array(), inputChannels, inputSamplesPerSec, inputBitsPerSample); } String SecRenderName = GetSecMonitorDevices(); if (m_pSecWaveOut) { m_pSecWaveOut->Uninitialize(); } if (SecRenderName.CompareI(strReanderName.Array()) && (!SecRenderName.Compare(TEXT("Disable")) || !SecRenderName.Compare(TEXT("禁用")))) { bSameDevice = true; } else if (!SecRenderName.Compare(TEXT("禁用")) && !m_pSecWaveOut) { m_pSecWaveOut = new AudioWaveOut; } else if (m_pSecWaveOut) { if ((SecRenderName.Compare(TEXT("Disable")) || SecRenderName.Compare(TEXT("禁用")))) { delete m_pSecWaveOut; m_pSecWaveOut = NULL; } } if (m_pSecWaveOut) { m_pSecWaveOut->Initialize(SecRenderName.Array(), inputChannels, inputSamplesPerSec, inputBitsPerSample); } return true; }