📄 ch17p1_visuals.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 + -