diff --git a/scripts/generate_re2c.sh b/scripts/generate_re2c.sh new file mode 100755 index 00000000..4f65b9e1 --- /dev/null +++ b/scripts/generate_re2c.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -e + +if ! test -d "src"; then + echo "Please run this in the project root directory." + exit 1 +fi + +for src in src/sfizz/OpcodeCleanup.re; do + re2c -o "${src%.re}.cpp" "$src" +done diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e786dae3..03f976d2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,7 +45,7 @@ sfizz_add_simd_sources (SFIZZ_SOURCES ".") # Parser core library add_library (sfizz_parser STATIC) target_sources (sfizz_parser PRIVATE - sfizz/Parser.cpp sfizz/Opcode.cpp sfizz/SfzHelpers.cpp + sfizz/Parser.cpp sfizz/Opcode.cpp sfizz/OpcodeCleanup.cpp sfizz/SfzHelpers.cpp sfizz/parser/Parser.cpp sfizz/parser/ParserPrivate.cpp) target_include_directories (sfizz_parser PUBLIC sfizz) target_include_directories (sfizz_parser PUBLIC external) diff --git a/src/sfizz/Opcode.h b/src/sfizz/Opcode.h index 189aca0b..b6f64e09 100644 --- a/src/sfizz/Opcode.h +++ b/src/sfizz/Opcode.h @@ -36,6 +36,18 @@ enum OpcodeCategory { kOpcodeSmoothCcN, }; +/** + * @brief A scope where an opcode may appear. + */ +enum OpcodeScope { + //! unknown scope or other + kOpcodeScopeGeneric, + //! region scope + kOpcodeScopeRegion, + //! effect scope + kOpcodeScopeEffect, +}; + /** * @brief Opcode description class. The class parses the parameters * of the opcode on construction. @@ -51,6 +63,15 @@ struct Opcode { std::vector parameters; OpcodeCategory category; + /* + * @brief Normalize in order to make the ampersand-name unique, and + * facilitate subsequent processing. + * + * @param scope scope where this opcode appears + * @return normalized opcode + */ + Opcode cleanUp(OpcodeScope scope) const; + /* * @brief Get the derived opcode name to convert it to another category. * diff --git a/src/sfizz/OpcodeCleanup.cpp b/src/sfizz/OpcodeCleanup.cpp new file mode 100644 index 00000000..b42c44e1 --- /dev/null +++ b/src/sfizz/OpcodeCleanup.cpp @@ -0,0 +1,1797 @@ +/* Generated by re2c 1.3 on Tue May 5 03:27:40 2020 */ +#line 1 "src/sfizz/OpcodeCleanup.re" +/* -*- mode: c++; -*- */ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +#include "Opcode.h" +#include "absl/strings/string_view.h" +#include "absl/strings/str_cat.h" +#include + +namespace sfz { + +static std::string cleanUpOpcodeName(absl::string_view rawOpcode, OpcodeScope scope) +{ + std::string opcode { rawOpcode }; + + #line 23 "src/sfizz/OpcodeCleanup.re" + + #define YYMAXNMATCH 4 + + + const char* YYCURSOR; + const char* YYMARKER; + const char* yypmatch[2 * YYMAXNMATCH]; + size_t yynmatch; + + const char* yyt1; const char* yyt2; const char* yyt3; + + auto group = [&yypmatch](size_t i) -> absl::string_view { + const char *beg = yypmatch[2 * i]; + const char *end = yypmatch[2 * i + 1]; + return absl::string_view(beg, end - beg); + }; + + #line 44 "src/sfizz/OpcodeCleanup.re" + + + //-------------------------------------------------------------------------- + + YYCURSOR = opcode.c_str(); + + +#line 48 "src/sfizz/OpcodeCleanup.cpp" +{ + char yych; + yych = *YYCURSOR; + switch (yych) { + case 0x00: goto yy2; + case '_': + yyt1 = YYCURSOR; + goto yy5; + default: + yyt1 = YYCURSOR; + goto yy4; + } +yy2: + ++YYCURSOR; +yy3: +#line 57 "src/sfizz/OpcodeCleanup.re" + { + goto end_generic; + } +#line 68 "src/sfizz/OpcodeCleanup.cpp" +yy4: + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= 0x00) goto yy3; + goto yy7; +yy5: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 0x00: goto yy3; + case 'c': goto yy11; + default: goto yy7; + } +yy6: + yych = *++YYCURSOR; +yy7: + switch (yych) { + case 0x00: goto yy8; + case '_': goto yy9; + default: goto yy6; + } +yy8: + YYCURSOR = YYMARKER; + goto yy3; +yy9: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: goto yy8; + case '_': goto yy9; + case 'c': goto yy11; + default: goto yy6; + } +yy11: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: goto yy8; + case '_': goto yy9; + case 'c': goto yy12; + default: goto yy6; + } +yy12: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: goto yy8; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + yyt2 = YYCURSOR; + goto yy13; + case '_': goto yy9; + default: goto yy6; + } +yy13: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: goto yy15; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': goto yy13; + case '_': goto yy9; + default: goto yy6; + } +yy15: + ++YYCURSOR; + yynmatch = 3; + yypmatch[2] = yyt1; + yypmatch[4] = yyt2; + yypmatch[0] = yyt1; + yypmatch[1] = YYCURSOR; + yypmatch[3] = yyt2 - 3; + yypmatch[5] = YYCURSOR - 1; +#line 52 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat(group(1), "_oncc", group(2)); + goto end_generic; + } +#line 157 "src/sfizz/OpcodeCleanup.cpp" +} +#line 61 "src/sfizz/OpcodeCleanup.re" + + +end_generic: + /* end */; + + //-------------------------------------------------------------------------- + + if (scope == kOpcodeScopeRegion) { + + YYCURSOR = opcode.c_str(); + + +#line 172 "src/sfizz/OpcodeCleanup.cpp" +{ + char yych; + yych = *YYCURSOR; + switch (yych) { + case 'a': + yyt1 = YYCURSOR; + goto yy21; + case 'b': goto yy22; + case 'c': + yyt1 = YYCURSOR; + goto yy23; + case 'e': + yyt1 = YYCURSOR; + goto yy24; + case 'f': + yyt1 = YYCURSOR; + goto yy25; + case 'g': + yyt1 = YYCURSOR; + goto yy26; + case 'l': + yyt1 = YYCURSOR; + goto yy27; + case 'o': goto yy28; + case 'p': + yyt1 = YYCURSOR; + goto yy29; + case 'r': + yyt1 = YYCURSOR; + goto yy30; + case 't': + yyt1 = YYCURSOR; + goto yy31; + default: goto yy19; + } +yy19: + ++YYCURSOR; +yy20: +#line 149 "src/sfizz/OpcodeCleanup.re" + { + goto end_region; + } +#line 215 "src/sfizz/OpcodeCleanup.cpp" +yy21: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'm': goto yy32; + default: goto yy20; + } +yy22: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'e': goto yy34; + default: goto yy20; + } +yy23: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'u': goto yy35; + default: goto yy20; + } +yy24: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'q': goto yy36; + default: goto yy20; + } +yy25: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'i': goto yy37; + default: goto yy20; + } +yy26: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'a': goto yy38; + default: goto yy20; + } +yy27: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'f': goto yy39; + case 'o': goto yy40; + default: goto yy20; + } +yy28: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'f': goto yy41; + case 'n': goto yy42; + default: goto yy20; + } +yy29: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'i': goto yy43; + case 'o': goto yy44; + default: goto yy20; + } +yy30: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'e': goto yy45; + default: goto yy20; + } +yy31: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case 'u': goto yy46; + default: goto yy20; + } +yy32: + yych = *++YYCURSOR; + switch (yych) { + case 'p': goto yy47; + default: goto yy33; + } +yy33: + YYCURSOR = YYMARKER; + goto yy20; +yy34: + yych = *++YYCURSOR; + switch (yych) { + case 'n': goto yy48; + default: goto yy33; + } +yy35: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy49; + default: goto yy33; + } +yy36: + yych = *++YYCURSOR; + switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': goto yy50; + default: goto yy33; + } +yy37: + yych = *++YYCURSOR; + switch (yych) { + case 'l': goto yy52; + default: goto yy33; + } +yy38: + yych = *++YYCURSOR; + switch (yych) { + case 'i': goto yy53; + default: goto yy33; + } +yy39: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy54; + default: goto yy33; + } +yy40: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy55; + default: goto yy33; + } +yy41: + yych = *++YYCURSOR; + switch (yych) { + case 'f': goto yy56; + default: goto yy33; + } +yy42: + yych = *++YYCURSOR; + switch (yych) { + case '_': goto yy57; + default: goto yy33; + } +yy43: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy58; + default: goto yy33; + } +yy44: + yych = *++YYCURSOR; + switch (yych) { + case 'l': goto yy59; + default: goto yy33; + } +yy45: + yych = *++YYCURSOR; + switch (yych) { + case 's': goto yy60; + default: goto yy33; + } +yy46: + yych = *++YYCURSOR; + switch (yych) { + case 'n': goto yy61; + default: goto yy33; + } +yy47: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy62; + case 'l': goto yy63; + default: goto yy33; + } +yy48: + yych = *++YYCURSOR; + switch (yych) { + case 'd': goto yy64; + default: goto yy33; + } +yy49: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy65; + default: goto yy33; + } +yy50: + yych = *++YYCURSOR; + switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': goto yy50; + case '_': goto yy66; + default: goto yy33; + } +yy52: + yych = *++YYCURSOR; + switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + yyt1 = YYCURSOR; + goto yy67; + case '_': goto yy69; + case 'e': goto yy62; + case 'l': goto yy63; + case 't': goto yy70; + default: goto yy33; + } +yy53: + yych = *++YYCURSOR; + switch (yych) { + case 'n': goto yy71; + default: goto yy33; + } +yy54: + yych = *++YYCURSOR; + switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': goto yy72; + default: goto yy33; + } +yy55: + yych = *++YYCURSOR; + switch (yych) { + case 'p': goto yy74; + default: goto yy33; + } +yy56: + yych = *++YYCURSOR; + switch (yych) { + case 'b': + yyt1 = YYCURSOR; + goto yy75; + case 'm': + yyt1 = YYCURSOR; + goto yy76; + default: goto yy33; + } +yy57: + yych = *++YYCURSOR; + switch (yych) { + case 'h': goto yy77; + case 'l': goto yy78; + default: goto yy33; + } +yy58: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy79; + default: goto yy33; + } +yy59: + yych = *++YYCURSOR; + switch (yych) { + case 'y': goto yy80; + default: goto yy33; + } +yy60: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy81; + default: goto yy33; + } +yy61: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy82; + default: goto yy33; + } +yy62: + yych = *++YYCURSOR; + switch (yych) { + case 'g': goto yy83; + default: goto yy33; + } +yy63: + yych = *++YYCURSOR; + switch (yych) { + case 'f': goto yy84; + default: goto yy33; + } +yy64: + yych = *++YYCURSOR; + switch (yych) { + case 'd': + yyt1 = YYCURSOR; + goto yy85; + case 'u': + yyt1 = YYCURSOR; + goto yy86; + default: goto yy33; + } +yy65: + yych = *++YYCURSOR; + switch (yych) { + case 'f': goto yy87; + default: goto yy33; + } +yy66: + yych = *++YYCURSOR; + switch (yych) { + case 'b': + yyt2 = YYCURSOR; + goto yy88; + case 'f': + yyt2 = YYCURSOR; + goto yy89; + case 'g': + yyt2 = YYCURSOR; + goto yy90; + default: goto yy33; + } +yy67: + yych = *++YYCURSOR; + switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': goto yy67; + case 't': goto yy91; + default: goto yy33; + } +yy69: + yych = *++YYCURSOR; + yyt1 = YYCURSOR; + goto yy95; +yy70: + yych = *++YYCURSOR; + switch (yych) { + case 'y': goto yy96; + default: goto yy33; + } +yy71: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: + yyt2 = yyt3 = NULL; + goto yy97; + case '_': + yyt3 = YYCURSOR; + goto yy99; + default: goto yy33; + } +yy72: + yych = *++YYCURSOR; + switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': goto yy72; + case '_': goto yy101; + default: goto yy33; + } +yy74: + yych = *++YYCURSOR; + switch (yych) { + case 'e': + yyt1 = YYCURSOR; + goto yy102; + case 'm': + yyt1 = YYCURSOR; + goto yy103; + case 's': + yyt1 = YYCURSOR; + goto yy104; + default: goto yy33; + } +yy75: + yych = *++YYCURSOR; + switch (yych) { + case 'y': goto yy105; + default: goto yy33; + } +yy76: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy106; + default: goto yy33; + } +yy77: + yych = *++YYCURSOR; + switch (yych) { + case 'i': goto yy107; + default: goto yy33; + } +yy78: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy107; + default: goto yy33; + } +yy79: + yych = *++YYCURSOR; + switch (yych) { + case 'h': goto yy47; + default: goto yy33; + } +yy80: + yych = *++YYCURSOR; + switch (yych) { + case 'p': goto yy108; + default: goto yy33; + } +yy81: + yych = *++YYCURSOR; + switch (yych) { + case 'n': goto yy109; + default: goto yy33; + } +yy82: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: + yyt2 = yyt3 = NULL; + goto yy110; + case '_': + yyt3 = YYCURSOR; + goto yy112; + default: goto yy33; + } +yy83: + yych = *++YYCURSOR; + switch (yych) { + case '_': goto yy114; + default: goto yy33; + } +yy84: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy115; + default: goto yy33; + } +yy85: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy116; + default: goto yy33; + } +yy86: + yych = *++YYCURSOR; + switch (yych) { + case 'p': goto yy117; + default: goto yy33; + } +yy87: + yych = *++YYCURSOR; + switch (yych) { + case 'f': goto yy118; + default: goto yy33; + } +yy88: + yych = *++YYCURSOR; + switch (yych) { + case 'w': goto yy119; + default: goto yy33; + } +yy89: + yych = *++YYCURSOR; + switch (yych) { + case 'r': goto yy120; + default: goto yy33; + } +yy90: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy121; + default: goto yy33; + } +yy91: + yych = *++YYCURSOR; + switch (yych) { + case 'y': goto yy122; + default: goto yy33; + } +yy92: + ++YYCURSOR; + yynmatch = 2; + yypmatch[2] = yyt1; + yypmatch[0] = yyt1 - 4; + yypmatch[1] = YYCURSOR; + yypmatch[3] = YYCURSOR - 1; +#line 136 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("fil1_", group(1)); + goto end_region; + } +#line 735 "src/sfizz/OpcodeCleanup.cpp" +yy94: + yych = *++YYCURSOR; +yy95: + if (yych <= 0x00) goto yy92; + goto yy94; +yy96: + yych = *++YYCURSOR; + switch (yych) { + case 'p': goto yy123; + default: goto yy33; + } +yy97: + ++YYCURSOR; + yynmatch = 2; + yypmatch[0] = yyt1; + yypmatch[2] = yyt3; + yypmatch[3] = yyt2; + yypmatch[1] = YYCURSOR; +#line 122 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("volume", group(1)); + goto end_region; + } +#line 759 "src/sfizz/OpcodeCleanup.cpp" +yy99: + yych = *++YYCURSOR; + if (yych <= 0x00) { + yyt2 = YYCURSOR; + goto yy97; + } + goto yy99; +yy101: + yych = *++YYCURSOR; + switch (yych) { + case 'o': + yyt2 = YYCURSOR; + goto yy124; + case 'r': + yyt2 = YYCURSOR; + goto yy125; + case 's': + yyt2 = YYCURSOR; + goto yy126; + case 'w': + yyt2 = YYCURSOR; + goto yy127; + default: goto yy33; + } +yy102: + yych = *++YYCURSOR; + switch (yych) { + case 'n': goto yy128; + default: goto yy33; + } +yy103: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy129; + default: goto yy33; + } +yy104: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy130; + default: goto yy33; + } +yy105: + yych = *++YYCURSOR; + if (yych <= 0x00) goto yy131; + goto yy33; +yy106: + yych = *++YYCURSOR; + switch (yych) { + case 'd': goto yy133; + default: goto yy33; + } +yy107: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy134; + default: goto yy33; + } +yy108: + yych = *++YYCURSOR; + switch (yych) { + case 'h': goto yy135; + default: goto yy33; + } +yy109: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy136; + default: goto yy33; + } +yy110: + ++YYCURSOR; + yynmatch = 2; + yypmatch[0] = yyt1; + yypmatch[2] = yyt3; + yypmatch[3] = yyt2; + yypmatch[1] = YYCURSOR; +#line 126 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("pitch", group(1)); + goto end_region; + } +#line 842 "src/sfizz/OpcodeCleanup.cpp" +yy112: + yych = *++YYCURSOR; + if (yych <= 0x00) { + yyt2 = YYCURSOR; + goto yy110; + } + goto yy112; +yy114: + yych = *++YYCURSOR; + switch (yych) { + case 'a': + yyt2 = YYCURSOR; + goto yy137; + case 'd': + yyt2 = YYCURSOR; + goto yy138; + case 'h': + yyt2 = YYCURSOR; + goto yy139; + case 'r': + yyt2 = YYCURSOR; + goto yy140; + case 's': + yyt2 = YYCURSOR; + goto yy141; + default: goto yy33; + } +yy115: + yych = *++YYCURSOR; + switch (yych) { + case '_': goto yy142; + default: goto yy33; + } +yy116: + yych = *++YYCURSOR; + switch (yych) { + case 'w': goto yy143; + default: goto yy33; + } +yy117: + yych = *++YYCURSOR; + if (yych <= 0x00) goto yy144; + goto yy33; +yy118: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: + yyt2 = yyt3 = NULL; + goto yy146; + case '_': + yyt3 = YYCURSOR; + goto yy148; + default: goto yy33; + } +yy119: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy150; + default: goto yy33; + } +yy120: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy151; + default: goto yy33; + } +yy121: + yych = *++YYCURSOR; + switch (yych) { + case 'i': goto yy152; + default: goto yy33; + } +yy122: + yych = *++YYCURSOR; + switch (yych) { + case 'p': goto yy153; + default: goto yy33; + } +yy123: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy154; + default: goto yy33; + } +yy124: + yych = *++YYCURSOR; + switch (yych) { + case 'f': goto yy155; + default: goto yy33; + } +yy125: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy156; + default: goto yy33; + } +yy126: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy157; + default: goto yy33; + } +yy127: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy158; + default: goto yy33; + } +yy128: + yych = *++YYCURSOR; + switch (yych) { + case 'd': goto yy159; + default: goto yy33; + } +yy129: + yych = *++YYCURSOR; + switch (yych) { + case 'd': goto yy160; + default: goto yy33; + } +yy130: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy161; + default: goto yy33; + } +yy131: + ++YYCURSOR; + yynmatch = 2; + yypmatch[2] = yyt1; + yypmatch[0] = yyt1 - 3; + yypmatch[1] = YYCURSOR; + yypmatch[3] = YYCURSOR - 1; +#line 100 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("off_", group(1)); + goto end_region; + } +#line 981 "src/sfizz/OpcodeCleanup.cpp" +yy133: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy105; + default: goto yy33; + } +yy134: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy162; + default: goto yy33; + } +yy135: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy163; + default: goto yy33; + } +yy136: + yych = *++YYCURSOR; + switch (yych) { + case 'n': goto yy164; + default: goto yy33; + } +yy137: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy165; + default: goto yy33; + } +yy138: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy166; + default: goto yy33; + } +yy139: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy167; + default: goto yy33; + } +yy140: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy168; + default: goto yy33; + } +yy141: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy169; + case 'u': goto yy170; + default: goto yy33; + } +yy142: + yych = *++YYCURSOR; + switch (yych) { + case 'd': + yyt2 = YYCURSOR; + goto yy171; + case 'f': + yyt2 = YYCURSOR; + goto yy172; + default: goto yy33; + } +yy143: + yych = *++YYCURSOR; + switch (yych) { + case 'n': goto yy117; + default: goto yy33; + } +yy144: + ++YYCURSOR; + yynmatch = 2; + yypmatch[2] = yyt1; + yypmatch[0] = yyt1 - 4; + yypmatch[1] = YYCURSOR; + yypmatch[3] = YYCURSOR - 1; +#line 104 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("bend_", group(1)); + goto end_region; + } +#line 1066 "src/sfizz/OpcodeCleanup.cpp" +yy146: + ++YYCURSOR; + yynmatch = 2; + yypmatch[0] = yyt1; + yypmatch[2] = yyt3; + yypmatch[3] = yyt2; + yypmatch[1] = YYCURSOR; +#line 140 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("cutoff1", group(1)); + goto end_region; + } +#line 1079 "src/sfizz/OpcodeCleanup.cpp" +yy148: + yych = *++YYCURSOR; + if (yych <= 0x00) { + yyt2 = YYCURSOR; + goto yy146; + } + goto yy148; +yy150: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy173; + default: goto yy33; + } +yy151: + yych = *++YYCURSOR; + switch (yych) { + case 'q': goto yy119; + default: goto yy33; + } +yy152: + yych = *++YYCURSOR; + switch (yych) { + case 'n': goto yy119; + default: goto yy33; + } +yy153: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy174; + default: goto yy33; + } +yy154: + yych = *++YYCURSOR; + if (yych <= 0x00) goto yy175; + goto yy33; +yy155: + yych = *++YYCURSOR; + switch (yych) { + case 'f': goto yy177; + default: goto yy33; + } +yy156: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy178; + default: goto yy33; + } +yy157: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy179; + default: goto yy33; + } +yy158: + yych = *++YYCURSOR; + switch (yych) { + case 'v': goto yy180; + default: goto yy33; + } +yy159: + yych = *++YYCURSOR; + if (yych <= 0x00) goto yy181; + goto yy33; +yy160: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy159; + default: goto yy33; + } +yy161: + yych = *++YYCURSOR; + switch (yych) { + case 'r': goto yy183; + default: goto yy33; + } +yy162: + yych = *++YYCURSOR; + switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + yyt1 = YYCURSOR; + goto yy184; + default: goto yy33; + } +yy163: + yych = *++YYCURSOR; + switch (yych) { + case 'n': goto yy186; + default: goto yy33; + } +yy164: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy187; + default: goto yy33; + } +yy165: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy188; + default: goto yy33; + } +yy166: + yych = *++YYCURSOR; + switch (yych) { + case 'c': + case 'l': goto yy189; + default: goto yy33; + } +yy167: + yych = *++YYCURSOR; + switch (yych) { + case 'l': goto yy190; + default: goto yy33; + } +yy168: + yych = *++YYCURSOR; + switch (yych) { + case 'l': goto yy191; + default: goto yy33; + } +yy169: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy192; + default: goto yy33; + } +yy170: + yych = *++YYCURSOR; + switch (yych) { + case 's': goto yy193; + default: goto yy33; + } +yy171: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy194; + default: goto yy33; + } +yy172: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy195; + case 'r': goto yy196; + default: goto yy33; + } +yy173: + yych = *++YYCURSOR; + switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + yyt3 = YYCURSOR; + goto yy197; + default: goto yy33; + } +yy174: + yych = *++YYCURSOR; + if (yych <= 0x00) goto yy199; + goto yy33; +yy175: + ++YYCURSOR; + yynmatch = 1; + yypmatch[0] = YYCURSOR - 8; + yypmatch[1] = YYCURSOR; +#line 108 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("fil1_type"); + goto end_region; + } +#line 1265 "src/sfizz/OpcodeCleanup.cpp" +yy177: + yych = *++YYCURSOR; + switch (yych) { + case 's': goto yy201; + default: goto yy33; + } +yy178: + yych = *++YYCURSOR; + switch (yych) { + case 'i': goto yy202; + default: goto yy33; + } +yy179: + yych = *++YYCURSOR; + switch (yych) { + case 'l': goto yy180; + default: goto yy33; + } +yy180: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy203; + default: goto yy33; + } +yy181: + ++YYCURSOR; + yynmatch = 2; + yypmatch[2] = yyt1; + yypmatch[0] = yyt1 - 4; + yypmatch[1] = YYCURSOR; + yypmatch[3] = YYCURSOR - 1; +#line 96 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("loop_", group(1)); + goto end_region; + } +#line 1302 "src/sfizz/OpcodeCleanup.cpp" +yy183: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy159; + default: goto yy33; + } +yy184: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: goto yy204; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': goto yy184; + default: goto yy33; + } +yy186: + yych = *++YYCURSOR; + switch (yych) { + case 'y': goto yy206; + default: goto yy33; + } +yy187: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy207; + default: goto yy33; + } +yy188: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy208; + default: goto yy33; + } +yy189: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy209; + default: goto yy33; + } +yy190: + yych = *++YYCURSOR; + switch (yych) { + case 'd': goto yy210; + default: goto yy33; + } +yy191: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy211; + default: goto yy33; + } +yy192: + yych = *++YYCURSOR; + switch (yych) { + case 'r': goto yy212; + default: goto yy33; + } +yy193: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy213; + default: goto yy33; + } +yy194: + yych = *++YYCURSOR; + switch (yych) { + case 'p': goto yy214; + default: goto yy33; + } +yy195: + yych = *++YYCURSOR; + switch (yych) { + case 'd': goto yy215; + default: goto yy33; + } +yy196: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy216; + default: goto yy33; + } +yy197: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: goto yy217; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': goto yy197; + default: goto yy33; + } +yy199: + ++YYCURSOR; + yynmatch = 2; + yypmatch[2] = yyt1; + yypmatch[0] = yyt1 - 3; + yypmatch[1] = YYCURSOR; + yypmatch[3] = YYCURSOR - 5; +#line 112 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("fil", group(1), "_type"); + goto end_region; + } +#line 1419 "src/sfizz/OpcodeCleanup.cpp" +yy201: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy219; + default: goto yy33; + } +yy202: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy203; + default: goto yy33; + } +yy203: + yych = *++YYCURSOR; + if (yych <= 0x00) goto yy220; + goto yy33; +yy204: + ++YYCURSOR; + yynmatch = 3; + yypmatch[4] = yyt1; + yypmatch[0] = yyt1 - 7; + yypmatch[1] = YYCURSOR; + yypmatch[2] = yyt1 - 4; + yypmatch[3] = yyt1 - 2; + yypmatch[5] = YYCURSOR - 1; +#line 131 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("start_", group(1), "cc", group(2)); + goto end_region; + } +#line 1450 "src/sfizz/OpcodeCleanup.cpp" +yy206: + yych = *++YYCURSOR; + switch (yych) { + case '_': goto yy222; + default: goto yy33; + } +yy207: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: + yyt2 = yyt3 = NULL; + goto yy223; + case '_': + yyt3 = YYCURSOR; + goto yy225; + default: goto yy33; + } +yy208: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy227; + default: goto yy33; + } +yy209: + yych = *++YYCURSOR; + switch (yych) { + case 'y': goto yy210; + default: goto yy33; + } +yy210: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy228; + default: goto yy33; + } +yy211: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy229; + default: goto yy33; + } +yy212: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy210; + default: goto yy33; + } +yy213: + yych = *++YYCURSOR; + switch (yych) { + case 'a': goto yy230; + default: goto yy33; + } +yy214: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy231; + default: goto yy33; + } +yy215: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy232; + default: goto yy33; + } +yy216: + yych = *++YYCURSOR; + switch (yych) { + case 'q': goto yy232; + default: goto yy33; + } +yy217: + ++YYCURSOR; + yynmatch = 4; + yypmatch[2] = yyt1; + yypmatch[4] = yyt2; + yypmatch[6] = yyt3; + yypmatch[0] = yyt1; + yypmatch[1] = YYCURSOR; + yypmatch[3] = yyt2 - 1; + yypmatch[5] = yyt3 - 2; + yypmatch[7] = YYCURSOR - 1; +#line 87 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat(group(1), "_", group(2), "_oncc", group(3)); + goto end_region; + } +#line 1538 "src/sfizz/OpcodeCleanup.cpp" +yy219: + yych = *++YYCURSOR; + switch (yych) { + case 't': goto yy203; + default: goto yy33; + } +yy220: + ++YYCURSOR; + yynmatch = 3; + yypmatch[2] = yyt1; + yypmatch[4] = yyt2; + yypmatch[0] = yyt1; + yypmatch[1] = YYCURSOR; + yypmatch[3] = yyt2 - 1; + yypmatch[5] = YYCURSOR - 1; +#line 91 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat(group(1), "_", group(2), "1"); + goto end_region; + } +#line 1559 "src/sfizz/OpcodeCleanup.cpp" +yy222: + yych = *++YYCURSOR; + switch (yych) { + case 'g': goto yy233; + default: goto yy33; + } +yy223: + ++YYCURSOR; + yynmatch = 2; + yypmatch[0] = yyt1; + yypmatch[2] = yyt3; + yypmatch[3] = yyt2; + yypmatch[1] = YYCURSOR; +#line 144 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat("resonance1", group(1)); + goto end_region; + } +#line 1578 "src/sfizz/OpcodeCleanup.cpp" +yy225: + yych = *++YYCURSOR; + if (yych <= 0x00) { + yyt2 = YYCURSOR; + goto yy223; + } + goto yy225; +yy227: + yych = *++YYCURSOR; + switch (yych) { + case 'k': goto yy210; + default: goto yy33; + } +yy228: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy234; + default: goto yy33; + } +yy229: + yych = *++YYCURSOR; + switch (yych) { + case 's': goto yy235; + default: goto yy33; + } +yy230: + yych = *++YYCURSOR; + switch (yych) { + case 'i': goto yy236; + default: goto yy33; + } +yy231: + yych = *++YYCURSOR; + switch (yych) { + case 'h': goto yy232; + default: goto yy33; + } +yy232: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy237; + default: goto yy33; + } +yy233: + yych = *++YYCURSOR; + switch (yych) { + case 'r': goto yy238; + default: goto yy33; + } +yy234: + yych = *++YYCURSOR; + switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + yyt3 = YYCURSOR; + goto yy239; + default: goto yy33; + } +yy235: + yych = *++YYCURSOR; + switch (yych) { + case 'e': goto yy210; + default: goto yy33; + } +yy236: + yych = *++YYCURSOR; + switch (yych) { + case 'n': goto yy210; + default: goto yy33; + } +yy237: + yych = *++YYCURSOR; + switch (yych) { + case 'c': goto yy241; + default: goto yy33; + } +yy238: + yych = *++YYCURSOR; + switch (yych) { + case 'o': goto yy242; + default: goto yy33; + } +yy239: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: goto yy243; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': goto yy239; + default: goto yy33; + } +yy241: + yych = *++YYCURSOR; + switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + yyt3 = YYCURSOR; + goto yy245; + default: goto yy33; + } +yy242: + yych = *++YYCURSOR; + switch (yych) { + case 'u': goto yy247; + default: goto yy33; + } +yy243: + ++YYCURSOR; + yynmatch = 4; + yypmatch[2] = yyt1; + yypmatch[4] = yyt2; + yypmatch[6] = yyt3; + yypmatch[0] = yyt1; + yypmatch[1] = YYCURSOR; + yypmatch[3] = yyt2 - 1; + yypmatch[5] = yyt3 - 2; + yypmatch[7] = YYCURSOR - 1; +#line 83 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat(group(1), "_", group(2), "_oncc", group(3)); + goto end_region; + } +#line 1724 "src/sfizz/OpcodeCleanup.cpp" +yy245: + yych = *++YYCURSOR; + switch (yych) { + case 0x00: goto yy248; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': goto yy245; + default: goto yy33; + } +yy247: + yych = *++YYCURSOR; + switch (yych) { + case 'p': goto yy250; + default: goto yy33; + } +yy248: + ++YYCURSOR; + yynmatch = 4; + yypmatch[2] = yyt1; + yypmatch[4] = yyt2; + yypmatch[6] = yyt3; + yypmatch[0] = yyt1; + yypmatch[1] = YYCURSOR; + yypmatch[3] = yyt2 - 1; + yypmatch[5] = yyt3 - 2; + yypmatch[7] = YYCURSOR - 1; +#line 79 "src/sfizz/OpcodeCleanup.re" + { + opcode = absl::StrCat(group(1), "_", group(2), "_oncc", group(3)); + goto end_region; + } +#line 1763 "src/sfizz/OpcodeCleanup.cpp" +yy250: + yych = *++YYCURSOR; + if (yych >= 0x01) goto yy33; + ++YYCURSOR; + yynmatch = 1; + yypmatch[0] = YYCURSOR - 16; + yypmatch[1] = YYCURSOR; +#line 117 "src/sfizz/OpcodeCleanup.re" + { + opcode = "group"; + goto end_region; + } +#line 1776 "src/sfizz/OpcodeCleanup.cpp" +} +#line 153 "src/sfizz/OpcodeCleanup.re" + + +end_region: + /* end */; + + } // scope == kOpcodeScopeRegion + + //-------------------------------------------------------------------------- + + #undef YYMAXNMATCH + + return opcode; +} + +Opcode Opcode::cleanUp(OpcodeScope scope) const +{ + return Opcode(cleanUpOpcodeName(opcode, scope), value); +} + +} // namespace sfz diff --git a/src/sfizz/OpcodeCleanup.re b/src/sfizz/OpcodeCleanup.re new file mode 100644 index 00000000..05305bff --- /dev/null +++ b/src/sfizz/OpcodeCleanup.re @@ -0,0 +1,172 @@ +/* -*- mode: c++; -*- */ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +#include "Opcode.h" +#include "absl/strings/string_view.h" +#include "absl/strings/str_cat.h" +#include + +namespace sfz { + +static std::string cleanUpOpcodeName(absl::string_view rawOpcode, OpcodeScope scope) +{ + std::string opcode { rawOpcode }; + + /*!re2c + re2c:flags:posix-captures = 1; + re2c:define:YYCTYPE = char; + re2c:yyfill:enable = 0; + */ + /*!maxnmatch:re2c*/ + + const char* YYCURSOR; + const char* YYMARKER; + const char* yypmatch[2 * YYMAXNMATCH]; + size_t yynmatch; + + /*!stags:re2c format = "const char* @@; "; */ + + auto group = [&yypmatch](size_t i) -> absl::string_view { + const char *beg = yypmatch[2 * i]; + const char *end = yypmatch[2 * i + 1]; + return absl::string_view(beg, end - beg); + }; + + /*!re2c + digit = [0-9]; + number = digit+; + any = [^\x00]*; + END = [\x00]; + */ + + //-------------------------------------------------------------------------- + + YYCURSOR = opcode.c_str(); + + /*!re2c + + (any) "_cc" (number) END { + opcode = absl::StrCat(group(1), "_oncc", group(2)); + goto end_generic; + } + + * { + goto end_generic; + } + + */ + +end_generic: + /* end */; + + //-------------------------------------------------------------------------- + + if (scope == kOpcodeScopeRegion) { + + YYCURSOR = opcode.c_str(); + + /*!re2c + + lfoV1 = "amplfo"|"fillfo"|"pitchlfo"; + egV1 = "ampeg"|"fileg"|"pitcheg"; + eqV1 = "eq" number; + lfoV2 = "lfo" number; + + (lfoV1) "_" ("depth"|"freq"|"fade") "cc" (number) END { + opcode = absl::StrCat(group(1), "_", group(2), "_oncc", group(3)); + goto end_region; + } + (egV1) "_" ("delay"|"start"|"attack"|"hold"|"decay"|"sustain"|"release") "cc" (number) END { + opcode = absl::StrCat(group(1), "_", group(2), "_oncc", group(3)); + goto end_region; + } + (eqV1) "_" ("bw"|"freq"|"gain") "cc" (number) END { + opcode = absl::StrCat(group(1), "_", group(2), "_oncc", group(3)); + goto end_region; + } + (lfoV2) "_" ("wave"|"offset"|"ratio"|"scale") END { + opcode = absl::StrCat(group(1), "_", group(2), "1"); + goto end_region; + } + + "loop" ("mode"|"start"|"end") END { + opcode = absl::StrCat("loop_", group(1)); + goto end_region; + } + "off" ("by"|"mode") END { + opcode = absl::StrCat("off_", group(1)); + goto end_region; + } + "bend" ("up"|"down") END { + opcode = absl::StrCat("bend_", group(1)); + goto end_region; + } + "filtype" END { + opcode = absl::StrCat("fil1_type"); + goto end_region; + } + "fil" (number) "type" END { + opcode = absl::StrCat("fil", group(1), "_type"); + goto end_region; + } + + "polyphony_group" END { + opcode = "group"; + goto end_region; + } + + "gain" ("_" any)? END { + opcode = absl::StrCat("volume", group(1)); + goto end_region; + } + "tune" ("_" any)? END { + opcode = absl::StrCat("pitch", group(1)); + goto end_region; + } + + "on_" ("hi"|"lo") "cc" (number) END { + opcode = absl::StrCat("start_", group(1), "cc", group(2)); + goto end_region; + } + + "fil_" (any) END { + opcode = absl::StrCat("fil1_", group(1)); + goto end_region; + } + "cutoff" ("_" any)? END { + opcode = absl::StrCat("cutoff1", group(1)); + goto end_region; + } + "resonance" ("_" any)? END { + opcode = absl::StrCat("resonance1", group(1)); + goto end_region; + } + + * { + goto end_region; + } + + */ + +end_region: + /* end */; + + } // scope == kOpcodeScopeRegion + + //-------------------------------------------------------------------------- + + #undef YYMAXNMATCH + + return opcode; +} + +Opcode Opcode::cleanUp(OpcodeScope scope) const +{ + return Opcode(cleanUpOpcodeName(opcode, scope), value); +} + +} // namespace sfz diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index 117a6d26..965b9745 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -31,8 +31,10 @@ bool extendIfNecessary(std::vector& vec, unsigned size, unsigned defaultCapac return true; } -bool sfz::Region::parseOpcode(const Opcode& opcode) +bool sfz::Region::parseOpcode(const Opcode& rawOpcode) { + const Opcode opcode = rawOpcode.cleanUp(kOpcodeScopeRegion); + switch (opcode.lettersOnlyHash) { // Sound source: sample playback case hash("sample"): @@ -65,7 +67,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("offset_random"): setValueFromOpcode(opcode, offsetRandom, Default::offsetRange); break; - case hash("offset_cc&"): + case hash("offset_oncc&"): // also offset_cc& if (opcode.parameters.back() > config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::offsetCCRange)) @@ -77,8 +79,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("count"): setValueFromOpcode(opcode, sampleCount, Default::sampleCountRange); break; - case hash("loopmode"): // fallthrough - case hash("loop_mode"): + case hash("loop_mode"): // also loopmode switch (hash(opcode.value)) { case hash("no_loop"): loopMode = SfzLoopMode::no_loop; @@ -96,12 +97,10 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) DBG("Unkown loop mode:" << std::string(opcode.value)); } break; - case hash("loopend"): // fallthrough - case hash("loop_end"): + case hash("loop_end"): // also loopend setRangeEndFromOpcode(opcode, loopRange, Default::loopRange); break; - case hash("loopstart"): // fallthrough - case hash("loop_start"): + case hash("loop_start"): // also loopstart setRangeStartFromOpcode(opcode, loopRange, Default::loopRange); break; @@ -121,15 +120,13 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) break; // Instrument settings: voice lifecycle - case hash("group"): // fallthrough - case hash("polyphony_group"): + case hash("group"): // also polyphony_group setValueFromOpcode(opcode, group, Default::groupRange); break; - case hash("offby"): // fallthrough - case hash("off_by"): + case hash("off_by"): // also offby setValueFromOpcode(opcode, offBy, Default::groupRange); break; - case hash("off_mode"): + case hash("off_mode"): // also offmode switch (hash(opcode.value)) { case hash("fast"): offMode = SfzOffMode::fast; @@ -292,15 +289,13 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) DBG("Unknown trigger mode: " << std::string(opcode.value)); } break; - case hash("on_locc&"): // fallthrough - case hash("start_locc&"): + case hash("start_locc&"): // also on_locc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::midi7Range)) ccTriggers[opcode.parameters.back()].setStart(normalizeCC(*value)); break; - case hash("on_hicc&"): // fallthrough - case hash("start_hicc&"): + case hash("start_hicc&"): // also on_hicc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::midi7Range)) @@ -308,30 +303,28 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) break; // Performance parameters: amplifier - case hash("volume"): + case hash("volume"): // also gain setValueFromOpcode(opcode, volume, Default::volumeRange); break; - case hash("volume_curvecc&"): + case hash("volume_curvecc&"): // also gain_curvecc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::curveCCRange)) volumeCC[opcode.parameters.back()].curve = *value; break; - case hash("volume_stepcc&"): + case hash("volume_stepcc&"): // also gain_stepcc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::volumeStepRange)) volumeCC[opcode.parameters.back()].step = *value; break; - case hash("volume_smoothcc&"): + case hash("volume_smoothcc&"): // also gain_smoothcc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::smoothCCRange)) volumeCC[opcode.parameters.back()].smooth = *value; break; - case hash("gain_cc&"): - case hash("gain_oncc&"): // fallthrough - case hash("volume_oncc&"): + case hash("volume_oncc&"): // also gain_oncc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::volumeCCRange)) @@ -359,8 +352,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) if (auto value = readOpcode(opcode.value, Default::smoothCCRange)) amplitudeCC[opcode.parameters.back()].smooth = *value; break; - case hash("amplitude_cc&"): // fallthrough - case hash("amplitude_oncc&"): + case hash("amplitude_oncc&"): // also amplitude_cc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::amplitudeRange)) @@ -388,8 +380,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) if (auto value = readOpcode(opcode.value, Default::smoothCCRange)) panCC[opcode.parameters.back()].smooth = *value; break; - case hash("pan_cc&"): - case hash("pan_oncc&"): + case hash("pan_oncc&"): // also pan_cc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::panCCRange)) @@ -417,8 +408,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) if (auto value = readOpcode(opcode.value, Default::smoothCCRange)) positionCC[opcode.parameters.back()].smooth = *value; break; - case hash("position_cc&"): // fallthrough - case hash("position_oncc&"): + case hash("position_oncc&"): // also position_cc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::positionCCRange)) @@ -567,8 +557,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) break; // Performance parameters: filters - case hash("cutoff"): // fallthrough - case hash("cutoff&"): + case hash("cutoff&"): // also cutoff { const auto filterIndex = opcode.parameters.empty() ? 0 : (opcode.parameters.back() - 1); if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) @@ -576,8 +565,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) setValueFromOpcode(opcode, filters[filterIndex].cutoff, Default::filterCutoffRange); } break; - case hash("resonance"): // fallthrough - case hash("resonance&"): + case hash("resonance&"): // also resonance { const auto filterIndex = opcode.parameters.empty() ? 0 : (opcode.parameters.back() - 1); if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) @@ -585,12 +573,9 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) setValueFromOpcode(opcode, filters[filterIndex].resonance, Default::filterResonanceRange); } break; - case hash("cutoff_oncc&"): - case hash("cutoff_cc&"): - case hash("cutoff&_oncc&"): // fallthrough - case hash("cutoff&_cc&"): + case hash("cutoff&_oncc&"): // also cutoff_oncc&, cutoff_cc&, cutoff&_cc& { - const auto filterIndex = opcode.parameters.size() == 1 ? 0 : (opcode.parameters.front() - 1); + const auto filterIndex = opcode.parameters.front() - 1; if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; @@ -601,12 +586,9 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) ); } break; - case hash("resonance&_oncc&"): - case hash("resonance&_cc&"): - case hash("resonance_oncc&"): // fallthrough - case hash("resonance_cc&"): + case hash("resonance&_oncc&"): // also resonance_oncc&, resonance_cc&, resonance&_cc& { - const auto filterIndex = opcode.parameters.size() == 1 ? 0 : (opcode.parameters.front() - 1); + const auto filterIndex = opcode.parameters.front() - 1; if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; @@ -617,60 +599,54 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) ); } break; - case hash("fil_keytrack"): // fallthrough - case hash("fil&_keytrack"): + case hash("fil&_keytrack"): // also fil_keytrack { - const auto filterIndex = opcode.parameters.empty() ? 0 : (opcode.parameters.front() - 1); + const auto filterIndex = opcode.parameters.front() - 1; if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].keytrack, Default::filterKeytrackRange); } break; - case hash("fil_keycenter"): // fallthrough - case hash("fil&_keycenter"): + case hash("fil&_keycenter"): // also fil_keycenter { - const auto filterIndex = opcode.parameters.empty() ? 0 : (opcode.parameters.front() - 1); + const auto filterIndex = opcode.parameters.front() - 1; if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].keycenter, Default::keyRange); } break; - case hash("fil_veltrack"): // fallthrough - case hash("fil&_veltrack"): + case hash("fil&_veltrack"): // also fil_veltrack { - const auto filterIndex = opcode.parameters.empty() ? 0 : (opcode.parameters.front() - 1); + const auto filterIndex = opcode.parameters.front() - 1; if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].veltrack, Default::filterVeltrackRange); } break; - case hash("fil_random"): // fallthrough - case hash("fil&_random"): + case hash("fil&_random"): // also fil_random { - const auto filterIndex = opcode.parameters.empty() ? 0 : (opcode.parameters.front() - 1); + const auto filterIndex = opcode.parameters.front() - 1; if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].random, Default::filterRandomRange); } break; - case hash("fil_gain"): // fallthrough - case hash("fil&_gain"): + case hash("fil&_gain"): // also fil_gain { - const auto filterIndex = opcode.parameters.empty() ? 0 : (opcode.parameters.front() - 1); + const auto filterIndex = opcode.parameters.front() - 1; if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].gain, Default::filterGainRange); } break; - case hash("fil_gaincc&"): // fallthrough - case hash("fil&_gaincc&"): + case hash("fil&_gain_oncc&"): // also fil_gain_oncc& { - const auto filterIndex = opcode.parameters.size() == 1 ? 0 : (opcode.parameters.front() - 1); + const auto filterIndex = opcode.parameters.front() - 1; if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; @@ -681,10 +657,9 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) ); } break; - case hash("fil_type"): // fallthrough - case hash("fil&_type"): + case hash("fil&_type"): // also fil_type, filtype { - const auto filterIndex = opcode.parameters.empty() ? 0 : (opcode.parameters.front() - 1); + const auto filterIndex = opcode.parameters.front() - 1; if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; @@ -710,8 +685,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) setValueFromOpcode(opcode, equalizers[eqNumber - 1].bandwidth, Default::eqBandwidthRange); } break; - case hash("eq&_bw_oncc&"): // fallthrough - case hash("eq&_bwcc&"): + case hash("eq&_bw_oncc&"): // also eq&_bwcc& { const auto eqNumber = opcode.parameters.front(); if (eqNumber == 0) @@ -732,8 +706,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) setValueFromOpcode(opcode, equalizers[eqNumber - 1].frequency, Default::eqFrequencyRange); } break; - case hash("eq&_freq_oncc&"): // fallthrough - case hash("eq&_freqcc&"): + case hash("eq&_freq_oncc&"): // also eq&_freqcc& { const auto eqNumber = opcode.parameters.front(); if (eqNumber == 0) @@ -767,8 +740,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) setValueFromOpcode(opcode, equalizers[eqNumber - 1].gain, Default::eqGainRange); } break; - case hash("eq&_gain_oncc&"): // fallthrough - case hash("eq&_gaincc&"): + case hash("eq&_gain_oncc&"): // also eq&_gaincc& { const auto eqNumber = opcode.parameters.front(); if (eqNumber == 0) @@ -827,44 +799,37 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("transpose"): setValueFromOpcode(opcode, transpose, Default::transposeRange); break; - case hash("tune"): // fallthrough - case hash("pitch"): + case hash("pitch"): // also tune setValueFromOpcode(opcode, tune, Default::tuneRange); break; - case hash("pitch_curvecc&"): // fallthrough - case hash("tune_curvecc&"): + case hash("pitch_curvecc&"): // also tune_curvecc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::curveCCRange)) tuneCC[opcode.parameters.back()].curve = *value; break; - case hash("pitch_stepcc&"): // fallthrough - case hash("tune_stepcc&"): + case hash("pitch_stepcc&"): // also tune_stepcc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::tuneStepRange)) tuneCC[opcode.parameters.back()].step = *value; break; - case hash("pitch_smoothcc&"): // fallthrough - case hash("tune_smoothcc&"): + case hash("pitch_smoothcc&"): // also tune_smoothcc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::smoothCCRange)) tuneCC[opcode.parameters.back()].smooth = *value; break; - case hash("tune_cc&"): - case hash("tune_oncc&"): - case hash("pitch_cc&"): - case hash("pitch_oncc&"): + case hash("pitch_oncc&"): // also pitch_cc&, tune_cc&, tune_oncc& if (opcode.parameters.back() >= config::numCCs) return false; if (auto value = readOpcode(opcode.value, Default::tuneCCRange)) tuneCC[opcode.parameters.back()].value = *value; break; - case hash("bend_up"): + case hash("bend_up"): // also bendup setValueFromOpcode(opcode, bendUp, Default::bendBoundRange); break; - case hash("bend_down"): + case hash("bend_down"): // also benddown setValueFromOpcode(opcode, bendDown, Default::bendBoundRange); break; case hash("bend_step"): @@ -923,32 +888,25 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) return false; // Was not vel2... setValueFromOpcode(opcode, amplitudeEG.vel2sustain, Default::egOnCCPercentRange); break; - case hash("ampeg_attackcc&"): // fallthrough - case hash("ampeg_attack_oncc&"): + case hash("ampeg_attack_oncc&"): // also ampeg_attackcc& setCCPairFromOpcode(opcode, amplitudeEG.ccAttack, Default::egOnCCTimeRange); break; - case hash("ampeg_decaycc&"): // fallthrough - case hash("ampeg_decay_oncc&"): + case hash("ampeg_decay_oncc&"): // also ampeg_decaycc& setCCPairFromOpcode(opcode, amplitudeEG.ccDecay, Default::egOnCCTimeRange); break; - case hash("ampeg_delaycc&"): // fallthrough - case hash("ampeg_delay_oncc&"): + case hash("ampeg_delay_oncc&"): // also ampeg_delaycc& setCCPairFromOpcode(opcode, amplitudeEG.ccDelay, Default::egOnCCTimeRange); break; - case hash("ampeg_holdcc&"): // fallthrough - case hash("ampeg_hold_oncc&"): + case hash("ampeg_hold_oncc&"): // also ampeg_holdcc& setCCPairFromOpcode(opcode, amplitudeEG.ccHold, Default::egOnCCTimeRange); break; - case hash("ampeg_releasecc&"): // fallthrough - case hash("ampeg_release_oncc&"): + case hash("ampeg_release_oncc&"): // also ampeg_releasecc& setCCPairFromOpcode(opcode, amplitudeEG.ccRelease, Default::egOnCCTimeRange); break; - case hash("ampeg_startcc&"): // fallthrough - case hash("ampeg_start_oncc&"): + case hash("ampeg_start_oncc&"): // also ampeg_startcc& setCCPairFromOpcode(opcode, amplitudeEG.ccStart, Default::egOnCCPercentRange); break; - case hash("ampeg_sustaincc&"): // fallthrough - case hash("ampeg_sustain_oncc&"): + case hash("ampeg_sustain_oncc&"): // also ampeg_sustaincc& setCCPairFromOpcode(opcode, amplitudeEG.ccSustain, Default::egOnCCPercentRange); break; diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 66871fcc..e9797e8a 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -236,7 +236,7 @@ void sfz::Synth::handleControlOpcodes(const std::vector& members) } } -void sfz::Synth::handleEffectOpcodes(const std::vector& members) +void sfz::Synth::handleEffectOpcodes(const std::vector& rawMembers) { absl::string_view busName = "main"; @@ -252,6 +252,11 @@ void sfz::Synth::handleEffectOpcodes(const std::vector& members) return *bus; }; + std::vector members; + members.reserve(rawMembers.size()); + for (const Opcode& opcode : rawMembers) + members.push_back(opcode.cleanUp(kOpcodeScopeEffect)); + for (const Opcode& opcode : members) { switch (opcode.lettersOnlyHash) { case hash("bus"): diff --git a/tests/OpcodeT.cpp b/tests/OpcodeT.cpp index c45357ff..733a185c 100644 --- a/tests/OpcodeT.cpp +++ b/tests/OpcodeT.cpp @@ -158,3 +158,65 @@ TEST_CASE("[Opcode] Derived names") REQUIRE(sfz::Opcode("noise_level_smoothcc55", "").getDerivedName(sfz::kOpcodeStepCcN) == "noise_level_stepcc55"); REQUIRE(sfz::Opcode("sample", "").getDerivedName(sfz::kOpcodeSmoothCcN, 66) == "sample_smoothcc66"); } + +TEST_CASE("[Opcode] Normalization") +{ + REQUIRE(sfz::Opcode("foo_cc7", "").cleanUp(sfz::kOpcodeScopeGeneric).opcode == "foo_oncc7"); + REQUIRE(sfz::Opcode("foo_cc7", "").cleanUp(sfz::kOpcodeScopeRegion).opcode == "foo_oncc7"); + + static const std::pair regionSpecific[] = { + // LFO SFZv1 + {"amplfo_depthcc1", "amplfo_depth_oncc1"}, + {"fillfo_freqcc2", "fillfo_freq_oncc2"}, + {"pitchlfo_fadecc3", "pitchlfo_fade_oncc3"}, + // EG SFZv1 + {"ampeg_delaycc4", "ampeg_delay_oncc4"}, + {"fileg_startcc5", "fileg_start_oncc5"}, + {"pitcheg_attackcc6", "pitcheg_attack_oncc6"}, + {"ampeg_holdcc7", "ampeg_hold_oncc7"}, + {"fileg_decaycc8", "fileg_decay_oncc8"}, + {"pitcheg_sustaincc9", "pitcheg_sustain_oncc9"}, + {"ampeg_releasecc10", "ampeg_release_oncc10"}, + // EQ SFZv1 + {"eq11_bwcc12", "eq11_bw_oncc12"}, + {"eq13_freqcc14", "eq13_freq_oncc14"}, + {"eq15_gaincc16", "eq15_gain_oncc16"}, + // LFO SFZv2 + {"lfo17_wave", "lfo17_wave1"}, + {"lfo18_offset", "lfo18_offset1"}, + {"lfo19_ratio", "lfo19_ratio1"}, + {"lfo20_scale", "lfo20_scale1"}, + // LinuxSampler aliases + {"loopmode", "loop_mode"}, + {"loopstart", "loop_start"}, + {"loopend", "loop_end"}, + {"offby", "off_by"}, + {"offmode", "off_mode"}, + {"bendup", "bend_up"}, + {"benddown", "bend_down"}, + {"filtype", "fil1_type"}, + {"fil21type", "fil21_type"}, + // ARIA aliases + {"polyphony_group", "group"}, + {"gain", "volume"}, + {"gain_foobar", "volume_foobar"}, + {"tune", "pitch"}, + {"tune_foobar", "pitch_foobar"}, + // SFZv2 aliases + {"on_hicc22", "start_hicc22"}, + {"on_locc23", "start_locc23"}, + // Filter SFZv1 + {"fil_foobar", "fil1_foobar"}, + {"cutoff", "cutoff1"}, + {"cutoff_foobar", "cutoff1_foobar"}, + {"resonance", "resonance1"}, + {"resonance_foobar", "resonance1_foobar"}, + }; + + for (auto pair : regionSpecific) { + absl::string_view input = pair.first; + absl::string_view expected = pair.second; + REQUIRE(sfz::Opcode(input, "").cleanUp(sfz::kOpcodeScopeRegion).opcode == expected); + REQUIRE(sfz::Opcode(input, "").cleanUp(sfz::kOpcodeScopeGeneric).opcode == input); + } +} diff --git a/tests/RegionT.cpp b/tests/RegionT.cpp index fa73bd51..bce542c1 100644 --- a/tests/RegionT.cpp +++ b/tests/RegionT.cpp @@ -1199,7 +1199,7 @@ TEST_CASE("[Region] Parsing opcodes") region.parseOpcode({ "resonance3_cc24", "10" }); REQUIRE(region.filters[2].resonanceCC.contains(24)); REQUIRE(region.filters[2].resonanceCC[24] == 10); - region.parseOpcode({ "fil2_gaincc12", "-50" }); + region.parseOpcode({ "fil2_gain_oncc12", "-50" }); REQUIRE(region.filters[1].gainCC.contains(12)); REQUIRE(region.filters[1].gainCC[12] == -50.0f);