📄 audiodrv.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 + -