arensb@cvl.umd.edu (Andrew Arensburger) (12/05/90)
In article <1990Dec4.134944.16669@cbnewsl.att.com> jpg@moss.ATT.COM writes: >>BTW, has anyone heard about Keynote language for the Amiga? >>I saw it in Keyboard Mag. that it's available for the Ami and I was >>wondering where I can get a copy. > >send mail to Tim Thompson tjt@twitch.att.com, who developed keynote and >he should be able to tell you how to get a copy, I think you can get it >for $50.00. I haven't even seen the beast, and I'm already sold on it. For general information, I am including the following blurb that Mr. Thompson was kind enough to send me (reprinted without permission, but I don't think they'll mind me pushing their stuff): ----- Begin quoted stuff ------------------------------------------------ Keynote User's Group A Keynote User's Group is being organized to provide a way for users to share new functions and example applications through a quarterly newsletter and a BBS archive. Keynote has also been sub-licensed, allowing the distribution of binaries directly to end users. This will be a much more convenient way of getting Keynote for many people, especially personal computer owners (Amiga, Macintosh, Atari ST and IBM PC's). For more information, please contact: Jon W. Backstrom Applied Digital Arts P.O. Box 176 Bloomington, IN 47402-0176 (812) 336-3660 (after June 1, 1990) Internet: media@silver.ucs.indiana.edu UUCP: {ames,rutgers,att}!iuvax.silver.media Membership in the Keynote User's Group is $20 annually, which includes a subscription to the quarterly newsletter and access to a growing library of Keynote functions and musical sequences. Sub-licensed Keynote binaries are being distributed for $49, including a one year membership in the Keynote User's Group. (Source code is only available from the AT&T UNIX Toolchest.) ----- End quoted stuff -------------------------------------------------- As noted above, Keynote is to sequencing as Emacs is to text editing: it's programmable, so if you don't like the way it does something, rewrite it! And yes, that includes the windows, menus and stuff. -- -------------------------------------------------------------------\\\\^ Andrew Arensburger | K&R C! | I hate Lisp functions o\\\\\- arensb@cvl.umd.edu | ANSI no! | that start with / ...!uunet!mimsy!cvl!arensb | | "(catch (mapcon (throw" \_/
nichomax@cattell.psych.upenn.edu (Nicholas Maxwell) (12/05/90)
What's the language in which you must program keynote? C? nichomax@cattell.psych.upenn.edu
mab@druco.ATT.COM (Alan Bland) (12/08/90)
In article <34068@netnews.upenn.edu> nichomax@cattell.psych.upenn.edu (Nicholas Maxwell) writes: >What's the language in which you must program keynote? C? > >nichomax@cattell.psych.upenn.edu The language itself is called Keynote, and is a derivative of AWK (a C-like language available on UNIX). Keynote is an interpreted language, so you don't have to go through the edit-compile-link-run cycle. As such you get immediate feedback on changes you make at the expense of some overhead during execution. It's terrific for musical "hacking!" The language includes some very powerful constructs for manipulating phrases of MIDI notes. For example, ph = 'c,d,e,f,g' sets the phrase variable ph to contain the first five notes of a C-major scale. To transpose the pitch of phrase up an octave (12 tones), just type ph.pitch += 12 You can play the phrase backwards by reverse(ph) Included below is the actual Keynote code to the "reverse" function so you can get a feel for what the language is like. Keynote comes with hundreds of functions like this, and of course you can write your own. func reverse(ph, leng,nt,r) { if ( nargs() == 0 ) { print "usage: reverse(phrase)" return ''; } leng = ph.length r = '' for ( nt in ph ) { nt.time = leng - nt.time - nt.dur r |= nt } return r; } -- -- Alan Bland -- att!drutx!mab == mab@drutx.ATT.COM -- AT&T Bell Laboratories, Denver CO -- (303)538-3510
jpg@moss.ATT.COM (Jeff Grundvig,14C-316,7324,ATTBL) (12/08/90)
In article <34068@netnews.upenn.edu> nichomax@cattell.psych.upenn.edu (Nicholas Maxwell) writes: >What's the language in which you must program keynote? C? > >nichomax@cattell.psych.upenn.edu Keynote is a programming language, so you program in keynote. By modifying the menu functions that come with it you change your menus.... jeff g. jpg@floyd.att.com
tjt@cbnewsh.att.com (timothy.j.thompson) (12/10/90)
> >What's the language in which you must program keynote? C? > Keynote is a programming language, so you program in keynote. By > modifying the menu functions that come with it you change your menus.... Here's some more info and examples to supplement what Alan Bland gave in a previous article. Keynote has associative arrays, just like awk, except that you can also use musical phrases as the array subscripts. This comes in handy for look-up tables and other things, e.g. this made it very easy to write a markov-chain function. Realtime programming is easy. The following is the complete code for an 'echo' function that echos all incoming MIDI notes, 1 beat later: function echoit(a) { sched(a,1b) # hard-coded echo time of 1 beat } function echo() { interrupt(echoit,NOTEON | NOTEOFF) realtime() } Since it's an interpreted language, there is a limit to the processing you can do before delays are noticeable, but you can still do fairly interesting things. Scheduling computations 'off the beat' is one trick I use a lot. The contents of all pop-up menus are user-defined, and it is trivial to add new ones. E.g. let's say you wrote a new function to add a copy of a phrase to itself, transposed by a fifth: function addafifth(ph, r) { r = ph r.pitch += 7 return ( ph | r ) } This would be added to the pop-up menus with the single statement: menu( "proc", "Add A Fifth", "{MODIFY(Pick=addafifth(Pick))}" ) This would add an item to the "proc" menu. The MODIFY macro is a convention used to include the code tha allows you to undo the effects of any editing operation. You can undo any number of operations, and you can undo the last undo. By the way, the undo facitiliy of the graphical editor is not actually built into the Keynote language, it is all implemented with Keynote code. This points out an area of potential confusion. The graphical user interface of Keynote (which looks a bit like your typical piano-roll sequencer) is completely implemented with Keynote code - the language itself actually (and purposely) has very few built-in capabilities - ie. it has just enough built-in capabilities to make to possible to implement the rest at the 'user level' with Keynote code. This arrangement has been a huge win for both development and use. You can easily write code that simultaneously handles MIDI I/O, console I/O, mouse actions and graphics. So, even though the graphical features of Keynote were somewhat tailored to providing a piano-roll sequencer interface, you can do completely different things. For example, the code at the end of this article implements a complete graphical drum-pattern editor. Any other questions, mail to tjt@twitch.att.com. If you'd like a hardcopy of the language reference manual, send me your postal address. ...Tim Thompson...AT&T Bell Labs/Holmdel/NJ...tjt@twitch.att.com... ======================================================================== # This code implements a drum-pattern editor. To specify the MIDI # channel and pitches of your drum machine, create a file that looks like: # # chan 10 # bass 35 # snare 38 # closed_hat 42 # open_hat 46 # # Then, invoke: # # kboom(nsteps,filename) # # where nsteps is the number of steps you want in the drum pattern. # The step size is 1b/8 (a 32nd) by default, but you can set it (Stepsize) # to whatever you want. # # The screen will show a matrix (drums on vertical axis, beats on # horizontal axis). The drum pattern will be playing constantly - # click mouse button 1 wherever you want to add/delete drum hits. # Press 's' to start and stop the pattern, 'q' to quit. Nsteps = 0 Stepsize = 1b/8 function kboom(nsteps,mapfile) { readdrums(mapfile) arrayinit(Dbeat) Nsteps = nsteps for ( n=0; n<Nsteps; n++ ) Dbeat[n] = '' Showstart = Showlow = Showbar = 0 Showhigh = 128 Kbcount = -1 Kbon = 1 Kbxinc = (Nsteps*Stepsize)/50 Kbxinit = Kbxinc * 12 Kbyinc = Showhigh / (Kbdrums+1) Showleng = Kbxinit + Nsteps * Stepsize Grid = '' # set up actions for triggering drums and user interaction sched(Dbeat[0],0) # scheduled only once sched(kbtrig,Stepsize/2,Stepsize) # repeatedly scheduled temposet(1) # allows tempo control from console action(BUTTON1DOWN,kbmouse) interrupt(kbcmd,CONSOLE) print "Press 's' to toggle sound, 'q' to quit." kbdrawall() realtime() # realtime loop during which everything happens # Construct a single phrase containing completed pattern. Kbpattern = '' for ( n=0; n<Nsteps; n++ ) { ph = Dbeat[n] ph.time = n * Stepsize Kbpattern |= ph } Kbpattern.length = Nsteps * Stepsize print "Result is in Kbpattern." } function kbcmd(c) { # handle keyboard commands if ( c == "q" ) stop() else if ( c == "s" ) { # toggle sound Kbon = 1 - Kbon if ( Kbon ) Kbcount = -1 # reset to beginning of pattern } } function drawbeat0() { # draw flashing marker on beat 0 y = kbystart(0)+1 draw(kbxstart(0)+1,y,kbxstart(1)-1,y,XOR) } function kbtrig(b) { # repeatedly executed every Stepsize beats if ( Kbon ) { b = (Kbcount++)%Nsteps sched(Dbeat[b],Now+Stepsize/2) if ( b == 0 ) { # make beat 0 obvious with a flashing line sched(drawbeat0,Now+3*Stepsize/8) sched(drawbeat0,Now+11*Stepsize/8) } } } function kbxstart(n) { # return x value of beat n in matrix display return Kbxinit+n*Stepsize; } function kbystart(n) { # return y value of drum n in matrix display return Showhigh-(n+1)*Kbyinc; } function kbmouse() { # handle mouse button presses, adding/deleting drums kb = kd = -1 # figure out which beat (b) and drum (d) is being chosen for ( b=0; b<Nsteps; b++ ) { if ( Mouseclick > kbxstart(b) && Mouseclick < (kbxstart(b+1))){ kb = b; break; } } for ( d=0; d<Kbdrums; d++ ) { if ( Mousepitch < kbystart(d) && Mousepitch > (kbystart(d+1))){ kd = d; break; } } if ( kb < 0 || kd < 0 ) return; if ( Kbdrumnote[kd] in Dbeat[kb] ) Dbeat[kb] -= Kbdrumnote[kd] # if already there, delete it else Dbeat[kb] |= Kbdrumnote[kd] # if not there, add it # draw (or undraw) an X in the specified box draw(kbxstart(kb),kbystart(kd),kbxstart(kb+1),kbystart(kd+1),XOR) draw(kbxstart(kb),kbystart(kd+1),kbxstart(kb+1),kbystart(kd),XOR) } function kbdrawall() { # draw matrix and labels redraw() # clear screen for ( b=0; b<Nsteps; b++ ) { x = kbxstart(b) draw(x,Showlow,x,Showhigh) # draw line # show beat number at top draw(string(b+1),x+3*Stepsize/8,Showhigh-Kbyinc/2) } for ( d=0; d<Kbdrums; d++ ) { y = kbystart(d) draw(0,y,Showleng,y) # draw line # show drum label on left draw(Kbdrum[d],Kbxinc,y-5*Kbyinc/8) } } function readdrums(mapfile, arr) { # read a drum map file arrayinit(arr) Kbdrums = 0 Kbchan = 1 while ( read ln < mapfile ) { split(ln,arr) if ( arr[0] == "chan" ) { Kbchan = 0 + arr[1] continue } Kbdrum[Kbdrums] = arr[0] Kbdrumnote[Kbdrums] = makenote(0+arr[1],Stepsize,'a'.vol,Kbchan) Kbdrums++ } close mapfile }
dgold@basso.actrix.gen.nz (Dale Gold) (12/13/90)
Quoted from - mab@druco.ATT.COM (Alan Bland): > Keynote is an interpreted language, so you don't have to go through > the edit-compile-link-run cycle. [...] > It's terrific for musical "hacking!" > Bearing in mind of course, that "hacking" has a completely different meaning in the musical world! :-) -- /%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\ < dgold@basso.actrix.gen.nz | Eschew Obfuscation > \%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/