buldthensnip/src/lua_wav.h

233 lines
5.8 KiB
C

/*
This file is part of Iceball.
Iceball is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Iceball is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Iceball. If not, see <http://www.gnu.org/licenses/>.
*/
// client functions
#ifndef DEDI
/*
client.wav_cube_size(size)
sets the size of a block in metres for sound calculations
*/
int icelua_fn_client_wav_cube_size(lua_State *L)
{
int top = icelua_assert_stack(L, 1, 1);
wav_cube_size = lua_tonumber(L, 1);
if(wav_cube_size < 0.00001f)
wav_cube_size = 0.00001f;
return 0;
}
/*
chn = client.wav_play_global(wav, x, y, z, vol = 1.0, freq_mod = 1.0, vol_spread = ?)
play the given sound at the given world position
TODO: define vol_spread properly
returns an index of a channel
returns nil on error
*/
int icelua_fn_client_wav_play_global(lua_State *L)
{
int top = icelua_assert_stack(L, 4, 7);
if(lua_islightuserdata(L, 1) || !lua_isuserdata(L, 1))
return luaL_error(L, "not a wav");
wav_t *wav = *(wav_t**)lua_touserdata(L, 1);
if(wav == NULL || wav->udtype != UD_WAV)
return luaL_error(L, "not a wav");
float x = lua_tonumber(L, 2);
float y = lua_tonumber(L, 3);
float z = lua_tonumber(L, 4);
float vol = (top < 5 ? 1.0f : lua_tonumber(L, 5));
float freq_mod = (top < 6 ? 1.0f : lua_tonumber(L, 6));
float vol_spread = (top < 7 ? 1.0f : lua_tonumber(L, 7));
wavchn_t *chn = wav_chn_alloc(WCF_ACTIVE|WCF_GLOBAL, wav, x, y, z, vol, freq_mod, vol_spread);
if(chn == NULL)
// wups.
return 0;
lua_pushinteger(L, chn->idx);
return 1;
}
/*
chn = client.wav_play_local(wav, x = 0.0, y = 0.0, z = 0.0, vol = 1.0, freq_mod = 1.0, vol_spread = ?)
play the given sound at the given camera-local position
returns an index of a channel
returns nil on error
*/
int icelua_fn_client_wav_play_local(lua_State *L)
{
int top = icelua_assert_stack(L, 1, 7);
if(lua_islightuserdata(L, 1) || !lua_isuserdata(L, 1))
return luaL_error(L, "not a wav");
wav_t *wav = *(wav_t**)lua_touserdata(L, 1);
if(wav == NULL || wav->udtype != UD_WAV)
return luaL_error(L, "not a wav");
float x = (top < 2 ? 0.0f : lua_tonumber(L, 2));
float y = (top < 3 ? 0.0f : lua_tonumber(L, 3));
float z = (top < 4 ? 0.0f : lua_tonumber(L, 4));
float vol = (top < 5 ? 1.0f : lua_tonumber(L, 5));
float freq_mod = (top < 6 ? 1.0f : lua_tonumber(L, 6));
float vol_spread = (top < 7 ? 1.0f : lua_tonumber(L, 7));
wavchn_t *chn = wav_chn_alloc(WCF_ACTIVE, wav, x, y, z, vol, freq_mod, vol_spread);
if(chn == NULL)
// wups.
return 0;
lua_pushinteger(L, chn->idx);
return 1;
}
/*
exists = client.wav_chn_exists(chn)
checks if an allocated channel still exists
if a channel stops, it is garbage collected
*/
int icelua_fn_client_wav_chn_exists(lua_State *L)
{
int top = icelua_assert_stack(L, 1, 1);
int cidx = lua_tointeger(L, 1);
wavchn_t *wc = &wchn[cidx & (WAV_CHN_COUNT-1)];
lua_pushboolean(L, wc->idx == cidx && (wc->flags & WCF_ACTIVE));
return 1;
}
/*
success = client.wav_chn_update(chn, x = nil, y = nil, z = nil, vol = nil, freq_mod = nil, vol_spread = nil)
updates information pertaining to a channel
any field which is nil is not affected
returns false if the channel no longer exists
*/
int icelua_fn_client_wav_chn_update(lua_State *L)
{
int top = icelua_assert_stack(L, 1, 7);
// TODO!
int cidx = lua_tointeger(L, 1);
wavchn_t *wc = &wchn[cidx & (WAV_CHN_COUNT-1)];
int isactive = (wc->idx == cidx && (wc->flags & WCF_ACTIVE));
if(isactive)
{
if(top >= 2 && !lua_isnil(L, 2))
wc->x = lua_tonumber(L, 2);
if(top >= 3 && !lua_isnil(L, 3))
wc->y = lua_tonumber(L, 3);
if(top >= 4 && !lua_isnil(L, 4))
wc->z = lua_tonumber(L, 4);
if(top >= 5 && !lua_isnil(L, 5))
wc->vol = lua_tonumber(L, 5);
if(top >= 6 && !lua_isnil(L, 6))
wc->freq_mod = lua_tonumber(L, 6);
if(top >= 7 && !lua_isnil(L, 7))
wc->vol_spread = lua_tonumber(L, 7);
}
lua_pushboolean(L, isactive);
return 1;
}
/*
client.wav_kill(chn)
stops and removes a channel
if chn == "true", kills all channels
*/
int icelua_fn_client_wav_kill(lua_State *L)
{
int top = icelua_assert_stack(L, 1, 1);
int i;
// TODO!
if(lua_isboolean(L, 1) && lua_toboolean(L, 1))
{
for(i = 0; i < WAV_CHN_COUNT; i++)
wav_chn_kill(&wchn[i]);
return 0;
}
if(!lua_isnumber(L, 1))
return luaL_error(L, "not a number");
int idx = lua_tointeger(L, 1);
wav_chn_kill(&wchn[idx & (WAV_CHN_COUNT-1)]);
return 0;
}
#endif
// common functions
/*
wav = common.wav_load(fname)
loads a sound with filename "fname"
remember to free it when you're done
as this is only a light userdata
*/
int icelua_fn_common_wav_load(lua_State *L)
{
int top = icelua_assert_stack(L, 1, 1);
const char *fname = lua_tostring(L, 1);
if(fname == NULL)
return luaL_error(L, "filename must be a string");
lua_getglobal(L, "common");
lua_getfield(L, -1, "fetch_block");
lua_remove(L, -2);
lua_pushstring(L, "wav");
lua_pushvalue(L, 1);
lua_call(L, 2, 1);
return 1;
}
/*
common.wav_free(wav)
free the given sound
if you don't do this then it's memoryleaktopia
(plus i'm allowed to kill you)
*/
int icelua_fn_common_wav_free(lua_State *L)
{
int top = icelua_assert_stack(L, 1, 1);
if(lua_islightuserdata(L, 1) || !lua_isuserdata(L, 1))
return luaL_error(L, "not a wav");
wav_t *wav = *(wav_t**)lua_touserdata(L, 1);
if(wav == NULL || wav->udtype != UD_WAV)
return luaL_error(L, "not a wav");
wav_kill(wav);
return 0;
}