⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch17p1_visuals.cpp

📁 游戏音频程序设计-Beginning.Game.Audio.Programming
💻 CPP
字号:
// Ch17p1_Visuals.cpp : Defines the entry point for the application.
//

#include <windows.h>
#include <commctrl.h>
#include <string>
#include <vector>
#include <sstream>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>

#include <vector>

#include "resource.h"

#include "dsound.h"
#include "dxerr8.h"
#include "AudioEngine/dxutil.h"

#include "AudioEngine/AudioEngine.h"


using namespace std;
using namespace AudioEngine;

CAudioManager g_AudioMgr;
CAudioManager *AudioEngine::GetAudioManager() { return(&g_AudioMgr); }

string g_Filename;
LPDIRECTSOUND8 g_pDS = NULL;
LPDIRECTSOUNDBUFFER g_pPrimaryBuffer = NULL;
LPDIRECTSOUNDBUFFER8 g_pWAVBuffer = NULL;
CDiscreteFourierTransform *g_FT = NULL;

const int BUFFERSIZE = 512;

// InitAudio: initializes DirectX Audio
void InitAudio(HWND hwnd)
{
  HRESULT hr;
  stringstream err;

  // step 1: create primary DS interface
  if (FAILED(hr = DirectSoundCreate8(NULL, &g_pDS, NULL))) {
    err << "DirectSoundCreate8 failed: " << DXGetErrorString8(hr) << endl;
    throw(err.str());
  }

  // step 2: Set cooperative level                  
  if(FAILED(hr = g_pDS->SetCooperativeLevel(hwnd, DSSCL_PRIORITY))) {
    err << "SetCooperativeLevel failed: " << DXGetErrorString8(hr) << endl;
    throw(err.str());
  }

  // Get the primary buffer 
  DSBUFFERDESC dsbd;
  ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  dsbd.dwSize        = sizeof(DSBUFFERDESC);
  dsbd.dwFlags       = DSBCAPS_PRIMARYBUFFER;
  dsbd.dwBufferBytes = 0;
  dsbd.lpwfxFormat   = NULL;
     
  // "create it" (or get it if it already exists, which it does)
  if( FAILED( hr = g_pDS->CreateSoundBuffer( &dsbd, &g_pPrimaryBuffer, NULL ) ) ) {
    err << "CreateSoundBuffer failed: " << DXGetErrorString8(hr) << endl;
    throw(err.str());
  }

  // set its format
  WAVEFORMATEX wfx;
  ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); 
  wfx.wFormatTag      = WAVE_FORMAT_PCM; 
  wfx.nChannels       = (WORD)2; 
  wfx.nSamplesPerSec  = 22050; // 22 Khz (CD quality is ~ 44 Khz, so this is "half-CD" quality)
  wfx.wBitsPerSample  = (WORD) 16; // 2 bytes per sample * 22050 samples/sec = 44100 bytes/sec)
  wfx.nBlockAlign     = (WORD) (wfx.wBitsPerSample / 8 * wfx.nChannels);
  wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;

  if( FAILED( hr = g_pPrimaryBuffer->SetFormat(&wfx) ) ) {
    err << "pSDBPrimary->SetFormat() failed: " << DXGetErrorString8(hr) << endl;
    throw(err.str());
  }
}

int CreateSecondaryBuffer(LPDIRECTSOUNDBUFFER8 *ppBuffer, CWAVFile &wav)
{
  HRESULT hr;
  stringstream err;
  
  DSBUFFERDESC dsbd;
  WAVEFORMATEX wfx;
  
  ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); 
  wfx.wFormatTag      = wav.m_AudioFormat;
  wfx.nChannels       = wav.m_NumberOfChannels; 
  wfx.nSamplesPerSec  = wav.m_SampleRate; 
  wfx.wBitsPerSample  = wav.m_BitsPerSample; 
  wfx.nBlockAlign     = (WORD) (wfx.wBitsPerSample / 8 * wfx.nChannels);
  wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;

  ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  dsbd.dwSize          = sizeof(DSBUFFERDESC);
  dsbd.dwFlags         = 0;
  dsbd.dwBufferBytes   = wav.m_DataLen;
  dsbd.guid3DAlgorithm = GUID_NULL;
  dsbd.lpwfxFormat     = &wfx;

  if( FAILED( hr = g_pDS->CreateSoundBuffer( &dsbd, (LPDIRECTSOUNDBUFFER *)ppBuffer, NULL ) ) )
  {
      err << "CreateSecondaryBuffer: CreateSoundBuffer failed: " << DXGetErrorString8(hr) << endl;
      throw(err.str());;
  }

  return(dsbd.dwBufferBytes); // return size of buffer
}

void LoadSound(HWND hDlg, string filename)
{
  try {
    SAFE_RELEASE(g_pWAVBuffer);
    CWAVFile wavfile;
    wavfile.Load(filename);
    CreateSecondaryBuffer(&g_pWAVBuffer, wavfile);
    unsigned char *ptr1 = NULL;
    unsigned long len1 = 0;

    g_pWAVBuffer->Lock(0, 0, (void **)&ptr1, &len1, NULL, NULL, DSBLOCK_ENTIREBUFFER);

    memcpy(ptr1, wavfile.GetData(), wavfile.m_DataLen);

    g_pWAVBuffer->Unlock(ptr1, len1, NULL, NULL);

    // initialize DFT object
    SAFE_DELETE(g_FT);
    g_FT = new CDiscreteFourierTransform(BUFFERSIZE, wavfile.m_SampleRate, wavfile.m_BitsPerSample, wavfile.m_NumberOfChannels);
  }
  catch(...) {
    MessageBox(hDlg, "Error loading sound!", "Ch17p1_Visuals", MB_OK | MB_ICONSTOP);
  }
  g_Filename = filename;
}

void OnBrowse(HWND hDlg)
{
  char filename[MAX_PATH] = { 0 };
    
  OPENFILENAME ofn = { sizeof(OPENFILENAME), hDlg, NULL,
                       "Audio Files\0*.wav\0All Files\0*.*\0\0", NULL,
                       0, 1, filename, MAX_PATH, NULL, 0, NULL,
                       "Open WAV File",
                       OFN_FILEMUSTEXIST|OFN_HIDEREADONLY, 0, 0,
                       TEXT(".wav"), 0, NULL, NULL };

  // Display the OpenFileName dialog. Then, try to load the specified file
  if(GetOpenFileName(&ofn))
  {
    LoadSound(hDlg, filename);
  }
}

void RenderSpectrum(HDC hdc, HWND hDlg)
{
  HWND framewin = GetDlgItem(hDlg, IDC_FRAME);
  
  RECT framerect;
  int framewidth,frameheight;
  GetWindowRect(framewin, &framerect);
  ScreenToClient(hDlg, (POINT *)&framerect.left);
  ScreenToClient(hDlg, (POINT *)&framerect.right);
  framewidth = framerect.right - framerect.left;
  frameheight = framerect.bottom - framerect.top;

  // draw each bar
  int n=0;
  for (float x=framerect.left; x < framerect.right; x += framewidth / ((float)BUFFERSIZE/2.0f), n++) {
    RECT barrect;
    barrect.left = x;
    barrect.right = x + (framewidth / ((float)BUFFERSIZE/2.0f));
    barrect.bottom = framerect.bottom;
    barrect.top = framerect.bottom - (g_FT->GetAmp(n) / 50.0f * (float)frameheight);
    if (barrect.top < framerect.top) { barrect.top = framerect.top; }
    FillRect(hdc, &barrect, (HBRUSH)GetStockObject(GRAY_BRUSH));
    
    // fill in the top portion black
    if (barrect.top > framerect.top) {
      barrect.bottom = barrect.top;
      barrect.top = framerect.top;
      FillRect(hdc, &barrect, (HBRUSH)GetStockObject(BLACK_BRUSH));
    }
  }
}

void UpdateSpectrum(HDC hdc, HWND hDlg, LPDIRECTSOUNDBUFFER8 pDSBuf)
{
  unsigned char curbuf[BUFFERSIZE*4];

  unsigned char *ptr1 = NULL;
  unsigned long len1 = 0;
  DWORD playpos = 0;

  int numbytes = BUFFERSIZE * g_FT->m_NumChannels * (g_FT->m_BitsPerSample/8);

  ThrowIfFailed(pDSBuf->GetCurrentPosition(&playpos, NULL), "Can't get current position!");
  if (SUCCEEDED(pDSBuf->Lock(playpos, numbytes, (void **)&ptr1, &len1, NULL, NULL, 0))) {

    memcpy(curbuf, ptr1, len1);
    if (len1 < BUFFERSIZE) { memset(&curbuf[len1], 0, numbytes-len1); }
  
    pDSBuf->Unlock(ptr1, len1, NULL, NULL);
  }
  else {
    memset(curbuf, 0, BUFFERSIZE*4);
  }

  // perform DFT on buf
  g_FT->LoadInputData(curbuf);
  g_FT->PerformSlowFourierTransform();

  // draw output
  RenderSpectrum(hdc, hDlg);
}

void OnPlay(HWND hDlg)
{
  if (g_pWAVBuffer) {
    g_pWAVBuffer->Play(0,0,0);

    bool playing=true;

    HDC hdc = GetDC(hDlg);
    while (playing) {
      DWORD status;
      g_pWAVBuffer->GetStatus(&status);
      playing = (status == DSBSTATUS_PLAYING);

      UpdateSpectrum(hdc, hDlg, g_pWAVBuffer);


    }
    ReleaseDC(hDlg, hdc);

  }
}


INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
  try {
    switch( msg ) 
    {
      case WM_INITDIALOG:
        // init audio engine
        InitAudio(hDlg);
        LoadSound(hDlg, "test.wav"); // by default, load test.wav
        break;

      case WM_COMMAND:
        switch(HIWORD(wParam)) {
          case CBN_SELCHANGE:
          break;

          case BN_CLICKED:
          {
            // a button was clicked... which one?
            switch(LOWORD(wParam)) {
             
              case IDC_BROWSE:
                OnBrowse(hDlg);
                break;

              case IDC_PLAYSOUND:
                OnPlay(hDlg);
                break;

            } // switch LOWORD(wParam)
          }
          break;

        } // notification code
        break;

      case WM_CLOSE:
        DestroyWindow(hDlg);
        PostQuitMessage(0);
        break; 

      default:
        return FALSE; // Didn't handle message
    }
  } 
  catch(char *err) {
    MessageBox(hDlg, err, "Ch17p1_Visuals Error", MB_OK);
    return(FALSE);

  }
  return TRUE; // Handled message
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	HWND    hDlg = NULL;
  MSG     msg;


  // we need to init common controls for our trackbars
  InitCommonControls();

  
  // Display the main editor dialog
  hDlg = CreateDialog( hInstance, MAKEINTRESOURCE(IDD_MAIN), 
                       NULL, (DLGPROC)MainDlgProc );
  
  ShowWindow(hDlg, SW_SHOW);

  
  while(1) 
  { 
    // Windows messages are available
    if(GetMessage(&msg, NULL, 0, 0)) 
    { 
      if(!IsDialogMessage(hDlg, &msg))  
      {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
      }
    }
    else {
      DestroyWindow(hDlg);
      SAFE_RELEASE(g_pWAVBuffer);
      SAFE_RELEASE(g_pPrimaryBuffer);
      SAFE_RELEASE(g_pDS);
      SAFE_DELETE(g_FT);
      return(msg.wParam);
    }
  }
	return 0;
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -