diff options
-rw-r--r-- | CMakeLists.txt | 36 | ||||
-rw-r--r-- | cmake/FindLIBVLC.cmake | 92 | ||||
-rw-r--r-- | include/adlmidi.h | 4 | ||||
-rw-r--r-- | src/adlmidi.cpp | 31 | ||||
-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 |
9 files changed, 575 insertions, 27 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4446231..031152b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ ENDIF() option(WITH_MIDIPLAY "Build also demo MIDI player" OFF) option(MIDIPLAY_WAVE_ONLY "Build Demo MIDI player without support of real time playing. It will output into WAV only." OFF) option(WITH_ADLMIDI2 "Build also classic ADLMIDI player [EXPERIMENTAL]" OFF) +option(WITH_VLC_PLUGIN "Build also a plugin for VLC Media Player" OFF) option(WITH_OLD_UTILS "Build also old utilities" OFF) option(WITH_EMBEDDED_BANKS "Use embedded banks" ON) option(WITH_GENADLDATA "Build and run full rebuild of embedded banks cache" OFF) @@ -46,6 +47,7 @@ option(WITH_CPP_EXTRAS "Build with support for C++ extras (features are can option(libADLMIDI_STATIC "Build static library of libADLMIDI" ON) option(libADLMIDI_SHARED "Build shared library of libADLMIDI" OFF) + if(CMAKE_VERSION VERSION_EQUAL "3.1" OR CMAKE_VERSION VERSION_GREATER "3.1") set(CMAKE_CXX_STANDARD 11) endif() @@ -292,6 +294,40 @@ if(WITH_ADLMIDI2) list(APPEND libADLMIDI_INSTALLS adlmidi2) endif() +if(WITH_VLC_PLUGIN) + include(cmake/FindLIBVLC.cmake) + include_directories(${LIBVLC_INCLUDE_DIR}/vlc/plugins) + include_directories(${LIBVLC_INCLUDE_DIR}/vlc) + message("Found ${LIBVLC_LIBRARY} of version ${LIBVLC_VERSION} with includes ${LIBVLC_INCLUDE_DIR}") + + set(adlmidi_vlc_src) + list(APPEND adlmidi_vlc_src + ${libADLMIDI_SOURCE_DIR}/utils/vlc_codec/libadlmidi.c) + + add_library(adlmidi_plugin MODULE ${adlmidi_vlc_src}) + target_compile_options(adlmidi_plugin PUBLIC "-DVLC_MODULE_COPYRIGHT=\"Copyright \(c\) Vitaly Novichkov\"") + target_compile_options(adlmidi_plugin PUBLIC "-DVLC_MODULE_LICENSE=\"GPLv3\"") + target_compile_options(adlmidi_plugin PUBLIC "-DMODULE_STRING=\"adlmidi\"") + #target_link_options() + #target_compile_definitions(adlmidi_plugin + # PUBLIC -DVLC_MODULE_COPYRIGHT="Copyright \(c\) Vitaly Novichkov" -DVLC_MODULE_LICENSE="GPLv3" -DMODULE_STRING="adlmidi") + target_link_libraries(adlmidi_plugin ADLMIDI vlccore m stdc++) + target_link_libraries(adlmidi_plugin INTERFACE "-export-symbol-regex ^vlc_entry") + #target_compile_definitions(adlmidi_plugin -DVLC_MODULE_LICENSE="GPLv3") + #target_compile_definitions(adlmidi_plugin -DMODULE_STRING="adlmidi") + + if(libADLMIDI_SHARED) + add_dependencies(adlmidi_plugin ADLMIDI_shared) + # ========= WIP ========= + # set_target_properties(adlmidiplay PROPERTIES COMPILE_FLAGS "-Wl,-rpath='$$ORIGIN/../lib'") + else() + if(NOT libADLMIDI_STATIC) + message(FATAL_ERROR "libADLMIDI is required to be built!") + endif() + add_dependencies(adlmidi_plugin ADLMIDI_static) + endif() + +endif() install(TARGETS ${libADLMIDI_INSTALLS} RUNTIME DESTINATION "bin" diff --git a/cmake/FindLIBVLC.cmake b/cmake/FindLIBVLC.cmake new file mode 100644 index 0000000..abbfb6c --- /dev/null +++ b/cmake/FindLIBVLC.cmake @@ -0,0 +1,92 @@ + +# CMake module to search for LIBVLC (VLC library) +# Authors: Rohit Yadav <rohityadav89@gmail.com> +# Harald Sitter <apachelogger@ubuntu.com> +# +# If it's found it sets LIBVLC_FOUND to TRUE +# and following variables are set: +# LIBVLC_INCLUDE_DIR +# LIBVLC_LIBRARY +# LIBVLC_VERSION + +if(NOT LIBVLC_MIN_VERSION) + set(LIBVLC_MIN_VERSION "0.0") +endif(NOT LIBVLC_MIN_VERSION) + +# find_path and find_library normally search standard locations +# before the specified paths. To search non-standard paths first, +# FIND_* is invoked first with specified paths and NO_DEFAULT_PATH +# and then again with no specified paths to search the default +# locations. When an earlier FIND_* succeeds, subsequent FIND_*s +# searching for the same item do nothing. + +if (NOT WIN32) + find_package(PkgConfig) + pkg_check_modules(PC_LIBVLC libvlc) + set(LIBVLC_DEFINITIONS ${PC_LIBVLC_CFLAGS_OTHER}) +endif (NOT WIN32) + +#Put here path to custom location +#example: /home/user/vlc/include etc.. +find_path(LIBVLC_INCLUDE_DIR vlc/vlc.h +HINTS "$ENV{LIBVLC_INCLUDE_PATH}" +PATHS + "$ENV{LIB_DIR}/include" + "$ENV{LIB_DIR}/include/vlc" + "/usr/include" + "/usr/include/vlc" + "/usr/local/include" + "/usr/local/include/vlc" + #mingw + c:/msys/local/include +) +find_path(LIBVLC_INCLUDE_DIR PATHS "${CMAKE_INCLUDE_PATH}/vlc" NAMES vlc.h + HINTS ${PC_LIBVLC_INCLUDEDIR} ${PC_LIBVLC_INCLUDE_DIRS}) + +#Put here path to custom location +#example: /home/user/vlc/lib etc.. +find_library(LIBVLC_LIBRARY NAMES vlc libvlc +HINTS "$ENV{LIBVLC_LIBRARY_PATH}" ${PC_LIBVLC_LIBDIR} ${PC_LIBVLC_LIBRARY_DIRS} +PATHS + "$ENV{LIB_DIR}/lib" + #mingw + c:/msys/local/lib +) +find_library(LIBVLC_LIBRARY NAMES vlc libvlc) +find_library(LIBVLCCORE_LIBRARY NAMES vlccore libvlccore +HINTS "$ENV{LIBVLC_LIBRARY_PATH}" ${PC_LIBVLC_LIBDIR} ${PC_LIBVLC_LIBRARY_DIRS} +PATHS + "$ENV{LIB_DIR}/lib" + #mingw + c:/msys/local/lib +) +find_library(LIBVLCCORE_LIBRARY NAMES vlccore libvlccore) + +set(LIBVLC_VERSION ${PC_LIBVLC_VERSION}) +if (NOT LIBVLC_VERSION) +# TODO: implement means to detect version on windows (vlc --version && regex? ... ultimately we would get it from a header though...) +endif (NOT LIBVLC_VERSION) + +if (LIBVLC_INCLUDE_DIR AND LIBVLC_LIBRARY AND LIBVLCCORE_LIBRARY) +set(LIBVLC_FOUND TRUE) +endif (LIBVLC_INCLUDE_DIR AND LIBVLC_LIBRARY AND LIBVLCCORE_LIBRARY) + +if (LIBVLC_VERSION STRLESS "${LIBVLC_MIN_VERSION}") + message(WARNING "LibVLC version not found: version searched: ${LIBVLC_MIN_VERSION}, found ${LIBVLC_VERSION}\nUnless you are on Windows this is bound to fail.") +# TODO: only activate once version detection can be garunteed (which is currently not the case on windows) +# set(LIBVLC_FOUND FALSE) +endif (LIBVLC_VERSION STRLESS "${LIBVLC_MIN_VERSION}") + +if (LIBVLC_FOUND) + if (NOT LIBVLC_FIND_QUIETLY) + message(STATUS "Found LibVLC include-dir path: ${LIBVLC_INCLUDE_DIR}") + message(STATUS "Found LibVLC library path:${LIBVLC_LIBRARY}") + message(STATUS "Found LibVLCcore library path:${LIBVLCCORE_LIBRARY}") + message(STATUS "Found LibVLC version: ${LIBVLC_VERSION} (searched for: ${LIBVLC_MIN_VERSION})") + endif (NOT LIBVLC_FIND_QUIETLY) +else (LIBVLC_FOUND) + if (LIBVLC_FIND_REQUIRED) + message(FATAL_ERROR "Could not find LibVLC") + endif (LIBVLC_FIND_REQUIRED) +endif (LIBVLC_FOUND) + diff --git a/include/adlmidi.h b/include/adlmidi.h index bc1b2d3..49dcbc0 100644 --- a/include/adlmidi.h +++ b/include/adlmidi.h @@ -35,7 +35,7 @@ extern "C" { typedef uint8_t ADL_UInt8; typedef uint16_t ADL_UInt16; typedef int8_t ADL_SInt8; -typedef int16_t ADL_Sint16; +typedef int16_t ADL_SInt16; #else typedef unsigned char ADL_UInt8; typedef unsigned short ADL_UInt16; @@ -239,7 +239,7 @@ extern void adl_rt_controllerChange(struct ADL_MIDIPlayer *device, ADL_UInt8 cha extern void adl_rt_patchChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 patch); /*Apply pitch bend change*/ -extern void adl_rt_pitchBend(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 pitch); +extern void adl_rt_pitchBend(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt16 pitch); /*Apply pitch bend change*/ extern void adl_rt_pitchBendML(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 msb, ADL_UInt8 lsb); diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp index dd4a3e1..b9e67cb 100644 --- a/src/adlmidi.cpp +++ b/src/adlmidi.cpp @@ -653,34 +653,21 @@ ADLMIDI_EXPORT int adl_generate(struct ADL_MIDIPlayer *device, int sampleCount, ssize_t n_periodCountStereo = 512; int left = sampleCount; - bool hasSkipped = setup.tick_skip_samples_delay > 0; - double delay = double(sampleCount) / double(setup.PCM_RATE); while(left > 0) { {//... const double eat_delay = delay < setup.maxdelay ? delay : setup.maxdelay; - if(hasSkipped) - { - size_t samples = setup.tick_skip_samples_delay > sampleCount ? sampleCount : setup.tick_skip_samples_delay; - n_periodCountStereo = samples / 2; - } - else - { - delay -= eat_delay; - setup.carry += setup.PCM_RATE * eat_delay; - n_periodCountStereo = static_cast<ssize_t>(setup.carry); - setup.carry -= n_periodCountStereo; - } + delay -= eat_delay; + setup.carry += setup.PCM_RATE * eat_delay; + n_periodCountStereo = static_cast<ssize_t>(setup.carry); + setup.carry -= n_periodCountStereo; { ssize_t leftSamples = left / 2; if(n_periodCountStereo > leftSamples) - { - setup.tick_skip_samples_delay = (n_periodCountStereo - leftSamples) * 2; n_periodCountStereo = leftSamples; - } //! Count of stereo samples ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo; //! Total count of samples @@ -719,13 +706,7 @@ ADLMIDI_EXPORT int adl_generate(struct ADL_MIDIPlayer *device, int sampleCount, gotten_len += (in_generatedPhys) /* - setup.stored_samples*/; } - if(hasSkipped) - { - setup.tick_skip_samples_delay -= n_periodCountStereo * 2; - hasSkipped = setup.tick_skip_samples_delay > 0; - } - else - player->TickIteratos(eat_delay); + player->TickIteratos(eat_delay); }//... } @@ -833,7 +814,7 @@ void adl_rt_patchChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UI player->realTime_PatchChange(channel, patch); } -void adl_rt_pitchBend(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 pitch) +void adl_rt_pitchBend(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt16 pitch) { if(!device) return; 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 |