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
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;
|
|
}
|
|
|