Jump to content


Buffer size,duration and other parameters!!


1 reply to this topic

#1 Jack_thomas

    New Member

  • Members
  • Pip
  • 1 posts

Posted 31 March 2006 - 09:55 PM

Hi I've got this code and I am trying to implement a thread with it.
Could someone tell me what are the sizes of the capture and playback buffers and their durations ? Are these parameters fixed or can be manipulated ?
What other parameters are being used in this code which can be manipulated ?
What is the rate at which samples are being played from output.

code:

HRESULT __fastcall  TDSFilter::InitDirectSound()
{
  HRESULT             hr;
  DSBUFFERDESC        dsbdesc;

//  ZeroMemory( &aPosNotify, sizeof(DSBPOSITIONNOTIFY) * FNumBuffers);
  dwOutputBufferSize  = 0;
  dwCaptureBufferSize = 0;
  dwNotifySize        = 0;
  dwNextOutputOffset  = 0;

  //  Initialize COM
  if( FAILED( hr = CoInitialize(NULL) ) ) return DXTRACE_ERR_MSGBOX( TEXT("CoInitialize"), hr );

  // Create IDirectSound using the preferred sound device
  if( FAILED( hr = DirectSoundCreate8( NULL, &pDS, NULL ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("DirectSoundCreate"), hr );
  
  // Set coop level to DSSCL_PRIORITY
  if( FAILED( hr = pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("SetCooperativeLevel"), hr );

  // Obtain primary buffer
  ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
  dsbdesc.dwSize  = sizeof(DSBUFFERDESC);
  dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
  if( FAILED( hr = pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("CreateSoundBuffer"), hr );

  // Create IDirectSoundCapture using the preferred capture device
  if( FAILED( hr = DirectSoundCaptureCreate8( NULL, &pDSCapture, NULL ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("DirectSoundCaptureCreate"), hr );
  return S_OK;
}
HRESULT __fastcall  TDSFilter::FreeDirectSound()
{
  // Release DirectSound interfaces
  SAFE_RELEASE( pDSNotify );

  SAFE_RELEASE( pDSBPrimary );
  SAFE_RELEASE( pDSBOutput );
  SAFE_RELEASE( pDSBCapture );

  SAFE_RELEASE( pDSCapture );
  SAFE_RELEASE( pDS );

  // Release COM
  CoUninitialize();

  return S_OK;
}
HRESULT __fastcall  TDSFilter::ScanAvailableOutputFormats()
{
    WAVEFORMATEX wfx;
    WAVEFORMATEX wfxSet;
    HRESULT      hr;
    
    ZeroMemory( &wfxSet, sizeof(wfxSet) );
    wfxSet.wFormatTag = WAVE_FORMAT_PCM;

    ZeroMemory( &wfx, sizeof(wfx) );
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    
    // Try 20 different standard format to see if they are supported
    for( INT iIndex = 0; iIndex < 20; iIndex++ )
    {
        GetWaveFormatFromIndex( iIndex, &wfx );

        // To test if a playback format is supported, try to set the format 
        // using a specific format.  If it works then the format is 
        // supported, otherwise not.
        if( FAILED( hr = pDSBPrimary->SetFormat( &wfx ) ) )
        {
            abOutputFormatSupported[ iIndex ] = FALSE;
        }
        else
        {
            // Get the format that was just set, and see if it 
            // is actually supported since SetFormat() sometimes returns DS_OK 
            // even if the format was not supported
            if( FAILED( hr = pDSBPrimary->GetFormat( &wfxSet, sizeof(wfxSet),
                                                       NULL ) ) )
                return DXTRACE_ERR_MSGBOX( TEXT("GetFormat"), hr );

            if( memcmp( &wfx, &wfxSet, sizeof(wfx) ) == 0 )
                abOutputFormatSupported[ iIndex ] = TRUE;
            else
                abOutputFormatSupported[ iIndex ] = FALSE;
        }
    }

    return S_OK;
}
void  __fastcall  TDSFilter::GetWaveFormatFromIndex( INT nIndex, WAVEFORMATEX* pwfx )
{
    INT iSampleRate = nIndex % 5;
    INT iType = nIndex / 5;

    switch( iSampleRate )
    {
        case 0: pwfx->nSamplesPerSec = 48000; break;
        case 1: pwfx->nSamplesPerSec = 44100; break;
        case 2: pwfx->nSamplesPerSec = 22050; break;
        case 3: pwfx->nSamplesPerSec = 11025; break;
        case 4: pwfx->nSamplesPerSec =  8000; break;
    }

    switch( iType )
    {
        case 0: pwfx->wBitsPerSample = 16; pwfx->nChannels = 2; break;
        case 1: pwfx->wBitsPerSample = 16; pwfx->nChannels = 1; break;
        case 2: pwfx->wBitsPerSample =  8; pwfx->nChannels = 2; break;
        case 3: pwfx->wBitsPerSample =  8; pwfx->nChannels = 1; break;
    }

    pwfx->nBlockAlign = pwfx->nChannels * ( pwfx->wBitsPerSample / 8 );
    pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;
}
void  __fastcall  TDSFilter::ConvertWaveFormatToString( WAVEFORMATEX* pwfx, TCHAR* strFormatName)
{
    wsprintf( strFormatName,
              TEXT("%u Hz, %u-bit %s"),
              pwfx->nSamplesPerSec,
              pwfx->wBitsPerSample,
              ( pwfx->nChannels == 1 ) ? TEXT("Mono") : TEXT("Stereo") );
}
HRESULT __fastcall  TDSFilter::ScanAvailableInputFormats()
{
    WAVEFORMATEX  wfx;
    DSCBUFFERDESC dscbd;
    LPDIRECTSOUNDCAPTUREBUFFER pDSCaptureBuffer = NULL;

    ZeroMemory( &wfx, sizeof(wfx) );
    wfx.wFormatTag = WAVE_FORMAT_PCM;

    ZeroMemory( &dscbd, sizeof(dscbd) );
    dscbd.dwSize = sizeof(dscbd);

    // Try 20 different standard format to see if they are supported
    for( INT iIndex = 0; iIndex < 20; iIndex++ )
    {
        GetWaveFormatFromIndex( iIndex, &wfx );

        // To test if a capture format is supported, try to create a 
        // new capture buffer using a specific format.  If it works
        // then the format is supported, otherwise not.
        dscbd.dwBufferBytes = wfx.nAvgBytesPerSec;
        dscbd.lpwfxFormat = &wfx;
        
        if( FAILED( pDSCapture->CreateCaptureBuffer( &dscbd, &pDSCaptureBuffer, NULL ) ) ) abInputFormatSupported[ iIndex ] = FALSE;
          else abInputFormatSupported[ iIndex ] = TRUE;
        SAFE_RELEASE( pDSCaptureBuffer );
    }
    return S_OK;
}
HRESULT __fastcall  TDSFilter::SetBufferFormats( WAVEFORMATEX* pwfxInput, WAVEFORMATEX* pwfxOutput )
{
  HRESULT hr ;
  // Set the format of the primary buffer
  // to the format of the output buffer
  if( FAILED( hr = pDSBPrimary->SetFormat( pwfxOutput ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("SetFormat"), hr );

  // Set the notification size
  dwNotifySize = FBufferSize ;
  dwNotifySize -= dwNotifySize % pwfxInput->nBlockAlign;

  // Set the buffer sizes
  dwOutputBufferSize  = FNumBuffers * dwNotifySize / 2;
  dwCaptureBufferSize = dwNotifySize * FNumBuffers ;

  SAFE_RELEASE( pDSBCapture );

  // Create the capture buffer
  DSCBUFFERDESC dscbd;
  ZeroMemory( &dscbd, sizeof(dscbd) );
  dscbd.dwSize        = sizeof(dscbd);
  dscbd.dwBufferBytes = dwCaptureBufferSize;
  dscbd.lpwfxFormat   = pwfxInput; // Set the format during creatation

  if( FAILED( hr = pDSCapture->CreateCaptureBuffer( &dscbd, &pDSBCapture, NULL))) return DXTRACE_ERR_MSGBOX( TEXT("CreateCaptureBuffer"), hr );
  return S_OK;
}
HRESULT __fastcall  TDSFilter::CreateOutputBuffer()
{
    HRESULT hr; 
    WAVEFORMATEX wfxInput;

    // This sample works by creating notification events which 
    // are signaled when the capture buffer reachs specific offsets 
    // WinMain() waits for the associated event to be signaled, and
    // when it is, it calls HandleNotifications() which copy the 
    // data from the capture buffer into the output buffer

    ZeroMemory( &wfxInput, sizeof(wfxInput) );
    pDSBCapture->GetFormat( &wfxInput, sizeof(wfxInput), NULL );

    // Create the direct sound buffer using the same format as the 
    // capture buffer. 
    DSBUFFERDESC dsbd;
    ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
    dsbd.dwSize          = sizeof(DSBUFFERDESC);
    dsbd.dwFlags         = DSBCAPS_GLOBALFOCUS;
    dsbd.dwBufferBytes   = dwOutputBufferSize;
    dsbd.guid3DAlgorithm = GUID_NULL;
    dsbd.lpwfxFormat     = &wfxInput;

    // Create the DirectSound buffer 
    if( FAILED( hr = pDS->CreateSoundBuffer( &dsbd, &pDSBOutput, NULL ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("CreateSoundBuffer"), hr );

    // Create a notification event, for when the sound stops playing
    if( FAILED( hr = pDSBCapture->QueryInterface( IID_IDirectSoundNotify, (VOID**)&pDSNotify ) ) )
        return DXTRACE_ERR_MSGBOX( TEXT("QueryInterface"), hr );

    // Setup the notification positions
    for( unsigned int i = 0; i < FNumBuffers ; i++ ) {
        aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1;
        aPosNotify[i].hEventNotify = 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 = pDSNotify->SetNotificationPositions( FNumBuffers, aPosNotify ) ) )
        return DXTRACE_ERR_MSGBOX( TEXT("SetNotificationPositions"), hr );

    return S_OK;
}
HRESULT __fastcall  TDSFilter::StartBuffers()
{
  WAVEFORMATEX wfxOutput;
  VOID*        pDSLockedBuffer = NULL;
  DWORD        dwDSLockedBufferSize;
  HRESULT hr;

    // Restore lost buffers
  if( FAILED( hr = RestoreBuffer( pDSBOutput, NULL ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("RestoreBuffer"), hr );

    // Reset the buffers
    dwNextOutputOffset = 0;
    pDSBOutput->SetCurrentPosition( 0 );

    // Find out where the capture buffer is right now, then write data
    // some extra amount forward to make sure we're ahead of the write cursor
    pDSBCapture->GetCurrentPosition( &dwNextCaptureOffset, NULL );
    dwNextCaptureOffset -= dwNextCaptureOffset % dwNotifySize;

    dwNextOutputOffset = dwNextCaptureOffset + ( dwNotifySize << 1);
    dwNextOutputOffset %= dwOutputBufferSize;  // Circular buffer

    // Tell the capture buffer to start recording
    pDSBCapture->Start( DSCBSTART_LOOPING );
    
    // Rewind the output buffer, fill it with silence, and play it
    pDSBOutput->SetCurrentPosition( dwNextOutputOffset );

    // Save the format of the capture buffer in g_pCaptureWaveFormat
    ZeroMemory( &wfxCaptureWaveFormat, sizeof(WAVEFORMATEX) );
    pDSBCapture->GetFormat( &wfxCaptureWaveFormat, sizeof(WAVEFORMATEX), NULL );

    // Get the format of the output buffer
    ZeroMemory( &wfxOutput, sizeof(wfxOutput) );
    pDSBOutput->GetFormat( &wfxOutput, sizeof(wfxOutput), NULL );

    // Fill the output buffer with silence at first
    // As capture data arrives, HandleNotifications() will fill
    // the output buffer with wave data.
    if( FAILED( hr = pDSBOutput->Lock( 0, dwOutputBufferSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0)))
        return DXTRACE_ERR_MSGBOX( TEXT("Lock"), hr );
        
    FillMemory( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, 
                (BYTE)( wfxOutput.wBitsPerSample == 8 ? 128 : 0 ) );
    pDSBOutput->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, NULL );

    // Play the output buffer
    pDSBOutput->Play( 0, 0, DSBPLAY_LOOPING );

    return S_OK;
}
HRESULT __fastcall  TDSFilter::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSBuffer, BOOL* pbRestored )
{
    HRESULT hr;

    if( pbRestored) *pbRestored = FALSE;
    if( !pDSBuffer ) return S_FALSE;

    DWORD dwStatus;
    if( FAILED( hr = pDSBuffer->GetStatus( &dwStatus ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("GetStatus"), hr );

    if( dwStatus & DSBSTATUS_BUFFERLOST ) {
        // Since the app could have just been activated, then
        // DirectSound may not be giving us control yet, so 
        // the restoring the buffer may fail.  
        // If it does, sleep until DirectSound gives us control.
        do { 
            hr = pDSBuffer->Restore();
            if( hr == DSERR_BUFFERLOST )
                Sleep( 10 );
        } while( ( hr = pDSBuffer->Restore() ) == DSERR_BUFFERLOST );

        if( pbRestored) *pbRestored = TRUE;
        return S_OK;
    } else return S_FALSE;
}
HRESULT __fastcall  TDSFilter::HandleNotification()
{
    HRESULT hr;
    VOID* pDSCaptureLockedBuffer    = NULL;
    VOID* pDSOutputLockedBuffer     = NULL;
    DWORD dwDSCaptureLockedBufferSize;
    DWORD dwDSOutputLockedBufferSize;
   
    DWORD dwStatus;

    // Make sure buffers were not lost, if the were we need 
    // to start the capture again
    if( FAILED( hr = pDSBOutput->GetStatus( &dwStatus))) return DXTRACE_ERR_MSGBOX( TEXT("GetStatus"), hr );

    if( dwStatus & DSBSTATUS_BUFFERLOST ) {
        if( FAILED( hr = StartBuffers())) return DXTRACE_ERR_MSGBOX( TEXT("StartBuffers"), hr );
        return S_OK;
    }

    // Lock the capture buffer down
    if( FAILED( hr = pDSBCapture->Lock( dwNextCaptureOffset, dwNotifySize, &pDSCaptureLockedBuffer,
                                        &dwDSCaptureLockedBufferSize, NULL, NULL, 0L))) 
        return DXTRACE_ERR_MSGBOX( TEXT("Lock"), hr );

    // Lock the output buffer down
    if( FAILED( hr = pDSBOutput->Lock( dwNextOutputOffset, dwNotifySize, &pDSOutputLockedBuffer,
                                         &dwDSOutputLockedBufferSize, NULL, NULL, 0L)))
        return DXTRACE_ERR_MSGBOX( TEXT("Lock"), hr );

    // These should be equal
    if( dwDSOutputLockedBufferSize != dwDSCaptureLockedBufferSize ) return E_FAIL;  // Sanity check unhandled case

    // Just copy the memory from the 
    // capture buffer to the playback buffer 
    Process( (short*) pDSCaptureLockedBuffer, dwDSOutputLockedBufferSize) ;
    CopyMemory( pDSOutputLockedBuffer, pDSCaptureLockedBuffer, dwDSOutputLockedBufferSize );

    // Unlock the play buffer
    pDSBOutput->Unlock( pDSOutputLockedBuffer, dwDSOutputLockedBufferSize, NULL, 0 );

    // Unlock the capture buffer
    pDSBCapture->Unlock( pDSCaptureLockedBuffer, dwDSCaptureLockedBufferSize, NULL, 0 );

    // Move the capture offset along
    dwNextCaptureOffset += dwDSCaptureLockedBufferSize;
    dwNextCaptureOffset %= dwCaptureBufferSize; // Circular buffer

    // Move the playback offset along
    dwNextOutputOffset += dwDSOutputLockedBufferSize;
    dwNextOutputOffset %= dwOutputBufferSize; // Circular buffer

    return S_OK;
}



I would really appreciate your help.

Thanks.

#2 Reedbeta

    DevMaster Staff

  • Administrators
  • 4979 posts
  • LocationBellevue, WA

Posted 01 April 2006 - 01:01 AM

First, please use the [ code ] [ /code ] tags when you post source code in the forum, so it will be nicely formatted. I have added them for you this time. Second, you should read the comments in the code and if necessary look up some of the function calls in the MSDN to find the information you are looking for.
reedbeta.com - developer blog, OpenGL demos, and other projects





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users