GithubHelp home page GithubHelp logo

atsushieno / mugene-ng Goto Github PK

View Code? Open in Web Editor NEW
7.0 3.0 0.0 1.22 MB

Music Macro Language to MIDI 1.0 / 2.0 compiler

License: MIT License

Kotlin 92.53% ANTLR 1.19% JavaScript 1.09% TypeScript 5.19%
mml midi music kotlin kotlin-multiplatform midi2

mugene-ng's Introduction

mugene-ng: mugene MML compiler, next-gen

maven repo

What is this?

This is the successor of my mugene Music Macro Language compiler to Kotlin Multiplatform (from C#), so that I can go forward and improve the entire ecosystem and toolchains. Now it can be used as a JVM library, native library, or a JavaScript library, as well as standalone native compiler or a JVM standalone jar.

The new version in Kotlin has preliminary support for MIDI 2.0 UMP stream format beyond the past C# version did. Any new features will be developed only in this project.

Everything, including the project name, is subject to change at this moment.

The entire language is partly documented as docs/UsersGuide.md.

Using mugene-ng as a library

mugene-ng is available at Maven Central. If you would like to use it as part of your application, add the following lines in the dependencies section in build.gradle(.kts):

dependencies {
    implementation "dev.atsushieno:mugene:+" // replace + with the actual version
}

Building and using command-line compiler

To use mugene-ng as command line compiler, at this state, you have to run a couple of Gradle tasks to build whatever you'll likely need:

./gradlew mugene:generateKotlinCommonGrammarSource build packJsNpmPublication publishToMavenLocal mugene-console-jvm:jar

This generates some syntax file support code, builds libs and tools, package a single jar for JVM desktop, and generate NPM artifacts that are also used by VSCodium extension (under development).

Once you are done with build Gradle build task, there will be mugene-console/build/bin/native/debugExecutable/mugene-console.kexe (or .exe on Windows). You can then run it to compile mugene MML files like: (the/path/to/)mugene-console.kexe samples/escape.mugene. For the complete list of command line arguments, just run this executable without arguments.

mugene-ng VSCode extension

mugene-ng is a Kotlin Multiplatform project that supports Kotlin/JS. We publish mugene-ng as an NPM package, as well as vscode-mugene-language extension (the extension used to support .NET based mugene that only ran the compiler as a "native" executable, but now we are fully JS based).

mugene-ng applications

While mugene-ng can be evaluated as a standalone command line MML compiler project, it is actually part of the ktmidi ecosystem. It is the core part of augene-ng project, which makes use of its MML to MIDI 2.0 compiler then to target audio plugins sequencer engine.

mugene-ng is also used in a virtual MIDI 1.0/2.0 keyboard kmmk project, which is also part of ktmidi ecosystem.

mugene-ng limitations

When porting from C#, I disabled __STORE_FORMAT primitive operation (because it had C# String.Format() as its premise), which effectively killed Vocaloid2 VSQ support and around the feature. Vocaloid2 is too ancient anyways, so there wouldn't be significant drawback.

License and dependencies

mugene-ng is distributed under the MIT License.

mugene-ng depends on Strumenta/antlr-kotliin which is distributed under the Apache 2.0 License.

mugene-ng depends on atsushieno/ktmidi which is distributed under the MIT License.

mugene-ng's People

Contributors

atsushieno avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

mugene-ng's Issues

make `build` task work

Currently it fails to build if ANTLR generation task was not run in prior.

The build command for now is: ./gradlew mugene:generateKotlinCommonGrammarSource build mugene-console:jar but it should be simply ./gradlew build

Compiler should not crash with stack trace for simple syntax error

Currently if we compile MML like this simple (note that - is at wrong place):

1 e0g0-b4.

It results in:

Exception in thread "main" dev.atsushieno.mugene.MmlException: (unknown) (152, 40) : error: no viable alternative at input '0.0'
	at dev.atsushieno.mugene.MmlCompiler.reportOnConsole(mml_compiler_main.kt:70)
	at dev.atsushieno.mugene.MmlCompiler.access$reportOnConsole(mml_compiler_main.kt:41)
	...

But that's absurd. It should report simple syntax error instead.

Remove `B` pitch bend operation (altered by `B=`), `P`, `E`, `V`, ... too

Pitchbend operation B can bring in syntactical confusion in combination with B-, because we may perform pitch bend changes like:

  • B -100 i.e. set absolute B value to -100 (which is 8192 - (100 * bend_cent_mode_intermadiate))
  • B- 100 i.e. set relative B value by -100 (which is current_pitch_bend - 100 * bend_cent_mode_intermadiate)

and if we write B-100 to set absolute value, we find it not working and get lost. B- takes precedence by because our tokenizer finds B- as the longest match.

A better syntax would be to change B as relative operation, but immediately making it so would make old MMLs inaccurate.

Therefore we set B= as the new absolute pitchbend operation, and remove B from the next major upgrade (mugene-ng 2.0?).

possible need for note-off and note-on prioritizing

(copied from atsushieno/mugene#32)

When I was authoring some phrase like this:

1   @30 o4 V110 v100 l8 RSD20 DSD40
    Kc+Kf+
    [ fg(50g)50g^2.b4a4f4 : fg(50g)50g^1. ]2  fg(50g)50g^1f2  [r-1]8
    [ de(50e)50e^2.g4f4d4 : de(50e)50e^1. ]2  de(50e)50e^1d2  [r-1]8
    < [ ab(50b)50b^2.>e4d4<a4 : ab(50b)50b^1. ]2  ab(50b)50b^1a2

It is like, I wanted to enter each note on the tritone (possibly quadtone, after this) chords respectively and entered MML like this, making use of [r-1] to roll back. However at the end of the fourth bar (at b4a4f4 bar), only a4 is noted on.

It is because the other chord notes emit note-offs, resulting that the first note-on events (e.g. b4a4f4) are suppressed by the following note-offs of the chord note sequence (e.g. g4f4d4, note that f4 is connected).

It can be easily workarounded if the song gives q operation e.g. q1 but that's not ideal.

Solution:

  • (1) detect and warn about zero-length note operations. It has points because this kind of problems may happen in other use cases, but does not resolve the present issue.
  • (2) detect zero-length note operations and alter note-on/off operations by prioritizing them, if applicable. It should exactly resolve the problem, but complicates the MML processing rules.

import vscodium extension and publish to open-vsx

We likely have to fix JS stream resolver issue and any relevant JS issues first. Once it's done, we can start importing "vscode-extension" into this repo. This time don't have to run .NET command anymore!

MIDI 2.0 primitives

Now that mugene-ng is going to generate MIDI 2.0 UMP based song files using Midi2Music class in ktmidi, it makes more sense to support MIDI 2.0 primitives beyond MIDI 1.0 primitive operations. It should be fairly doable.

Rename division operator

Currently we use / as a "divide" operator. It is quite standard, but it prevents defining it as an aliasing macros like #macro / { LOOP_BREAK }.

Renaming '/' as an escaped construct (i.e. \/) is an option.

MML tokenizer drops tokens under some condition after note that skips length

After implementing checks for open-ended loop (i.e. [ ... to report an error) at 3a7a113, it uncovered an issue that our ANTLR parser stopped parsing in the middle of the loop under certain condition. Example MML:

1	[c8c,,60 ]1

It was reported as a regression and build now fails.

I'm going to refine the existing test that failed to succeed for its original purpose and add a disabled test.

native executables

There should be mugene, mugene-console or mugene-ng to simply run the compiler as a console tool, instead of depending on JVM. It should be possible by native backend.

Actions:

  • replace mugene-console module with a new MPP executable module (especially binaries.executable() on native).
  • set up build matrix and collect build artifacts on GitHub Actions. It would also help native libmugene shared/static libs.

compileKotlinNative causes build failure

e: Could not find "org.jetbrains.kotlinx:atomicfu-cinterop-interop" in [/media/atsushi/extssd0/sources/commons-music-prog/mugene-ng, /home/atsushi/.konan/klib, /home/atsushi/.konan/kotlin-native-prebuilt-linux-1.5-M1/klib/common, /home/atsushi/.konan/kotlin-native-prebuilt-linux-1.5-M1/klib/platform/linux_x64]
Daemon vm is shutting down... The daemon has exited normally or was terminated in response to a user interrupt.

Known as https://youtrack.jetbrains.com/issue/KT-44884

in-advance specification of variables

Text music sakura has a cool feature that lets you specify verlocity, gatetime, length, key-on delay (TIMING in our syntax) or octave in advance e.g. v.onNote(100,90,80,70,60) cdefg (plays c to g with decreasing velocity). They can be .onNote(), .onTime(), .onCycle() (works like LFO) etc.

It is likely doable within current mugene syntax, but I want to have them within default-macro,mml.

Documentable macro definition syntax

Macros (and probably variables) should be documentable so that their docs can be shown on hover or documentLink operations on language server protocols.

build failure: "module-info.class is a duplicate but no duplicate handling strategy has been set."

The latest build is broken
https://github.com/atsushieno/mugene-ng/runs/3291827328?check_suite_focus=true

It is due to:

Entry META-INF/versions/9/module-info.class is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/7.1.1/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.

which seems to be an issue, one mentioned at https://youtrack.jetbrains.com/issue/KT-46165 (fixed) which reports that there was still a regression for Java project (which mugene-console is) https://youtrack.jetbrains.com/issue/KT-46978 (fixed).

Since I'm still seeing the issue, it is possible that kotlin 1.5.10 does not have a fix.

regression: cannot compile looped note with velocity without length like `[c,,50]`

While there has been no MML tokenization changes I started to get compilation errors like:

/sources/ktmidi/mugene-ng/mugene-console-project$ mugene-console/build/bin/native/debugExecutable/mugene-console.kexe ../mugene-project/samples/mugene-fantasy-suite/2-f.h.t.u.mugene 
error: There is an unclosed loop

This seems to be caused by [c,,50]. Loop is involved, and skipped argument is involved. [c4,8,55] compiles. [c,8,55] doesn't. There must be some invalid tokenization issue, but we did not alter antlr-kotlin. Though I have to say it definitely has issues in token resolution, so anything like JVM version, Kotlin compiler version, or even Gradle version could impact.

We need somewhat difficult inspection.

Context note operations using `_` prefix

After adding Bn operation, I figured that it is still not very user-friendly. How can we do better?

Idea:

  • _B= operation, as well as _B_ operations to take immediately preceding note context
    • e.g. BEND_CENT_MODE24 c0_B_0,4,0,1200 e4_B_0,4,0,-1200 (per-note pitchbend on both c and e, where c gets pitch goes up, while e gets pitch goes down.

JS: local file resolver

Right now LocalFileStreamResolver cannot find default-macro.mml which is part of src/commonMain/resources because we don't know where it is...

Offline build

Hello,

I am a packager from the GeekosDAW project on openSUSE GNU/Linux and I'd like to make a package for mugene-ng, so that openSUSE users can easily discover and install it from their package manager. To build and publish packages on openSUSE we use the Open Build Server (OBS), which offers offline virtualized environments. For this reason, it's very important that programs can be built without an Internet connection and, if there are any dependencies, they are either vendored with the programs or packaged separately by us (ktmidi is a useful library so I can probably package it separately).

Premise: I am no gradle expert even if I've built Java programs in the past (also with Maven). I tried to follow the official build instructions in the README but the build process required an Internet connection. I tried to use gradle -offline build with the tasks you indicated in the README but that did not work. Could you please help me build this project without an Internet connection, so that I can make a package for it on openSUSE? We really need a well-written, still-maintained MML-to-MIDI translator in our repository. Thank you! ๐Ÿ™‡

Introduce functions

One of the most annoying issue with the current syntax is that there is no "return value" for a macro. If we can call macros like functions, then composing macros is much easier.

some negative length problem

This is an extracted simpler repro from our samples - this results in negative length failure at dev.atsushieno.mugene.MmlSmfGenerator.generateTrack(mml_smf_generator.kt:56)

1       CH4 @47 V100 P79 l16 v100
        E_64,127,0,4.,24
        [g24]12
        [c8c,,60c8c,,60c8c8 ]1

switch to JSIR and support Web (also for Compose for Web)

It is desirable if we can migrate to JSIR from JS Legacy for better performance. But at this state it is not possible due to various restrictions as well as complicated bug in JSIR.

At the most advanced status, I could...

  • successfully compile some MML files into SMF (e.g. samples/rain.mugene)
  • fails to compile another sample (e.g. samples/mugene-fantasy-suite/*)

It is at the deep of antlr-kotlin implementation that is almost impossible to fix.

image

We will likely have to wait for further maturity on Kotlin/JSIR.

Compiler sometimes drops MML after encountering syntax error without reporting it

Similar issue, to issue #25, but probably different:

1 @58 o3 80  o5c

There is a syntax error at 80 but it is not reported as an error.

    fun tokenizerShouldReportError() {
        val mml = "1 @58 o3 80  o5c"
        assertFails("should report syntax error at orphan number token") { MmlTestUtility.testCompile2("midi2", mml) }
        assertFails("should report syntax error at orphan number token") { MmlTestUtility.testCompile("midi1", mml) }
    }

unblock upgrading to ktmidi 0.3.7

Currently we use ktmidi 0.3.5 which is somewhat behind the latest ktmidi main tree. And it is currently blocked by run-time problem in vscode-extension.

It seems that it fails to load ktor (converted to JS).

image

ktor is used only to detect ByteOrder so far, so it might be easier to alter it with own implementation.

build node.js executable

I set up webpack.config.d for this purpose, but if add binaries.executable() at kotlin { js { ... } } section in build.gradle.kts build fails like:

Module 'fs' not found
Module 'kotlinx-coroutines-core' not found

This needs to be sorted out.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.