guys. I am using direct sound to capture audio from microphone. Everything was fine except captured sample rate is not correct. Sample rate I got was 2/3 of what I required. I don't know what is wrong with it.
Here's a piece of codes of initialization.
long audio_rec::init_capture_buffer(
const long dwNotifyArraySize,
const long dwNotifyTickInterval,
const GUID& guidDevice,
const WAVEFORMATEX& wfxInput)
{
HRESULT hr = S_OK;
SAFE_RELEASE(m_pDSCapture); // LPDIRECTSOUNDCAPTURE
SAFE_RELEASE(m_pDSNotify); // LPDIRECTSOUNDNOTIFY
SAFE_RELEASE(m_pDSCaptureBuffer); // LPDIRECTSOUNDCAPTUREBUFFER
SAFE_DELETE_ARRAY(m_pNotifyArray);// LPDSBPOSITIONNOTIFY
// Save Notify Array Size
m_dwNotifyArraySize = dwNotifyArraySize;
// Init Notification Event
if (nullptr == m_hNotificationEvent) {
m_hNotificationEvent = ::CreateEventW(NULL, FALSE, FALSE, NULL);
}
if (m_hNotificationEvent) { ::ResetEvent(m_hNotificationEvent); }
// Init Direct Sound
// Create IDirectSoundCapture using the preferred capture device
if (FAILED(hr = ::DirectSoundCaptureCreate(&guidDevice, &m_pDSCapture, NULL))) {
return hr;
}
// Allocate Buffer for Recording
// Create Capture Buffer
// Initialize Notification
long dwNotifyByteInterval
= (long)(((dwNotifyTickInterval) / 1000.0) * mic_wfx.nAvgBytesPerSec);
dwNotifyByteInterval -= dwNotifyByteInterval % mic_wfx.nBlockAlign;
m_dwNotifyByteInterval = dwNotifyByteInterval;
// Set the buffer sizes
m_dwBufferSize = dwNotifyByteInterval * dwNotifyArraySize;
// Set the format during creatation
DSCBUFFERDESC dscbd = { 0 };
dscbd.dwSize = sizeof(dscbd);
dscbd.dwBufferBytes = m_dwBufferSize;
dscbd.lpwfxFormat = (LPWAVEFORMATEX)&wfxInput;
// Create the capture buffer
if (FAILED(hr = m_pDSCapture->CreateCaptureBuffer(&dscbd, &m_pDSCaptureBuffer, nullptr))) {
SAFE_RELEASE(m_pDSCapture);
return hr;
}
// Set Notification
if (FAILED(hr = m_pDSCaptureBuffer->QueryInterface(IID_IDirectSoundNotify, (VOID**)&m_pDSNotify))) {
SAFE_RELEASE(m_pDSCapture);
SAFE_RELEASE(m_pDSCaptureBuffer);
return hr;
}
// Allocate Notification Array
if (m_pNotifyArray) { SAFE_DELETE_ARRAY(m_pNotifyArray); }
m_pNotifyArray = new DSBPOSITIONNOTIFY[dwNotifyArraySize + 1];
::memset(m_pNotifyArray, 0, sizeof(DSBPOSITIONNOTIFY) * (dwNotifyArraySize + 1));
// Setup the notification positions
for (int i = 0; i < (int)m_dwNotifyArraySize; i++)
{
m_pNotifyArray[i].dwOffset = m_dwNotifyByteInterval * (i + 1) - 1;
m_pNotifyArray[i].hEventNotify = m_hNotificationEvent;
}
// Tell DirectSound when to notify us. the notification will come in the from
// of signaled events that are handled in WinMain()
if (FAILED(hr = m_pDSNotify->SetNotificationPositions(dwNotifyArraySize, m_pNotifyArray))) {
SAFE_RELEASE(m_pDSCapture);
SAFE_RELEASE(m_pDSNotify);
SAFE_RELEASE(m_pDSCaptureBuffer);
SAFE_DELETE_ARRAY(m_pNotifyArray);
return hr;
}
return hr;
}
and another piece of codes of main thread.
void audio_rec::record_loop()
{
HANDLE& hNotiEvent = m_hNotificationEvent;
long hr = S_OK;
// Prepare buffer to record
std::vector<unsigned char> buffer1;
std::vector<unsigned char> buffer2;
long dwNextOffset = 0;
WAVEFORMATEX wfx = this->mic_wfx;
// Reset Notify Event
::ResetEvent(hNotiEvent);
// Start Recording
if (FAILED(hr = this->m_pDSCaptureBuffer->Start(DSCBSTART_LOOPING))) {
return;
}
// Loop Until Stop sign is signaled
while (this->flag_stop_capture == false)
{
::WaitForSingleObject(hNotiEvent, INFINITE);
// read buffer
// ReadCapturedData()함수에서 Buffer를 할당
hr = this->read_captured_data(
this->m_pDSCaptureBuffer,
buffer1,
buffer2,
dwNextOffset);
if (FAILED(hr)) {
break;
}
...
::ResetEvent(hNotiEvent);
}
}
and this is codes reading captured audio.
long audio_rec::read_captured_data(
__in LPDIRECTSOUNDCAPTUREBUFFER pCaptureBuffer,
__out std::vector<unsigned char>& buffer1,
__out std::vector<unsigned char>& buffer2,
__inout long& dwNextOffset)
{
HRESULT hr = S_OK;
PVOID pbCaptureData1 = nullptr;
unsigned long dwCapturedLength1 = 0;
PVOID pbCaptureData2 = nullptr;
unsigned long dwCapturedLength2 = 0;
unsigned long dwReadPos = 0;
unsigned long dwCapturePos = 0;
long lLockSize = 0;
buffer1.clear();
buffer2.clear();
if (nullptr == pCaptureBuffer) {
return S_FALSE;
}
if (FAILED(hr = pCaptureBuffer->GetCurrentPosition(&dwCapturePos, &dwReadPos))) {
return (long)hr;
}
//assert(dwCapturePos - dwReadPos == dwNotiByteInterval);
//dwLockSize = dwNotiByteInterval;
lLockSize = dwReadPos - dwNextOffset;
if (lLockSize < 0) {
lLockSize += m_dwBufferSize;
}
// Block align lock size
lLockSize -= (lLockSize % m_dwNotifyByteInterval);
if (lLockSize == 0) {
return S_FALSE;
}
// Lock the capture buffer down
if (FAILED(hr = m_pDSCaptureBuffer->Lock(
dwNextOffset, lLockSize,
&pbCaptureData1, &dwCapturedLength1,
&pbCaptureData2, &dwCapturedLength2, 0L))) {
return hr;
}
// copy captured buffer
if (pbCaptureData1 != nullptr)
{
if (dwCapturedLength1 > 0) {
//buffer1.resize(dwCapturedLength1);
//::memcpy(buffer1.data(), (unsigned char*)pbCaptureData1, dwCapturedLength1);
buffer1.assign((unsigned char*)pbCaptureData1, ((unsigned char*)pbCaptureData1) + dwCapturedLength1);
}
// Move the capture offset along
dwNextOffset += dwCapturedLength1;
dwNextOffset %= m_dwBufferSize; // Circular buffer
}
if (pbCaptureData2 != nullptr)
{
if (dwCapturedLength2 > 0) {
buffer2.assign(
(unsigned char*)pbCaptureData2,
((unsigned char*)pbCaptureData2) + dwCapturedLength2);
}
dwNextOffset += dwCapturedLength2;
dwNextOffset %= m_dwBufferSize; // Circular buffer
}
// Unlock the capture buffer
hr = pCaptureBuffer->Unlock(
pbCaptureData1, dwCapturedLength1,
pbCaptureData2, dwCapturedLength2);
return S_OK;
}
I tried to capture audio with sample rate 44100 but actual sample rate captured was like 30320. I had changed required sample rate to 22050 and I got sample rate like 14690.