TODO:
 * way to disable optimization
 * reduce redundant calculation of operands to functions, i.e., f[x] := x+x; should evaluate x only once...using temps or something.
 * maybe generally examine calculation dependencies:
   - constants => no dependencies
   - per note constants => no dependency on t
   - common subexpressions => can depend on t, but is referenced more often than it needs to be computed (like above)
 * optimize exp() (in compile.c and lang.c)
 * FIX :: (zero crossing mute)
 * pattern rhythm normalization needs to specify duration
 * think about layering of live-input without rhythm tweaking
 * when messing around with tempo, it would be nice to have something that would start at an arbitrary measure offset, even fractional
 * may someday be handy to improve timing of MIDI input events beyond the
   audio buffer size (which has currently been reduced to 128 bytes, or
   0.7ms)
 * tinyfugue interface?
 * maybe someday try FREQ_MULT=1.0 and simplify myfmod() to assume y=1
 * realtime scheduling
 * completion for command names, function names, maybe a hotkey to see a definition for a function (most specifically, the argument names)
 * perhaps a way to pass parameters through dictionaries in tracker? (i.e., "dict($0)")

 * NEXT VERSION: (a naming convention?  shall I be bold and label this 20050601)
  - work with ALSA or at least SDL or something like it.  availability of ALSA 0.9.0 tutorial gives hope, let's see if it even works ahem?
  - think of a way to do a scripted language for the tracker thing
  - think of a way to do phase shifting
  - need a 'loop' flag on waveform
  - implement 'loop' (on trackers) and however tracker rehash should work
  - make it not die out if you get strings into the compiler
  - make it recognize when you use ""s inappropriately, i.e., instead of '' for notes
  - some way to split the keyboard into octaves or something, like a 'map' shortcut, for autochord and the like...
  - invent samples i can play with, especially for percussive sounds (snare, cymbal, tom, timpany, bass, hihat)
  - func: 'clip'
  - func: 'logarithmic'...seems maybe useful for frequency-dependent changes?
  - func: 'pink' and 'blue' functions (averaging)
  - left-associate...  a/b*c => (a/b)*c not a/(b*c)  augh
 * AFTER THAT:
  - figure out how to cut out some of the noise in samples
  - make a sample recorder, and make gga work better for cutting up samples
  - add a general 'set' variable interface?
  - really cool idea: develop a way to add events to a layered (even heirarchical?) loop that is going on in real time, for evolving beats -- might be a good upgrade to that tracker scripting language.  that tracker file will eventually need a from the bottom up overhaul, when i settle on a methodology.
  - FM to try:
    - op2r harmonic: "weighted spectra", inharmonic: "wild"
    - try modulating the multiplier.... (try lfo and high freq)
    - try modulating by noise (?)
  - think about how we would implement subtractive synthesis (square, saw, triangle => filter)
  - try additive synthesis (just adsr applied to harmonic multiples of the base freq)
  - fm synthesis from publicly available OPL3 GENMIDI files
 * band names (heh)
  + soft contender
  + sparkle prowess (beats the google test!)
  + chipotle sparkle    !
  + sparkle frond
  + sparkle fiddy
  + sparkle six
  + sparkleshire
 * ALBUM 1:
  + names? acid is a four letter word
  + several other songs (don't love anyone?)
  + kitz on the cover
  + HAPPY SONG:
    - syncopate up the lighter snaps
    - coughing, maybe syncopated?
    - maybe a round using an instrument?
    - maybe something to play off the arpeggios?
    - line-draw music video?  maybe make a 3D linedraw interaction program that uses the glove?  with a crazy object heirarchy, perhaps even the same scripting language!  that would be kind of sweet.  i suspect really a most inappropriate mixing of projects.
 * ALBUM 2:
  + log song cover

11-09-03.txt: ######################################################

Design for FM synth program.

The overall shape will be an interactive realtime music editing and playing
environment.  It will have a 'scripting language' which should be
generic enough to control all levels of sound generation from editing
to real time user interface to the actual generated waveform.  The
scripting language will use GCC as a back-end because I am lazy.  GCC
will generate .so files which will then be transparently linked into
the running executable.  Stupid but works everywhere!  This is not so
dissimilar from an all-C approach except that we get the added power
of a full parser instead of the C preprocessor to organize the code
most efficiently and we get an interactive environment to hide the C
compiler from us, and avoid restarting the program (or even
necessarily stopping playback) to add new waveforms etc.

Is this problem ammenable to treatment with object orientation?  I am
unconvinced.  While it would be nice to have an 'envelope' base class
or template, I do not think it is actually a good idea.  Every
function should be defined over ranges for its inputs.  And ranges
should be full expressions, capable of holding variables determined
even at run-time (such as the time that a 'key up' event occurs, or
the frequency of the note being played).

v(t,A,D,S,R,t_S) =
	[0, A: t/A]
	[A, A+D: 1-(t-A)*S/D]
	[A+D, A+D+t_S: S]
	[A+D+t_S, A+D+t_S+R: S-(t-(A+D+t_S))*S/R]

Over all other ranges it should be 0, or perhaps undef to indicate
when the note is over?

t_S in that case is not defined until runtime, perhaps, as it is the
length of the sustain period.  It should probably be specified in a
different form, perhaps as the total duration of the key down, and it
should have a range specified somehow, so it is always >= A+D.

It cleans up a bit if we add the variable 'last' which just stands for
the end of the previous range (this is optional, and is used to
make it easier to have like a specific chain of events and satisfy
yourself that they should never be simultaneous).  Perhaps when a
time variable is used in the computation of the endpoint of a range,
it should assume that the variable will be greater than the start
time, and enforce this.

v(t,A,D,S,R,t_up) =
	[0, A: t/A]
	[last, last+D: 1-(t-last)*S/D]
	[last, t_up: S]
	[last, last+R: S-(t-last)*S/R]

What if we specify times as like waypoints.

v_ADSR(A,D,S,R)[t] =
	[t[0], t[0]+A: t-t[0]/A]
	[last, last+D: 1-(t-last)*S/D]
	[last, t[1]: S]
	[last, last+R: S-(t-last)*S/R]

I don't like that, but I also want to be able to consider multiple
events on a note, perhaps even unordered.  I think for a given
formula they should be ordered, but there should be independent ones,
like there could be controls to trigger 'next waypoint' for any number
of attributes about a signal.  

Screw that t[0] concept, but waypoints are good.  Also, specifying
just the duration (and instead of the duration we can specify the
waypoint it must reach), and having t always be since the beginning
of this portion of the range makes stuff easier:
v_ADSR(A,D,S,R) =
	[A: t/A]
	[D: 1-t*S/D]
	[t_1: S]
	[R: S-t*S/D]
I think this is best.  If t has to be cumulative for this to be
efficient, let the back end cobble that together through arbitrary
wizardry.  We don't care if it's only efficient at a specific subset
of its functionality, so long as it is fully functional.

When t_X is used in the RHS, it will evaluate to the total duration of
the tone prior to that event.  I.e., it will be almost useless.

Now I should figure out how to do frequency modulation in this format,
but I must go.

11-13-03.txt: ######################################################

So I have been thinking again about how to make an algorithmic music
maker.  I am happy with the system I defined in 11-09-03.txt.

So essentially we make just a bunch of mathematical formulas that
define a waveform, be it one used for modulation (frequency or
amplitude) or for direct use as an audio waveform.  Each formula has
"arguments", or "free variables."  The final top-level formula for the
song will presumably not have any free variables, except of course
"t".  Individual instrument waveforms will for the most part just have
a free variable for frequency and note-up (i.e., when to switch from
"sustain" to "release").  Waveforms can be a straight formula like
f() = sin(2.0*t), or they can be defined over ranges, which would be
specified just by the duration of each region.  All waveforms start at
t=0 for the waveform, but musical "phrases" or "measures" or "loops"
or "tracks" will consist of a special formula that will be defined
something like
    f(tempo) = g()@0 + g()@tempo + g()@(tempo*2) + g()@(tempo*3),
which would play whatever the tone for g() is 4 times.  @ would
therefore be a special operator that controls the offset from f()'s t
to g()'s t.

There should be strength reduction on anything multiplied by t.
For more details see 11-09-03.txt -- in particular, this strength
reduction should be "flawed" in a useful way so that we can do FM
synthesis easily.

All time values should be normalized such that 1.0 = 1 second, and all
amplitude values should be normalized such that 1.0 = full volume.
This may be hard to pull off, because full volume is 32767 but a full
second will probably be 44100.  The only thing I can think of is that
any formula inside a time-domain (i.e., an arg to a built-in waveform
such as sin() or even dsp()) will have 44100-based arithmetic, and any 
other contexts are treated as 32767-based arithmetic.

The language should be syntactically and semantically the same at all
levels, but it should have some sort of keyword to differentiate a
low-level function from a high-level function.  Any function called
from a low-level function will be completely inlined, constant
propagated, and compiled by gcc.

This 44100 vs 32767 thing has me worried.  Consider simple FM:
   sin((100+sin(t))*t)
100+sin(t) is simple arithmetic, so it can proceed in either and it
doesn't matter so long as the 100 and the result of the inner sin()
are represented by the same multiplier.  But for the strength
reduction, since it is itself an argument to the outer sin(), it is
best thought of in 44100-base.  But the sin() table's values will
probably be in 32767-base, to facilitate playing as a sound.  Augh,
it is such a nuissance, programming efficiently is.  Also we are
going to constantly be bumping against 32-bit limits if I am not
careful.  I guess the x*44100/32760 conversion is not very expensive.

I think it all works out.  The strength reduction is key and prevents
us from overflowing anything.  So let's pretend sin() returns a
*32767, and all evaluation is done *32767, except that t is *44100, so
in order to get t=1 (t' = 44100) to be *32767, we must multiply by
32767/44100
   sin((3276700+sin(32767*t*32767/44100))*t*32767/44100)
Actually, let's try leaving t alone, because we'll multiply by
44100/32767 to get the result back to sin()'s natural range...
  sin((3276700+sin(32767*t))*t)
Now strength-reduce...  For every step of t+=1/44100...
  sin((3276700+sin(32767/44100+

Fuck, this isn't working.  I know it can't be that hard.  I'll
probably figure it out in bed.

Okay, try this...  Multiply everythingy (well, not necessarily
everything, we should figure out carefully the actual rules for that)
by 32767...
   sin((3276700+sin(32767*t))*t)
Then *44100/32767 if it feeds into a sin():
   sin((3276700+sin(44100*t))*t*44100/32767)
Then strength reduce, considering t to increment 1/44100 every step.
   sin((3276700+sin(44100/44100+prev0))*44100/(32767*44100)+prev1)
Now reduce the divisions using LCD:
   sin((3276700+sin(1+prev0))/32767+prev1)
We can't reduce out that 32767 because dividing sin() by 32767 isn't
really happening.

In addition, that *44100/32767 step amove, it should probably be
*4*44100/32767, make the sin() and other waveforms sample at 176400 so
we get reduced rounding error.  t still increments by 44100, though.
To be used as an operand to an @, it should be *44100/32767, that will
not be increased accuracy.

So we need something that builds a tree with doubles everywhere, and
every node would then have a 'double', '*32767', '*44100', or
'*4', or '*1' field.  Very first pass will underline everything under the
'low-level' mark.  Then one pass will convert everything from doubles
to whatever it should be as integers, perhaps using long longs just
in case.  Then the next pass should perform basic simplification and
reduction to normal int32.  Then a pass should convert everything below
the 'low-level' mark into C code and link it in.  Then a UI will
simply take additional function definitions and calls and add them
into the same tree.  This is not really very interactive, that's a
disadvantage -- you wouldn't want to just set up a beat and start
adding to it.  It's fairly easy to convert keyboard events into
function calls though.

Another weird thing...so far this is a totally side-effect-free
language (they are all implicit in relation to t).  I think it should
stay that way.  The only really complicated thing I want to add is
{start, step, count}, which would be legitimate I guess in @
expressions to say "play this at start, then again every step later
for count times."  We could have {start} instead of @.

So our syntax looks like:
   statement: fn_def ; | fn_call ;
   fn_def:    lhs assn expr
   lhs:       sym ) | sym ( formals
   formals:   sym | sym , formals
   assn:      = | :=                 := would be the low-level "compile this"
   expr:      term | [ term_seq | str
   term:      factor + term | factor - term | factor
   factor:    value * factor | value / factor | value
   value:     sym | number | - number | ( expr ) | fn_call
                                     distinguishing fn_call from sym = blow
   term_seq:  term_seq1 | term_seq1 [ term_seq
   term_seq1: term : expr
   fn_call:   sym ( arg_list | sym { time ( arg_list
   arg_list:  expr ) | expr , arg_list
   time:      term } | term , term , term }

Our lexer must recognize:
   ; ( ) [ ] { } , : := + - * / 
   sym: [a-zA-Z_][a-zA-Z0-9_]
   number: [0-9]*\.[0-9]*e[+-][0-9]*
   str: ".*"

The lexer should be pretty easy.

This project will be called ggb.  Greg's Great Beeps.

The convert to integer pass will probably be the hardest, but the
strength reducer is not necessarily a picknick.  Free variables should
have their type inferred from how they're used -- i.e., they're only
strings if they're used as arguments to a built-in such as wavefile()
that takes a string.  In fact, I have no respect for the string.
wavefile() should take a handle, so in the C code it will just be
passing int32s around...it will be the responsibility of the
interpreter to convert strings into file handles.

The interactive program should be structured with two threads just
like gga, one of which will be just for readline.  There will be no X
interaction, but eventually there will be MIDI.

Let's accept comments as anything beginning with a #, to the end of
the line.

I guess it's time to start laying down code.

I think a reasonable plan of attack is to make a bare lexer, then a
bare parser, then the integerizer and strength-reducer, then an
interpretter, then the compiler, then the sound output and command-line.


November 23rd....
I laid out a bare lexer, it is fine I guess.  I expect it to work on
the first try even though it has never been executed.  Laying out a
syntax definition is tough work.  It is so tempting to realize "this
is useless information" and drop it...Like semicolons between
statements, or commas between function arguments.  Why does everyone
else use them?  Are they really that helpful?  I don't think they
really disambiguate anything...  Parentheses have meaning and role but
even in C I think commas in function calls are useless.

I posed the question in the channel and Dennis quickly got to the
heart of the way I was thinking of it, are there any operators that
can implicitly occur between two pieces of data, or would you only
have two pieces of data in a row for the purpose of generating a list
of arguments?  But Neil got to the heart of it, what about unary
operators?  I can give up ++, but I want to be able to use - as both a
unary operator and binary.


November 25th...
On error do we return NULL or use setjmp/longjmp?  If we are willing to
depend on setjmp/longjmp then will that even really help us continue
if the buffer runs out?  I do not think so...

I think this is a characteristic of other compilers, that they are able
to continue after an error condition...  They just start generating
valid but inaccurate structures (i.e., structures that have valid
pointers but represent a program different from what the user typed in).
And they set flags so the final stage doesn't run that generates the
object code (or, in this case, integrates this statement into the
run-time environment).

I think it's obvious I should do it this way because this is already
what the lexer does, it doesn't even generate the error messages.
The actual check for an "error state" would be performed at the top in
scan_statement, to decide whether or not to either integrate a
definition into the dictionary or executes the code.

Another pretty much unrelated question is: should compilation be
incremental?  I.e., whenever a := word is defined, should it compile
it and add it to the pre-compiled dictionary, or should we only do so
whenever a := word is first executed, and at that point compile
everything needed at once?

I guess my only real change in scanning behaviour after encountering
an error will be to only report the first error, as the later ones are
probably cascades?  What about scanning past a semicolon?  That should
probably be impossible - nothing should actually 'consume' a token
unless it's got a use for it.  A semicolon might get inappropriately
scanned somehow but it would be rare or difficult.  Of course a
missing semicolon would be all sorts of bad, it would presumably scan
one token at a time trying to find the end of the statement, but it
never would.  I guess really we'd have to make it just drop everything
in the input buffer when an error is encountered in the top-level
routine, to prevent potential infinite looping if we have a token
nobody can consume.


January 8th 2004.

Most everything works.  Even compiling.  Occaisonally tones get clipping
when I feel it would be inappropriate, but it's fairly rare.  Perhaps
even just a CPU speed problem rather than clipping.  It is not as fast
as I would like -- a likely excuse is that gcc SUCKS at 64-bit math.
Wait, no it doesn't.  It gets multiplies good, but divides are still a
function call.  But what can we do about it?  I don't think I can
implement a much better divide.  I could get a 64-bit processor, but I
bet most of the CPU time is spent outside of the interesting code --
function call overhead and the like.  I wonder if all these stupid
casts in the interesting code make any difference at all.  Hmmm.

So I have 3-operator synthesis going on and everything...  I think it
is to the point where tomorrow with luck I could start running
soundblaster "GENMIDI" patches on it with a simple C translation
program.  We'll see.  I may need some sort of reverb concept, or some
other forms of distorts...but I think I can fake it.  I'm a bit
curious what like "drum mode" is all about.


January 12th, 2004.

Fixed some bugs in the compiler, especially involving termseqs.
Bug fixes aren't exciting...so...I added a new "evt.c" to handle recording
and then playing back streams of events.  The idea is we save a stream
of events, then go at it with a text editor to make everything line up
just so.  I haven't decided if this format allows us to really do what
i want to with regards to overlapping sequences.  Right now it looks
like we're best off storing overlapping sequences in a separate file.
But I think with some effort we could store overlapping sequences in
the same file, but the syntax is hard to decide.  I guess if we run
with the separate file construct then we want separate files to
potentially just be separate functions within one file.  But then I'm
inventing a whole new function syntax.  And just using "play foo.evt"
as a kind of function call, I think that's actually pretty sweet.

I also added conversions so that strings can contain note
specifications that work like the numerical frequency:
    C-5  middle C
    G#3  G in octave 3
    Cb5  same as B-4
Note that my octave starts at C, but maybe it should start at A.
Prior art?  MIDI users seem to start at A, but MOD tracker people and
MIDI actual technical people think of it as starting at C.  It has
been decided - start at C.


January 18th, 2004.

I have decided I need to make a tracker.  I think it needs the basic
file format of a starting line that identifies it as a tracker object
with a "bpm" setting, and maybe some other optional flags.  Then the
actual lines will be one beat per line (so a beat should be a 16th or
32nd note or something).  A line starts out with an event for the
first track, then an optional sequence of "|" followed by further
events for other tracks.  Really, mixing one track with another is
just gonna fuck with your head, there's no problem with it.  And
there's no problem with multiple notes being active for one track.  I
am going to stop relying on the "noteup" command and instead interpret
the special "@1" (lasts for one beat until note up) opcode.  snd_add
will return a reference of some kind to the structure in which note_up
should be modified (to be used by the tracker and the midi part).  It
needs to be decided how "noteup" will be handled in the old-style .evt
files, which should mostly stick around..

The tracker will provide some commands like tload (load a tracker
object into memory for fucking around with), tplay (play a loaded
tracker object), tsave (save changes, maybe make this implicit on
exit, with like a ttrash to drop them), tloop (play the tracker over
and over again, to be mixed with tedit), and tedit (load vi in a new
screen with the waveform open [tmpfile], and poll so it is reloaded
when vi saves).  

Tracker "current location" should be marked with indexes, not
pointers, so as to make it more ammenable to reloading..

Converting a .evt file to a .gtr file will be almost but not quite
non-trivial.

I have been playing with waveforms a bit trying to come up with, for
example, percussive sounds.  Using op1 we can survey a large number of
timbres, which are difficult to characterize or remember.  op2r
(modulating the modulator) is just op1 with distortion, so find the
general tone with op1 then tune it with op2r, that's my bet.  op2a
(added) is totally unpredictable for me at this stage, i think, except
that it sounds like op1+op1 with the two different modulators.  For
the "amount" arguments (A1, etc), I have been using "300", but I think
I should be using "x/2", so that it scales as like a percent of
frequency.

I want to try modulating a wave with white noise.  I just did.  It's
pretty boring...just kind of gurgly.  Might be nice for some drum
effects.

I think all of the interesting waveforms i want to play with require
lots of over-time changes.  like adsr on the FM or even some
mutilation of the frequency.


January 21st, 2004.

Mostly everything is working fine.  I decided to through out the "evt"
crap because it didn't really fit all the existing framework that
well.  I vetoed making the tracker do load/save, it just plays direct
from the file one line at a time, with basically the syntax discussed
above. (events separated by |, with as many events as you want on a
line, with @ specifying when the note up happens).  I think I need to
make a "record to tracker" functionality of some sort, and display
functions for the existing tracker stuff (just status, not actual
displays of the tracked data, probably).

The number at the top of a .trk file is "ticks per minute" (tpm).  One
tick per line, as you would imagine.  The loop functionality and
everything works on the first try now that I've got it written...

I started to get some jumpiness, so I increased buffering from 2x to
4x 4096-byte buffers (which should be about 25ms each).  It still
seems responsive, I don't even really notice the difference.  But just
two 3-operator sounds at once eats 10% CPU, so I fear in order to do
serious music, I will eventually hit the limit, so I should figure out
what needs more optimization..  From a performance perspective, it
would be unacceptable to need to "burp" for recompiles, but I think
the current framework could actually be kept and we just make all the
pre-compiled instruments happen at original load time, then use the
interpretter to direct everything from there.  I should probably
profile it -- is the compiled code eating that much CPU?  Also should
play to decide if I should be using gcc-3.3 -O3 or what.


March 26th, 2004.

I sure have done a good job at building up a huge todo list.  And the
little things I've been fucking around with have all not been on it.

I've decided my first real project is going to be a cover of Belle and
Sebastian's I Don't Love Anyone.  The biggest issue that I haven't
even begun to firm up is how to deal with vocals -- I'm tempted to run
my voice through a pitch-shifter or similar distortions, but that
would require essentially a whole new program (maybe plugins for gga?
I'd have to finish writing gga then...) to deal with waveform audio.
Alternatively, I could somehow make these plugins work in ggb.  Which
is also feasible, but it would require a framework for
effects-processing in ggb, which has so far been untouched.

A framework for effects-processing may be a good idea regardless, as I
would like to be able to apply various filters to white noise to aid
in the generation of percussive sounds.  I guess I could make a new
type of function taht allocates a lot more temporary space and uses it
for linear convolvements or whatever the fuck that's called.  In this
case I should perhaps start out by throwing together some basic filter
programs just to make sure I understand the math before I break my
main program.  Or maybe I should just break my main program because
it's easier to experiment here.

I'm trying to figure out the best way to solve the performance
problem.  There is a definite tendency to simply buy better hardware,
even though that's a peonic approach.  I have decided what I want is
an iBook G5 (64-bit w00t).  They are not yet manufactured.

But the more immediate concern is how to write a tracker.  I think the
idea so far is to define a set of dictionaries.  Each dictionary
defines a mapping of [a-zA-Z] to either a track or a command (52
distinct letters in each dictionary).  Each track specifies which
 dictionary it uses and the number of ticks for each event (which
may be zero) and a chain of events which are played separated by ticks.
The "main" dictionary has all letters played at once.  When defining
something in a tracker file it looks like this:

  dict_X fromdict 128 [a b a b a b a b a b a b ccbbccbba b a b ]
  dict_Y: command
  # comment

the first example defines a letter "X" in dictionary "dict" using
fromdict_a, fromdict_b, fromdict_c played at 128-tick intervals.
The next line defines letter "Y" in dictionary "dict" to execute
command as if it had been typed, but with a special @xx syntax to
generate a "note-up" event 16 ticks later.

The normal command "rate 123" sets the tick rate in ticks per minute.

Ideally the tracker file is read in its entirety and reduced to a
stream of events in memory identical to the current format.  The
"next event" pointer should also maintain a "total elapsed ticks"
counter so if the file is re-read while it is playing, it can jump
into the new data structure.


April 3rd, 2004.

Implemented the tracker pretty much exactly as specified above.  There
were some "oh shit" moments as I ran into unexpected difficulties
actually using it, but once I wrapped my mind around the act of using
it, it's actually very flexible and fun to change around.  The lack of
a 'stop' tracker command is actually the most annoying limitation...
*sigh* finishing touches are butt.

As far as making the pink() and blue() functions, it should be pretty
trivial...  The only concern is I want the buffer length to be (within
reason) variable.  I think I should make it just allocate a static 16
or 32-sample buffer and cap the variable at that.  So in temps it would
need a buffer index (counting down?) and the slots for the buffer...then
actually computing the value would count up that many steps into the
buffer.  The pink filter would add the samples and divide by num (the
number of samples).  The blue filter is a little bit more debatable...
I think it should be half of the first sample minus the other samples
divided by 2*(num-1).  I guess we really should accumulate everything,
so we would do it as (num-1)*samp[0], then for samp[1] to samp[n-1] it
would just be subtracted, and in the end we divide by (num-1)*2.  The
blue will probably be overall quieter than the pink, it is perhaps
dumb, I'm not sure normalizing by absolute value is necessary, but
let's honour the principle of least surprise applied to clipping.

I looked back at old entries and discovered I spelled out what GGB is,
so it's not necessarily going to be one of those forever-mysteries.
*sigh*  and it's a really lame name, it was clearly meant to be a
forever-mystery.  Unfortunately, spelling this program's original
design out in a stoned fashion has not been kind to what details were
recorded :)


May 2nd, 2004.

Looking for some busywork, I have implemented a basic stupid online help
system.  Also added some useless crap to cmd.c.  Yay.

I'm increasingly convinced that my cover of I Don't Love Anyone should
be extremely abstract.  It should have essentially the same lyrics,
and I think I would keep the chord progression, but that is all.
Rhythms, in particular, are going to be totally mechanized, and the
vocal melodies will be smashed.  For this I will definitely want
distortions.  I originally thought I'd try to sing it and use
distortions to conceal the fact that I can't sing, but I think that
should become central.  Read it like a poem, then maybe muss it up a
bit.  I think excessive repetition may be key here.  And perhaps also
vocal-overlapping (like a round).  Very cut-up.  Tension created by
holding onto a repetition or a chord riff longer than natural.

I still think I ought to pound out the keyboard solo, that can
definitely be taken and run with, especially once it is understood.


July 7, 2004.

The things that frustrate me when I sit down and play with it are my
poor variety of instruments and an inability to do any sort of
recording.  So I think I ought to make something that records to .mid
(or similar) and then other tools can extract from that to whatever
sort of information I need for tracking (i.e., they can solve the
quantization problem).  I don't know what to do about the instruments,
except to become more comfortable tweaking them.


September 1, 2004.

Looks like a good place to start would be with saving MIDI events with
timing information...Will be a simple text-format file that looks as
follows:
   [A-Z][0-9]+,[0-9]+
The first character will be a command, then an integer number, then
another integer number.  The integers are optional and default to 0 if
omitted.
   T123       delay 123 ms
   N123,123   press key 123 with velocity 123
   U123       release key 123
   S123       sysex event #123
Okay, done.  My taste is being offended, but I don't know a better way
to be building this stuff.  I will count on experience to show me my
errors, rather than looking for them.
Not tested.


September 2, 2004.

Time for some waveform() functioning!  Every time things get a little
uglier, I guess, but waveform() works now.  A valuable thing to know
about a project, especially when it is getting ugly, is that you will
finish it.  I don't know if I know that about this project, but if I
did, I'd know that I'd work through (refactor, if it becomes obvious)
any mistakes in this code, so I wouldn't worry about them discouraging
further progress.


October 18, 2004.

So I have played around with some modifications to the tone over time.
Some fairly subtle effects with chirps and wahs by changing the FM
synthesis arguments.  Then I added a volume tremolo to ADSR as part
of a mistake and it became quite another diety.  You get polyrhythms
between the tremolo in the FM synthesis and the tremolo on the main
volume.  It's pretty cool.


November 20, 2004.

Disco beat:
beat       1+2+3+4+
hihat      xxxxxxxo
rhythmguit  x x x x
bass       x ? x ?
snare        x   x

Or maybe it should be 2 measures of 4/4, with a more sophisticated rhythm guit
beat       1 2 3 4 1 2 3 4
hihat      x x x x x x x o
rhythmguit xxX xxX xxX xxX
bass       x   ?   x   ?
snare          x       x

It looks like this rhythm guitar moves the emphasis off of the off
beats (2&4), but the eight-note on beats.  Two smaller beats don't
sound significant when leading up to a stronger beat.


December 25, 2004.

So I was playing around and Katy wanted to play, but she hated all the
instruments, so she had me build a xylophone instrument ('fi()' was our
final creation).  She kept on giving me ideas to make it a little
better until she finally could say that it didn't suck completely.  So
it was the first time I really refined an instrument until it didn't
really suck, and it was a positive experience and came out with a very
nice sounding instrument (at least compared to the other ones).  So
I'm gonna add the 'write' command to give some demo for IRC. heh.


January 2, 2005.

I've been playing around with some more 'termseq' stuff, like using it
to make auto-chord sort of stuff.  And I'm finding I really want a
loop construct.  I think the best way to do it is a termseq that, when
it ends, automatically restarts.  Easy enough.  It would be kind of
nice if it would reset any embedded termseqs as well, but i don't
think that's really plausible.  To leave the possibility open, though,
I think I will avoid embedding finite ones inside of infinite ones --
only vice versa.  The new syntax will be [0.1: x, ..., 0.1: y]:

That was pretty fun.  There might even be good ways to exploit the
unintended behaviour for nested termseqs to give indefinitely
increasing sequences?

I'm also adding an 'inst' command to maintain a list of instruments.
It's pretty simple, pretty much the minimum hack necessary to have the
Scroll keys on my keyboard select instruments from the big list..

And finally documenting the language in ggb_help.


January 3, 2005.

Everything is pretty much documented.  I made a 'make release' target,
integrated the meow demo, and made a README file.  It'd be release
quality if it weren't for all the incomplete technical issues.

I noticed there's really no point in building the sine table at compile
time instead of run time.  That was a remnant from running a very early
pre-version of this program on my iPAQ with a StrongARM 206MHz,
computing the sine table took real time.  Jon pointed out that the
same is true of my extensive and painstaking use of fixed point
arithmetic.  He may actually be right -- even the lowest Duron today
has some sort of superscalar megamagical FPU.  It is tempting because
it would simplify some code, it would get rid of some aliasing errors
(which are becoming more audible as I get used to the sound of it), it
might even be faster.  On the other hand I think it is very cool to
use fixed point, and it is still possible (reluctantly) to run this on
like a StrongARM or other non-FPU processor.  It would be a neat
experiment to try.  I should probably do some benchmarking first.


January 5, 2005.

I'm on vacation so I needed to see if it would run on my laptop.
Thankfully whatever issue there was with the OSS output has sorted
itself out.  So I added a keyboard module that displays a graphical
keyboard in a window and when you type in that window, it generates
note events.  It also displays note events that are happening...


January 15, 2005.

I implemented a path search function, so that you can run ggb in a
project subdirectory and it will find the global .ggbrc and fm files.
Also in the directory happy is my bong's theme song.  In doing this
I'm discovering a dramatic limitation of the tracker format.

Really, I'd like to be able to specify note and octave and loudness
and maybe one other thing for each note (i.e., in a sequence
definition), but I really like the easy editability of having a single
letter represent each note.  It is true that we will almost never
need more than 52 unique events in a single sequence, but it kind of
sucks to define a new vocabulary for every little track, and it makes
it pretty much a write-only format.  Which is maybe a livable
restriction.

But I think I will definitely be wanting ways to change the low-level
sound characteristics at even a very high level (i.e., through
several levels of sequence nesting), so a totally new system will be
necessary.  I can't think of any good ideas for this.  I remember I
once had an idea for it that I lost, but rediscovered in that book
about the history of electronic audio, so perhaps I should look
through the photos I took of that...

It does kind of suck how it reads one .ggb_history, then writes another.
There is a better way -- perhaps remembering which one it read and
always writing to that one, so it will never create a new one unless
it couldn't find one in the default path (.:..:$HOME).


January 16, 2005.

I've been thinking about how to make the squencer more powerful.
There are two concepts that are needed...one is to be able to do
complete function calls (like "inst('A-5',0.4);") inside of a
sequence definition.  The other is to be able to have arguments to
dictionaries, or something.

The former can be solved by a new definition format:
   mary_a 8 {
     inst('E-5',0.5); @ 1

     inst('D-5',0.5); @ 1

     inst('C-5',0.5); @ 1
     ...
   }
Basically, one line per sequence point instead of one character.

The other can be solved by somehow giving parameters to either whole
dictionaries or individual definitions.  The parameters should have
default values, and there should be a way to pass them even in the
condensed sequencer definition format.

Consider putting the arguments into dict_0-dict_9...they would be
inserted into the input stream through some sort of macro expansion
capability as like $0-$9, and they would have defaults from regular
definitions, and passing arguments to them would be done on regular
sequencer lines with just parens after the dictionary name, and on
extended sequencer definitions you would need to have a way to call a
tracker element (special character, like colon?):
  melody_0: 1.0   # default loudness
  melody_a: inst('A-5',$0);
  melody_z melody 8 [a a ]
  main_a melody(0.5) 32 [zz  ]
  main_b 32 {


    :melody_z(1.0)
    :melody_z(2.0)
  }
    
When invoking self without specifying arguments the ones passed to us
should be used, so that it doesn't go back to default when calling
local samples.  So like for calls to self from one-line sequence
definitions, implicitly pass ($1,$2,...).  Multi-line sequence
definitions, everything should be explicit.

And god said, let it be.

And it works pretty well after just the usual half hour brush with
the debugger.  Now I need to decide how it is best used.  I'm going to
convert the melody (ha - py - ha - py - bong - bong) to it then mess
around.

It made the crescendo convenient.  Now I just need to decide how I
want to pursue the variation verses.  There should be one very quiet,
one "broken down" without any melody, one with high bouncy arpeggios,
one with "fun" instead of the first bong.  Also of course need to add
bubbling throughout the song.

So as far as the tracker goes, the only feature really lacking now is
some sort of 'reload from file' so I can change it and continue
playing it.  That should be pretty easy, but I may want to add some
sort of "add this starting at the next 8-aligned tick", to make improv
easier..

Also it is becoming very clear that we're going to need some sort of
compiled instrument cache.  Maybe generate an md5 for the complete
text of the function and all called functions, and make a .so with
that name.  If it exists, use that, otherwise recompile and save with
that name.

Implemented an initial version of this .so cache concept, it is now
working well.  Yay!  Instant loading now.  I wonder how long until I
bother to clean out my cache directory.


January 20, 2004.

You know what I am finding really annoying about this program is
there's no way to start halfway through a tracker file.  The song
I am writing I am writing concatenatively (perhaps this is an
argument against it, heh), and so I am always working on the very end
of the song but listening to the very beginning of it over and over.
I really think it would be nice to solve it in the shape of this
existing scripting language, but I don't have any obvious ideas that
sound great off the top of my head.

I suppose I could split main much more coarsely, and have it call an
intermediate layer that triggers the individual instrument
dictionaries?  That way you could even put arguments to the instrument
dictionaries in the middle of the song more easily.  Except there's no
good way to do that because of this offset issue.  The song is
generally on a 10 or 12-bar pattern (I can't remember), but it has
two-bar intros scattered throughout, so we'd need a new way to divide
up time.

The best overall solution I can come up with is to include longer
sequences in the instrument dictionaries, but to still track the main
sequences very coarsely.  This has a more abstract level of control
but it still has the obnoxious very long blocks in main, and it
doesn't really solve any of the real issues.  

I am getting some mileage out of this really elementary idea of
putting instrument definitions in events.  It doesn't solve every
problem, but it allows some of the same sort of manipulation that I
was trying to get at before with the argument concept (which is almost
totally unused).

I keep forgetting that there is a way to reload the tracker file once
it is already playing.

And there's another extended mix for IRC, woo.


February 1, 2005.

I have been considering this concept of making the tracker file a
language in its own right that, when executed, adds events to the
tracker queue.  It could be executed either immediately or from
events (I guess).  It would need to be based either on for loops (and
counters and other support functionality) or perhaps tail recursion
or some continuation passing style.  The syntax and capabilities of
this language still evade me but that such a thing must someday exist,
even if it is totally backwards compatible, seems inevitable now.


February 5, 2005.

What about phase shifting from left to right?  Would this provide an
interesting '3D sound' sort of effect when used with headphones?  I
don't really know but the trouble is, I don't think this language
supports phase shifting, it would mess up evaluation of timest.  That's
something I think I really want, in the next version, in addition to
being FP-based.  Also, I should finally comprende ALSA.  This means
comprehend it, not JUST write up a flame in the why alsa sucks
article.  Post some code in there to really show em :P

I'd like to ideally do these things in a new program for some reason,
in hopes of shaking the dust out of this one.  But I think this one
has reached the point where it is worthwhile, almost necessary, to
chase down the bugs from within it.  The hardest big step will be
switching to FP without totally committing to it.  I guess I can just
rely on RCS to save me if that turns out to be a nightmare in
performance world.  It probably wouldn't be such a big change.

Maybe instead of ALSA I should use SDL!!  Or some other ALSA library.
Do more research on this later!

While I'm at it, I should clear every single todo item!

Especially that language for the tracker scripting!

I've been playing a little with this real nit pick of an issue:
  - way to begin recording automatically at the beginning of a tracker, and stop at the end

I'd gotten to the point already of putting 'write' commands into the
tracker file so the track is of a fixed length.  But the process of
recording the track was still not automated, the shell script could
not run ggb because ggb would not terminate.  I think I've simply
decided that I will put a 'quit' command in the tracker file
and I will just disable this when I'm working with it, and enable it
when I release.  For some reason I feel it is important that this is
the sort of compromise that is made in this project, keep the code as
simple as possible where it's poorly formed, so we don't have layers
of crap piling up on top of eachother in that way that scares off
newcomers.

Now my crap is in distinct little piles, thank you very much for
noticing.

Okay, I have to make my happy bong song into a music video also, with
frame-by-frame style animation created somehow.  So I need a drawing
program that makes it easy for me to draw extremely simple stick
figure stuff.  Ideally the tablet would work well and I'd use that,
hah!  Maybe I should buy a real tablet.  Anyways, I should get back to
specifying all the stuff that I need for next version.  In the TODO
list, I am going to branch off a 'next version' and a 'someday'
version of the list.

Wow this is quite satisfying, I am deleting things out of the list
left and right because they've already been implemented.

I have no idea really how to deal with this phase shift / 3D sound
kind of idea.  I'd kind of like it to be as easy (or easier) to access
as the modifier system in place already for stereo sounds, but
integrating any of this functionality into the thing might be a bad
idea.  It would probably be better to just make it so that the
timest-oriented stuff can handle phase shifts, basically, can handle
addition of more than one timest element to make a function argument.
should be pretty easy.

I'm trying to put all of the "well, this is just a lot of tedious
work, but really should be done" things on the 'next version' list,
and most of the real 'dream a little dream' items on the 'after that'
list.  What I'm learning about project management!  The only one I
have no idea on so far is an important one though, it is making the
new tracker format.  The previous hacks did little to address its
usability hurdles.  Everything those hacks helped with, I found other
hacks that worked with theold way of doing things that worked just as
well, I think, except for maybe in the case of the
ha-py-ha-py-bong-bong tracks, because they featured 3 different
samples in a directly connected rhythm (but thinking too much like
this is hurtful because there's no way to trigger two events on the
same channel this way).  It seems a common approach to solving the
problem I am seeing is to lay out a track as just a long straight-line
sequence rather than trying to enforce internal heirarchy.  I reject
this approach as un-Greg-like although I can see it's tremendous
appeal.  

And so we need for example a language that will at least allow me to
build up tracks based on a more arbitrary time scale, so that I can,
for example, clip out the 'verse' in the happy song.  Also, perhaps a
more 'aspect-oriented' way we should be able to specify the various
additions.  By that I mean we can specify where a tracker element goes
where the tracker element is defined, rather than in some master
sequencer definition..  I should decide if that will be sufficient.
It very well might be.  The only trouble I see is "inserting" tracker
elements, I don't see any way to make that correct the aspects of
things correctly, without involving some clever editor macros or just
doing it by hand.  I guess if sequencer elements could just have an
offset in ticks from their virtual start to when their sounds start
executing, that would probably be sufficient.  That would screw the
aspect-oriented nature, but it would get across the functionality
that is actually needed maybe.  Tempted to implement it and see what
happens, but I'm scared it will enter the same world that my
'dictionary arguments' concept went (a useless piece of code).  I
guess one more piece of useless code will just give me a better
excuse to really gut the tracker format when I do perform the
inevitable gutting.


March 1, 2005.

Well the OS X (Darwin) port using CoreAudio is nearly done.  CoreAudio
appears to prefer Float32 (but will happily convert from SInt16 for us,
apparently), so that is one interesting hint for me about a potential
future direction.

The dynamic linker is a PITA on OS X.  Not so simple to build dylib
files, and no good way to have them reference externs (such as
sine_table).  So a simple init_globals() function to set all that
up doesn't present too much difficulty, and makes the code much more
generally portable (i.e., no longer relies on special gnu binutils
dynamic lib features).

A big issue is the way the sound architecture works...you register a
call back and then it is called by magic.  Unfortunately, magic is not
an accepted computing process.  It is well-demonstrated because if our
render callback goes into an inf loop, it takes out OS X completely
for about ten seconds until (presumably) some timeout gets hit.  Very
frustrating, and very bizarre.  ktracing has given no clues as to how
these callbacks are invoked.  I have a suspicion that they're invoked
in kernel mode and this is OS X's way of saying "rm -rf me plz".

The dlopen() seems to take a while, but only sometimes.  That is to
say, even cached instruments do not sound immediately.

Also, it is abhorrently slow.  Instead of a single sound taking 3-5% CPU,
it takes about 70%.  A serious problem.

Also, I still haven't found out how to set the sound buffer size.

Also, the X keyboard mapping is all wrong.  So 4 new todo items..

And for some reason, waveforms don't work either.


March 3, 2005.

I have somehow broken the audio output on my Mac.  That makes it about
ten times more fragile than kernel-level drivers are allowed to be.

On the other hand, I seem to have figured out the X keyboard repeat
problem.  The problem is that when XAutoRepeat is enabled, the X
server generates extra down events (of course) with no stateless way
to recognize that they are not actual down events.  The problem is
compounded by the fact that there is a wrong up event generated
immediately before the down event.  The fact that the key never went
up and that therefore we have an actual loss of information situation
happening here apparently doesn't bother you if you're stupid and
writing X servers.  But the hack is to just make it so that if a down
event immediately follows an up event in the same call to
keyboard_poll() (i.e., in essentially one X protocol packet), ignore
the down event.  And to make it bulletproof, we also just queue up
events rather than performing them immediately, so that we do not
generate a note up when repeat starts.  This works great under OS X,
though I cannot hear sounds.  I will try rebooting.  *sigh*

Rebooting "corrected" the audio output problem.  

Playing around, we have no problem managing half a dozen simultaneous
notes, so long as new notes are not beginning.  That is to say that if
you pound on the notes, it skips, but if you start them one at a time,
it is all happiness.  Most peculiar.  gprof shows that substantial
time is being spent in __divdi3 (64-bit integer divide I think),
indicating that perhaps life would be improved if we were floating
point.  And I guess it is possible that it is just skipping.  In fact,
it looks a lot now like that is what is happening.  So there may be a
performance problem, but the clipping appears to be an actual sore
point -- I don't know why I never noticed it with the PC version, I
suppose.

I need to learn how Apple's CoreAudio events happen.  My current
hypothesis is that somehow in a way invisible to ktrace, a separate
thread (perhaps in Mach space, rather than ?xnu? space) is created
which is responsible for handling this sort of stuff.  Perhaps these
threads are persistent?

Brain flash: the waveform() function isn't working due to Endian issues.
I guess I will just keep gga as a little-endian format, and swap for
big-endian world.


March 5, 2005.

Now that the waveform output works, it's easy to test it with a song,
and it definitely has dramatically inferior rendering capacity -- it
can't keep up with realtime.  But it's not a linear increase in CPU
time.  I wonder if it is just some ridiculous overhead or if it is
actually way too slow.  I guess I should seriously consider just
writing an FP version to see how it performs.  Make a cvs tag so I
don't regret it.


July 10, 2005.

Well, I've been considering my various scripting formats trying to come
up with a grand new design that brings them together and makes them all
easier to use.  So far I have met with failure.

However, I have another idea for an interface.  This one would exist
mostly as an interactive interface rather than a file format, though
obviously it would be savable.  I would call this one 'patterns.'  The
idea is to record a sequence (some number of measures) live from the
keyboard, then simply set it looping.  Layering would of course be
the main feature.

The main command would be "pattern", followed by an optional pattern
number, then a subcommand.  If the pattern number is left out, either
the most recently referenced pattern will be used or a new pattern
will be created.  All time will be in miliseconds.

Some basic pattern commands:

  tempo [measure length]
    This sets the global measure length, which is how long it takes
    for a single-measure pattern to repeat.  If a single-measure
    pattern is longer than the measure length, it will play on top of
    itself.  The tempo is only used to repeat patterns, not to alter/clip
    what is inside of them.  If the measure length is unspecified, the
    currently selected patterns will begin playing without any repeat,
    and the measure length will be set to correspond to when a user
    touches a key on the midi keyboard.

  new [measures [sequence]]
    Builds a new pattern (or overwrites one if one is explicitly named).
    If measures is specified, that will be how many measures to record
    for at the current tempo (the default is 1).  If sequence is
    specified, it provides the notes of the pattern.  Otherwise the
    notes are taken from the keyboard.  The sequence format is
    "offset1,note1,velocity1,duration1 o2,n2,v2,d2 ..."  Offset is time
    in ms from the beginning of the pattern for the start of the note.
    Note is the MIDI note number (0-127).  Velocity is how loud the
    note is (0-127).  Duration is how long (in ms) the note lasts.
    The notes need not be presented in any specific order.  Notes with
    a negative offset occur offset from the end of the last measure in
    the pattern.

  mute
    Toggles the mute flag for this pattern (default is unmuted).

  start
    Starts the pattern playback engine for all unmuted patterns.

  stop
    Stops the pattern playback engine (also "stop pattern").

  write <file>
    Writes all patterns (or a single pattern if one is explicitly
    specified) to the specified file, with ".pat" added if no
    extension is specified.  The files will contain a sequence of
    pattern commands to be loaded with "source."

  shift <amount>
    Shifts the current pattern amount ms in time (i.e., adds amount to
    all of the offsets).  Negative amount is of course allowed and
    should work flawlessly due to the behaviour for negative offsets.

  inst <instname>
    Specifies the function to be used for the instrument for the
    current pattern.

  list
    Displays a list of all patterns, with maybe some basic display
    information of the contents.


July 26, 2005.

I am having a hard time envisioning how this will be used to produce
actual structured songs.  But other than that, I am very happy with
this pattern interface, by far the most fun way to track with this
synthesizer yet.  I just pounded out an arpeggio, then layered random
stuff on top.  When I realized I hadn't really planned any of the
random stuff and therefore it sucked, I simply imposed an unnatural
rhythm on it ("pattern rhythm 0 2 4") and it all came together.
Very happy.


July 27, 2005.

So really what has happened with this pattern thing is I decided to
build something I first started tossing around back on September 21,
2002 in an LJ article.  The idea is a live performance system with
interestingly tunable parameters that will keep on playing while you
tune the parameters for the audience.  The feature that really made
this interesting to me was a total afterthought.  The first thing
I did was pound in an arpeggio sequence, but I'm not a terribly
awesome keyboardist so after 3 cuts I had two with tonal errors
and three with rhythm errors.  So I made a stupid command to reassign
the 'offset' (miliseconds) value for all the notes in a sequence
according to a super-trivial formula (you specify fractions of a
measure, so "4 4 4 4" is four quarter notes).  When I was deciding
what to do when we run out of parameters before we run out of notes,
I decided on a whim that we should go through the parameters better.
So straightening up this sequence of arpeggios was just the single
command "pattern rhythm 0 4".  Then I realized you could arbitrarily
syncopate things really naively, and I made a result that's almost
listenable.

The real surprise came when I could take an essentially random
sequence that happened to be in the right key and syncopate it into
something pleasant to listen to.  Then I could resyncopate it over
and over again, and it was seamless and etc.

So today's innovation is applying the same concept to the velocity of
the keys.  I had kind of accepted that I would do that after I saw how
fun rhythm was, just as another aspect of rhythm.  But what I really
wanted to control was tonal aspects, like FM synthesis or ADSR
parameters.  Eventually I was like "so really what I need is like a
'y' for my tonal 'x'" then I realized I had such a thing, velocity.
So I think I will use velocity to control various synthesis parameters
to maximum fun and profit.

So now the only lingering pain with this 'pattern' concept is that
there is no way to record a performance, and little way to make an
interesting performance through editing pattern files.  The parts that
make patterned performances interesting is the twiddling with pattern
parameters in approximately realtime.  I could record them using a
simple .evt-style recording of timestamped commandline interactions.
I'll consider it.

I guess if I am controlling rhythm (offset) and velocity, I ought to
control note and duration as well.  I will worry about that later though.
I guess I may also want to keep like a 'reversion list' for each pattern
so that after I apply an effect to it, I can return it to previous
states...  Perhaps "pattern revert [nchanges]", and just something
that saves the pattern every time it is changed, and pushes that
onto a stack?  nchanges then would say how far to dig into the stack.
Maybe it makes more sense for nchanges to count from the top of the stack
(the original waveform), so that we can have revert use a non-destructive
pop, then we can still reference things the same way.  We'll need a more
detailed pattern listing.  Maybe "pattern list" would give the stack if
an explicit pattern were used.

So far I like that reversion idea I think I may implement it tonight.

One thing I'd like to be able to do that I cannot fathom how to do
simply is insert notes.  Like sometimes a rhythm works best if we can
insert a repetition of a note or whatever.  I guess it is an easy
enough interface if we make it just for repetitions.  Or we could
make it like "pattern new", but it would be additive.  That's probably
the best option.

Also, I want an interface like tinyfugue, where you have a command line
at the bottom that is not interrupted by stuff scrolling by.  Or
alternatively I need to be able to output changing status information
(such as measure number) into an X window.  Perhaps I should have that
X window contain some clickable buttons, and I could run it on
something with a touch screen (like my ipaq heh ugh).

Also, it might be nice if there were a way to control the actual
playback speed of patterns.  The tempo obviously isn't what we want,
that's just a loop rate.  Probably we'd need to modify the 43 in the
"what is 1ms" determiner.  But that would foul up any recording that
is going on too.

A neat way to modify note values would be to invert something around
either it's mean note, or either extremes.  Should be easy too.


July 28, 2005.

I'm already finding myself wanting to manipulate ways of looking at
the data that I haven't even considered, and which wouldn't be really
trivial, at least not in a "clever" sort of way.  For example, I would
like to mute the fourth quarter of every 2 measures.  


December 12, 2005.

I've kind of had this same brainstorm going on for a while, so let's
write it down.  I want to input "a rhythm" and distill it down to an
enumeration of event types in a particular sequence.  It's not a large
conceptual change.  Then the rhythm would be stored as just a sequence
of timed numerical events, stored independent of what the numerical
events represent.  The current "pattern" concept is almost nearly
this, except that it conceptually stores a uniform function invocation
for each event.  For example patterns would store:
    inst('C-5',1.0);
    inst('E-5',1.0);
    inst('G-5',1.0);
    inst('E-5',1.0);
for an arpeggio, but I would like to store more like:
    func1();
    func2();
    func3();
    func2();
If you want to reproduce it as an arpeggio, you would define
    func1() = inst('C-5',1.0);
    ... and so on ...
But you could get something that is not immediately related with:
    func1() = bassdrum();
    func2() = snare();
    func3() = hihat();
You could do this with a much larger number of events -- with complex
Orbital rhythm sequences or melody lines.  Basically I want one way to
abstract away a "theme" and then port it between scales, instruments,
and so on.


March 9, 2006.

I've become more convinced after playing with some professional
keyboards that if I'm to remain naive in how I program this thing,
I need to compensate by using floating point.

The conversion is pretty much done.  Bizarrely, interpreted stuff
sounds great, but compiled stuff is (I believe) simply way too slow.
Perhaps it's something about branching into another address space or
something?


May 28, 2006.

I've been trying to figure out why the compiled stuff doesn't work.
A couple things make me suspicious, such as tmp_for_idx and
tmp_for_countdown should probably be ints instead of floats (there are
some suspect comparisons to zero about).  But really it just seems to
be *way* too slow.  Even if termseqs aren't used.  I don't understand
why interpreted code is almost "fast enough".

Oh, and the thing that really bugged me about ggb compared to
professional synths is the timing.  You can very much hear how two
keys plunked 'at about the same time' are aliased.  We need some way
to consider midi events that do not begin necessarily at the beginning
of the frame.  Perhaps it would even be worthwhile to introduce a
one-frame delay, if it meant that the spacing within the frame would
be more accurate.  Even acoustic instruments produce a predictable
delay, it only sounds like shit because the delay is quantized.

Finally I profiled the ggb_inst_src.c file and found it was spending
almost all of its time in this naive little fmod:
   static value_t fmod(value_t x, value_t y) {
      while (x >= y) { x -= y; } return x;
   }
I noticed it was only used for generating an index for sine_table[]
dereferences, so I changed it to this simple #define:
   #define fmod(x,y) (((unsigned)(x))%((unsigned)(y)))

It still doesn't work, but I think it's much closer.

Actually, fmod() should really have a float result, so I've settled on:
   #define fmod(x,y) ((x) - (((int)(y))*((int)(((int)(x))/((int)(y))))))
though
   #define fmod(x,y) ((x) - ((y)*((int)((x)/(y)))))
is faster when we can't guarantee that y is an integer literal.

Actually, I'm using:
   #define fmod(x,y) ((x) - ((((int)(y))*((int)(((int)(x))/((int)(y)))))) + \
	(((x) < 0) ? ((int)(y)) : 0))
because it has a fudge factor so it works on negative numbers.

I changed everything to use itmps as appropriate.  Still need to make
all occurances of 44100 and 22050 use SEC_MULT and eliminate the useless
attempt at rounding.

Now it "works".  It is a little slow.  More importantly it doesn't sound
"right."  I would say it may actually sound worse than the integer
version.  It is time to numerically compare the outputs and see where the
difference iscoming from.  Also, it is slower than the integer version,
I think by about 5x.  Not too bad, really.


July 3, 2006.

I messed around with fmod() some more, and it now sounds the same as the
integer version.  The only difference I can detect is that the beat
notes present when chords are played have mostly disappeared, or at
least been reduced to only relatively high frequencies.  Which is the
kind of thing you'd expect to come from rounding error.  I'd say now
the sound is somewhat less interesting because it deos less zany
slightly-detuned things like that, but it is also more 'rich' because
all of the parts of chords tend to come through better now.

The nice part is that float is almost as fast as the integer version.
On the iBook it has actually improved from 7-note to 8-note polyphony.


July 4, 2006.

Just doing lots of little touchups today.  Got rid of t_ and FAST_MULT,
some help changes, and so on.  The more I play with it and think about it,
the more happy I am with the float change.  It isn't a performance hit,
and it just makes a lot of nuissances go away.  I also changed the
sound buffer from 23ms to 0.7ms and that is an improvement as well,
though really I should add realtime scheduling.  You really notice
all of the improvements a lot more when you play it on a MIDI keyboard,
the responsiveness is up and the overall crappiness is down.  Still too
slow to quite render happy happy bong bong on the mac though.

I still haven't produced too many instruments that I'm very impressed
with.


July 16, 2006.

I added a really basic pattern editor.  It just dumps a pattern to a
temporary text file, launches nvi on the file, and then reads it back
in when you're done.  Really, to be useful, I need a pattern trace as
well.  Also, the editor should be launched in a separate screen, with
a separate thread monitoring the file and reading it in every time it
is changed.

I also added the "split" command that splits the keyboard on an
arbitrary note, assigning the notes above or below that point to a
different default instrument.

As a stop gap, I went ahead and added "pattern trace", just to provide
a real-time trace of what is going on.


July 24, 2006.

The "pattern rhythm" command needs to be able to specify the duration of
the notes, rather than just keeping the old durations (at least, as an
option).  Also, it would be nice to be able to think of the involved
numbers as more of a ratio.  Perhaps a common divisor?  So, try this new
usage:
    pattern rhythm <divisor> <delay0> <delay1[:duration1]> ...

delay should be specified in 'delay/divisor', so for example, you would
use:
    pattern rhythm 16 0 8 2 2 2 2
to provide you with a measure of half-note at the beginning of the
measure, then 8th, 8th, 8th, 8th.  The duration would work as a decimal,
i.e., if you changed that to 
    pattern rhythm 16 0 8:5 2:95 2:95 2:95 2:95
The first note will play for 50% of its duration (I.e., it would play a
quarter note, then a release/rest for the first half-note), and the 8th
notes would be legato, they would play for 95% of their duration.  We
could even keep the 'o' concept (just use the original offset), 'x' (make
it divisor/delay), and 'm' (absolute position based on delay/divisor).

This seems a little cumbersome.

A related goal is to be able to edit these more naturally, as if it were
sheet music.  Another related goal is to be able to treat patterns and
tracker elements interchangably.  Perhaps a quick-and-dirty quantization
of the pattern would do what we need, or perhaps we need to make it so
that they are both really the same, and make it so that you can edit a
tracker in real-time the same way we now manipulate patterns?

In the mean-time, I'm just going to make "pattern trace" take an argument
for how many notes per measure to divide time up into.


September 11, 2006.

I just saw some live drum and bass at a goth night and it was very
primitive and reinspired me to pursue my original simplistic take on
layered live performance.  I am every bit capable of doing as well as
this guy, at least.

The elements I want to accomplish are:
  * orthogonally specified rhythms
  * orthogonally specified sequences (i.e., arpeggios or boom-tss or ...)
  * orthogonally specified floats (i.e., crescendos or knobs)
  * timing-independent generation

I think I've got a basic idea for a command set.  Each line has the
following elements (lines are probably entered in some modal fashion):
   <delay> <channel> <op> <args>

  delay: omit for immediate, '+' for next measure start, '+123' for
    123 measures from now, '.' for "the measure we delayed until last
    time".
  channel: numeric for selection, 'a' for all, x-y numeric for
    inclusive range of channels, x-y,z for range and z
  op args: a few possibilities:
    i select the instrument
    r set the rhythm
    l perform a logical operation on the rhythm
    m mute
    c reset (clear)
    s record a sequence from the keyboard

auxiliary commands that are not really channel specific:
  tempo set
  master stop/reset
  load/save of channel state
  slider controls - set level, set fade, set analog input (to use a
    knob or so on)
  map a specific knob to a specific global variable
  undo last command
  
Here are some specifics about how I imagine the ops working...  The
instrument should be an expression that takes one formal, call it i,
that is incremented for each note event on that channel.  If your
instrument were a bass drum, you would ignore i.  If it is a 3-note
arpeggio, i%3 would be an index into it.  As a helper for this, I
think I would add a new piece of syntax that would be something like:
   { i : expr_0, expr_1, expr_2, ..., expr_(n-1) }
which would play expr_(i%n) depending on the value of i.  In other
words, your basic switch statement.  So your basic arpeggio could be
defined as:
   inst( {i : 'A-4', 'C-5', 'E-5'}, 0.5);
That would only work if the switch syntax worked in interpreted mode
as well as compiled, but it might as well -- it is not
performance-critical like termseq, since it is a much simpler
selection criteria.

Maybe the instrument expression should get a second formal called 'j'
that is the fractional value for how far through the measure we are.
I.e., for a sequence of quarter notes it would be 0, 0.25, 0.5, 0.75,
0, ...  If you wanted to switch it, you would do like { j*4: ... }.
The switch would need to have reasonable rounding rules.  Probably add
epsilon ("almost zero") and then round down.

The rhythm op would just take a list of nibbles, and divide up the
measure into the number of bits you get, and trigger a note event on
each set bit.  So, for example, to hit 4 quarter notes in each
measure, you could just use 'f' (binary 1111) or '1111' (binary
1000100010001000) or so on.  Generally I would probably specify a
measure as 16th notes (i.e., a 4-nibble value), and use 6 nibbles for
triplets.  Probably there should be some technique to specify multiple
measures, like r1 would use two measures, r2 would do 4, and r3 would
do 8 measures and so on.

The logical operation would be for combining channels.  They would
side effect onto the selected channel (call it 'x') and use the <arg>
channel for an operand.  Like AND would be:
   x &= y
The interesting ones are probably XOR (x ^= y) and AND-NOT (x &= ~y).
For completeness we should probably have AND and OR and maybe OR-NOT.
The logical operation would be applied on the rhythm mask.  If the
rhythm masks are the same bitlength, it proceeds in the obvious
fashion.  Otherwise we need to invent some principle of least
astonishment semantics for lining them up.  The idea of the logical
operations is mostly so you could, for example, define a sequence of
quarter notes on the bass drum and then allocate a channel with a
snare on beats 1 and 3, then you could use AND-NOT to combine the two
channels to get rid of the bass hits that overlap the snare hits.  May
be awkward in practice.

Mute would just take the number of measures to stay muted.  

Reset would completely clear everything about the channel, killing
output.

Recording a sequence is a bit of an afterthought, but I like it just
because it would break up the trackeresque sound that will become
overwhelming if everything is done with (at best) 16th note
resolution.  Probably the best way to implement it is to record the
rhythm from the keyboard at a high resolution (like 64ths of a
measure).  I am kind of torn how it should record which notes you
play.  It could ignore them and take just rhythm input (maybe it
should have several possible recording modes).  Or it could take the
name of a more traditional instrument function that takes (freq, vol)
and it would generate its own expression using switch expressions to
do the appropriate playback.

Dealing with crescendos is a real difficult subject for me.  Probably
we should have a general bank of global registers used for these sorts
of things, something like x1-xNNN.  Typically you would use x1 for
channel 1's volume, x2 for channel 2's, and so on.  But you could use
whichever x for whichever property you want.  The x's could be
assigned to knobs (which I don't have hardware for, but I guess I
could use a joystick or a mouse).  Or I need to invent a way to
manipulate them automatically for implementing a variety of crescendos
and so on.  It is tempting to just implement a set-volume and
fade-volume syntax, but a little bit more flexibility might be nice,
particularly because I might like to add an LFO or something.  The
simplistic version might be enough, since I could add a function
wrapper around the x values that implements LFOs and so on.

The graphical display would be important.  Probably it should have a
window that shows like the next 16 measures or something.  It should
have a marker for where it is currently playing.  When it reaches the
end of a measure (or every four measures or something...just to save
on screen refreshes), it should shift all of the measures to the left
so that the measure that is just starting is at the left end of the
screen.  There should be a marker for where the "current measure" is
(i.e., what you get with '.'), and it should have a marker for where
the "next" measure is.  Time goes from left to right, channels from
top to bottom.  For each measure it should show a box that represents
the rhythm bitmap, and maybe just a little bit of text to represent
the instrument.  Beneath all of the channels, there should be a list
of the global variables, showing a basic graph of their anticipated
values.  Where queued changes are, the graphics should be colored or
highlighted.

The idea seems pretty overly simple, especially since melody or verses
would be tremendously cumbersome.  It is really not any more capable
than the existing 'pattern' concept, but I think it has a better level
of abstraction.  At any rate, I'm certain it is sufficient to generate
a performance like the one I heard tonight.

I think probably the key idea of all of this jibber-jabber is the idea
that rhythms should be a bitmask, and that abstracting away the
sequencing should be done somewhat separately from the patterns (i.e.,
in the switch expressions).


Sep 12, 2006.

Some ideas that might help with rhythm instruments...
You can assembly a triangle wave in a retarded fashion:
   inst[x,y] := 0.3*y*[1/x: (t/(1/x)), 1/x: 1-(t/(1/x))];
that is:
    |   /\
    | /    \
  --|--------\----
   0|        t=2
    |

A single wave of a triangle wave doesn't sound that much different
than a single wave of a sine wave.  It turns out relatively low sine
waves sound for like 10ms, which is long enough to use a single wave
for an entire base drum.  Which I suppose is pretty much what you
hear with the initial oomph.  I wonder if it goes much higher frequency
after that?

One cycle of a sine wave:
   inst[x,y] := 0.3*y*[1/x: sin(x*t)];
Or a half cycle sounds about the same, but more staccato.
A quarter cycle has a click because it ends at 1.0.  It seems to me that
there should be a better way to fade off than the way the sine wave
naturally crosses zero, but I'm not seeing it.  I mean, I guess the best
would be to go for maybe 10 cycles but get quieter very quickly.

You really don't get much audio information in a single cycle, but it
does sound rather convincingly like a minimalist drum.  It sounds almost
woody.

Wee staticy:
   inst[x,y] := sr(0.5*y,0.02)*sin(((x+300*white())/4)*t);


January 24, 2007.

I have just listened to the two patterns I made on 050726, from
the context of trying to understand groove/layering techno.  And
they really aren't bad, especially for the first (and only) two 
snippits I've made with that particular patterning tool.  So I
don't know why I found it so discouraging and gave up.  I really
just don't have much interest in exploring the range of things you
can do with this program, and it is frustrating because when I do,
I discover cool things, like the better xylophone, or these simple
melodies.  But I just can't convince myself to be "creative" in this
medium, or even to systematically explore the possible variations.
When I try I'm just like "meh, it all sounds the same, whatever."


August 4, 2007.

I looked back at some previous entries and I still am not happy with
any design for a good tracker thing with a separation of rhythm and
melody and instrument.  I think the "switch" concept might be nice,
and it puts the expression of melodies in the language, and allows
other things (like amplitude or instrument) to be specified the same
way a melody is.  Very generalized.  So maybe I should do that, even
if I don't wind up doing the bitmasked rhythm thing from the Sep 11,
2006 entry.  But I think the bitmasked rhythm should be sufficient,
so maybe I should just do that too.

I'm just hesitant to write yet another throw-away tracker module.  By
now I ought to have found a lowest common denominator, I should be
able to write a language in which I can write these throw-away tracker
modules.  That would be nice.  I think the answer is that I need to
read the computer music book I have, and allow its greater wisdom to
inspire me.


August 5, 2007.

I'm going to try to do an exercise for each of the articles in this
Curtis Roads/John Strawn "Foundations of Computer Music."

Looks like in order to really get his envelopes right, I have to add
exponential envelopes.  It looks like what would be useful is a
function that is defined from 0.0 to 1.0 and has output going from
0.0 to 1.0 over this range.  It looks like we need two arguments, one
to specify the deepness of the curve.  Call them "x" and "depth".  It
looks like we want something like:
   (exp(x*depth)-1)/(exp(depth)-1)
As depth approaches 0, it approaches a straight line (but at 0, it
becomes 0/0 and fails).  At around depth of 2 or 3 looks like a
regular exponential curve.  At higher depths, it becomes more deeply
curved.  So that's what I'll use.

I've went ahead and implemented it using the floating point exp()
routine.  It looks like I can call that about 5 million times a
second, so it is very potentially performance-limiting.  But I'll
have to think for a while to come up with a better idea.

Also, I'm going ahead and adding the gnuplot output debugging function
graph().

For Chowning's bell, the exponent is very useful because it's just a
regular exponential decay.  Playing with the "depth" of the exponent
produces very different sounds.  Also, the envelope clearly should
change somehow with frequency.  It sounds best to have the exponential
depth change with frequency.

...

Well, that was fun.  And getting exp() and graph() finally implemented
was all goodness.

Along the way I realized I was making a ton of inefficient code.
Currently to play one of the "chfm2" (C1:M+C2:M) sounds, it takes 4-5%
CPU per note on my PC.  That's really not so bad, really.  To play a
bell sound (uses exp()), it takes about 8% per note, which is worse.

So the lower-hanging fruit is exp(), but the interesting problem I want
to address is common sub-expressions and constant merging.

It seems like I need to implement an optimization pass.  First it needs
to expand everything into one tree (this is done already in
eval.c:one_tree()), then it needs to perform some optimizations.  To do
the optimizations, it needs to do some sort of depth-first traversal of
the nodes.  It seems this is best as three passes...
  1> a depth-first walk eats up low-hanging constants.
  2> another depth-first walk implements value numbering to merge
common sub-expressions, which are put into a structure which compile.c
evaluates into local variables before evaluating everything else.
the reference points are replaced with references to the local variables
  3> then we walk all of the common sub-expressions and the remaining
one_tree and find largest expressions which do depend only on formals
and constants, and put them in another structure which is used to
initialize temps (like num_temps)..

I am a compiler guy, after all.

In order to do this meaningfully, we need some sort of benchmark.  I
propose the happy song benchmark (do this after everything is
pre-compiled into the cache.so dir):
   [greg@stallion] ~/music/happy$ ggb 'source happy.cmd'
   ...
   50.9u+0.9s (gcc: 0.6u+0.0s) out of 53 (98.9%)
That is for a 2005-02-06 ggb (integer) that is just sitting around.
For current, it takes:
   55.5u+2.9s (gcc: 0.7u+0.1s) out of 61 (97.0%)
so that is probably mostly just floating point penalty.  Not so bad.
It's a 2:31 minute song, so that's over 30% utilization for a spare
arrangement with spare instruments.

And the FP one sounds better on the specific part that sounded bad to
me before!  Yay!

Anyways, so that's our target to beat.

...

Always pick the low-hanging fruit first, so, I made exptest.trk,
which takes:
   21.4u+0.6s (gcc: 0.0u+0.0s) out of 37 (59.5%)

First, let's make exp() use the builtin..
   21.7u+0.6s (gcc: 0.0u+0.0s) out of 30 (74.3%)
Thankfully, no significant change from the function call overhead..

I tried a super-naive caching exponential that saved the last ten results,
and no substantial change:
   21.8u+0.7s (gcc: 0.0u+0.0s) out of 27 (83.3%)

I tried just caching the second exponent (which is always the same), and
that brought about a change:
   18.2u+0.6s (gcc: 0.0u+0.0s) out of 25 (75.2%)

We could surely do better, but considering how dumb this hack was, that's
a pretty good ROI.  The most robust approach would be to have exp()
just do a regular base e exponent, and the scaling magic could happen
in the language.  It would be mostly as efficient, though it would have
twice the function call overhead.  But then constant folding could get
rid of the second exp() call and it all gets quite brilliant.  I think
that is the thing to do, because it provides a convenient test for
constant folding too.


August 6, 2007.

I was about to sit down and make constant folding happen, but we have
an issue...  compile.c does not currently work with an op_one_tree,
instead it walks op_fn_calls in compile_tree().  So I guess we need
to first adapt compile.c to work with one_trees.

I think I'm going to go through compile.c and try to simplify it.
First, I'm going to get rid of VALUE_MULT.

To be sure that I am not breaking anything as I go, I have made a
reference copy of "happy.gga" to do binary compares against.

And VALUE_MULT is now gone, with no changes in happy.gga.

Now to remove intermed_t and uvalue_t.

They're gone and tested.  And FWIW our times haven't changed either:
   54.7u+3.0s (gcc: 0.7u+0.1s) out of 61 (95.9%)

So, now to build an optimization framework..

Okay, that was pretty easy.

I will build a constant folder tomorrow I suppose.  It should know
several rules:
   const OP const --> const          (OP is of + - * /)
   builtin(const) --> const          (builtin is of sin cos exp)
   x + const      --> const + x      constants on LHS
   x - const      --> (-const) + x   normalize to addition
   x * const      --> const * x      constants on LHS
   x / const      --> (1/const) * x  normalize to multiplication
   c1 + (c2 OP x) --> (c1 + c2) OP x associative rule (OP is of + -)
   c1 * (c2 OP x) --> (c1 * c2) OP x associative rule (OP is of * /)
   (x + y) OP z   --> x + (y OP z)   associative rule (OP is of + -)
   (x * y) OP z   --> x * (y OP z)   associative rule (OP is of * /)
   x + (c OP y)   --> c + (x OP y)   associative rule (OP is of + -)
   x * (c OP y)   --> c * (x OP y)   associative rule (OP is of * /)
   x / x          --> 1
   x - x          --> 0

Every time one of these rules are invoked, it should be marked to repeat
the whole constant folding game until there are no changes.


August 9, 2007.

Well, implementing the constant folding proved pretty trivial.  But it
reminds me enough of Dignus pat.c that I am confident there are some
doosies hanging out there in terms of bugs.  It's something like 250
lines of rote code so there are probably typos, and there are probably
mindos in the rule set.  At least it doesn't infinite loop!

In the future I'm going to need a way to disable optimization so that
we can prove a bug isn't in the optimizer.

More immediately, we need to be able to trace the activities of the
optimizer.  Currently it gets the wrong answer *and* it takes longer.
Maybe a fuzzy comparison would help, since it could be rounding error.

...

Okay, I found one bug.  An associative rule was flipping over some
divisions.  Also, the x/const => (1/const)*x causes rounding errors,
but they're relatively minor and the fuzzy comparison seems to take
care of them.

The big "happy" test still shows errors with fuzzy comparison (average
deviation of 65!), but only when the 1/const optimization is in effect.
So I guess it must somehow be a sensitive rounding error.  I guess
x/3.0 is substantially different than 0.333*x in base 2.  Removing the
1/const brings it to like 0.0003 average deviation.

Ah-hah!  Changing the %f in compile.c into %.25f seems to have
"fixed" the rounding problem.  Really, a double contains about 16
useful digits, but the default of 6 is way too low.

Well, it totally fixed the rounding problem for my simple test, but
not quite for "happy".  It has reduced the average deviation to 23.4,
though.  It's kind of silly that this little rounding error thing
makes a bigger difference than an erroneous inversion of a division.
I suppose probably the erroneous inversion doesn't happen in my
example except when the division doesn't? (I didn't discover it until
I disabled the constant division optimization).


August 11, 2007.

There is still the fact that the "optimized" version is slower.  I can
only assume gcc just "randomly" happens to create a bad instruction
scheduling or something for the new code.  

The "optimized" exptest also is slower:
   20.2u+0.6s (gcc: 0.0u+0.0s) out of 41 (51.0%)

Which is worse than the 18.2s of cache_exp.  Oh!  It is because "depth"
in this case depends on the frequency, a per-note constant.  We need to
deal with those now.

Wow, that was pretty easy.  The things which only depend on formals
(and constants... no dependencies on "t" in particular) are now
brought out into an op_raised_formals top-level tree, which compile.c
uses to initialize the first several entries of tmps[] on the first
go through.

Immediately this impressive exptest result is achieved:
   16.0u+0.5s (gcc: 0.0u+0.0s) out of 20 (82.5%)

Much improved!

And happy is improved to:
   55.5u+3.6s (gcc: 0.7u+0.1s) out of 66 (90.8%)
Which is basically where it was before I started on the optimizer.


Common subexpressions are a good idea, especially because of the
cavalier way that complex expressions are copied for formal
expansion.  But it will wait.

...

Wow!  Common subexpression elimination was fairly simple, and it
seems to work great too.  Here is exptest:
   13.6u+0.5s (gcc: 0.0u+0.0s) out of 19 (74.2%)
Happy is still unimproved:
   55.8u+2.9s (gcc: 0.8u+0.0s) out of 61 (97.5%)

But it has less room for improvement because the specific inefficiency
I feared wasn't invented yet when happy's instruments were written.


So 763 lines total for opt.c, and essentially no gain or loss for the
common cases.  I think constant folding, in particular, may be a complete
waste because simply evaluating them once per note instead of each sample
is essentially as good savings as computing it once per each function.
The normalization (associative/commutative laws) might help, except it
is not geared towards op_timest or op_termseq, which are the only two that
"raise formals" can't handle.

But if I disable constant folding, I get...
exptest:
   17.0u+0.6s (gcc: 0.0u+0.0s) out of 23 (76.5%)
and happy:
   55.9u+2.9s (gcc: 0.8u+0.1s) out of 61 (97.9%)
So in other words, exptest needs constant folding and happy is immutable.

And for whatever reason, without constant folding it still gets the
same slightly different output as with it.

It looks a lot like my ggb version isn't changing, but it really is.


August 15, 2007.

That first article, the Chowning (1973) FM one (070805.rc), describes
a system called "Music V", which isn't described in detail but appears
to work by making instruments out of "unit generators", which appear
to be like operators in my tree.  They have ones for
envelope(amplitude,duration), add(x,y), multiply(x,y), and
sine(amplitude,freq).  It isn't clear how it's implemented, but you
can see it's not very refined because multiply is both an operator and
an argument (amplitude).  But they were operating on *very* slow
computers back then so other tradeoffs may have been their hot
diggity.

Chapter 2 is "Trumpet Algorithms for Computer Composition" and uses
"Stanford Mus10", which is like a refined Music V.  It has three unit
generators:
   envelope(amplitude,attack,decay,duration,array)
   sine(amplitude,increment)
   random(range,rate)
Now, I'm not sure how random works, but envelope in this case is
explicitly a lot like sine...array specifies a function (a lookup
table), and the other arguments control how that table is traversed.
Just like how I do sine waves, which they now explicitly also do that
way, with a phase increment instead of a frequency.  It is gratifying
to see that they have a similar evolution as I did when I first
started working on these ideas.  They've extracted add and multiply
out as operators instead of unit generators, which is fundamental to
putting it into formulas.

Their trumpet instrument is much more sophisticated and uses some
"reverb" operator which is not described.  But it should be
expressable in ggb language, just a bit of a chore to code.


September 28, 2007.

Neil has got me thinking about theremin.  He wants to build one out of
a wiimote, which gives basically the same information as the USB glove
I got...position and orientation for a single hand.  From youtube it
is obvious that people who have solved this problem already have two
different solutions:
 1) just play a sinewave at the frequency corresponding to the
location for the entire duration of the time between samples, so it
plays a series of discrete frequencies and sounds very computery
 2) interpolate in some way between locations so that we generate a
smooth frequency change over time, so it sounds like a theremin.

We obviously want #2.  The only reason I haven't even tried so far is
I kind of figure with the limitations of my input device (at most like
600 discrete values) and using approach #1 it wouldn't even be
slightly similar to a usable instrument.

This brings a little bit of a question of how to implement it...my
first thought is that we somehow want to keep the second derivative
approximately constant or something.  It seems splines are designed to
do something like this, so that's probably what I should use.  And
if I make the spline degree adjustable, then it can emulate approach
#1 with degree 0 (using 0 points of history), or become arbitrarily
smooth (and unresponsive).

There is a lot to learn about splines theoretically.  A spline is just
a polynomial that takes a sequence of discrete vectors and defines a
continuous path between them.  I kind of want a spline that actually
crosses through the points.  I feel a distinct need to be overly
trivial with this...
  A degree 0 spline is simple, just the step function
  A degree 1 spline is simple, just a linear interpolation
  A degree 2 spline is ... what, a linear interpolation of a linear
interpolation?  

I'd like to find some general way of expressing what a degree 2 spline
is.  One approach is to use a "cardinal spline" which basically...you
have four points of history: p0 (newest), p1, p2, and p3 (oldest).
You define the tangents at the points, such that the tangent at point
p1 is basically (p0-p2) and the tangent at point p2 is (p1-p3), and
use linear interpolation or something between the points (see "cubic
hermite spline") to determine the actual path.  Somehow that doesn't
seem clean to me and it is obvious that it is degree 3, not degree 2.
But it is fixed to degree 3 so I could use it as the degree 3 spline.
Its "tension" is adjustable, which is seems to affect the
interpolation between points.  It must not be linear, I guess that's
why it's cubic.  It seems pretty promising, really, and I could even
just tune it based on the tension variable and have a degree of
flexibility.

Anyways, back to a degree 2 spline defined intuitively.  I'll accept
that it has to be quadratic, and I know there is a way to define a
quadratic function such that it passes through three points.  Then
i'll just evaluate it between the last two points for each frame, and
it's fine.  I can presumably do the same thing with a cubic, though
I'm not 100% certain that a cubic can pass through *any* four points,
and I'm a bit concerned that a degree 4 spline may not be any better
at passing through five points.

...

Even though my intuition tells me that the splining is the interesting
part of this problem, I'm just going to do the simple degree 1 hack
(linear interpolation) and do the tedious parts...namely interfacing
to this USB whatchamajig and coding it into ggb.

...

There is an existing program to convert P5 glove data to Open Sound
Control (OSC), which sounds kind of like basically an IPC-oriented
MIDI-alike...really it's not really any different from gconf or
whatever the gnome IPC settings sharing thing is.  It's so general,
I don't see any advantage to implementing it, unless I happened to
have something that needed it.  So for the moment, I think I will
stick to MIDI as a convenient abstraction layer.  So I will hack
something together to send P5 position information as MIDI events
to a named pipe, and make midi.c capable of reading from several
devices at once.  In fact, this is attractive because if I could make a
general system to map midi events per device/channel to different
instruments and effects, that could actually be useful (MIDI has a
"pass through" connector, after all).  I could hook up both my MIDI
keyboards as input devices, and then have a slide-knob or whatever
mapped to a function..  So that's what I think I'll do.

As for the language interface, I think it needs to just provide another
builtin function, let's call it slider(channel_num, smoothness_factor).
Smoothness would probably be something like 0=stair step,
1=linear interpolation, 2=quadratic fit, or so on.

And then I can resolve the jitter and so on in the input of the glove,
and other hacks that are necessary to providing reasonable channel
values for this glove.

...

I was skimming the computer music book and found an article on
"waveshaping."  Their idea is essentially to apply a function on
sine(), with an arbitrary distortion on its input.  You could map >0
to 1 and <0 to -1 and turn everything into squarewaves, or clip like a
fuzz distortion amp, or introduce higher harmonics in any number of
ways.  In essence it changes the shape of your sinewave, to a square
or triangle or arbitrary "jaggy".  You may think of it as substituting
another single cycle waveform for the sine function.  I am not crazy
about it but I briefly played with the simplest effect, applying an
exponential to the result of sine, and it generated a decent sound.
My intuition tells me it is a sound trivially produced with FM, very
generic organy.

XXX make p5->midi
XXX make multiple midi input
XXX make midi slider input (is this a 'sysex' event or whatever?) in midi.c
XXX make slider builtin in lang.c
XXX add slider builtin call to compile.c
