ref: 2fde5c7c3678b14200e91b7ea1fd04b6a75a08f7
parent: 11e06205d034eddcb13aca847dbc6de9a63b747e
author: rrt <rrt>
date: Tue Jan 16 14:04:51 EST 2007
Add proper output of Lua effects.
--- a/src/luaeff.c
+++ b/src/luaeff.c
@@ -19,17 +19,16 @@
* USA. */
-/* TODO: If efficiency is a problem, move the call of the Lua script
- into the flow phase. Instrument the Lua environment so that scripts
- can still be written naively: reading beyond the end of the input
- array yields to read more data, and writing output similarly. In
- order not to need nonetheless to buffer all input and output until
- finished, need low-water-marks that the script can update to signal
- that it has finished reading and writing respectively.
- Alternatively, assume that each location can only be read/written
- once. */
+/* TODO: To increase speed, move the call of the Lua script into the
+ flow phase. Instrument the Lua environment so that scripts can
+ still be written naively: have script called as a coroutine, and
+ make reading beyond the end of the input array yields to read more
+ data, and writing output similarly. In order not to need
+ nonetheless to buffer all input and output until finished, add
+ low-water-marks that the script can update to signal that it has
+ finished reading and writing respectively. */
-
+
#include "st_i.h"
#include <string.h>
@@ -38,9 +37,12 @@
/* Private data for effect */
typedef struct luaeff {
- char *script; /* Script filename */
lua_State *L; /* Lua state */
- st_size_t nsamp; /* Number of samples in input */
+ char *script; /* Script filename */
+ bool gotdata; /* Script has been run */
+ st_size_t isamp; /* Number of samples in input */
+ st_size_t osamp; /* Number of samples in output */
+ st_size_t ostart; /* Next sample to output */
st_sample_t *data; /* Input data */
} *luaeff_t;
@@ -88,9 +90,9 @@
{
luaeff_t lua = (luaeff_t)effp->priv;
- lua->data = (st_sample_t *)xrealloc(lua->data, (lua->nsamp + *isamp) * sizeof(st_sample_t));
- memcpy(lua->data + lua->nsamp, ibuf, *isamp * sizeof(st_sample_t));
- lua->nsamp += *isamp;
+ lua->data = (st_sample_t *)xrealloc(lua->data, (lua->isamp + *isamp) * sizeof(st_sample_t));
+ memcpy(lua->data + lua->isamp, ibuf, *isamp * sizeof(st_sample_t));
+ lua->isamp += *isamp;
*osamp = 0; /* Signal that we didn't produce any output */
@@ -103,21 +105,43 @@
static int lua_drain(eff_t effp, st_sample_t *obuf, st_size_t *osamp)
{
luaeff_t lua = (luaeff_t)effp->priv;
- int ret;
- st_sample_t_array_t inarr, outarr;
+ int ret, i;
+ st_sample_t_array_t inarr;
- inarr.size = lua->nsamp;
- inarr.data = lua->data;
- outarr.size = *osamp;
- outarr.data = obuf;
+ if (!lua->gotdata) {
+ inarr.size = lua->isamp;
+ inarr.data = lua->data;
+ st_lua_pusharray(lua->L, inarr);
+
+ if ((ret = lua_pcall(lua->L, 1, 1, 0)) != 0) {
+ st_fail("error in Lua script: %d", ret);
+ return ST_EOF;
+ } else if (lua_type(lua->L, -1) != LUA_TTABLE) {
+ st_fail("Lua script did not return an array");
+ return ST_EOF;
+ }
+ lua->gotdata = true;
+ lua->osamp = lua_objlen(lua->L, -1);
+ lua->ostart = 0;
+ }
- st_lua_pusharray(lua->L, inarr);
- st_lua_pusharray(lua->L, outarr);
- if ((ret = lua_pcall(lua->L, 2, 0, 0)) != 0)
- st_fail("error in Lua script: %d", ret);
+ *osamp = min(*osamp, lua->osamp);
+ if (*osamp > INT_MAX) {
+ st_fail("output buffer size %d too large for Lua", *osamp);
+ return ST_EOF;
+ }
+ for (i = 0; i < (int)*osamp; i++) {
+ lua_rawgeti(lua->L, -1, i);
+ obuf[i] = lua_tointeger(lua->L, -1);
+ lua_pop(lua->L, 1);
+ }
+ lua->osamp -= *osamp;
+ lua->ostart += *osamp;
- *osamp = 0;
- return ST_EOF;
+ if (lua->osamp > 0)
+ return ST_SUCCESS;
+ else
+ return ST_EOF;
}
/*
@@ -151,7 +175,7 @@
*/
static st_effect_t st_lua_effect = {
"lua",
- "Usage: lua script [options]",
+ "Usage: lua lua-script [option...]",
ST_EFF_MCHAN,
lua_getopts,
st_effect_nothing,