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

📄 sinsound.cpp

📁 Lakey这是一个免费的CW练习/收/发软件
💻 CPP
字号:
#include "StdAfx.h"
#include "dsound.h"
#include "math.h"
#include "sinsound.h"

CSinSound::CSinSound()
	:m_pDs(NULL),
	m_pDsb(NULL),
	m_pBlankDsb(NULL),
	m_rScale(1.0l),
	m_bFormatValid(FALSE),
	m_bDsbValid(FALSE),
	m_bDataValid(FALSE)
{
	memset(&m_oPlayedBufferDesc, 0, sizeof(m_oPlayedBufferDesc)); 
	memset(&m_oFormat, 0, sizeof(m_oFormat)); 

	m_oFormat.wFormatTag = WAVE_FORMAT_PCM;
	m_oFormat.nChannels = 1;
	m_oFormat.nSamplesPerSec = 44100;
	m_oFormat.wBitsPerSample = 16;
	m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
	m_oFormat.nBlockAlign = 2;
	m_oFormat.cbSize = 0;

	SetFrequency(1000);
}

CSinSound::~CSinSound(void)
{
	if (NULL != m_pDsb)
	{
		m_pDsb->Release();
		m_pDsb = NULL;
	}
	if (NULL != m_pBlankDsb)
	{
		m_pBlankDsb->Release();
		m_pBlankDsb = NULL;
	}
	if (NULL != m_pDs)
	{
		m_pDs->Release();
		m_pDs = NULL;
	}
}

BOOL CSinSound::Initialize(HWND hWnd)
{
	HRESULT hr =
		DirectSoundCreate(NULL, &m_pDs, NULL);
	if (FAILED(hr))
		return FALSE;

	hr = m_pDs->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
	if (FAILED(hr))
		return FALSE;

	return InitBufferFormat();
}

BOOL CSinSound::InitBufferFormat()
{
	DSBUFFERDESC dsbd;
	memset(&dsbd, 0, sizeof(DSBUFFERDESC));
	dsbd.dwSize = sizeof(DSBUFFERDESC);
	dsbd.dwFlags = DSBCAPS_STATIC;
	dsbd.dwBufferBytes = 8; 
	dsbd.lpwfxFormat = &m_oFormat;

	HRESULT hr = m_pDs->CreateSoundBuffer(&dsbd, &m_pBlankDsb, NULL);
	if (m_bFormatValid = SUCCEEDED(hr))
	{
		PlayBlank();
		return InitPlayedBuffer();
	}

	return FALSE;
}

BOOL CSinSound::InitPlayedBuffer()
{
	HRESULT hr; 

	m_oPlayedBufferDesc.dwSize = sizeof(DSBUFFERDESC); 
	m_oPlayedBufferDesc.dwFlags = DSBCAPS_STATIC; 
	m_oPlayedBufferDesc.dwBufferBytes = (DWORD)(m_rBufferLengthMs * m_oFormat.nAvgBytesPerSec / 1000); 
	m_oPlayedBufferDesc.lpwfxFormat = &m_oFormat;
	
	hr = m_pDs->CreateSoundBuffer(&m_oPlayedBufferDesc, &m_pDsb, NULL);
	if (m_bDsbValid = SUCCEEDED(hr))
		return WriteBuffer();

	return FALSE;
}

BOOL CSinSound::WriteBuffer()
{
	LPVOID  lpvPtr1; 
	DWORD dwBytes1; 

	HRESULT hr = m_pDsb->Lock(0, m_oPlayedBufferDesc.dwBufferBytes, &lpvPtr1, &dwBytes1, NULL, NULL, 0); 

	// If the buffer was lost, restore and retry lock. 

	if (DSERR_BUFFERLOST == hr) 
	{ 
		m_pDsb->Restore(); 
		hr = m_pDsb->Lock(0, m_oPlayedBufferDesc.dwBufferBytes, &lpvPtr1, &dwBytes1, NULL, NULL, DSBLOCK_ENTIREBUFFER); 
	}

	if (FAILED(hr))
		return (m_bDataValid = FALSE);
	
	double dt = 1.0l / m_oFormat.nSamplesPerSec;
	DWORD nBytesPerSample = m_oFormat.wBitsPerSample / 8;

	for (DWORD i = 0; i < dwBytes1 / nBytesPerSample; ++i)
	{
		double v = sin(2 * PI * dt * i * m_rFrequencyHz) * m_rScale;	// -1.0 ~ +1.0

		for (DWORD j = 0; j < m_oFormat.nChannels; ++j)
		{
			if (16 == m_oFormat.wBitsPerSample)
			{
				*(((short int *)lpvPtr1) + i * m_oFormat.nChannels + j) = (short int)(v * 32767);
			}
			else if (8 == m_oFormat.wBitsPerSample)
			{
				*(((char *)lpvPtr1) + i * m_oFormat.nChannels + j) = (char)(v * 255);
			}
			else
			{
				return (m_bDataValid = FALSE);
			}
		}
	}

	return (m_bDataValid = SUCCEEDED(m_pDsb->Unlock(lpvPtr1, dwBytes1, NULL, NULL)));
}

void CSinSound::Play()
{
	m_pDsb->SetCurrentPosition(0);
	HRESULT hr = m_pDsb->Play(0, 0, DSBPLAY_LOOPING);
	if (DSERR_BUFFERLOST == hr)
	{
		m_pDsb->Restore();
		WriteBuffer();
		m_pDsb->Play(0, 0, DSBPLAY_LOOPING);
	}
}

void CSinSound::Stop()
{
	m_pDsb->Stop();
}

void CSinSound::PlayBlank()
{
	HRESULT hr = m_pBlankDsb->Play(0, 0, DSBPLAY_LOOPING);
	if (DSERR_BUFFERLOST == hr)
	{
		m_pBlankDsb->Restore();
		m_pBlankDsb->Play(0, 0, DSBPLAY_LOOPING);
	}
}

void CSinSound::StopBlank()
{
	m_pBlankDsb->Stop();
}

void CSinSound::SetSampleRate(DWORD nSamplesPerSec)
{
	if (m_oFormat.nSamplesPerSec != nSamplesPerSec)
	{
		m_oFormat.nSamplesPerSec = nSamplesPerSec;
		m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
		m_bFormatValid = FALSE;
	}
}

void CSinSound::SetBitsPerSample(WORD nBits)
{
	if (m_oFormat.wBitsPerSample != nBits)
	{
		m_oFormat.wBitsPerSample = nBits;
		m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
		m_bFormatValid = FALSE;
	}
}

void CSinSound::SetBufferLength(double rMSec)
{
	if (m_rBufferLengthMs != rMSec)
	{
		m_rBufferLengthMs = rMSec;
		m_bDsbValid = FALSE;
	}
}

void CSinSound::SetFrequency(double rFrequency)
{
	if (m_rFrequencyHz != rFrequency)
	{
		double w = 1.0l / rFrequency;
		double d = 1.0l / m_oFormat.nSamplesPerSec;
		int nTimes;
		for (nTimes = 100; nTimes <= 1000; ++nTimes)
		{
			double rRemScale = fmod(w * nTimes, d) / w;

			if (rRemScale < 0.001l || rRemScale > 0.998l)
				break;
		}

		m_rFrequencyHz = rFrequency;
		m_rBufferLengthMs = nTimes * w * 1000.0l;
		m_bDsbValid = FALSE;
	}
}

void CSinSound::SetScale(double rScale)
{
	if (m_rScale != rScale)
	{
		m_rScale = rScale;
		m_bDataValid = FALSE;
	}
}

BOOL CSinSound::Validate()
{
	if (!m_bFormatValid)
	{
		m_pDsb->Release(); m_pDsb = NULL;
		m_pBlankDsb->Release(); m_pBlankDsb = NULL;
		return InitBufferFormat();
	}
	else if (!m_bDsbValid)
	{
		m_pDsb->Release(); m_pDsb = NULL;
		return InitPlayedBuffer();
	}
	else if (!m_bDataValid)
	{
		return WriteBuffer();
	}

	return true;
}

⌨️ 快捷键说明

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