On Thursday 22 May 2014 16:52:03 David Olofson wrote:
> Compatibility would of course be very nice in this case. Not really
> familiar with the Kontakt scripting language, so I can't tell how much
> work it would be to write a parser for it - 

There are various kick start introductions for the "KSP" (Kontakt Script 
Processor) script language. I.e.:

http://www.askaudiomag.com/articles/introduction-to-scripting-in-kontakt-
part-1

Also a lot of videos out there. You basically just use one of the defined 
event callback functions for two main purposes:
1) reacting on and processing MIDI events and
2) adding custom GUI controls (dials, input fields, labels, buttons) and write 
event handlers for their UI widget events.

For now I am mostly interested to implement aspect 1) (MIDI processing).

One thing I find suboptimal with KSP is that it is very focused on using 
function calls all over the place. For example if you want to trigger some 
note when a key is released, you would write something like:

on release
  declare $n := 42
  play_note($n, 127, 0, 0)
end

So as a user you need to remember the sequence of function arguments for 
play_note() (or you need to lookup in the manual each time). Using a rather 
more object oriented approach like:

on release
  Note $n
  $n.note := '42
  $n.velocity := 127
  //optional:
  //n.offset := 0
  //n.duration := 0
  $n.trigger()
end

would probably be more intuitive and easier to remember. Modifying incoming 
MIDI events is also a bit odd, with KSP it is like this:

on note
  if ($EVENT_VELOCITY > 100)
    ignore_event($EVENT)
  else
    change_note($EVENT, $EVENT_NOTE + 12)
    change_velo($EVENT, $EVENT_VELOCITY / 2)
  end if
end

which IMO I would found more intuitive like:

on note
  if ($NOTE.velocity > 100)
    $NOTE.ignore()
  else
    $NOTE.note += 12
    $NOTE.velocity /= 2
  end if
end

There are 3 different scopes for variables in KSP by the way. You declare 
global variable in the "init" callback:

on init
  declare $myGlobalVariable := 10
  declare %someGlobalArray[5] = ( 2, 3, 5, 7, 11 )
end

You can then access those global variables from any other callback function. 
Whereas if you declare a variable in some other callback like:

on note
  declare $i := 0
end

Then this variable by default is rather something like a static variable, 
bound in the namespace of that "on note" function, *but* shared by all 
callbacks that process that particular callback function! So you might 
interfere with other instances running this callback "at the same time". Even 
though KSP only has one thread, there is a wait() function which pushes the 
respective function execution on a wait queue, thus rendering a scenario that 
you can compare causally to the effect as if multiple instances of the same 
callback function were executing in parallel.

That's why KSP has a third variable scope as well:

on note
  declare polyphonic $i := 0
end

In this case such a "polyphonic" variable is not shared, it is bound to the 
event which triggered the callback function. So no other instance of the same  
callback can modify variable $i in between, preventing you from any trouble. 
However from memory management point of view this case is a bit problematic. 
Because you have no information at parse time how many instances of the 
callback might be triggered in parallel. I am not sure what the best solution 
would be to implement this case (from memory management POV). Do you have a 
solid idea?

> but that's basically how
> to go about it; write an alternative compiler that issues bytecode for
> an existing VM. A VM like this is basically just a high level virtual
> CPU, and not really tied to any specific language.

Probably, but in fact I would like to avoid opening the door for numerous 
flavors of high level script languages used in the sampler right now. Because 
it might create confusion among users when learning scripting with the sampler 
and/or by reading scripts of other people, if everybody is using a different 
language on top that is. So I would prefer to pick one single language flavor 
that should remain alone in this flavor (for quite some time at least).

> EEL exists mostly because I couldn't find anything like it. I looked
> into subverting Lua to suit my needs (replacing the GC, most
> critically), but the Lua community showed virtually no interest in it
> (not really needed, even for <100 Hz game scripting), so I would have
> been completely on my own with it - and I'd rather be in that
> situation with code that I know inside out.

Yes, I saw you went a bit deeper with EEL than what we probably need to 
achieve right now. From what you saw above, the typical use case for the 
script language in a sampler is event handling once in a while. Not at high 
frequencies. You are even defining tight DSP stuff with EEL if I saw it 
correctly. That's already beyond the scope what we need right now.

> For something really simple, you could look at the Audiality 2
> scripting engine (not physically related to EEL), but that's a small,
> domain specific language that's somewhat tied to the design of the
> audio engine. Apart from being massively microthreaded with message
> passing, it's a really small and simple language.

Why is it called "Extensible" by the way? What is the particular extensible 
aspect of EEL?

> > [...Bison and stuff...]
> 
> Not sure about parser and lexer generators, really... These tools only
> solve a small, simple part of the problem - and they're not even
> particularly good at dealing with some types of languages. I prefer
> just coding it all in plain C. Fewer tools to depend on, which is
> particularly nice when porting and cross-compiling! :-)

Well, I have a favor for compiler-compiler. You work with them at a more 
intuitive and compact level, they keep you safe from typical manual parser 
programming mistakes and can safe you a lot of time and stress for languages 
which grow in time.

> > Do you think that is necessary for the use case in the sampler?
> 
> Not strictly, but even disregarding raw speed, interpreting a proper
> scripting language from source in a realtime safe manner is going to
> be hairy. The normal, easy way of coding a parser involves deeply
> recursive code, associative arrays and other nasty things that are
> hard to do right in a realtime system.

Yeah, I already dropped the idea about interpreting script source in real-
time. We need some intermediary layer anyway. So we would not safe efforts by 
parsing on each event in real-time.

CU
Christian

------------------------------------------------------------------------------
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
_______________________________________________
Linuxsampler-devel mailing list
Linuxsampler-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxsampler-devel

Reply via email to