From e96c36c1a7abb062e36efc0ac95c35fedcef922e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 8 Apr 2007 06:04:32 +0000 Subject: De-template-ification of port types (req. for LV2 MIDI, but nice code size reduction). LV2 MIDI patching support (LV2 style MIDI throughout, inc. internal plugins). git-svn-id: http://svn.drobilla.net/lad/ingen@415 a436a847-0d15-0410-975c-d299462d15a1 --- src/common/lv2ext/Makefile.am | 2 +- src/common/lv2ext/lv2-midifunctions.h | 162 ++++++++++++++++++++++++++++++++++ src/common/lv2ext/lv2-miditype.h | 50 ++++++----- 3 files changed, 189 insertions(+), 25 deletions(-) create mode 100644 src/common/lv2ext/lv2-midifunctions.h (limited to 'src/common/lv2ext') diff --git a/src/common/lv2ext/Makefile.am b/src/common/lv2ext/Makefile.am index f346ae0f..6d6ebb6e 100644 --- a/src/common/lv2ext/Makefile.am +++ b/src/common/lv2ext/Makefile.am @@ -1 +1 @@ -noinst_HEADERS = lv2-miditype.h +noinst_HEADERS = lv2-miditype.h lv2-midifunctions.h diff --git a/src/common/lv2ext/lv2-midifunctions.h b/src/common/lv2ext/lv2-midifunctions.h new file mode 100644 index 00000000..2334eff3 --- /dev/null +++ b/src/common/lv2ext/lv2-midifunctions.h @@ -0,0 +1,162 @@ +/**************************************************************************** + + lv2-midifunctions.h - support file for using MIDI in LV2 plugins + + Copyright (C) 2006 Lars Luthman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA + +****************************************************************************/ + +#ifndef LV2_MIDIFUNCTIONS +#define LV2_MIDIFUNCTIONS + +#include +#include + +#include "lv2-miditype.h" + + +/** This structure contains information about a MIDI port buffer, the + current period size, and the position in the MIDI data buffer that + we are currently reading from or writing to. It needs to be recreated + or at least reinitialised every process() call. */ +typedef struct { + + /** The MIDI port structure that we want to read or write. */ + LV2_MIDI* midi; + + /** The number of frames in this process cycle. */ + uint32_t frame_count; + + /** The current position in the data buffer. Should be initialised to 0. */ + uint32_t position; + +} LV2_MIDIState; + + +static LV2_MIDI* lv2midi_new(uint32_t capacity) +{ + LV2_MIDI* midi = (LV2_MIDI*)malloc(sizeof(LV2_MIDI)); + + midi->event_count = 0; + midi->capacity = capacity; + midi->size = 0; + midi->data = (unsigned char*)malloc(sizeof(unsigned char) * capacity); + + return midi; +} + + +static void lv2midi_free(LV2_MIDI* midi) +{ + free(midi->data); + free(midi); +} + + +static void lv2midi_reset_buffer(LV2_MIDI* midi) +{ + midi->event_count = 0; + midi->size = 0; +} + +static void lv2midi_reset_state(LV2_MIDIState* state, LV2_MIDI* midi, uint32_t frame_count) +{ + state->midi = midi; + state->frame_count = frame_count; + state->position = 0; +} + + +/** This function advances the read/write position in @c state to the next + event and returns its timestamp, or the @c frame_count member of @c state + is there are no more events. */ +static double lv2midi_increment(LV2_MIDIState* state) { + + if (state->position + sizeof(double) + sizeof(size_t) >= state->midi->size) { + state->position = state->midi->size; + return state->frame_count; + } + + state->position += sizeof(double); + size_t size = *(size_t*)(state->midi->data + state->position); + state->position += sizeof(size_t); + state->position += size; + + if (state->position >= state->midi->size) + return state->frame_count; + + return *(double*)(state->midi->data + state->position); +} + + +/** This function reads one event from the port associated with the @c state + parameter and writes its timestamp, size and a pointer to its data bytes + into the parameters @c timestamp, @c size and @c data, respectively. + It does not advance the read position in the MIDI data buffer, two + subsequent calls to lv2midi_get_event() will read the same event. + + The function returns the timestamp for the read event, or the @c frame_count + member of @c state if there are no more events in the buffer. */ +static double lv2midi_get_event(LV2_MIDIState* state, + double* timestamp, + uint32_t* size, + unsigned char** data) { + + if (state->position >= state->midi->size) { + state->position = state->midi->size; + *timestamp = state->frame_count; + *size = 0; + *data = NULL; + return *timestamp; + } + + *timestamp = *(double*)(state->midi->data + state->position); + *size = *(size_t*)(state->midi->data + state->position + sizeof(double)); + *data = state->midi->data + state->position + + sizeof(double) + sizeof(size_t); + return *timestamp; +} + + +/** This function writes one MIDI event to the port buffer associated with + @c state. It returns 0 when the event was written successfully to the + buffer, and -1 when there was not enough room. The read/write position + is advanced automatically. */ +static int lv2midi_put_event(LV2_MIDIState* state, + double timestamp, + uint32_t size, + const unsigned char* data) { + + if (state->midi->capacity - state->midi->size < + sizeof(double) + sizeof(size_t) + size) + return -1; + + *(double*)(state->midi->data + state->midi->size) = timestamp; + state->midi->size += sizeof(double); + *(size_t*)(state->midi->data + state->midi->size) = size; + state->midi->size += sizeof(size_t); + memcpy(state->midi->data + state->midi->size, data, (size_t)size); + state->midi->size += size; + + ++state->midi->event_count; + + return 0; +} + + +#endif + diff --git a/src/common/lv2ext/lv2-miditype.h b/src/common/lv2ext/lv2-miditype.h index 332e57f1..5350e4f7 100644 --- a/src/common/lv2ext/lv2-miditype.h +++ b/src/common/lv2ext/lv2-miditype.h @@ -1,37 +1,38 @@ -/************************************************************************ - - LV2 MIDI Data Type Extension - Copyright 2006 Lars Luthman in 2006 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License - as published by the Free Software Foundation; either version 2.1 of - the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. +/**************************************************************************** + + lv2-miditype.h - header file for using MIDI in LV2 plugins + + Copyright (C) 2006 Lars Luthman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA -*************************************************************************/ +****************************************************************************/ #ifndef LV2_MIDITYPE_H #define LV2_MIDITYPE_H +#include /** This data structure is used to contain the MIDI events for one run() cycle. The port buffer for a LV2 port that has the datatype - should be a pointer + should be a pointer to an instance of this struct. To store two Note On events on MIDI channel 0 in a buffer, with timestamps - 12 and 35.5, you could use something like this code (assuming that midi_data - is a variable of type LV2_MIDI): + 12 and 35.5, you could use something like this code (assuming that + midi_data is a variable of type LV2_MIDI): @code size_t buffer_offset = 0; @@ -71,7 +72,8 @@ buffer_offset += sizeof(double); size_t size = *(size_t*)(midi_data->data + buffer_offset); buffer_offset += sizeof(size_t); - do_something_with_event(timestamp, size, midi_data->data + buffer_offset); + do_something_with_event(timestamp, size, + midi_data->data + buffer_offset); buffer_offset += size; } -- cgit v1.2.1