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

📄 sound.cpp

📁 信道仿真源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////
// Sound.cpp: implementation of the CSound class.
//////////////////////////////////////////////////////////////////////
// Copyright 2000.    Moe Wheatley AE4JY  <ae4jy@mindspring.com>
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
////////////////////////////////////////////////////////////////////////
// This class implements an object that reads/writes to a soundcard.
//
// The following member functions are used to perform all the tasks:
//
//  UINT m_InOpen( WAVEFORMATEX* pWFX, DWORD BufSize, DWORD SampleLimit, INT card);
//	LONG m_InRead( double* pData, INT Length );
//	void InClose();
//
//	UINT m_OutOpen( WAVEFORMATEX* pWFX,	DWORD BufSize, DWORD SampleLimit, INT card);
//	LONG m_OutWrite( double* pData, INT Length  );
//	void OutClose();
//
//+++++++++++++   WAVEFORMATEX  member variables     +++++++++++++++++++
//typedef struct { 
//    WORD  wFormatTag; 
//    WORD  nChannels; 
//    DWORD nSamplesPerSec; 
//    DWORD nAvgBytesPerSec; 
//    WORD  nBlockAlign; 
//    WORD  wBitsPerSample; 
//    WORD  cbSize; 
//} WAVEFORMATEX; 

#include "stdafx.h"
#include "Sound.h"
#include "ErrorCodes.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//local defines
#define TIMELIMIT 2000			// time limit to wait on a new soundcard buffer
								// to become ready in milliSeconds.

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSound::CSound()
{
	m_InputOpen = FALSE;
	m_OutputOpen = FALSE;
	m_hwvin = NULL;
	m_hwvout = NULL;
	m_InEventHandle = NULL;
	m_OutEventHandle = NULL;
	m_ErrorCode = 0;
	InitializeCriticalSection(&m_CriticalSection);
}

CSound::~CSound()
{
	DeleteCriticalSection(&m_CriticalSection);
}

//////////////////////////////////////////////////////////////////////
//  This function opens a Soundcard for input.  Sample size can be
//  1,2 or 4 bytes long depending on bits per sample and number of channels.
//( ie. a 1000 sample buffer for 16 bit stereo will be a 4000 byte buffer)
//   Sampling begins immediately so the thread must start calling m_InRead()
//       to prevent buffer overflow.
//  parameters:
//		pWFX		= WAVEFORMATEX structure with desired soundcard settings
//		BufSize		= DWORD specifies the soundcard buffer size number 
//						in number of samples to buffer.
//					  If this value is Zero, the soundcard is opened and
//						then closed. This is useful	for checking the
//						soundcard.
//		SampleLimit = limit on number of samples to be read. 0 signifies
//						continuous input stream.
//		card		= Which soundcard to use(0 to n-1) (-1 lets Windows decide)
//    returns:
//        0			if opened OK
//    ErrorCode		if not
//////////////////////////////////////////////////////////////////////
UINT CSound::InOpen( WAVEFORMATEX* pWFX, DWORD BufSize, DWORD SampleLimit, INT card)
{
INT i;
	m_InWaiting = FALSE;
	m_InOverflow = FALSE;
	m_InHeadPtr = 0;
	m_InTailPtr = 0;
	m_InSamplesRead = 0;
	m_InBufPosition = 0;
	m_InFormat = *pWFX;
	m_InBytesPerSample = (m_InFormat.wBitsPerSample/8)*m_InFormat.nChannels;
	m_InBufferSize = BufSize * m_InBytesPerSample;
	m_InSampleLimit = SampleLimit;
//	event for callback function to notify new buffer available
	m_InEventHandle = CreateEvent(NULL, FALSE,FALSE,NULL);
// open sound card input and get handle(m_hwvin) to device
	if( (m_ErrorCode = waveInOpen( &m_hwvin, card , pWFX,
			(DWORD)&WaveInCallback, (DWORD)this, CALLBACK_FUNCTION ) )
						!= MMSYSERR_NOERROR )
	{
		InClose();	// m_ErrorCode = MMSYSERR_xxx
		return m_ErrorCode;
	}

	if( BufSize == 0 )  // see if just a soundcard check
	{
		InClose();	// if so close the soundcard input
		return 0;
	}

	for(i=0; i<NUM_INPUT_SNDBUFFERS; i++ )
	{
// allocate input buffer headers
		m_pInputBuffer[i] = NULL;
		if( ( m_pInputBuffer[i] = new WAVEHDR[ sizeof(WAVEHDR)] ) == NULL )
		{
			m_ErrorCode = MEMORY_ERROR;
			InClose();
			return m_ErrorCode;
		}
// allocate input data buffers
		m_pInputBuffer[i]->dwBufferLength = m_InBufferSize;
		m_pInputBuffer[i]->dwFlags = 0;
		m_pInputBuffer[i]->dwUser = NULL;
		m_pInputBuffer[i]->dwBytesRecorded = NULL;
		if( (m_pInputBuffer[i]->lpData = new char[m_InBufferSize] ) == NULL )
		{
			m_ErrorCode = MEMORY_ERROR;
			InClose();
			return m_ErrorCode;
		}
		if( (m_ErrorCode = waveInPrepareHeader(m_hwvin, m_pInputBuffer[i],
					sizeof *m_pInputBuffer[i])) != MMSYSERR_NOERROR )
		{
			InClose( );	// m_ErrorCode = MMSYSERR_xxx
			return m_ErrorCode;
		}

		if( (m_ErrorCode = waveInAddBuffer(m_hwvin, m_pInputBuffer[i], 
			sizeof *m_pInputBuffer[i]) )!= MMSYSERR_NOERROR )
		{
			InClose();	// m_ErrorCode = MMSYSERR_xxx
			return m_ErrorCode;
		}
	}
//
// start input capturing to buffer
	if( (m_ErrorCode = waveInStart( m_hwvin) )!= MMSYSERR_NOERROR )
	{
		InClose();	// m_ErrorCode = MMSYSERR_xxx
		return m_ErrorCode;
	}
	m_InputOpen = TRUE;
	return 0;
}

///////////////////////////////////////////////////////////////////////
// Reads 'Length' samples of double data from the opened soundcard input
//	returns:
//   Length	if 'Length' samples were succesfully read
//   0 =	if reaches the specified sample limit
//	-1 =	if there is an error ( use GetError() to retrieve error )
///////////////////////////////////////////////////////////////////////
LONG CSound::InRead( double* pData, INT Length)
{
INT i;
	if( !m_InputOpen )		// return -1 if no inputs are active
	{
		m_ErrorCode = SOUNDIN_ERR_NOTOPEN;
		return -1;
	}
	if( m_InOverflow )
	{
		m_ErrorCode = SOUNDIN_ERR_OVERFLOW;
		InClose();
		return -1;			// return -1 if overflow
	}

	EnterCriticalSection(&m_CriticalSection);
	if( m_InTailPtr == m_InHeadPtr )		//if no buffer is filled
	{
		// wait for mmsystem to fill up a new buffer
		m_InWaiting = TRUE;
		LeaveCriticalSection(&m_CriticalSection);
		if( WaitForSingleObject( m_InEventHandle,TIMELIMIT )
									!= WAIT_OBJECT_0 )
		{
			m_ErrorCode = SOUNDIN_ERR_TIMEOUT; // if took too long error out
			InClose();
			return -1;
		}
	}
	else
		LeaveCriticalSection(&m_CriticalSection);
//here if there is data to retrieved
	if( m_InFormat.wBitsPerSample == 16 )
	{
		for( i=0; i < (Length*m_InFormat.nChannels); i++ )
		{
			m_usTemp.bytes.lsb = *(m_pInputBuffer[m_InTailPtr]->lpData
									+ (m_InBufPosition++) );
			m_usTemp.bytes.msb = *(m_pInputBuffer[m_InTailPtr]->lpData
									+ (m_InBufPosition++) );
			*(pData + i) = (double)m_usTemp.both;
		}
	}
	else
	{
		m_usTemp.bytes.lsb = 0;
		for( i=0; i < (Length*m_InFormat.nChannels); i++ )
		{
			m_usTemp.bytes.msb = *(m_pInputBuffer[m_InTailPtr]->lpData
									+ (m_InBufPosition++) ) - 128;
			*(pData + i) = (double)m_usTemp.both;
		}
	}
	if( m_InBufPosition >= m_InBufferSize )		//finished with this buffer
	{											//so add it back in to the Queue
		m_pInputBuffer[m_InTailPtr]->dwBytesRecorded = NULL;
		waveInAddBuffer(m_hwvin, m_pInputBuffer[m_InTailPtr], sizeof *m_pInputBuffer[m_InTailPtr]);
		m_InBufPosition = 0;
		if( ++m_InTailPtr >= NUM_INPUT_SNDBUFFERS)	// handle wrap around
			m_InTailPtr = 0;
	}
	m_InSamplesRead += Length;
	if( (m_InSampleLimit != 0) && (m_InSamplesRead >= m_InSampleLimit) )
	{
		InClose();
		return 0;
	}
	return Length;
}

//////////////////////////////////////////////////////////////////////
//  Closes the Soundcard Input if open and free up resources.
//
//////////////////////////////////////////////////////////////////////
void CSound::InClose()
{
INT i;
	m_InputOpen = FALSE;
	if (NULL != m_hwvin)
	{
		waveInReset(m_hwvin);
		Sleep(100);
		for( i=0; i<NUM_INPUT_SNDBUFFERS; i++ )
		{
			if( m_pInputBuffer[i] )
			{
				if( m_pInputBuffer[i]->lpData != NULL )
				{
					if( m_pInputBuffer[i]->dwFlags&WHDR_PREPARED )
					{
						waveInUnprepareHeader(m_hwvin, m_pInputBuffer[i],
							sizeof *m_pInputBuffer[i]);
					}
					if( m_pInputBuffer[i]->lpData )
					{
						delete m_pInputBuffer[i]->lpData;
						m_pInputBuffer[i]->lpData = NULL;
					}
				}
				if( m_pInputBuffer[i] )
				{
					delete m_pInputBuffer[i];
					m_pInputBuffer[i] = NULL;
				}
			}
		}
		Sleep(50);
		waveInClose(m_hwvin);
		Sleep(50);
		m_hwvin = NULL;
	}
	if(m_InEventHandle)
	{
		CloseHandle(m_InEventHandle);
		m_InEventHandle = NULL;
	}
}

//////////////////////////////////////////////////////////////////////
//  This function opens a Soundcard for writing.
//Sample size can be 1,2 or 4 bytes long depending on bits per sample
// and number of channels.( ie. a 1000 sample buffer for 16 bit stereo
// will be a 4000 byte buffer)
//  Output does not start until at least half the buffers are filled
//  or m_OutWrite() is called with a length of '0' to flush all buffers.
//    parameters:
//		pWFX	= WAVEFORMATEX structure with desired soundcard settings
//		BufSize		= DWORD specifies the soundcard buffer size number 
//						in number of samples to buffer.

⌨️ 快捷键说明

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