diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/vlc_codec/.gitignore | 16 | ||||
-rw-r--r-- | utils/vlc_codec/Makefile.am | 13 | ||||
-rwxr-xr-x | utils/vlc_codec/autogen.sh | 15 | ||||
-rw-r--r-- | utils/vlc_codec/configure.ac | 32 | ||||
-rw-r--r-- | utils/vlc_codec/libadlmidi.c | 363 |
5 files changed, 439 insertions, 0 deletions
diff --git a/utils/vlc_codec/.gitignore b/utils/vlc_codec/.gitignore new file mode 100644 index 0000000..75ea9cb --- /dev/null +++ b/utils/vlc_codec/.gitignore @@ -0,0 +1,16 @@ +Makefile +m4/* +compile +config.* +configure +missing +libtool +ltmain.sh +depcomp +install-sh +autom*.cache +aclocal.m4 +Makefile.in +.deps +.libs + diff --git a/utils/vlc_codec/Makefile.am b/utils/vlc_codec/Makefile.am new file mode 100644 index 0000000..8992451 --- /dev/null +++ b/utils/vlc_codec/Makefile.am @@ -0,0 +1,13 @@ +AUTOMAKE_OPTIONS = subdir-objects + +lib_LTLIBRARIES = libadlmidi_plugin.la + +CFLAGS = -DVLC_MODULE_COPYRIGHT="\"Copyright \(c\) Vitaly Novichkov\"" +CFLAGS += -DVLC_MODULE_LICENSE=\"GPLv3\" + +libadlmidi_plugin_la_SOURCES = libadlmidi.c +libadlmidi_plugin_la_CFLAGS = -DMODULE_STRING=\"adlmidi\" $(vlc_CFLAGS) +libadlmidi_plugin_la_CPPFLAGS = -DMODULE_STRING=\"adlmidi\" $(vlc_CFLAGS) +libadlmidi_plugin_la_LIBADD = $(vlc_LIBS) +libadlmidi_plugin_la_LDFLAGS = -avoid-version -module -export-symbol-regex ^vlc_entry -lADLMIDI -lm -lstdc++ $(vlc_LDFLAGS) + diff --git a/utils/vlc_codec/autogen.sh b/utils/vlc_codec/autogen.sh new file mode 100755 index 0000000..57eeb94 --- /dev/null +++ b/utils/vlc_codec/autogen.sh @@ -0,0 +1,15 @@ +#!/bin/sh +if [ -x "`which autoreconf 2>/dev/null`" ] ; then + exec autoreconf -ivf +fi + +LIBTOOLIZE=libtoolize +SYSNAME=`uname` +if [ "x$SYSNAME" = "xDarwin" ] ; then + LIBTOOLIZE=glibtoolize +fi +aclocal -I m4 && \ + autoheader && \ + $LIBTOOLIZE && \ + autoconf && \ + automake --add-missing --force-missing --copy diff --git a/utils/vlc_codec/configure.ac b/utils/vlc_codec/configure.ac new file mode 100644 index 0000000..3afee7a --- /dev/null +++ b/utils/vlc_codec/configure.ac @@ -0,0 +1,32 @@ +# Process this file with autoconf to produce a configure script. +AC_PREREQ([2.68]) +AC_INIT([vlc-libadlmidi], [1.0.0], [admin@wohlnet.ru]) +AC_CONFIG_SRCDIR([libadlmidi.c]) +AC_CONFIG_MACRO_DIR([m4]) +AC_USE_SYSTEM_EXTENSIONS +LT_INIT + +# Checks for programs. +AC_PROG_CXX +AC_PROG_CC +AC_PROG_CC_C99 +AC_PROG_INSTALL +AC_PROG_LN_S +PKG_PROG_PKG_CONFIG + +# Initialize automake stuff +AM_INIT_AUTOMAKE([foreign]) + +AC_C_INLINE +AC_FUNC_MALLOC +AC_FUNC_REALLOC +AC_FUNC_STRNLEN +AC_SEARCH_LIBS([sqrt], [m]) +AC_CHECK_FUNCS([memset sqrt strcasecmp strcspn strdup strndup strstr strtol]) + +PKG_CHECK_MODULES([vlc], [vlc-plugin >= 2.0]) +PKG_CHECK_MODULES([vlc212], [vlc-plugin >= 2.1]) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT + diff --git a/utils/vlc_codec/libadlmidi.c b/utils/vlc_codec/libadlmidi.c new file mode 100644 index 0000000..4a86b64 --- /dev/null +++ b/utils/vlc_codec/libadlmidi.c @@ -0,0 +1,363 @@ +/***************************************************************************** + * libadlmidi.c: Software MIDI synthesizer using OPL3 Synth emulation + ***************************************************************************** + * Copyright © 2017 Vitaly Novichkov + * $Id$ + * + * This program 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 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + *****************************************************************************/ + +//#ifdef HAVE_CONFIG_H +//# include "config.h" +//#endif + +#include <vlc_common.h> +#include <vlc_plugin.h> +#include <vlc_codec.h> +#include <vlc_dialog.h> + +#include <unistd.h> + +#ifndef N_ +#define N_(x) (x) +#endif + +#ifndef _ +#define _(x) (x) +#endif + +#include <adlmidi.h> + +#define SOUNDFONT_TEXT N_("Custom bank file") +#define SOUNDFONT_LONGTEXT N_( \ + "Custom bank file to use for software synthesis." ) + +//#define CHORUS_TEXT N_("Chorus") + +//#define GAIN_TEXT N_("Synthesis gain") +//#define GAIN_LONGTEXT N_("This gain is applied to synthesis output. " \ +// "High values may cause saturation when many notes are played at a time." ) + +//#define POLYPHONY_TEXT N_("Polyphony") +//#define POLYPHONY_LONGTEXT N_( \ +// "The polyphony defines how many voices can be played at a time. " \ +// "Larger values require more processing power.") + +//#define REVERB_TEXT N_("Reverb") + +#define SAMPLE_RATE_TEXT N_("Sample rate") + +static int Open (vlc_object_t *); +static void Close (vlc_object_t *); + +vlc_module_begin () + set_description (N_("ADLMIDI OPL3 Synth MIDI synthesizer")) + set_capability ("decoder", 150) + set_shortname (N_("ADLMIDI")) + set_category (CAT_INPUT) + set_subcategory (SUBCAT_INPUT_ACODEC) + set_callbacks (Open, Close) + add_loadfile ("custombank", "", + SOUNDFONT_TEXT, SOUNDFONT_LONGTEXT, false) + //add_bool ("synth-chorus", true, CHORUS_TEXT, CHORUS_TEXT, false) + //add_float ("synth-gain", .5, GAIN_TEXT, GAIN_LONGTEXT, false) + // change_float_range (0., 10.) + //add_integer ("synth-polyphony", 256, POLYPHONY_TEXT, POLYPHONY_LONGTEXT, false) + // change_integer_range (1, 65535) + //add_bool ("synth-reverb", true, REVERB_TEXT, REVERB_TEXT, true) + add_integer ("synth-sample-rate", 44100, SAMPLE_RATE_TEXT, SAMPLE_RATE_TEXT, true) + change_integer_range (22050, 96000) +vlc_module_end () + + +struct decoder_sys_t +{ + struct ADL_MIDIPlayer *synth; + int sample_rate; + int soundfont; + date_t end_date; +}; + + +//static int DecodeBlock (decoder_t *p_dec, block_t *p_block); //For different version +static block_t *DecodeBlock (decoder_t *p_dec, block_t **pp_block); +static void Flush (decoder_t *); + +static int Open (vlc_object_t *p_this) +{ + decoder_t *p_dec = (decoder_t *)p_this; + + if (p_dec->fmt_in.i_codec != VLC_CODEC_MIDI) + return VLC_EGENERIC; + + decoder_sys_t *p_sys = malloc (sizeof (*p_sys)); + if (unlikely(p_sys == NULL)) + return VLC_ENOMEM; + + p_sys->sample_rate = 44100;//var_InheritInteger (p_this, "synth-sample-rate"); + p_sys->synth = adl_init( p_sys->sample_rate ); + + char *font_path = var_InheritString (p_this, "custombank"); + if (font_path != NULL) + { + msg_Dbg (p_this, "loading custom bank file %s", font_path); + if (adl_openBankFile(p_sys->synth, font_path)) + msg_Err (p_this, "cannot load custom bank file %s: %s", font_path, adl_errorInfo(p_sys->synth)); + free (font_path); + } + else + { + adl_setBank(p_sys->synth, 58); + } + + p_dec->fmt_out.i_cat = AUDIO_ES; + + p_dec->fmt_out.audio.i_rate = p_sys->sample_rate; + p_dec->fmt_out.audio.i_channels = 2; + p_dec->fmt_out.audio.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; + + p_dec->fmt_out.i_codec = VLC_CODEC_S16L; + p_dec->fmt_out.audio.i_bitspersample = 16; + date_Init (&p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1); + date_Set (&p_sys->end_date, 0); + + p_dec->p_sys = p_sys; + //==For different version== + //p_dec->pf_decode = DecodeBlock; + //p_dec->pf_flush = Flush; + p_dec->pf_decode_audio = DecodeBlock; + return VLC_SUCCESS;//VLCDEC_SUCCESS +} + + +static void Close (vlc_object_t *p_this) +{ + decoder_sys_t *p_sys = ((decoder_t *)p_this)->p_sys; + + adl_close(p_sys->synth); + free (p_sys); +} + +static void Flush (decoder_t *p_dec) +{ + decoder_sys_t *p_sys = p_dec->p_sys; + + date_Set (&p_sys->end_date, VLC_TS_INVALID); + adl_panic(p_sys->synth); +} + + + +static block_t *DecodeBlock (decoder_t *p_dec, block_t **pp_block) +{ + block_t *p_block; + decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_out = NULL; + + if (pp_block == NULL) + return NULL; + p_block = *pp_block; + if (p_block == NULL) + return NULL; + *pp_block = NULL; + + if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) + { + date_Set (&p_sys->end_date, 0); + //fluid_synth_system_reset (p_sys->synth); + adl_panic(p_sys->synth); + adl_rt_resetState(p_sys->synth); + } + + if (p_block->i_pts > VLC_TS_INVALID && !date_Get (&p_sys->end_date)) + date_Set (&p_sys->end_date, p_block->i_pts); + else + if (p_block->i_pts < date_Get (&p_sys->end_date)) + { + msg_Warn (p_dec, "MIDI message in the past?"); + goto drop; + } + + if (p_block->i_buffer < 1) + goto drop; + + uint8_t event = p_block->p_buffer[0]; + uint8_t channel = p_block->p_buffer[0] & 0xf; + event &= 0xF0; + + if (event == 0xF0) + switch (channel) + { + case 0: + if (p_block->p_buffer[p_block->i_buffer - 1] != 0xF7) + { + case 7: + msg_Warn (p_dec, "fragmented SysEx not implemented"); + goto drop; + } + //fluid_synth_sysex (p_sys->synth, (char *)p_block->p_buffer + 1, + // p_block->i_buffer - 2, NULL, NULL, NULL, 0); + break; + case 0xF: + adl_rt_resetState(p_sys->synth); + break; + } + + uint8_t p1 = (p_block->i_buffer > 1) ? (p_block->p_buffer[1] & 0x7f) : 0; + uint8_t p2 = (p_block->i_buffer > 2) ? (p_block->p_buffer[2] & 0x7f) : 0; + + switch (event & 0xF0) + { + case 0x80: + adl_rt_noteOff(p_sys->synth, channel, p1); + break; + case 0x90: + adl_rt_noteOn(p_sys->synth, channel, p1, p2); + break; + /*case 0xA0: note aftertouch not implemented */ + case 0xB0: + adl_rt_controllerChange(p_sys->synth, channel, p1, p2); + break; + case 0xC0: + adl_rt_patchChange(p_sys->synth, channel, p1); + break; + case 0xD0: + adl_rt_channelAfterTouch(p_sys->synth, channel, p1); + break; + case 0xE0: + adl_rt_pitchBend(p_sys->synth, channel, (p2 << 7) | p1); + break; + } + + unsigned samples = + (p_block->i_pts - date_Get (&p_sys->end_date)) * 441 / 10000; + if (samples == 0) + goto drop; + + p_out = decoder_NewAudioBuffer (p_dec, samples); + if (p_out == NULL) + goto drop; + + p_out->i_pts = date_Get (&p_sys->end_date ); + samples = adl_generate(p_sys->synth, samples * 2, (short*)p_out->p_buffer); + samples /= 2; + p_out->i_length = date_Increment (&p_sys->end_date, samples) - p_out->i_pts; + +drop: + block_Release (p_block); + return p_out; +} + +#if 0 +static int DecodeBlock (decoder_t *p_dec, block_t *p_block) +{ + decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_out = NULL; + + if (p_block == NULL) /* No Drain */ + return VLC_SUCCESS;//VLCDEC_SUCCESS + + if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) + { + Flush (p_dec); + if (p_block->i_flags & BLOCK_FLAG_CORRUPTED) + { + block_Release(p_block); + return VLC_SUCCESS;//VLCDEC_SUCCESS + } + } + + if (p_block->i_pts > VLC_TS_INVALID && !date_Get (&p_sys->end_date)) + date_Set (&p_sys->end_date, p_block->i_pts); + else + if (p_block->i_pts < date_Get (&p_sys->end_date)) + { + msg_Warn (p_dec, "MIDI message in the past?"); + goto drop; + } + + if (p_block->i_buffer < 1) + goto drop; + + uint8_t event = p_block->p_buffer[0]; + uint8_t channel = p_block->p_buffer[0] & 0xf; + event &= 0xF0; + + if (event == 0xF0) + switch (channel) + { + case 0: + if (p_block->p_buffer[p_block->i_buffer - 1] != 0xF7) + { + case 7: + msg_Warn (p_dec, "fragmented SysEx not implemented"); + goto drop; + } + //fluid_synth_sysex (p_sys->synth, (char *)p_block->p_buffer + 1, + // p_block->i_buffer - 2, NULL, NULL, NULL, 0); + break; + case 0xF: + adl_rt_resetState(p_sys->synth); + break; + } + + uint8_t p1 = (p_block->i_buffer > 1) ? (p_block->p_buffer[1] & 0x7f) : 0; + uint8_t p2 = (p_block->i_buffer > 2) ? (p_block->p_buffer[2] & 0x7f) : 0; + + switch (event & 0xF0) + { + case 0x80: + adl_rt_noteOff(p_sys->synth, channel, p1); + break; + case 0x90: + adl_rt_noteOn(p_sys->synth, channel, p1, p2); + break; + /*case 0xA0: note aftertouch not implemented */ + case 0xB0: + adl_rt_controllerChange(p_sys->synth, channel, p1, p2); + break; + case 0xC0: + adl_rt_patchChange(p_sys->synth, channel, p1); + break; + case 0xD0: + adl_rt_channelAfterTouch(p_sys->synth, channel, p1); + break; + case 0xE0: + adl_rt_pitchBendML(p_sys->synth, channel, p2, p1); + break; + } + + unsigned samples = + (p_block->i_pts - date_Get (&p_sys->end_date)) * 441 / 10000; + if (samples == 0) + goto drop; + + if (decoder_UpdateAudioFormat (p_dec)) + goto drop; + p_out = decoder_NewAudioBuffer (p_dec, samples); + if (p_out == NULL) + goto drop; + + p_out->i_pts = date_Get (&p_sys->end_date ); + p_out->i_length = date_Increment (&p_sys->end_date, samples) + - p_out->i_pts; + adl_generate(p_sys->synth, samples * 2, p_out->p_buffer); +drop: + block_Release (p_block); + if (p_out != NULL) + decoder_QueueAudio (p_dec, p_out); + return VLC_SUCCESS;//VLCDEC_SUCCESS +} + +#endif |