wav 스트리밍 서버 만들려고 하는데 도대체 갈피를 못 잡겠어요

kknd345의 이미지

지금 어디서 잘못 됐는지 모르겠습니다.

이번에 wav파일의 스트리밍에 대해서 처음 해보는 거라서 책 보고 예제파일 보아도 각이 안 나오네요.

예제파일은 하드의 wav파일을 바로 플레이 하는거라 바로 스트리밍 시키는 거랑은 많이 차이가 나는 것 같습니다.

조언 부탁드립니다. 아님 비슷한 소스 파일이라도 ㅜㅜ..


밑에 소스 코드는 중요한 것만 올린거라.. 갑자기 등장하는게 있어도 이해해주세요.

	BOOL m_bIsPlaying;
	DWORD m_dwBufferBytes;
	
	LPDIRECTSOUNDBUFFER m_lpDSBuffer;//  Second Sound buffer
	LPDIRECTSOUND	m_pDSound; 
       LPDIRECTSOUNDBUFFER   pDSBPrimary ;
//DlgDownWaveFormat가 서버로 부터 보낼 wav 파일의   WAVEFORMATEX 형태인 wav해더이고요.

//DlgDownWaveFormat 를 이용하여  아래 처럼 1차 2차 버퍼를 생성했습니다.

 

////////////////////////////////////////////////////////////////////////////////    

// 1 차 버퍼 생성

   WAVEFORMATEX wfx;

    ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); 

    wfx.cbSize = DlgDownWaveFormat.cbSize;

    wfx.nAvgBytesPerSec =DlgDownWaveFormat.nAvgBytesPerSec;

    wfx.nBlockAlign =DlgDownWaveFormat.nBlockAlign;

    wfx.nChannels =DlgDownWaveFormat.nChannels;

    wfx.nSamplesPerSec =DlgDownWaveFormat.nSamplesPerSec;

    wfx.wBitsPerSample =DlgDownWaveFormat.wBitsPerSample;

    wfx.wFormatTag =DlgDownWaveFormat.wFormatTag;

 

    if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) )

    {

        ::AfxMessageBox("PRIMARY BUFFER의 포맷을 결정하지 못했습니다.");

        return hr;

    }

////////////////////////////////////////////////////////////////////////////////

// 2차 버퍼 생성

    DSBUFFERDESC dsbd;

    ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );

    dsbd.dwSize        = sizeof(DSBUFFERDESC);

    dsbd.dwFlags       = DSBCAPS_STICKYFOCUS;

    dsbd.dwBufferBytes = 500;      // 멀넣어야 할지 잘 몰라서 임의로 잡았습니다.

    dsbd.lpwfxFormat   = &DlgDownWaveFormat;

    //dsbd.dwBufferBytes = DlgDownWaveFormat.cbSize;

    //dsbd.lpwfxFormat   = DlgDownWaveFormat.;

 

    if( FAILED( hr = m_pDSound->CreateSoundBuffer( &dsbd, &m_lpDSBuffer, NULL ) ) )

    {

        ::AfxMessageBox("DIRECT BUFFER를 생성하는데 실패했습니다.");

        return hr;

    }

 

    // Remember how big the buffer is

    m_dwBufferBytes = dsbd.dwBufferBytes;

 

 

////////////////////////////////////////////////////////////////////////////////    

//예제 파일에 있던 함수 GetBufferControl를 실행 해주고요.

    DWORD dwStatus;

    if( FAILED( hr = m_lpDSBuffer->GetStatus( &dwStatus ) ) )

        return hr;

 

    if( dwStatus & DSBSTATUS_BUFFERLOST )

    {

        do 

        {

            hr = m_lpDSBuffer->Restore();

            if( hr == DSERR_BUFFERLOST )

                Sleep( 10 );

        }

        while( hr = m_lpDSBuffer->Restore() );

    }

 

////////////////////////////////////////////////////////////////////////////////

// 이렇게 Lock 하고     memcpy 하고 unlock 했는데요 음악이 다 꺠져서 들리네요 ㅜㅜ.

// 위에 과정까지 다 하고 나서 여기부터는 500 바이트 받아서 계속 반복 되는 구조입니다.

 

 

HRESULT hr; 

VOID*   pbData  = NULL;

VOID*   pbData2 = NULL;

DWORD   dwLength;

DWORD   dwLength2;

if( FAILED( hr = p_CDSound->m_lpDSBuffer->Lock( 0, p_CDSound->m_dwBufferBytes, &pbData, &dwLength, &pbData2, &dwLength2, 0L ) ) )               return hr;

 

       // Copy the memory to it.

       memcpy( pbData, &p_Data->p_Data, p_Data->nSize );

 

      // Unlock the buffer, we don't need it anymore.

       p_CDSound->m_lpDSBuffer->Unlock( pbData, p_CDSound->m_dwBufferBytes, NULL, 0 );

                 pbData = NULL;
maximus의 이미지

버퍼 사이즈를 더 올리시는게 좋을것 같습니다.

0x4000 정도로 올려 보시기 바랍니다.

=================================
:: how about a cup of tea ? ::
=================================

Prentice의 이미지

kknd345 wrote:
서버가 해더 파일을 날리고 rewind해서
파일을 날려서 클라이언트가 fwite를 써서 서버에서 받은 데이터를 저장해서 파일을 플레이 시키면 됩니다.
그러나 스트리밍은 왜 안되는지 모르겟네요 ㅜㅜ..

늘 같은 bitdepth, sampling rate의 wav를 보낸다고 가정했을 때, 헤더 내용은 스트리밍에 불필요합니다.

RIFF 헤더를 모두 뗀 PCM 정보만 보내고 받았을 때 PCM 스트리밍은 되시던가요? 아니면 헤더를 클라이언트가 해석 한 후 PCM만 재생시도를 한다거나 하시면요.

kknd345의 이미지

if( FAILED( hr = p_CDSound->m_lpDSBuffer->Lock( count*700, p_Data->nSize, &pbData, &dwLength, &pbData2, &dwLength2, 0L ) ) )
							return hr;
	
					// Copy the memory to it.
						memcpy( pbData, p_Data->p_Data, dwLength );
				
						if(dwLength2 > 0)
							memcpy(pbData2, p_Data->p_Data + dwLength, dwLength2);


					// Unlock the buffer, we don't need it anymore.
						p_CDSound->m_lpDSBuffer->Unlock( pbData, p_Data->nSize, pbData2, dwLength2 );
						pbData = NULL;

						count++;
								
						if( count == 299 ){
							
							if( start == false)
									hr = p_CDSound->m_lpDSBuffer->Play( 0, 0, DSBPLAY_LOOPING );
							
							count = 0;
						}

위처럼 해서 count를 올려서 해결했습니다.

lock이 무슨일을 하는지 잘 몰라서 안되었네요
lock의 첫번째 인자의 위치만큼 버퍼시작점에서 떨어진 포인터위치를 pbData에 넣어 주네요.

그런데 또 다른 문제가 ㅜㅜ..
버퍼에 데이터를 다 채우면 count가 0으로 돌아가서 다시 데이터를 쌓다가 재생하는 부분을 따라잡아 버려 노래가 나오지도 않았는데 그 부분을 겹쳐버리네요 ㅜㅜ..

혹시 directsound 가 세컨드 버퍼 어느지점만큼 재생하고 있는지 알수 없을까요?

1%의 가능성이면 충분하다!
최선을 다하자!

Prentice의 이미지

그런 질문은 윈도 관련 커뮤니티에 질문하셔야 좋지 않을까 생각합니다......

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.