📄 ch2p1_tonegenerator.cpp
字号:
// Ch2p1_ToneGenerator.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include <sstream>
#include <string>
#include <math.h>
#include <conio.h>
#include <dsound.h>
#include <dxerr8.h>
#include "dxutil.h"
using namespace std;
#define PI 3.14159
// tone frequencies: (C0 = lowest)
// C0 16.35 C#0/Db0 17.32 D0 18.35
// D#0/Eb0 19.45 E0 20.60 F0 21.83
// F#0/Gb0 23.12 G0 24.50 G#0/Ab0 25.96
// A0 27.50 A#0/Bb0 29.14 B0 30.87
// C1 32.70 C#1/Db1 34.65 D1 36.71
// D#1/Eb1 38.89 E1 41.20 F1 43.65
// F#1/Gb1 46.25 G1 49.00 G#1/Ab1 51.91
// A1 55.00 A#1/Bb1 58.27 B1 61.74
// C2 65.41 C#2/Db2 69.30 D2 73.42
// D#2/Eb2 77.78 E2 82.41 F2 87.31
// F#2/Gb2 92.50 G2 98.00 G#2/Ab2 103.83
// A2 110.00 A#2/Bb2 116.54 B2 123.47
// C3 130.81 C#3/Db3 138.59 D3 146.83
// D#3/Eb3 155.56 E3 164.81 F3 174.61
// F#3/Gb3 185.00 G3 196.00 G#3/Ab3 207.65
// A3 220.00 A#3/Bb3 233.08 B3 246.94
// C4 261.63 C#4/Db4 277.18 D4 293.66
// D#4/Eb4 311.13 E4 329.63 F4 349.23
// F#4/Gb4 369.99 G4 392.00 G#4/Ab4 415.30
// A4 440.00 A#4/Bb4 466.16 B4 493.88
// C5 523.25 C#5/Db5 554.37 D5 587.33
// D#5/Eb5 622.25 E5 659.26 F5 698.46
// F#5/Gb5 739.99 G5 783.99 G#5/Ab5 830.61
// A5 880.00 A#5/Bb5 932.33 B5 987.77
// C6 1046.50 C#6/Db6 1108.73 D6 1174.66
// D#6/Eb6 1244.51 E6 1318.51 F6 1396.91
// F#6/Gb6 1479.98 G6 1567.98 G#6/Ab6 1661.22
// A6 1760.00 A#6/Bb6 1864.66 B6 1975.53
// C7 2093.00 C#7/Db7 2217.46 D7 2349.32
// D#7/Eb7 2489.02 E7 2637.02 F7 2793.83
// F#7/Gb7 2959.96 G7 3135.96 G#7/Ab7 3322.44
// A7 3520.00 A#7/Bb7 3729.31 B7 3951.07
// C8 4186.01 C#8/Db8 4434.92 D8 4698.64
// D#8/Eb8 4978.03
// global variables /////////////////////////////////////////////////////////
LPDIRECTSOUND8 g_pDS = NULL;
// code /////////////////////////////////////////////////////////////////////
HWND GetConsoleWindowHandle()
{
char title[512];
HWND hWnd;
GetConsoleTitle(title, sizeof(title));
hWnd = FindWindow(NULL, title);
return(hWnd);
}
// InitAudio: initializes DirectX Audio
void InitAudio()
{
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(GetConsoleWindowHandle(), DSSCL_PRIORITY))) {
err << "SetCooperativeLevel failed: " << DXGetErrorString8(hr) << endl;
throw(err.str());
}
// step 3: Set primary buffer's format (stereo, 22050 Hz, 16 bits)
{
LPDIRECTSOUNDBUFFER pDSBPrimary = NULL;
// 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, &pDSBPrimary, 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 = pDSBPrimary->SetFormat(&wfx) ) ) {
err << "pSDBPrimary->SetFormat() failed: " << DXGetErrorString8(hr) << endl;
throw(err.str());
}
// we're done with it, so release!
SAFE_RELEASE( pDSBPrimary );
}
}
int CreateSecondaryBuffer(LPDIRECTSOUNDBUFFER *ppBuffer, int channels,
int secs, int samplerate, int bitspersample, DWORD flags)
{
HRESULT hr;
stringstream err;
DSBUFFERDESC dsbd;
WAVEFORMATEX wfx;
ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = channels;
wfx.nSamplesPerSec = samplerate;
wfx.wBitsPerSample = 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 = flags;
dsbd.dwBufferBytes = samplerate * bitspersample / 8 * channels * secs;
dsbd.guid3DAlgorithm = GUID_NULL;
dsbd.lpwfxFormat = &wfx;
if( FAILED( hr = g_pDS->CreateSoundBuffer( &dsbd, ppBuffer, NULL ) ) )
{
err << "CreateSecondaryBuffer: CreateSoundBuffer failed: " << DXGetErrorString8(hr) << endl;
throw(err.str());;
}
return(dsbd.dwBufferBytes); // return size of buffer
}
void FillBuffer(LPDIRECTSOUNDBUFFER pBuffer, float frequency, int buffersize, int samplerate)
{
HRESULT hr;
stringstream err;
unsigned char *pBufferBytes;
DWORD lockedsize;
// Lock the buffer down
if(FAILED(hr = pBuffer->Lock(0, buffersize, (void **)(&pBufferBytes),
&lockedsize, NULL, NULL, 0L))) {
err << "FillBuffer: Lock failed: " << DXGetErrorString8(hr) << endl;
throw(err.str());;
}
for (DWORD q=0; q < lockedsize; q++) {
/* What cycle are we in? */
float pos = frequency/(float)samplerate*(float)q;
/* Take fractional part of cycle and convert to degrees */
float r = (pos - floor(pos)) * 2 * PI;
float value = sin(r); // we now have a value somewhere between -1 and 1
// change multiplier to change amplitude of wave aka volume
pBufferBytes[q] = 127+(value * 127);
}
// Unlock the buffer
pBuffer->Unlock( pBufferBytes, lockedsize, NULL, 0 );
}
void PlayBuffer(LPDIRECTSOUNDBUFFER pBuffer)
{
pBuffer->Play(0, 0, DSBPLAY_LOOPING);
}
void Exit(int errorcode)
{
#ifdef _DEBUG
cout << endl << endl << "(Program ended, press a key to exit.)";
// so that the console window doesn't disappear before we have
// a chance to look at it.
getch();
#endif
exit(errorcode);
}
void main(int argc, char* argv[])
{
LPDIRECTSOUNDBUFFER soundbuf;
bool audioinited = false;
try {
cout << "ToneGenerator" << endl << "=========================================" << endl;
cout << "Initializing Audio..." << endl;
// initialize DirectX Audio
InitAudio();
audioinited = true;
// create secondary buffer
cout << "Creating sound buffer..." << endl;
int buffersize = CreateSecondaryBuffer(&soundbuf, 1, 1, 22010, 8, 0);
// fill secondary buffer with tone data
cout << "Filling sound buffer with data..." << endl;
FillBuffer(soundbuf, 440.0, buffersize, 22010); // 4th octave A note
// tell user to turn down speakers
cout << endl << endl << "*** TURN YOUR VOLUME DOWN ALL THE WAY! *** (then press a key)" << endl;
getch();
// play secondary buffer
cout << "Playing buffer (slowly increase your volume, then hit a key to stop)..." << endl;
PlayBuffer(soundbuf);
getch();
// stop secondary buffer
soundbuf->Stop();
// release secondary buffer
cout << "Releasing sound buffer..." << endl;
SAFE_RELEASE(soundbuf);
// un-init DirectSound
cout << "Un-Initializing Audio..." << endl;
SAFE_RELEASE(g_pDS);
}
catch(string err) {
cerr << err;
Exit(-1);
}
Exit(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -