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

📄 audiodrv.c

📁 一个操作系统源代码 用于嵌入式设备 在Vc++环境下仿真 成功移植到多款处理器上
💻 C
字号:
#include <windows.h>
#include <mmsystem.h>

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

#include <hardware\drball\audiodrv.h>

void InitSoundOut();
void StartOutput();
void StopOutput();
void CloseOutput();
void AddBuffer();

void RazBuffers();
void ComputeSamples(SHORT *);  

MMRESULT OpenOutput();
void WaveInitFormat( WORD nCh, DWORD nSampleRate, WORD BitsPerSample );

#define MAX_OUTPUT_SAMPLES 4096  
#define MAX_VOIE 2
#define MAX_SIZE_SAMPLES  1  // WORD
#define MAX_SIZE_OUTPUT_BUFFER   MAX_OUTPUT_SAMPLES*MAX_VOIE*MAX_SIZE_SAMPLES 

//AUDIO[ AUDIO_SIZE ] is a unit to play
unsigned char		*AUDIO;						//the AUDIO's first address
unsigned long		AUDIO_SIZE = 8000;			//the AUDIO size
unsigned long		LOOP_PT = 4800;				//the loop address of AUDIO
unsigned long		AUDIO_PT = 0;				//the pointer of note
unsigned char		PLAY_MODE = BY_SIZE;		//the flag of AUDIO and note ,AUDIO is 1,note 0
unsigned char		AUDIO_STATUS = STOP_STATUS;

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

#define CALL_BACK_TEST

struct SoundOut
{
	SHORT  OutputBuffer[2][MAX_SIZE_OUTPUT_BUFFER];

	WAVEOUTCAPS		m_WaveOutDevCaps;
    HWAVEOUT		m_WaveOut;
	WAVEHDR			m_WaveHeader[2];
    WAVEFORMATEX	m_WaveFormat;
	HANDLE m_WaveOutEvent;

	HANDLE *m_WaveOutThread;
	BOOL m_Terminate;

	UINT m_WaveOutSampleRate;
	int  m_NbMaxSamples;
	UINT m_SizeRecord;

	SHORT m_Toggle;
}SoundDevice;

void InitSoundOut()
{
	MMRESULT result;
	int	temp;

    result = waveOutGetNumDevs(); 
	if (result == 0)
	{
        MessageBox( NULL, "No Sound Output Device", "Error", MB_OK | MB_ICONERROR );
		return;
	}

	// test for Mic available   
	result = waveOutGetDevCaps (0, &SoundDevice.m_WaveOutDevCaps, sizeof(WAVEOUTCAPS));

	if ( result!= MMSYSERR_NOERROR)
	{
		MessageBox( NULL, "Sound output Cannot determine card capabilities !", "Error", MB_OK | MB_ICONERROR );
	}
  
	SoundDevice.m_NbMaxSamples = 4000; //MAX_OUTPUT_SAMPLES;
	SoundDevice.m_WaveOutSampleRate = 16000; // 11025;

	SoundDevice.m_Toggle = 0;

	// init format 
	WaveInitFormat(1/* mono*/,SoundDevice.m_WaveOutSampleRate /* khz */,8 /* bits */); 

	// The SoundOut Devive is OK now we can create an Event  and start the Thread
	SoundDevice.m_WaveOutEvent = CreateEvent(NULL,FALSE,FALSE,"WaveOutThreadEvent");

	// Open Output 
#ifdef CALL_BACK_TEST
	result = waveOutOpen( &SoundDevice.m_WaveOut,0, &SoundDevice.m_WaveFormat,(DWORD)WaveOutProc ,(ULONG)&SoundDevice ,CALLBACK_FUNCTION); 
#else
	result = waveOutOpen( &SoundDevice.m_WaveOut,0, &SoundDevice.m_WaveFormat,(DWORD)SoundDevice.m_WaveOutEvent , 0 ,CALLBACK_EVENT|WAVE_FORMAT_DIRECT); 
//	result = waveOutOpen( &SoundDevice.m_WaveOut,0, &SoundDevice.m_WaveFormat, 0, 0 ,CALLBACK_NULL); 
#endif
	if ( result!= MMSYSERR_NOERROR)
	{
		MessageBox( NULL, "Sound output Cannot Open Device!", "Error", MB_OK | MB_ICONERROR );
	    return;
	}
#ifndef CALL_BACK_TEST
//	SoundDevice.m_WaveOutThread= AfxBeginThread(WaveOutThreadProc,this,THREAD_PRIORITY_TIME_CRITICAL,0,CREATE_SUSPENDED,);   
	SoundDevice.m_WaveOutThread= CreateThread(
		NULL,
		0,
		WaveOutThreadProc,
		&SoundDevice,
		CREATE_SUSPENDED,
		&temp); 

//	SoundDevice.m_WaveOutThread->m_bAutoDelete = TRUE;
#endif
// start the thread at the end of the buffer init
}

///////////////////////////////////////////////////////////////////
MMRESULT OpenOutput()
{
	MMRESULT result;
//	int	temp;

	SoundDevice.m_Terminate = FALSE;


	SoundDevice.m_Toggle = 0;
	SoundDevice.m_SizeRecord = SoundDevice.m_NbMaxSamples;
//	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].lpData = (CHAR *)SoundDevice.OutputBuffer[SoundDevice.m_Toggle];
//	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwBufferLength = SoundDevice.m_SizeRecord*2;
	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].lpData = AUDIO;
    SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwBufferLength = AUDIO_SIZE;
	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwFlags = 0;
	
//	result = waveOutUnprepareHeader( SoundDevice.m_WaveOut, &SoundDevice.m_WaveHeader[SoundDevice.m_Toggle], sizeof(WAVEHDR) ); 
/*	if  (result!= MMSYSERR_NOERROR) 
	{
		MessageBox( NULL, "Sound output Cannot UnPrepareHeader !", "Error", MB_OK | MB_ICONERROR );
		return result;
	};
*/	

    result = waveOutPrepareHeader( SoundDevice.m_WaveOut, &SoundDevice.m_WaveHeader[SoundDevice.m_Toggle], sizeof(WAVEHDR) ); 
  //MMRESULT waveOutPrepareHeader( HWAVEOUT hwi, LPWAVEHDR pwh, UINT cbwh ); 
/*   if ( (result!= MMSYSERR_NOERROR) || ( SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwFlags != WHDR_PREPARED) )
   {
		MessageBox( NULL, " Sound Output Cannot Prepare Header !", "Error", MB_OK | MB_ICONERROR );
	    return result;
   }
*/
   result = waveOutWrite( SoundDevice.m_WaveOut, &SoundDevice.m_WaveHeader[SoundDevice.m_Toggle], sizeof(WAVEHDR) );
/*   if  (result!= MMSYSERR_NOERROR) 
   {
		MessageBox( NULL, " Sound Output Cannot Write Buffer !", "Error", MB_OK | MB_ICONERROR );
	    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 
	SoundDevice.m_Toggle = 1;
	SoundDevice.m_SizeRecord = SoundDevice.m_NbMaxSamples;
//	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].lpData = (CHAR *)&SoundDevice.OutputBuffer[SoundDevice.m_Toggle][0];
//	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwBufferLength = SoundDevice.m_SizeRecord*2;
    SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].lpData = AUDIO;
    SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwBufferLength = AUDIO_SIZE;
	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwFlags = 0;

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

	result = waveOutWrite( SoundDevice.m_WaveOut, &SoundDevice.m_WaveHeader[SoundDevice.m_Toggle], sizeof(WAVEHDR) );
	if  (result!= MMSYSERR_NOERROR) 
	{
		MessageBox( NULL, " Sound Output Cannot Write Buffer !", "Error", MB_OK | MB_ICONERROR );
		return result;
	}
*/
#ifndef CALL_BACK_TEST
	if( PLAY_MODE == BY_TIME )
		ResumeThread( SoundDevice.m_WaveOutThread );
#endif

   return result;
}

void AddBuffer()
{
	
	MMRESULT result;

//	if (SoundDevice.m_Toggle == 0) 
//	   SoundDevice.m_Toggle = 1; 
//	else 
	   SoundDevice.m_Toggle = 0;
	result = waveOutUnprepareHeader( SoundDevice.m_WaveOut, &SoundDevice.m_WaveHeader[SoundDevice.m_Toggle], sizeof(WAVEHDR) ); 
/*	if  (result!= MMSYSERR_NOERROR) 
	{
		MessageBox( NULL, "Sound output Cannot UnPrepareHeader !", "Error", MB_OK | MB_ICONERROR );
		return;
	};
*/	
	SoundDevice.m_SizeRecord = SoundDevice.m_NbMaxSamples;
	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].lpData = AUDIO+LOOP_PT;//(CHAR *)&SoundDevice.OutputBuffer[SoundDevice.m_Toggle][0];
	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwBufferLength = AUDIO_SIZE-LOOP_PT;//SoundDevice.m_SizeRecord *2;
	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwLoops = 0;
	SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwFlags = 0;//WHDR_BEGINLOOP;

	result = waveOutPrepareHeader( SoundDevice.m_WaveOut, &SoundDevice.m_WaveHeader[SoundDevice.m_Toggle], sizeof(WAVEHDR) ); 
//	if ( (result!= MMSYSERR_NOERROR) || ( SoundDevice.m_WaveHeader[SoundDevice.m_Toggle].dwFlags != WHDR_PREPARED) )
//		MessageBox( NULL, "Sound output Cannot Prepare Header !", "Error", MB_OK | MB_ICONERROR );

	result = waveOutWrite( SoundDevice.m_WaveOut, &SoundDevice.m_WaveHeader[SoundDevice.m_Toggle], sizeof(WAVEHDR) );
//	if  (result!= MMSYSERR_NOERROR) 
//		MessageBox( NULL, "Sound output Cannot Add Buffer !", "Error", MB_OK | MB_ICONERROR );

}


/*
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 WaveInitFormat(    WORD    nCh, // number of channels (mono, stereo)
						DWORD   nSampleRate, // sample rate
						WORD    BitsPerSample)
{
		SoundDevice.m_WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
		SoundDevice.m_WaveFormat.nChannels = nCh;
		SoundDevice.m_WaveFormat.nSamplesPerSec = nSampleRate;
		SoundDevice.m_WaveFormat.nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8;
		SoundDevice.m_WaveFormat.nBlockAlign = SoundDevice.m_WaveFormat.nChannels * BitsPerSample/8;
		SoundDevice.m_WaveFormat.wBitsPerSample = BitsPerSample;
		SoundDevice.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 ComputeSamples(SHORT *pt)
{
}  


void CloseOutput()
{
	if (SoundDevice.m_WaveOut) 
		waveOutPause(SoundDevice.m_WaveOut);
//    Sleep(50);  // wait for the pause
	//	CloseHandle(SoundDevice.m_WaveOut);
	SoundDevice.m_Terminate = TRUE;
//    if (SoundDevice.m_WaveOutEvent )
//		SetEvent(SoundDevice.m_WaveOutEvent);
	if( PLAY_MODE == BY_TIME )
		SuspendThread( SoundDevice.m_WaveOutThread );
//    Sleep(50);  // wait for the thread to terminate

   if (SoundDevice.m_WaveOut) 
   {
		waveOutReset(SoundDevice.m_WaveOut);
//		waveOutClose(SoundDevice.m_WaveOut);
   }
}

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

void StopOutput()
{
	waveOutPause(SoundDevice.m_WaveOut);
}

void StartOutput()
{
	waveOutRestart(SoundDevice.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 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI WaveOutThreadProc( LPVOID pParam )
{
//   CSoundOut * SoundOut = (class CSoundOut *)pParam;
	UINT result;
	UINT FirstPass = TRUE;


	if( FirstPass )
		result = WaitForSingleObject( SoundDevice.m_WaveOutEvent,INFINITE);
	FirstPass = FALSE;
    
//	while( !SoundDevice.m_Terminate )
	while( 1 )
	{
		result = WaitForSingleObject(SoundDevice.m_WaveOutEvent,INFINITE);
		if ((result == WAIT_OBJECT_0)&&(!SoundDevice.m_Terminate ))
		{
			AddBuffer();      // Toggle as changed state here !Toggle point to the just received buffer
		    ComputeSamples(&SoundDevice.m_Toggle);
		}
		else
		{
//			CloseHandle( SoundDevice.m_WaveOutEvent );
//			return 0;  // 
		}
	}
//	CloseHandle( SoundDevice.m_WaveOutEvent );
	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 (!SoundDevice.m_Terminate )
	switch (uMsg)
	{
	case WOM_DONE:
		AddBuffer();
	    ComputeSamples(&SoundDevice.m_Toggle);
		break;
	case WOM_OPEN:
		break;
	case WOM_CLOSE:
		break;
	}
}

#endif

//init the PWM
void init_PWM( void )
{
}

//cofig the PLAY_back rate ,sunch as 16khz
void config_PWM( unsigned char playback_rate )
{
	InitSoundOut();
}

//open the AUDIO device
void open_PWM( void )
{
	int	result;

//	result = PlaySound( AUDIO, NULL, SND_MEMORY | SND_SYNC );
	OpenOutput();
}

//close the AUDIO device
void close_PWM( void )
{
	CloseOutput();
}

//when on BY_TIME mode, set the loop address
void set_loop_addr( unsigned long loop_ad )
{
	LOOP_PT = loop_ad;
}

//set play mode
void set_play_mode( unsigned char mode )
{
	if( mode == BY_SIZE )		//ISSOUND 1
		PLAY_MODE = BY_SIZE;
	else
		PLAY_MODE = BY_TIME;
}

//the PWM interrupt service routine
void PWM_isr(void)
{
}

⌨️ 快捷键说明

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