更多音乐API

trival
Kirigaya Kazuto 2019-08-10 15:29:42 +08:00
parent 566a85f3db
commit e970050065
2 changed files with 364 additions and 40 deletions

View File

@ -14,21 +14,64 @@ using namespace std;
// Global single-thread unprotected event callback id counter
int callback_counter = 1;
void check(lua_State* L, const vector<int>& typearr)
bool LuaCompareType(lua_State* L, int index, const char* type, bool leave=false)
{
int indexType = lua_getfield(L, index, "type");
if (indexType == LUA_TSTRING)
{
if (strcmp(lua_tostring(L, -1), type) == 0)
{
if(!leave) lua_pop(L, 1);
return true;
}
else
{
if (!leave) lua_pop(L, 1);
return false;
}
}
else
{
lua_pop(L, 1);
if (leave) lua_pushstring(L, lua_typename(L, indexType));
return false;
}
}
void check(lua_State* L, const vector<int>& typearr, const vector<const char*>& userdata_type=vector<const char*>())
{
int sz = typearr.size();
int nextIndex = 0;
int maxIndex = userdata_type.size();
for (int i = 0; i < sz; i++)
{
if (lua_type(L, i + 1) != typearr[i])
int thisType = lua_type(L, i + 1);
if (thisType != typearr[i])
{
luaL_error(L, "Bad argument #%d. %s expected, got %s", i + 1, lua_typename(L, typearr[i]), lua_typename(L, lua_type(L, i + 1)));
}
if (maxIndex && thisType == LUA_TUSERDATA)
{
if (nextIndex < maxIndex)
{
if (!LuaCompareType(L, i + 1, userdata_type[nextIndex], true))
{
luaL_error(L, "Bad argument #%d. %s expected, got %s", i + 1, userdata_type[nextIndex], lua_tostring(L, -1));
}
nextIndex++;
}
else
{
luaL_error(L, "Not enough userdata type string.");
}
}
}
}
void ConvertMusicAsyncImpl(const string& filename, const string& targetname, int ticket)
{
string command = "bin\\ffmpeg.exe -y -loglevel error -hide_banner -i \""s + filename + "\" " + targetname;
string command = "bin\\ffmpeg.exe -y -loglevel error -hide_banner -i \""s + filename + "\" \"" + targetname + "\"";
cout << command << endl;
system(command.c_str());
SDL_Event e;
e.type = SDL_USEREVENT;
@ -252,6 +295,28 @@ struct Window
}
}
break;
case 1003:
{
// 稜있꺄렴供귄
if (lua_getfield(L, -1, "onmusicover") != LUA_TNIL)
{
lua_call(L, 0, LUA_MULTRET);
}
else lua_pop(L, 1);
break;
}
case 1004:
{
// 틉돛꺄렴供귄
if (lua_getfield(L, -1, "onchannelover") != LUA_TNIL)
{
lua_pushinteger(L, *(int*)e.user.data1);
delete e.user.data1;
lua_call(L, 1, LUA_MULTRET);
}
else lua_pop(L, 1);
break;
}
}
default:
{
@ -824,6 +889,14 @@ struct Chunk
return 0;
}
static int setVolume(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
Chunk* c = (Chunk*)lua_touserdata(L, 1);
Mix_VolumeChunk(c->chunk, lua_tointeger(L, 2));
return 0;
}
static int create(lua_State* L)
{
check(L, { LUA_TSTRING });
@ -843,6 +916,7 @@ struct Chunk
lua_newtable(L);
lua_pushstring(L, "chunk"); lua_setfield(L, -2, "type");
setfn(L, close, "close");
setfn(L, setVolume, "setVolumne");
// Set __index of metatable.
lua_setfield(L, -2, "__index");
@ -853,6 +927,7 @@ struct Chunk
lua_setmetatable(L, -2);
const char* filename = lua_tostring(L, 1);
cout << "LoadWAV: " << filename << endl;
c->chunk = Mix_LoadWAV(filename);
cout << "Load chunk error: " << SDL_GetError() << endl;
@ -924,7 +999,7 @@ struct MusicPlayer
return 0;
}
static int play(lua_State* L)
static int playMusic(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TUSERDATA });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
@ -933,7 +1008,7 @@ struct MusicPlayer
return 0;
}
static int resume(lua_State* L)
static int resumeMusic(lua_State* L)
{
check(L, { LUA_TUSERDATA });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
@ -941,7 +1016,15 @@ struct MusicPlayer
return 0;
}
static int pause(lua_State* L)
static int stopMusic(lua_State* L)
{
check(L, { LUA_TUSERDATA });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_HaltMusic();
return 0;
}
static int pauseMusic(lua_State* L)
{
check(L, { LUA_TUSERDATA });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
@ -949,7 +1032,15 @@ struct MusicPlayer
return 0;
}
static int fadeIn(lua_State* L)
static int rewindMusic(lua_State* L)
{
check(L, { LUA_TUSERDATA });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_RewindMusic();
return 0;
}
static int fadeInMusic(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TUSERDATA , LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
@ -958,7 +1049,16 @@ struct MusicPlayer
return 0;
}
static int fadeOut(lua_State* L)
static int fadeInMusicPos(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TUSERDATA , LUA_TNUMBER, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Music* m = (Music*)lua_touserdata(L, 2);
cout << "Fade in music ret: " << Mix_FadeInMusicPos(m->music, 1, lua_tointeger(L, 3), lua_tonumber(L, 4)) << " " << SDL_GetError() << endl;
return 0;
}
static int fadeOutMusic(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
@ -966,6 +1066,58 @@ struct MusicPlayer
return 0;
}
static int setMusicVolume(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_VolumeMusic(lua_tointeger(L, 2));
return 0;
}
static int setMusicPos(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_SetMusicPosition(lua_tonumber(L, 2));
return 0;
}
static int isPlayingMusic(lua_State* L)
{
check(L, { LUA_TUSERDATA });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
lua_pushboolean(L, Mix_PlayingMusic());
return 1;
}
static int isPausedMusic(lua_State* L)
{
check(L, { LUA_TUSERDATA });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
lua_pushboolean(L, Mix_PausedMusic());
return 1;
}
static int isFadingMusic(lua_State* L)
{
check(L, { LUA_TUSERDATA });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
int ret = 0;
switch (Mix_FadingMusic())
{
case MIX_NO_FADING:
ret = 0;
break;
case MIX_FADING_OUT:
ret = -1;
break;
case MIX_FADING_IN:
return 1;
}
lua_pushinteger(L, ret);
return 1;
}
static int playChannel(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TUSERDATA, LUA_TNUMBER, LUA_TNUMBER});
@ -975,6 +1127,123 @@ struct MusicPlayer
return 0;
}
static int fadeInChannel(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TUSERDATA, LUA_TNUMBER, LUA_TNUMBER, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Chunk* c = (Chunk*)lua_touserdata(L, 2);
Mix_FadeInChannel(lua_tointeger(L, 3), c->chunk, lua_tointeger(L, 4), lua_tointeger(L, 5));
return 0;
}
static int fadeOutChannel(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_FadeOutChannel(lua_tointeger(L, 2), lua_tointeger(L, 3));
return 0;
}
static int stopChannel(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_HaltChannel(lua_tointeger(L, 2));
return 0;
}
static int resumeChannel(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_Resume(lua_tointeger(L, 2));
return 0;
}
static int pauseChannel(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_Pause(lua_tointeger(L, 2));
return 0;
}
static int isPlayingChannel(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
lua_pushinteger(L, Mix_Playing(lua_tointeger(L, 2)));
return 1;
}
static int isPausedChannel(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
lua_pushinteger(L, Mix_Paused(lua_tointeger(L, 2)));
return 1;
}
static int isFadingChannel(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
int ret = 0;
switch (Mix_FadingChannel(lua_tointeger(L, 2)))
{
case MIX_NO_FADING:
ret = 0;
break;
case MIX_FADING_OUT:
ret = -1;
break;
case MIX_FADING_IN:
return 1;
}
lua_pushinteger(L, ret);
return 1;
}
static int setChannelVolume(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_Volume(lua_tointeger(L, 2), lua_tointeger(L, 3));
return 0;
}
static int setChannelDistance(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_SetDistance(lua_tointeger(L, 2), lua_tointeger(L, 3));
return 0;
}
static int setChannelPosition(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER, LUA_TNUMBER, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_SetPosition(lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4));
return 0;
}
static int setChannelPanning(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER, LUA_TNUMBER, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_SetPanning(lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4));
return 0;
}
static int setTotalChannel(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TNUMBER });
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
Mix_AllocateChannels(lua_tointeger(L, 2));
return 0;
}
static int create(lua_State* L)
{
cout << "In MusicPlayer::create" << endl;
@ -993,12 +1262,38 @@ struct MusicPlayer
lua_newtable(L);
lua_pushstring(L, "musicplayer"); lua_setfield(L, -2, "type");
setfn(L, close, "close");
setfn(L, play, "play");
setfn(L, pause, "pause");
setfn(L, resume, "resume");
setfn(L, fadeIn, "fadeIn");
setfn(L, fadeOut, "fadeOut");
setfn(L, playMusic, "playMusic");
setfn(L, resumeMusic, "resumeMusic");
setfn(L, pauseMusic, "pauseMusic");
setfn(L, stopMusic, "stopMusic");
setfn(L, rewindMusic, "rewindMusic");
setfn(L, fadeInMusic, "fadeInMusic");
setfn(L, fadeOutMusic, "fadeOutMusic");
setfn(L, fadeInMusicPos, "fadeInMusicPos");
setfn(L, setMusicVolume, "setMusicVolume");
setfn(L, setMusicPos, "setMusicPos");
setfn(L, isPlayingMusic, "isPlayingMusic");
setfn(L, isPausedMusic, "isPausedMusic");
setfn(L, isFadingMusic, "isFadingMusic");
setfn(L, playChannel, "playChannel");
setfn(L, resumeChannel, "resumeChannel");
setfn(L, pauseChannel, "pauseChannel");
setfn(L, stopChannel, "stopChannel");
setfn(L, fadeInChannel, "fadeInChannel");
setfn(L, fadeOutChannel, "fadeOutChannel");
setfn(L, setChannelVolume, "setChannelVolume");
setfn(L, setChannelDistance, "setChannelDistance");
setfn(L, setChannelPosition, "setChannelPosition");
setfn(L, setChannelPanning, "setChannelPanning");
setfn(L, setTotalChannel, "setTotalChannel");
setfn(L, isPlayingChannel, "isPlayingChannel");
setfn(L, isPausedChannel, "isPausedChannel");
setfn(L, isFadingChannel, "isFadingChannel");
// Set __index of metatable.
lua_setfield(L, -2, "__index");
@ -1053,6 +1348,23 @@ void check_init(lua_State* L, const char* name, int ret, int expected = 0)
}
}
void _Global_On_Music_Finished()
{
SDL_Event e;
e.type = SDL_USEREVENT;
e.user.code = 1003;
SDL_PushEvent(&e);
}
void _Global_On_Channel_Finished(int channel)
{
SDL_Event e;
e.type = SDL_USEREVENT;
e.user.code = 1004;
e.user.data1 = new int(channel);
SDL_PushEvent(&e);
}
int InitEngine(lua_State* L)
{
int ret;
@ -1068,6 +1380,8 @@ int InitEngine(lua_State* L)
ret = Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 512);
check_init(L, "AUDIO", ret);
Mix_AllocateChannels(16);
Mix_HookMusicFinished(_Global_On_Music_Finished);
Mix_ChannelFinished(_Global_On_Channel_Finished);
reg_in_lua(L, Window::create, "Window");
reg_in_lua(L, Renderer::create, "Renderer");

View File

@ -2,14 +2,35 @@ local wnd = Window("Hello", 1024, 768)
local rnd = Renderer(wnd)
local font = Font("asserts/msyh.ttf", 18)
local musicPlayer = MusicPlayer()
local music = Music("asserts/mp3/bgm1.mp3")
require("code/helper")
local all_bqb = fs.listdir("asserts/bqb_all")
for i, info in ipairs(all_bqb) do
print (i, info.name, info.type, info.size)
-- print (i, info.name, info.type, info.size)
i = i
end
local all_music = fs.listdir("asserts/mp3")
table.remove(all_music, 1)
table.remove(all_music, 1)
local music_table = {}
local last_channel = 0
local next_channel = 1
local next_music = 1
for i, info in ipairs(all_music) do
local filename = string.format("tmp\\tmp_%d.wav", i)
ConvertMusic(string.format("asserts\\mp3\\%s",info.name), filename, function()
print(filename, "convert finished.")
wnd:setTimeout(function()
print("Start loading: ", filename)
local c = Chunk(filename)
table.insert(music_table, c)
end, 1000)
end)
end
local texture_track = {}
@ -17,31 +38,7 @@ setmetatable(texture_track, {
__mode = "k"
})
wnd:setTimeout(function()
print("Playing music")
musicPlayer:play(music)
print("Music started playing.")
wnd:show()
local filename = string.format("tmp/tmp_%d.wav", math.random(50))
ConvertMusic("asserts/mp3/bgm2.flac", filename, function()
print("Convert finished.")
wnd:setTimeout(function()
print("Start fade out", os.time())
musicPlayer:fadeOut(3000)
print("Finished fade out", os.time())
local c = Chunk(filename)
musicPlayer:playChannel(c, -1, 1)
end, 2000)
end)
--[[
for i=1, 10 do
local filename = string.format("tmp/tmp_%d.wav", math.random(50))
print ("ConvertTickets: ", ConvertMusic("asserts/mp3/bgm1.mp3", filename, function() print("Convert finished.", filename) end))
end
--]]
end, 3000)
wnd:show()
wnd:on('mousedown', function(x, y)
print("Clicked", x, y)
@ -73,6 +70,19 @@ wnd:on('keydown', function(key)
end
print ("Tracked texture: ", cnt)
return
elseif key == string.byte('p') then
musicPlayer:fadeOutChannel(last_channel, 5000)
if not music_table[next_music] then
next_music = 1
end
print("Playing", next_music, next_channel)
musicPlayer:fadeInChannel(music_table[next_music], next_channel, 1, 3000)
next_music = next_music + 1
last_channel = next_channel
next_channel = next_channel + 1
if next_channel >= 16 then
next_channel = 0
end
end
print("Keydown", key)