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

📄 soundout.cpp

📁 基于Windows CE的正旋信号发生程序
💻 CPP
字号:
// SoundOut.cpp: implementation of the CSoundOut class.
//
//////////////////////////////////////////////////////////////////////
/*
   
	    This program is Developped by Yannick Sustrac
                   yannstrc@mail.dotcom.fr
		        http://www.mygale.org/~yannstrc/
 

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., 675 Mass Ave, Cambridge, MA 02139, USA.

MODIFICATION:
- CallBack function implementation 
- Double buffer to feed the sound system

*/
//////////////////////////////////////////////////////////////////////////////////////////    

#include "stdafx.h"
#include "math.h"
#include "PSignalGenerate.h"
#include "SoundOut.h"

//#pragma comment(lib, "winmm")

/////////////////////////////////////////////////////////////////////////////////////////////
// comment this line to compile with a thread implementation rather than a callback function
//#define CALL_BACK_TEST
/////////////////////////////////////////////////////////////////////////////////////////////

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

#define real double

UINT WaveOutThreadProc(void * pParam);
void CALLBACK WaveOutProc(HWAVEOUT hwo,UINT uMsg,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2);

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

CSoundOut::CSoundOut()
{
  m_NbMaxSamples = MAX_OUTPUT_SAMPLES;
  m_WaveOutSampleRate = 11025;

  m_Toggle = 0;
}

CSoundOut::~CSoundOut()
{
	CloseOutput();
}
///////////////////////////////////////////////////////////////////
MMRESULT CSoundOut::OpenOutput()
{
     MMRESULT result;

	 
    result=waveOutGetNumDevs(); 
	if (result == 0)
	{
        AfxMessageBox(L"No Sound Output Device");
		return result;
	}

   // test for Mic available   
   result=waveOutGetDevCaps (0, &m_WaveOutDevCaps, sizeof(WAVEOUTCAPS));
   
   if ( result!= MMSYSERR_NOERROR)
   {
       AfxMessageBox(_T("Sound output Cannot determine card capabilities !"));
   }

	m_Terminate = FALSE;
#ifndef CALL_BACK_TEST
	// The SoundOut Devive is OK now we can create an Event  and start the Thread
	m_WaveOutEvent = CreateEvent(NULL,FALSE,FALSE,L"WaveOutThreadEvent");
	m_WaveOutThread= AfxBeginThread(WaveOutThreadProc,this,THREAD_PRIORITY_TIME_CRITICAL,0,CREATE_SUSPENDED,NULL);   
	m_WaveOutThread->m_bAutoDelete = TRUE;
#endif
// start the thread at the end of the buffer init
	// init format 
	WaveInitFormat(1/* mono*/,m_WaveOutSampleRate /* khz */,16 /* bits */); 

	// Open Output 
#ifdef CALL_BACK_TEST
	result = waveOutOpen( &m_WaveOut,0, &m_WaveFormat,(DWORD)WaveOutProc ,(ULONG)this ,CALLBACK_FUNCTION); 
#else
	result = waveOutOpen( &m_WaveOut,0, &m_WaveFormat,(DWORD)m_WaveOutEvent ,NULL ,CALLBACK_EVENT); 
#endif

	if ( result!= MMSYSERR_NOERROR)
	{
        AfxMessageBox(_T("Sound output Cannot Open Device!"));
	    return result;
	}


	m_Toggle = 0;
	m_SizeRecord = m_NbMaxSamples;
    m_WaveHeader[m_Toggle].lpData = (CHAR *)&OutputBuffer[m_Toggle][0];
    m_WaveHeader[m_Toggle].dwBufferLength = m_SizeRecord*2;
	m_WaveHeader[m_Toggle].dwFlags = 0;

    result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader[m_Toggle], sizeof(WAVEHDR) ); 
  //MMRESULT waveOutPrepareHeader( HWAVEOUT hwi, LPWAVEHDR pwh, UINT cbwh ); 
   if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader[m_Toggle].dwFlags != WHDR_PREPARED) )
   {
        AfxMessageBox(_T(" Sound Output Cannot Prepare Header !"));
	    return result;
   }

   result = waveOutWrite( m_WaveOut, &m_WaveHeader[m_Toggle], sizeof(WAVEHDR) );
   if  (result!= MMSYSERR_NOERROR) 
   {
        AfxMessageBox(_T(" Sound Output Cannot Write Buffer !"));
	    return result;
   }


   // register the second frame don't wait for the end of the first one
   // so when we will be notified, this second frame will be currently output when we will reload the first one 
	m_Toggle = 1;
	m_SizeRecord = m_NbMaxSamples;
    m_WaveHeader[m_Toggle].lpData = (CHAR *)&OutputBuffer[m_Toggle][0];
    m_WaveHeader[m_Toggle].dwBufferLength = m_SizeRecord*2;
	m_WaveHeader[m_Toggle].dwFlags = 0;

    result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader[m_Toggle], sizeof(WAVEHDR) ); 
  //MMRESULT waveOutPrepareHeader( HWAVEOUT hwi, LPWAVEHDR pwh, UINT cbwh ); 
   if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader[m_Toggle].dwFlags != WHDR_PREPARED) )
   {
        AfxMessageBox(_T(" Sound Output Cannot Prepare Header !"));
	    return result;
   }

   result = waveOutWrite( m_WaveOut, &m_WaveHeader[m_Toggle], sizeof(WAVEHDR) );
   if  (result!= MMSYSERR_NOERROR) 
   {
        AfxMessageBox(_T(" Sound Output Cannot Write Buffer !"));
	    return result;
   }

#ifndef CALL_BACK_TEST
	m_WaveOutThread->ResumeThread();
#endif

   return result;
}



void CSoundOut::AddBuffer()
{
	
   MMRESULT result;

   /*
   if (m_Toggle == 0) 
	   m_Toggle = 1; 
   else 
	   m_Toggle = 0;
	   */
   m_Toggle=m_Toggle?0:1;
   result = waveOutUnprepareHeader( m_WaveOut, &m_WaveHeader[m_Toggle], sizeof(WAVEHDR) ); 
   if  (result!= MMSYSERR_NOERROR) 
   {
        AfxMessageBox(_T("Sound output Cannot UnPrepareHeader !"));
        return;
   };
 	m_SizeRecord = m_NbMaxSamples;
    m_WaveHeader[m_Toggle].lpData = (CHAR *)&OutputBuffer[m_Toggle][0];
    m_WaveHeader[m_Toggle].dwBufferLength = m_SizeRecord *2;
	m_WaveHeader[m_Toggle].dwLoops = 0;
	m_WaveHeader[m_Toggle].dwFlags = 0; //WHDR_BEGINLOOP ;

    result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader[m_Toggle], sizeof(WAVEHDR) ); 
   if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader[m_Toggle].dwFlags != WHDR_PREPARED) )
        AfxMessageBox(_T("Sound output Cannot Prepare Header !"));

   result = waveOutWrite( m_WaveOut, &m_WaveHeader[m_Toggle], sizeof(WAVEHDR) );
   if  (result!= MMSYSERR_NOERROR) 
        AfxMessageBox(_T("Sound output Cannot Add Buffer !"));

}


/*
WAVE_FORMAT_1M08  11.025 kHz, mono, 8-bit 
WAVE_FORMAT_1M16  11.025 kHz, mono, 16-bit 
WAVE_FORMAT_1S08  11.025 kHz, stereo, 8-bit 
WAVE_FORMAT_1S16  11.025 kHz, stereo, 16-bit 
WAVE_FORMAT_2M08  22.05 kHz, mono, 8-bit 
WAVE_FORMAT_2M16  22.05 kHz, mono, 16-bit 
WAVE_FORMAT_2S08  22.05 kHz, stereo, 8-bit 
WAVE_FORMAT_2S16  22.05 kHz, stereo, 16-bit 
WAVE_FORMAT_4M08  44.1 kHz, mono, 8-bit 
WAVE_FORMAT_4M16  44.1 kHz, mono, 16-bit 
WAVE_FORMAT_4S08  44.1 kHz, stereo, 8-bit 
WAVE_FORMAT_4S16  44.1 kHz, stereo, 16-bit 
*/ 

void CSoundOut:: WaveInitFormat(    WORD    nCh, // number of channels (mono, stereo)
								DWORD   nSampleRate, // sample rate
								WORD    BitsPerSample)
{
		m_WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
		m_WaveFormat.nChannels = nCh;
		m_WaveFormat.nSamplesPerSec = nSampleRate;
		m_WaveFormat.nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8;
		m_WaveFormat.nBlockAlign = m_WaveFormat.nChannels * BitsPerSample/8;
		m_WaveFormat.wBitsPerSample = BitsPerSample;
		m_WaveFormat.cbSize = 0;
}   


///////////////////////////////////////////////////////////////////////////
// the comutation for the Output samples need to be calibrated according
// to the SoundOut board  add an Offset and a Mult coef.

void CSoundOut::ComputeSamples(SHORT *pt)
{
}  


void CSoundOut::CloseOutput()
{
	if (m_WaveOut) 
		waveOutPause(m_WaveOut);
    Sleep(50);  // wait for the pause
	//	CloseHandle(m_WaveOut);
	m_Terminate = TRUE;
    if (m_WaveOutEvent )
		SetEvent(m_WaveOutEvent);
    Sleep(50);  // wait for the thread to terminate

   if (m_WaveOut) 
   {
		waveOutReset(m_WaveOut);
		waveOutClose(m_WaveOut);
   }
}

void CSoundOut::RazBuffers()
{
		for (int i=0;i<MAX_OUTPUT_SAMPLES;i++)
		{
	        OutputBuffer[0][i] = 0;
	        OutputBuffer[1][i] = 0;
		}
}

void CSoundOut::StopOutput()
{
	waveOutPause(m_WaveOut);
}

void CSoundOut::StartOutput()
{
	waveOutRestart(m_WaveOut);
}



/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//    Glogal Thread procedure for the CSoundOut class
//    It cannot be included inside the Class
//   
// The LPARAM is the Class pointer it can be the base class CSoundOut
// or a drived class like CFft 
// The value of this parametre can change according because 
//  OpenMic() call a virtual funtion 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define PT_S ((CSoundOut*)pParam) 

UINT WaveOutThreadProc(void * pParam)
{
//   CSoundOut * SoundOut = (class CSoundOut *)pParam;
   UINT result;
   UINT FirstPass = TRUE;


	if ( FirstPass)
		result = WaitForSingleObject(PT_S->m_WaveOutEvent,INFINITE);
	FirstPass = FALSE;
    
	while (!PT_S->m_Terminate)
	{
		result = WaitForSingleObject(PT_S->m_WaveOutEvent,INFINITE);
		if ((result == WAIT_OBJECT_0)&&(!PT_S->m_Terminate ))
		{
			PT_S->AddBuffer();      // Toggle as changed state here !Toggle point to the just received buffer
		    PT_S->ComputeSamples(&PT_S->m_Toggle);
		}
		else
			return 0;  // 
	}
    return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//    Test with a callback function instead of a thread
//    
//////////////////////////////////////////////////////////////////////////////////////////////////////////// 

#ifdef CALL_BACK_TEST

void CALLBACK WaveOutProc(HWAVEOUT hwo,UINT uMsg,DWORD pParam,DWORD dwParam1,DWORD dwParam2)
{
	if (!PT_S->m_Terminate )
	switch (uMsg)
	{
	case WOM_DONE:
		PT_S->AddBuffer();
	    PT_S->ComputeSamples(&PT_S->m_Toggle);
		break;
	case WOM_OPEN:
		break;
	case WOM_CLOSE:
		break;
	}
}

#endif

⌨️ 快捷键说明

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