You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

194 lines
4.2 KiB

#include "PcmPlayer.h"
//#define LENGTH 10240
BOOL getOutNumDrive()//音频数量
{
int count = waveOutGetNumDevs();
return count < 1 ? FALSE : TRUE;//1 音频输入数量
}
BOOL getOutDevCaps()
{
WAVEOUTCAPS waveOutcaps;
int i = 0;
MMRESULT mmResult;
mmResult = waveOutGetDevCaps(0, &waveOutcaps, sizeof(WAVEINCAPS));//2 设备描述
if (MMSYSERR_NOERROR != mmResult)
{
return FALSE;
}
return TRUE;
}
BOOL openOutFile(const TCHAR *cFileName, FILE **fp)
{
FILE *fpRead = NULL;
fpRead = fopen(cFileName, "rb");
if (NULL == fpRead)
{
fp = NULL;
return FALSE;
}
*fp = fpRead;
fclose(fpRead);
return TRUE;
}
BOOL initOutDrive()//BOOL initDrive(const TCHAR * cFileName)
{
if (FALSE == getOutNumDrive())
{
return FALSE;
}
//if (FALSE == getOutDevCaps())
//{
// return FALSE;
//}
return TRUE;
}
BOOL openOutPcm(LPHWAVEOUT phwo, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback)
{
if (MMSYSERR_NOERROR != waveOutOpen(0, 0, pwfx, 0, 0, WAVE_FORMAT_QUERY))
{
//fprintf(stderr, "不支持文件格式!\n");
return FALSE;
}
if (MMSYSERR_NOERROR != waveOutOpen(phwo, WAVE_MAPPER, pwfx, 0, 0, CALLBACK_NULL))
{
//fprintf(stderr, "文件打开失败!\n");
return FALSE;
}
return TRUE;
}
LPSTR loadOutAudioBlock(const TCHAR * filename, DWORD* blockSize)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD size = 0;
DWORD readBytes = 0;
void* block = NULL;
//LPCWSTR name = L"D:\\sdktest\\config\\ttsTest1.pcm";
if ((hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
{
int rest = GetLastError();
return NULL;
}
do
{
if ((size = GetFileSize(hFile, NULL)) == 0)
{
break;
}
if ((block = HeapAlloc(GetProcessHeap(), 0, size)) == NULL)
{
break;
}
ReadFile(hFile, block, size, &readBytes, NULL);
} while (0);
CloseHandle(hFile);
*blockSize = size;
return (LPSTR)block;
}
BOOL writeOutAudioBlock(HWAVEOUT phwo, LPSTR block, DWORD size)
{
WAVEHDR wHdr = { 0 };
wHdr.dwBufferLength = size;
wHdr.lpData = block;
if (MMSYSERR_NOERROR != waveOutPrepareHeader(phwo, &wHdr, sizeof(WAVEHDR)))
{
//fprintf(stderr, "文件缓冲区准备失败!\n");
return FALSE;
}
if (MMSYSERR_NOERROR != waveOutWrite(phwo, &wHdr, sizeof(WAVEHDR)))
{
//fprintf(stderr, "写文件缓冲区失败!\n");
return FALSE;
}
Sleep(500);
while (WAVERR_STILLPLAYING == waveOutUnprepareHeader(phwo, &wHdr, sizeof(WAVEHDR)))
{
Sleep(100);
}
return TRUE;
}
BOOL closeOutAudioBlock(HWAVEOUT phwo)
{
if (MMSYSERR_NOERROR != waveOutClose(phwo))
{
//fprintf(stderr, "写文件缓冲区失败!\n");
return FALSE;
}
return TRUE;
}
int playPcmFile(const char * cFileName)
{
//int iLength;
//TCHAR * tcharName="";
//iLength = MultiByteToWideChar(CP_ACP, 0, cFileName, strlen(cFileName) + 1, NULL, 0);
//MultiByteToWideChar(CP_ACP, 0, cFileName, strlen(cFileName) + 1, tcharName, iLength);
//char strUsr[10] = "Hello";
TCHAR tcharName[100];
#ifdef UNICODE
MultiByteToWideChar(CP_ACP, 0, cFileName, -1, tcharName, 100);
#else
strcpy(tcharName, cFileName);
#endif
LPSTR block;
DWORD blockSize;
if (NULL == (block = loadOutAudioBlock(tcharName, &blockSize)))
{
fprintf(stderr, "文件初始化失败!\n");
return -1;
}
if (FALSE == initOutDrive(tcharName))
{
fprintf(stderr, "设备初始化失败!\n");
return -1;
}
WAVEFORMATEX pwfx = {
WAVE_FORMAT_PCM,// wFormatTag,格式标志
1, // nChannels,通道数,单声道数据用单通道,立体声通道用双通道
16000, // nSamplesPerSec,采样率(HZ),每秒钟采取样本的次数
32000, // nAvgBytesPerSec,每秒转换数据的字节数,for WAVE_FORMAT_PCM,nAvgBytesPerSec = nSamplesPerSec * nBlockAlign,此处的大小与waveInOopen回调函数中写入数据的大小应该一直,否则会出现问题
2, // nBlockAlign,每个样本的字节数,for WAVE_FORMAT_PCM,nBlockAlign = (nChannels × wBitsPerSample) / 8
16, // wBitsPerSample,每个样本的位数,for WAVE_FORMAT_PCM,wBitsPerSample必须等于8或者16
0 // cbSize,附加在该结构体后面的格式信息的大小
};
HWAVEOUT phwo;
if (FALSE == openOutPcm(&phwo, &pwfx, NULL))
{
fprintf(stderr, "文件打开失败!\n");
return -1;
}
if (FALSE == writeOutAudioBlock(phwo, block, blockSize))
{
fprintf(stderr, "写音频设备失败!\n");
return -1;
}
if (FALSE == closeOutAudioBlock(phwo))
{
fprintf(stderr, "关闭音频设备失败!\n");
return -1;
}
return 0;
}