diff options
-rw-r--r-- | applause.c | 108 | ||||
-rw-r--r-- | applause.lua | 59 |
2 files changed, 104 insertions, 63 deletions
@@ -394,23 +394,25 @@ init_audio(int buffer_size) return 0; } -/* FIXME: Rewrite as an exported FFI-callable function */ -static int -l_MIDIVelocityStream_getValue(lua_State *L) +/** + * Get the MIDI velocity of the `note` last + * triggered on `channel` due to a NOTE ON message. + * This function is meant to be called using LuaJIT's + * FFI interface. + */ +int +applause_midi_velocity_getvalue(int note, int channel) { - int top = lua_gettop(L); - lua_Integer channel, note, value; - - luaL_argcheck(L, top == 2, top, "Note and channel number expected"); - luaL_checktype(L, 1, LUA_TNUMBER); - luaL_checktype(L, 2, LUA_TNUMBER); - - note = lua_tointeger(L, 1); - luaL_argcheck(L, 0 <= note && note <= 127, note, - "Invalid note number range (0 <= x <= 127)"); - channel = lua_tointeger(L, 2); - luaL_argcheck(L, 1 <= channel && channel <= 16, channel, - "Invalid channel range (1 <= x <= 16)"); + int value; + + /* + * It's enough to assert() here since this + * function should only be called by the + * MIDIVelocityStream generator. + */ + assert(0 <= note && note <= 127); + assert(1 <= channel && channel <= 16); + /* The NOTE arrays are 0-based */ channel--; @@ -426,23 +428,30 @@ l_MIDIVelocityStream_getValue(lua_State *L) value = midi_notes[channel][note]; pthread_mutex_unlock(&midi_mutex); - lua_pushinteger(L, value); - return 1; + return value; } -/* FIXME: Rewrite as an exported FFI-callable function */ -static int -l_MIDINoteStream_getValue(lua_State *L) +/** + * Get the MIDI note and velocity of the note last + * triggered on `channel`. + * This function is meant to be called using LuaJIT's + * FFI interface. + * + * @return A MIDI note number (least significant byte) and + * velocity (second least significant byte). + */ +int +applause_midi_note_getvalue(int channel) { - int top = lua_gettop(L); - lua_Integer channel, value; + int value; - luaL_argcheck(L, top == 1, top, "Channel number expected"); - luaL_checktype(L, 1, LUA_TNUMBER); + /* + * It's enough to assert() here since this + * function should only be called by the + * MIDINoteStream generator. + */ + assert(1 <= channel && channel <= 16); - channel = lua_tointeger(L, 1); - luaL_argcheck(L, 1 <= channel && channel <= 16, channel, - "Invalid channel range (1 <= x <= 16)"); /* The NOTE arrays are 0-based */ channel--; @@ -459,27 +468,28 @@ l_MIDINoteStream_getValue(lua_State *L) (midi_notes[channel][midi_notes_last[channel]] << 8); pthread_mutex_unlock(&midi_mutex); - lua_pushinteger(L, value); - return 1; + return value; } -/* FIXME: Rewrite as an exported FFI-callable function */ -static int -l_MIDICCStream_getValue(lua_State *L) +/** + * Get the last value of the MIDI control `control` + * on `channel`. + * This function is meant to be called using LuaJIT's + * FFI interface. + */ +int +applause_midi_cc_getvalue(int control, int channel) { - int top = lua_gettop(L); - lua_Integer channel, control, value; - - luaL_argcheck(L, top == 2, top, "Control and channel number expected"); - luaL_checktype(L, 1, LUA_TNUMBER); - luaL_checktype(L, 2, LUA_TNUMBER); - - control = lua_tointeger(L, 1); - luaL_argcheck(L, 0 <= control && control <= 127, control, - "Invalid control number range (0 <= x <= 127)"); - channel = lua_tointeger(L, 2); - luaL_argcheck(L, 1 <= channel && channel <= 16, channel, - "Invalid channel range (1 <= x <= 16)"); + int value; + + /* + * It's enough to assert() here since this + * function should only be called by the + * MIDICCStream generator. + */ + assert(0 <= control && control <= 127); + assert(1 <= channel && channel <= 16); + /* The NOTE arrays are 0-based */ channel--; @@ -495,8 +505,7 @@ l_MIDICCStream_getValue(lua_State *L) value = midi_controls[channel][control]; pthread_mutex_unlock(&midi_mutex); - lua_pushinteger(L, value); - return 1; + return value; } enum applause_audio_state { @@ -834,9 +843,6 @@ typedef struct NativeMethod { static const NativeMethod native_methods[] = { {"Stream", "fork", l_Stream_fork}, - {"MIDIVelocityStream", "getValue", l_MIDIVelocityStream_getValue}, - {"MIDINoteStream", "getValue", l_MIDINoteStream_getValue}, - {"MIDICCStream", "getValue", l_MIDICCStream_getValue}, {NULL, NULL, NULL} }; diff --git a/applause.lua b/applause.lua index dd1d78f..0f8e357 100644 --- a/applause.lua +++ b/applause.lua @@ -60,6 +60,10 @@ enum applause_audio_state { }; enum applause_audio_state applause_push_sample(double sample_double); + +int applause_midi_velocity_getvalue(int note, int channel); +int applause_midi_note_getvalue(int channel); +int applause_midi_cc_getvalue(int control, int channel); ]] -- Sample rate @@ -1140,21 +1144,33 @@ MIDIVelocityStream = DeriveClass(Stream) function MIDIVelocityStream:ctor(note, channel) self.note = note + assert(0 <= self.note and self.note <= 127, + "MIDI note out of range (0 <= x <= 127)") + self.channel = channel or 1 + assert(1 <= self.channel and self.channel <= 16, + "MIDI channel out of range (1 <= x <= 16)") end --- implemented in applause.c, private! +-- This is for calling from external code (e.g. from +-- streams supporting MIDI natively) function MIDIVelocityStream.getValue(note, channel) - error("C function not registered!") + -- NOTE: The native function assert() for invalid + -- notes or channels to avoid segfaults + assert(0 <= note and note <= 127, + "MIDI note out of range (0 <= x <= 127)") + assert(1 <= channel and channel <= 16, + "MIDI channel out of range (1 <= x <= 16)") + + return C.applause_midi_velocity_getvalue(note, channel) end function MIDIVelocityStream:tick() local note = self.note local channel = self.channel - local getValue = self.getValue return function() - return getValue(note, channel) + return C.applause_midi_velocity_getvalue(note, channel) end end @@ -1167,19 +1183,26 @@ MIDINoteStream = DeriveClass(Stream) function MIDINoteStream:ctor(channel) self.channel = channel or 1 + assert(1 <= self.channel and self.channel <= 16, + "MIDI channel out of range (1 <= x <= 16)") end --- implemented in applause.c, private! +-- This is for calling from external code (e.g. from +-- streams supporting MIDI natively) function MIDINoteStream.getValue(channel) - error("C function not registered!") + -- NOTE: The native function assert() for invalid + -- notes or channels to avoid segfaults + assert(1 <= channel and channel <= 16, + "MIDI channel out of range (1 <= x <= 16)") + + return C.applause_midi_note_getvalue(channel) end function MIDINoteStream:tick() local channel = self.channel - local getValue = self.getValue return function() - return getValue(channel) + return C.applause_midi_note_getvalue(channel) end end @@ -1188,20 +1211,32 @@ MIDICCStream = DeriveClass(Stream) function MIDICCStream:ctor(control, channel) self.control = control self.channel = channel or 1 + + assert(0 <= self.control and self.control <= 127, + "MIDI control number out of range (0 <= x <= 127)") + assert(1 <= self.channel and self.channel <= 16, + "MIDI channel out of range (1 <= x <= 16)") end --- implemented in applause.c, private! +-- This is for calling from external code (e.g. from +-- streams supporting MIDI natively) function MIDICCStream.getValue(control, channel) - error("C function not registered!") + -- NOTE: The native function assert() for invalid + -- notes or channels to avoid segfaults + assert(0 <= control and control <= 127, + "MIDI control number out of range (0 <= x <= 127)") + assert(1 <= channel and channel <= 16, + "MIDI channel out of range (1 <= x <= 16)") + + return C.applause_midi_cc_getvalue(control, channel) end function MIDICCStream:tick() local control = self.control local channel = self.channel - local getValue = self.getValue return function() - return getValue(control, channel) + return C.applause_midi_cc_getvalue(control, channel) end end |