truj / midica

A Music programming language. Translates source code into MIDI. Includes a player. Supports MIDI-Karaoke. Includes a MIDI analyzer.
https://www.midica.org/
Mozilla Public License 2.0
111 stars 13 forks source link

enable decompilation to ALDA #53

Closed truj closed 4 years ago

truj commented 4 years ago

1. The decompiler contains MIDI specific and MidicaPL specific parts. Separate these parte into different classes to make it easier to export MIDI to other languages.

Currently the inheritance hierarchy is: MidicaPLExporter <-- Exporter It should be this: MidicaPLExporter <-- Decompiler <-- Exporter

Move the MIDI specific parts into the new Decompiler class.

2. In the main window there should be only one Export button for all decompilation classes or maybe even only one for all exports.

3. The file choosers for export files should be in the same window. The type may be chosen by a tab or something else. The decompile options (and maybe other settings) can be the same for all files being exported.

4. Add an AldaExporter class, derived from Decompiler.

truj commented 4 years ago

It only makes sense to have a concrete target language. Therefore I think ALDA makes sense. Updated the headline accordingly.

daveyarwood commented 4 years ago

An idea to consider: it might be useful to decompile to MIDI, and then do a code generation phase that generates Alda. In other words, if you're at the point where you have a MIDI sequence in memory (or some other sort of low level MIDI representation), you could use that representation to generate Alda code.

In fact, if you did that, then we could potentially reuse just the code generation part to build a MIDI import tool for Alda (https://github.com/alda-lang/alda-core/issues/25) :)

truj commented 4 years ago

It's already planned that way. Midica's native format is MIDI. No matter if it's imported from a MIDI file or a MidicaPL file.

daveyarwood commented 4 years ago

Perfect!

truj commented 4 years ago

Just trying to implement META messages for tempo, key signature and time signature. According to the docs I can use attributes for 2 of them: tempo and key-signature

@daveyarwood, what about the time signature? Does there anything exist like that in ALDA?

daveyarwood commented 4 years ago

One of the interesting things about Alda is that it doesn't really have measures or time signatures. There are barlines, but they are purely for aesthetics / code organization.

At some point, I would like to make barlines meaningful and use the lengths of notes between barlines to infer time signatures so that we can include them in the MIDI sequence. But right now, Alda is completely agnostic to time signatures.

I think for what you're doing (going the other way, MIDI => Alda), you can just not translate time signature meta messages. I suppose if you really wanted to, you could emit | characters at every barline, but it's optional.

truj commented 4 years ago

OK, then I'll just ignore them.

truj commented 4 years ago

@daveyarwood the ALDA exporter is now working. So now Midica can import and export ALDA.

Limitations:

Regarding the last problem: Do you see any way to mitigate that problem?

truj commented 4 years ago

Just fixed 2 bugs. Should work now in most cases.

daveyarwood commented 4 years ago

Awesome! I'm excited to play around with this sometime soon when I have a little time.

  • Real world MIDI files often result in the error Ran out of MIDI channels. This is because an instrument switch inside the same channel results in a new channel in ALDA.

Regarding the last problem: Do you see any way to mitigate that problem?

Ah, interesting. Unfortunately, the approach I took with Alda doesn't work well in the context of importing MIDI files that work this way. Alda doesn't really have a notion of a part "switching instruments" like you can do on MIDI channel.

On the other hand, several years ago I had some thoughts about how to support having more than 16 instruments in a single Alda score. See https://github.com/alda-lang/alda/issues/178 and https://github.com/alda-lang/alda-sound-engine-clj/issues/5

I'd be curious to hear your thoughts. It's still something that would be great for Alda to support.

Another idea I had just now: right now, Alda doesn't let you specify which channel to use for an instrument part, but perhaps it could. I imagine we could add an attribute like (midi-channel 2), which tells Alda to use MIDI channel 2 instead of finding the next available channel. That way, you could use the same channel number in multiple parts and effectively "switch instruments" on a single channel, by way of having multiple Alda parts that use the same channel at different times, something like:

piano:
  (midi-channel 2)
  c8 d e f g a b > c

guitar:
  (midi-channel 2)
  r1 # piano is using channel 2 here
  o3 c1/e/g/>c
truj commented 4 years ago

Another idea I had just now: right now, Alda doesn't let you specify which channel to use for an instrument part, but perhaps it could. I imagine we could add an attribute like (midi-channel 2), which tells Alda to use MIDI channel 2 instead of finding the next available channel. That way, you could use the same channel number in multiple parts and effectively "switch instruments" on a single channel, by way of having multiple Alda parts that use the same channel at different times, something like:

piano:
  (midi-channel 2)
  c8 d e f g a b > c

guitar:
  (midi-channel 2)
  r1 # piano is using channel 2 here
  o3 c1/e/g/>c

For the decompilation that would be perfect. It would have made my work much easier if ALDA had such a feature.

But on the other hand something like this would not be possible:

piano:
  (midi-channel 2)
  c8 d e f g a b > c

guitar:
  (midi-channel 2)
  c8 d e f g a b > c

So it's up to the user to avoid such a thing. That makes the language more complicated.

truj commented 4 years ago

On the other hand you can assume that a user using this feature already knows what he's doing and why. And the feature would still be useful to debug a decompiled score. Then the channels of the original and decompiled version could be compared much easier.

daveyarwood commented 4 years ago

Yeah, the more I think about this, the more it feels like it would be a good thing to add to Alda.

I'll put it on the TODO list for Alda v2. I've also captured the idea in https://github.com/alda-lang/alda-sound-engine-clj/issues/5 so that I might implement it in Alda v1 as well, but it might be a while before I can get to it.

So far, I'm thinking that this will be an "assume the user knows what they're doing" kind of feature, like you just described. It would be sort of like a low-level escape hatch to work around Alda's default behavior of automatically finding an unused MIDI channel for each part. If two parts both include (midi-channel 2) and their notes overlap, then that would result in undefined behavior (probably one of the program change messages "winning" and both of the parts' notes being jumbled together and played on that instrument on the same channel)