From 3a1bfc0a6e78f006fc853c1acd2408ed9c383176 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 21 Jul 2018 11:16:24 +0200 Subject: Add humanized timing controls to the cli. --- drumgizmo/Makefile.am | 1 - drumgizmo/drumgizmoc.cc | 210 ++++++++++++++++++++++++++++++++---------------- drumgizmo/drumgizmoc.h | 27 ------- 3 files changed, 141 insertions(+), 97 deletions(-) delete mode 100644 drumgizmo/drumgizmoc.h (limited to 'drumgizmo') diff --git a/drumgizmo/Makefile.am b/drumgizmo/Makefile.am index 940630a..4bf578c 100644 --- a/drumgizmo/Makefile.am +++ b/drumgizmo/Makefile.am @@ -88,7 +88,6 @@ endif # HAVE_INPUT_JACKMIDI endif # HAVE_OUTPUT_JACKAUDIO EXTRA_DIST = \ - drumgizmoc.h \ jackclient.h \ enginefactory.h \ getoptpp/getoptpp.hpp \ diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 5172666..793967b 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -38,7 +38,6 @@ #include #include "drumgizmo.h" -#include "drumgizmoc.h" #include "enginefactory.h" #include "bytesizeparser.h" @@ -46,12 +45,11 @@ #include "nolocale.h" -typedef struct parm_token +struct ParmToken { std::string key; std::string value; -} parm_token_t; - +}; static std::string version() { @@ -60,11 +58,10 @@ static std::string version() return output.str(); } - static std::string copyright() { std::ostringstream output; - output << "Copyright (C) 2008-2011 Bent Bisballe Nyeng - Aasimon.org.\n"; + output << "Copyright (C) 2008-2018 Bent Bisballe Nyeng - Aasimon.org.\n"; output << "This is free software. You may redistribute copies of it under the terms "; output << "of\n"; output << "the GNU Lesser General Public License .\n"; @@ -74,66 +71,85 @@ static std::string copyright() return output.str(); } - static std::string usage(std::string name) { std::ostringstream output; - output << "Usage: " << name << " [options] drumkitfile\n"; - output << "Options:\n"; - output << " -a, --async-load Load drumkit in the background and start the "; - output << " -b --bleed Set and enable master bleed"; - output << "engine immediately.\n"; - output << " -i, --inputengine dummy|test|jackmidi|midifile Use said event "; - output << "input engine.\n"; - output << " -I, --inputparms parmlist Set input engine parameters.\n"; - output << " -o, --outputengine dummy|alsa|jackaudio|wavfile Use said audio "; - output << "output engine.\n"; - output << " -O, --outputparms parmlist Set output engine parameters.\n"; - output << " -e, --endpos Number of samples to process, -1: infinite.\n"; + output << + "Usage: " << name << " [options] drumkitfile\n" + "Options:\n" + " -a, --async-load Load drumkit in the background and start the" + " engine immediately.\n" + " -b --bleed Set and enable master bleed\n" + +// stddev +// velocity-attack +// velocity-release +// tightness +// timing-regain +// laidback + + " -i, --inputengine dummy|test|jackmidi|midifile Use said event " + "input engine.\n" + " -I, --inputparms parmlist Set input engine parameters.\n" + " -o, --outputengine dummy|alsa|jackaudio|wavfile Use said audio " + "output engine.\n" + " -O, --outputparms parmlist Set output engine parameters.\n" + " -e, --endpos Number of samples to process, -1: infinite.\n" #ifndef DISABLE_HUGIN - output << " -D, --debug ddd Enable debug messages on 'ddd'; see hugin "; - output << "documentation for details\n"; + " -D, --debug ddd Enable debug messages on 'ddd' see hugin " + "documentation for details\n" #endif /*DISABLE_HUGIN*/ - output << " -r, --no-resampling Disable resampling.\n"; - output << " -s, --streaming Enable streaming.\n"; - output << " -S, --streamingparms Streaming options.\n"; - output << " -v, --version Print version information and exit.\n"; - output << " -h, --help Print this message and exit.\n"; - output << "\n"; - output << "Input engine parameters:\n"; - output << " jackmidi: midimap=\n"; - output << " midifile: file=, speed= (default 1.0),\n"; - output << " track= (default -1, all tracks)\n"; - output << " midimap=, loop=\n"; - output << " ossmidi: midimap=, dev= (default '/dev/midi')\n"; - output << " test: p= (default 0.1)\n"; - output << " instr= (default -1, random instrument)\n"; - output << " len= (default -1, forever)\n"; - output << " dummy:\n"; - output << "\n"; - output << "Output engine parameters:\n"; - output << " alsa: dev= (default 'default'), frames= (default "; - output << "32)\n"; - output << " srate= (default 441000)\n"; - output << " oss: dev= (default '/dev/dsp'), srate=,\n"; - output << " max_fragments= (default 4, see man page for more info),\n"; - output << " fragment_size= (default 8, see man page for more info)\n"; - output << " wavfile: file= (default 'output'), srate= "; - output << "(default 44100)\n"; - output << " jackaudio:\n"; - output << " dummy:\n"; - output << "\n"; - output << "Streaming parameters:\n"; - output << " limit: Limit the amount of preloaded drumkit data to the size\n"; - // output << " chunk_size: chunk size in k,M,G\n" - output << "\n"; + " -r, --no-resampling Disable resampling.\n" + " -s, --streaming Enable streaming.\n" + " -S, --streamingparms parmlist\n" + " Streaming options.\n" + " -t, --timing-humanizer\n" + " Enable moving of notes in time. Note adds latency to the output so do not\n" + " use this with a real-time drumkit.\n" + " -T, --timing-humanizerparms parmlist\n" + " Timing humanizer options.\n" + " -v, --version Print version information and exit.\n" + " -h, --help Print this message and exit.\n" + "\n" + "Input engine parameters:\n" + " jackmidi: midimap=\n" + " midifile: file=, speed= (default 1.0),\n" + " track= (default -1, all tracks)\n" + " midimap=, loop=\n" + " ossmidi: midimap=, dev= (default '/dev/midi')\n" + " test: p= (default 0.1)\n" + " instr= (default -1, random instrument)\n" + " len= (default -1, forever)\n" + " dummy:\n" + "\n" + "Output engine parameters:\n" + " alsa: dev= (default 'default'), frames= (default " + "32)\n" + " srate= (default 441000)\n" + " oss: dev= (default '/dev/dsp'), srate=,\n" + " max_fragments= (default 4, see man page for more info),\n" + " fragment_size= (default 8, see man page for more info)\n" + " wavfile: file= (default 'output'), srate= " + "(default 44100)\n" + " jackaudio:\n" + " dummy:\n" + "\n" + "Streaming parameters:\n" + " limit: Limit the amount of preloaded drumkit data to the size\n" + //" chunk_size: chunk size in k,M,G\n" + "\n" + "Timing humanizer parameters:\n" + " laidback: Move notes ahead or behind in time in ms [+/-100].\n" + " tightness: Control the tightness of the drummer. [0; 1].\n" + " regain: Control how fast the drummer catches up the timing. [0; 1]\n" + "\n"; return output.str(); } -std::vector parse_parameters(std::string &parms) +std::vector parseParameters(std::string &parms) { - std::vector result; + std::vector result; std::string parm; std::string val; bool inval = false; @@ -239,7 +255,7 @@ int main(int argc, char* argv[]) opt.add("inputparms", required_argument, 'I', [&]() { std::string parms = optarg; - auto tokens = parse_parameters(parms); + auto tokens = parseParameters(parms); for(auto &token : tokens) { ie->setParm(token.key, token.value); @@ -273,7 +289,7 @@ int main(int argc, char* argv[]) opt.add("outputparms", required_argument, 'O', [&]() { std::string parms = optarg; - auto tokens = parse_parameters(parms); + auto tokens = parseParameters(parms); for(auto &token : tokens) { oe->setParm(token.key, token.value); @@ -308,7 +324,7 @@ int main(int argc, char* argv[]) opt.add("streamingparms", required_argument, 'S', [&]() { std::string parms = optarg; - auto tokens = parse_parameters(parms); + auto tokens = parseParameters(parms); for(auto &token : tokens) { if(token.key == "limit") @@ -316,22 +332,78 @@ int main(int argc, char* argv[]) settings.disk_cache_upper_limit = byteSizeParser(token.value); if(settings.disk_cache_upper_limit == 0) { - std::cerr << "Invalid argument for streamparms limit: " << token.value << std::endl; + std::cerr << "Invalid argument for streamparms limit: " << + token.value << std::endl; exit(1); } } - // else if(token.key == "chunk_size") - // { - // settings.disk_cache_chunk_size = byteSizeParser(token.value); - // if(settings.disk_cache_chunk_size == 0) - // { - // std::cerr << "Invalid argument for streamparms chunk_size: " << token.value << std::endl; - // exit(1); - // } + //else if(token.key == "chunk_size") + //{ + // settings.disk_cache_chunk_size = byteSizeParser(token.value); + // if(settings.disk_cache_chunk_size == 0) + // { + // std::cerr << "Invalid argument for streamparms chunk_size: " << + // token.value << std::endl; + // exit(1); + // } // } else { - std::cerr << "Unknown streamingparms argument " << token.key << std::endl; + std::cerr << "Unknown streamingparms argument " << token.key << + std::endl; + exit(1); + } + } + }); + + // Default is to disable timing humanizer + settings.enable_latency_modifier.store(false); + + opt.add("timing-humanizer", no_argument, 't', [&]() { + settings.enable_latency_modifier.store(true); + }); + + opt.add("timing-humanizerparms", required_argument, 'T', [&]() { + std::string parms = optarg; + auto tokens = parseParameters(parms); + for(auto &token : tokens) + { + if(token.key == "laidback") + { + // Input range [+/- 100] ms + auto val = atof_nol(token.value.data()); + if(val < -100.0 || val > 100.0) + { + std::cerr << "laidback range is +/- 100 and is in ms.\n"; + exit(1); + } + settings.latency_laid_back_ms.store(val); + } + else if(token.key == "tightness") + { + // Input range [0; 1] + auto val = atof_nol(token.value.data()); + if(val < 0.0 || val > 1.0) + { + std::cerr << "tightness range is [0; 1].\n"; + exit(1); + } + settings.latency_stddev.store((-1.0 * val + 1.0) * 500.0); + } + else if(token.key == "regain") + { + auto val = atof_nol(token.value.data()); + if(val < 0.0 || val > 1.0) + { + std::cerr << "regain range is [0; 1].\n"; + exit(1); + } + settings.latency_regain.store(val); + } + else + { + std::cerr << "Unknown timing-humanizerparms argument " << token.key << + std::endl; exit(1); } } diff --git a/drumgizmo/drumgizmoc.h b/drumgizmo/drumgizmoc.h deleted file mode 100644 index cc2f96c..0000000 --- a/drumgizmo/drumgizmoc.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * drumgizmoc.h - * - * Mon Jan 12 00:36:37 CET 2015 - * Copyright 2015 Sergey 'Jin' Bostandzhyan - * jin@mediatomb.cc - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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 3 of the License, or - * (at your option) any later version. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once -- cgit v1.2.3