fmod是个可利用于多平台的音频api接口,可贵的是基于非商业的应用是免费的
而且貌似合适的音频库也不是很多,就选用它了。win7下面有个新的音频接口(wasapi)
那个接口是低延时的,而且fmod也可以直接调用,所以还是很不错的。
在调用时使用2d模式,和wasapi独占模式。由于是要尽量简单,只是实现了多线程的监听全局键盘事件
和简单的停止和下一曲功能,还有很大的改进空间。。
听感来说,明显wasapi的能量更为集中,定位感也更好,而其他像dsound的模糊的一塌糊涂,wave的好一点,但是还是比不上独占模式。
不多说了,直接上代码!
#include "fmod.hpp"
#include "fmod_errors.h"
//#include "lisDll2.h"
#include <iostream>
#include <assert.h>
#include <Windows.h>
using namespace std;
FMOD_RESULT result;
FMOD::System *fsystem;
FMOD::Sound *fsound;
HHOOK hHook;
bool needChang = false;
bool needStop = false;
#define CHKERR(X) {if (X != FMOD_OK)\
{\
printf("FMOD error! (%d) %s\n", X,FMOD_ErrorString(X));\
exit(-1);\
}\
}
void init_mus(){
result = FMOD::System_Create(&fsystem);
assert(result == FMOD_OK);
result = fsystem->setOutput(FMOD_OUTPUTTYPE::FMOD_OUTPUTTYPE_WASAPI);
assert(result == FMOD_OK);
result = fsystem->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
assert(result == FMOD_OK);
// fsystem->set3DSpeakerPosition(FMOD_SPEAKER_FRONT_LEFT, -1.5f, 0.0f, true);
// fsystem->set3DSpeakerPosition(FMOD_SPEAKER_FRONT_RIGHT, 1.5f, 0.0f, true);
result = fsystem->init(100,FMOD_INIT_WASAPI_EXCLUSIVE,0);
assert(result == FMOD_OK);
}
void play_mus(char* path){
bool isp;
FMOD::Channel *channel = NULL;
FMOD::Channel* ch;
result = fsystem->createStream(path,FMOD_HARDWARE,0,&fsound);
CHKERR(result);
result = fsystem->playSound(FMOD_CHANNEL_FREE,fsound,false,&ch);
CHKERR(result);
ch->isPlaying(&isp);
while(isp){
Sleep(100);
ch->isPlaying(&isp);
if(needChang){
fsystem->playSound(FMOD_CHANNEL_FREE,fsound,true,&ch);
ch->stop();
needChang = 0;
break;
}
}
}
void my_release(){
fsystem->release();
}
void get_Path(char* dd){
WIN32_FIND_DATA FD ;
HANDLE hFind = NULL;
char my_path_name[1024];
SetCurrentDirectory(dd);
sprintf(my_path_name,"%s%s",dd,"\\*.mp3");
hFind = FindFirstFile(my_path_name,&FD);
if(hFind != INVALID_HANDLE_VALUE){
printf("%s\n",FD.cFileName);
puts("about to play...");
play_mus(FD.cFileName);
// hFind = FindFirstFile(my_path_name,&FD);
}
while(FindNextFile(hFind,&FD) == true){
if(needStop == true){
needStop = false;
hFind = NULL;
break;
}
printf("%s\n",FD.cFileName);
puts("about to play...");
play_mus(FD.cFileName);
}
hFind = NULL;
}
LRESULT CALLBACK kb_proc(int code, WPARAM w, LPARAM l)
{
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)l;
const char* info = NULL;
if (w == WM_KEYDOWN)
if(p->vkCode ==0xff && p->scanCode == 3){
needChang = true;
puts("<--");
}
else if(p->vkCode ==0xff && p->scanCode == 9){
puts("-->");
needChang = true;
}
else if(p->vkCode == 178 && p->scanCode == 36){
puts("stop!");
needStop = true;
}
// always call next hook
return CallNextHookEx(hHook, code, w, l);
};
DWORD WINAPI myCall(LPVOID lpParameter){
MSG msg;
hHook=SetWindowsHookExW(WH_KEYBOARD_LL,(HOOKPROC)kb_proc, GetModuleHandle(NULL),0);
puts("start!");
while(GetMessageW(&msg,0,0,0)!=-1);
puts("end!");
return 0;
}
void initThread(HANDLE* wh){
*wh = CreateThread(NULL,NULL,myCall,NULL,0,NULL);
assert(*wh != NULL);
}
int main(){
int n;
char dd[1024];
HANDLE waitHandle;
bool needNext = true;//需要继续听么
initThread(&waitHandle);
init_mus();
while(1){
puts("Please input path");
gets(dd);
if(dd[0] == '0')
break;
get_Path(dd);
system("pause");
}
CloseHandle(waitHandle);
my_release();
return 0;
}