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

📄 sound.cpp

📁 QAM module to use in Java with an easy interface and powerful performance
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************\
 * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
 * Copyright (c) 2001
 *
 * Author(s):
 *	Volker Fischer
 *
 * Description:
 * Sound card interface for Windows operating systems
 *
 ******************************************************************************
 *
 * 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 (at your option) 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
 *
\******************************************************************************/

#include "Sound.h"


/* Implementation *************************************************************/
/******************************************************************************\
* Wave in                                                                      *
\******************************************************************************/
bool CSound::Read(vector<short>& psData)
{
	int			i;
	bool	bError;

	/* Check if device must be opened or reinitialized */
	if (bChangDevIn == TRUE)
	{
		OpenInDevice();

		/* Reinit sound interface */
		InitRecording(iBufferSizeIn, bBlockingRec);

		/* Reset flag */
		bChangDevIn = FALSE;
	}

	/* Wait until data is available */
	if (!(m_WaveInHeader[iWhichBufferIn].dwFlags & WHDR_DONE))
	{
		if (bBlockingRec == TRUE)
			WaitForSingleObject(m_WaveInEvent, INFINITE);
		else
			return FALSE;
	}

	/* Check if buffers got lost */
	int iNumInBufDone = 0;
	for (i = 0; i < NUM_SOUND_BUFFERS_IN; i++)
	{
		if (m_WaveInHeader[i].dwFlags & WHDR_DONE)
			iNumInBufDone++;
	}

	/* If the number of done buffers equals the total number of buffers, it is
	   very likely that a buffer got lost -> set error flag */
	if (iNumInBufDone == NUM_SOUND_BUFFERS_IN)
		bError = TRUE;
	else
		bError = FALSE;

	/* Copy data from sound card in output buffer */
	for (i = 0; i < iBufferSizeIn; i++)
		psData[i] = psSoundcardBuffer[iWhichBufferIn][i];

	/* Add the buffer so that it can be filled with new samples */
	AddInBuffer();

	/* In case more than one buffer was ready, reset event */
	ResetEvent(m_WaveInEvent);

	return bError;
}

void CSound::AddInBuffer()
{
	/* Unprepare old wave-header */
	waveInUnprepareHeader(
		m_WaveIn, &m_WaveInHeader[iWhichBufferIn], sizeof(WAVEHDR));

	/* Prepare buffers for sending to sound interface */
	PrepareInBuffer(iWhichBufferIn);

	/* Send buffer to driver for filling with new data */
	waveInAddBuffer(m_WaveIn, &m_WaveInHeader[iWhichBufferIn], sizeof(WAVEHDR));

	/* Toggle buffers */
	iWhichBufferIn++;
	if (iWhichBufferIn == NUM_SOUND_BUFFERS_IN)
		iWhichBufferIn = 0;
}

void CSound::PrepareInBuffer(int iBufNum)
{
	/* Set struct entries */
	m_WaveInHeader[iBufNum].lpData = (LPSTR) &psSoundcardBuffer[iBufNum][0];
	m_WaveInHeader[iBufNum].dwBufferLength = iBufferSizeIn * BYTES_PER_SAMPLE;
	m_WaveInHeader[iBufNum].dwFlags = 0;

	/* Prepare wave-header */
	waveInPrepareHeader(m_WaveIn, &m_WaveInHeader[iBufNum], sizeof(WAVEHDR));
}

void CSound::InitRecording(int iNewBufferSize, bool bNewBlocking)
{
	/* Check if device must be opened or reinitialized */
	if (bChangDevIn == TRUE)
	{
		OpenInDevice();

		/* Reset flag */
		bChangDevIn = FALSE;
	}

	/* Set internal parameter */
	iBufferSizeIn = iNewBufferSize;
	bBlockingRec = bNewBlocking;

	/* Reset interface so that all buffers are returned from the interface */
	waveInReset(m_WaveIn);
	waveInStop(m_WaveIn);
	
	/* Reset current buffer ID (it is important to do this BEFORE calling
	   "AddInBuffer()" */
	iWhichBufferIn = 0;

	/* Create memory for sound card buffer */
	for (int i = 0; i < NUM_SOUND_BUFFERS_IN; i++)
	{
		/* Unprepare old wave-header in case that we "re-initialized" this
		   module. Calling "waveInUnprepareHeader()" with an unprepared
		   buffer (when the module is initialized for the first time) has
		   simply no effect */
		waveInUnprepareHeader(m_WaveIn, &m_WaveInHeader[i], sizeof(WAVEHDR));

		if (psSoundcardBuffer[i] != NULL)
			delete[] psSoundcardBuffer[i];

		psSoundcardBuffer[i] = new short[iBufferSizeIn];


		/* Send all buffers to driver for filling the queue ----------------- */
		/* Prepare buffers before sending them to the sound interface */
		PrepareInBuffer(i);

		AddInBuffer();
	}

	/* Notify that sound capturing can start now */
	waveInStart(m_WaveIn);

	/* This reset event is very important for initialization, otherwise we will
	   get errors! */
	ResetEvent(m_WaveInEvent);
}

void CSound::OpenInDevice()
{
	/* Open wave-input and set call-back mechanism to event handle */
	if (m_WaveIn != NULL)
	{
		waveInReset(m_WaveIn);
		waveInClose(m_WaveIn);
	}

	MMRESULT result = waveInOpen(&m_WaveIn, iCurInDev, &sWaveFormatEx,
		(DWORD) m_WaveInEvent, NULL, CALLBACK_EVENT);
	if (result != MMSYSERR_NOERROR)
		throw CGenErr("Sound Interface Start, waveInOpen() failed. This error "
			"usually occurs if another application blocks the sound in.");
}

void CSound::SetInDev(int iNewDev)
{
	/* Set device to wave mapper if iNewDev is greater that the number of
	   sound devices in the system */
	if (iNewDev >= (int)iNumDevs)
		iNewDev = WAVE_MAPPER;

	/* Change only in case new device id is not already active */
	if (iNewDev != iCurInDev)
	{
		iCurInDev = iNewDev;
		bChangDevIn = TRUE;
	}
}


/******************************************************************************\
* Wave out                                                                     *
\******************************************************************************/
bool CSound::Write(vector<short>& psData)
{
	int			i, j;
	int			iCntPrepBuf;
	int			iIndexDoneBuf;
	bool	bError;

	/* Check if device must be opened or reinitialized */
	if (bChangDevOut == TRUE)
	{
		OpenOutDevice();

		/* Reinit sound interface */
		InitPlayback(iBufferSizeOut, bBlockingPlay);

		/* Reset flag */
		bChangDevOut = FALSE;
	}

	/* Get number of "done"-buffers and position of one of them */
	GetDoneBuffer(iCntPrepBuf, iIndexDoneBuf);

	/* Now check special cases (Buffer is full or empty) */
	if (iCntPrepBuf == 0)
	{
		if (bBlockingPlay == TRUE)
		{
			/* Blocking wave out routine. Needed for transmitter. Always
			   ensure that the buffer is completely filled to avoid buffer
			   underruns */
			while (iCntPrepBuf == 0)
			{
				WaitForSingleObject(m_WaveOutEvent, INFINITE);

				GetDoneBuffer(iCntPrepBuf, iIndexDoneBuf);
			}
		}
		else
		{
			/* All buffers are filled, dump new block ----------------------- */
// It would be better to kill half of the buffer blocks to set the start
// back to the middle: TODO
			return TRUE; /* An error occurred */
		}
	}
	else if (iCntPrepBuf == NUM_SOUND_BUFFERS_OUT)
	{
		/* ---------------------------------------------------------------------
		   Buffer is empty -> send as many cleared blocks to the sound-
		   interface until half of the buffer size is reached */
		/* Send half of the buffer size blocks to the sound-interface */
		for (j = 0; j < NUM_SOUND_BUFFERS_OUT / 2; j++)
		{
			/* First, clear these buffers */
			for (i = 0; i < iBufferSizeOut; i++)
				psPlaybackBuffer[j][i] = 0;

			/* Then send them to the interface */
			AddOutBuffer(j);
		}

		/* Set index for done buffer */
		iIndexDoneBuf = NUM_SOUND_BUFFERS_OUT / 2;

		bError = TRUE;
	}
	else
		bError = FALSE;

	/* Copy stereo data from input in soundcard buffer */
	for (i = 0; i < iBufferSizeOut; i++)
		psPlaybackBuffer[iIndexDoneBuf][i] = psData[i];

	/* Now, send the current block */
	AddOutBuffer(iIndexDoneBuf);

	return bError;

⌨️ 快捷键说明

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