James Dashow - INHNTRVL programs for the Dyad System

The suite of programs, inhntrvl.exe inhntrvd.exe inhntric.exe inhntrid.exe i6ntrvl.exe inhntr30.c, are all designed to apply the Dyad System concept of the Generating Dyad (and Generating Trichord) to a group of algorithms whose results are to be used in a straightforward additive synthesis procedure.  A specific interval, the version of a Dyad System basic dyad form that is used at each moment in the specific realization of a composition, is made to generate the frequency content of a variety of sounds by determining the way that each of these algorithms produce frequency values.  The composer specifies the two pitches of the dyad, where in the sound spectrum these pitches are to be heard (i.e. which spectrum components are to be the frequencies of these pitches), and the algorithm produces a set of frequencies two of which are the Generating Dyad.  By changing the position of the Generating Dyad in the spectrum, the quality or timbre of the sound that is generated changes, sometimes radically, sometimes very little, and every gradation in between.  For example, the pitches of a system dyad minor 2nd are composed specifically as a minor 9th, say b and c (in octave point pitch class notation, we can use 8.11 10.00).  These two pitches can be called for as the 2nd and 4th component of a spectrum generated by procedure 5, to produce a particular kind of sound.  But these same two pitches could be called for as the 3rd and 7th components of a procedure 5 spectrum as well, and the generated sound will be quite different.  The composer has at his disposition a very wide variety of possibilities all of which contain that same Generating Dyad at various positions within the spectra.  Since the most interesting of these generated sounds are known as inharmonic sounds, these sounds can be thought of as a wide variety of inharmonic "harmonizations" of the Generating Dyad.  Needless to say, there is a great deal of room for experimentation, and there are many more operational details that I've dealt with fully in the detailed write-up of the Dyad System in Perspectives of New Music.  

The INHNTRVL menu, at the end of this document, shows the algorithms that have been coded in the various programs (except for i6ntrvl which is dedicated to another procedure).  The executable versions of these programs have been compiled under DOS, not Windows.  Any Windows except XP can run these programs.  The c source code has been included for any user who wants to compile these programs for a Windows or Mac environment. 

All of the executable programs allow the composer to input pitch and positional data and view the frequency content of the resultant sounds on-screen.  They do not directly generate the sound.  The data can be transferred to a Csound or similar software synthesis program for audio execution.  Rather than transfer all the frequency data by hand, it is possible to transfer the same data that is input to the pc program via the option to write a MUSIC30 score card (which the user can modify to his/her specific requirements) for interfacing with a csound function generator based on the inhntr30.c code (which will have to be compiled and linked to csound) shown as gen21 in the genfuncs.c file.  Another possibility is compile and link the inhntr30.c code as an external subroutine call from a csound instrument, the frequency results being written in an array which is accessed by a bank of oscillators.  There are comments in this code that call attention to the minor changes that must be made so that the MUSIC30 context is modified to that of csound.  Implementing inhntr30.c in one or another of these ways allows the composer to generate these spectra directly from instrument or function calls.

However, the simplest way to adapt this data for csound synthesis is adapt the inhntrvd and inhntrid programs so that the data output is not the pitch, position and AM factors to a score card, but rather the generation of 8 different score cards each of which contain the frequency produced by the algorithm during its generative loop.  This would involve adding an appropriate fprintf statement wherever there is already some kind of print statement for the variable "newHz", in the  genSpecMltAd,  genSpecAdMlt and genSpecAdMlt2 functions found at the end of the inhntr30 code.  This fprintf would be set up so that it is writing to the p-field that expects to contain the raw frequency value to used on a single oscillator in an additive synthesis environment.  Or some sort of procedure can be worked out for automated score generation within the csound environment using inhntr30 code.  etc.


Notational and other conventions-

The Generating Dyad is made up of a "lower" pitch (bottom pitch), referred to as LP and an "upper" pitch, referred to as UP.
The quotes around lower and upper mean refer to the fact that you can have a "lower" pitch actually be the higher frequency of the two pitches in the Gen Dyad, and get different kinds of results.

8.pc (octave point pitch class notation) is the convention whereby the digit to the left of the decimal refers to the octave in which the pitch lies, and the two digits following the decimal refer to the pitch class from 00 to 11, where .00 is c, .06 is gb, .11 is b, etc.  middle C = 8.00; a minor second below is 7.11; A 440 = 8.09; the Queen of the Night F is 10.05;  the 4 strings on a contrabass are 5.04, 5.09, 6.02, 6.07;  the violin is tuned to 7.07, 8.02, 8.09 and 9.04.


sblu is short hand for sidebandLowerUpper; one data number contains the spectral position parameter of the Lower Pitch and Upper Pitch of the Gen Dyad;  1.03 means LP is on the 1st frequency in the spectrum (SBL = 1), UP on the 3rd (SBU = 3);  
3.07 means LP is on the 3rd frequency in the spectrum (SBL = 3), UP on the 7th (SBU = 7).  I use the word sideband and position (in the spectrum) interchangeably here.

All of these algorithms are designed around a fundamental ADD then MULTIPLY process or MULTIPLY then ADD process.  That is to say, they generate frequency values as the result of doing some operation involving both an ADD and a MULTIPLY.  As such, there are two further determining parameters (beside UP LP and their spectral position), an ADD factor (referred to by 'a'), and a MULTIPLY factor (referred to by 'm').  The composer supplies EITHER an ADD frequency (Hz) and the algorithm calculates the MULTIPLY factor, or the composer enters the MULTIPLY factor and the algorithm finds the ADD hz.  Not all of the algorithms permit both possibilities, some are limited to user supplying only the MULTIPLY, others allow both kinds factors but with restrictions.  When you choose your algorithm, there will appear a comment describing the restrictions, if any.  Some of the restrictions are "fail-safe" insofar as even if you violate the restriction, the program will adjust your input data so that the algorithm can proceed anyway.   All of this is documented with on-screen comments at the appropriate moment during execution.

Depending on where you begin in the spectrum (which position number, or sideband number) will be that for the LP (again, not necessarily the lowest frequency of the Gen Dyad), each run for a particular Dyad-position-factor input will be from 1 to 7 different possible spectra, where LP is always fixed at the SBL (lowest sideband position) and UP is progressively pushed up from position SBL+1 to 8 as the maximum.  For example if you call for the LP to be on SBL = 3, then the procedure generates 5 successive frequency spectra where UP generated first as SBU = 4, then SBU = 5, then 6, then 7, and then 8, SBL is always 3.  The distance in sideband position increases, which means that the frequency content that is generated between the LP and UP gets progressively denser.  You generally don't get a very interesting sound for LP and UP as a minor 6th being generated as the 2nd and 8th components in the spectrum.  On the other hand, experimentation will show that for some algorithms, this configuration can be very interesting for some exaggerated value of 'a' or 'm' because the frequencies generated for the other sidebands, those on positions 3,4,5,6,7 of this example, are not necessarily between the two pitches of the Gen Dyad;  they can just as easily be all over the frequency map since these algorithms are not by any means linear.

Each of these spectra will be shown with 8 components, more than enough to create a characteristic sound.  If you need more, you can just play two 8-frequency spectra together both generated by the same Gen Dyad, or by different ones, whatever is desired at any place in the composition.  It is useful to be able NOT play some of the components, because they are far outside the audible frequency range, i.e. some numbers will be generated that are less than 20.0 or far greater than 20,000.  To ignore those values as inputs to the frequency parameter in an oscillator requires an easily constructed program control logic, that says roughly,    if Hz > 20000 (or other cutoff point) or Hz < 20 (or other), SKIP IT!
 

Using INHNTRVL and INHNTRVD.
The only difference between these two versions of the program is that INHNTRVD is programmed to create MUSIC30 score cards from the pitch, position and generated control data for use with inhntr30 as described above.  Again, the user can modify this or just take the MUSIC30 score cards and modify them with any text editor so that the p-fields correspond with the user's own csound instrument.  Otherwise the two programs are identical.

Here we step through the program.

Start inhntrvl.exe or inhntrvd.exe

First prompt: if you want to save ALL the data output that is going to be written to the screen to a separate file you can enter the name of the file (to be created or appended to if it already exists), with or without extension, but the file name can be no longer than 8 characters and the extension no longer than 3 (after all this is an old DOS compilation).  
     If you don't want an output file, just hit Enter.

The Algorithm menu.  Here you decide which procedure you want to use and enter the algorithm choice.

Enter bottom pitch LP of Gen Dyad in 8.pc form -> here you enter the LP of your Dyad, for example 7.10 (Bb below middleC)

Enter upper pitch UP of Gen Dyad in 8.pc form ->  here you enter the UP of your Dyad, for example 9.04 (the Dyad is the                                                   interval of an octave and a tritone)

Enter position of LP in the spectrum (the sbl) -> here you enter the number of the frequency component which will be the frequency of the Lower Pitch LP;  this is the lower sideband number, or SBL.  The number refers to the order in which the components are generated.  Since these routines generate only 8 frequencies at a time, the SBL number refers to which of those 8 the LP will be generated on.  
     Note that by declaring LP to be on any other position number than 1, the algorithm generates a frequency for position 1 and all those "below" the LP.  This is usually the way to use these procedures, so that you generate a wide spectrum around (below, in between, and above the pitches of) the Gen Dyad.
     Note also that you can declare just as easily (following on our current example) LP = 9.04 UP = 7.10.  This inversion of the Gen Dyad can often produce very useful sounds.

Declare the Multiply factor or the Add factor
Enter  m  and Mult factor, or  a  and Add Hz ->  Careful here.  This is the only place in the program where you do NOT have a chance to correct a keystroke.  The program immediately reads the m or a that you type, you cannot backspace to it to change it;  you do NOT hit enter until AFTER you have typed the Mult factor or Add Hz.  If you do not type an m or an a, and begin to type a number, the program sometimes reads the first digit as the default 'm' and processes the the next digits as a MULT fact, or sometimes it just gets confused and not only produces incoherent results, but when you try to do another run, the program is stuck and will never read a or m at this point anymore.  You have to exit and re-start the program.  

    So you must type  m1.3129 for a MULT factor of 1.3129  or a417.292 for an ADD hz of 417.292.  Again, hit ENTER only AFTER you have entered the numeric value.   m or a MUST BE lower case.  You can, however, make corrections to the MULT or ADD number as usual with backspace with the cursor arrows, AFTER you have input the m or the a.  Only the m or a input is one time only, no errors allowed.
    The MULT and ADD numbers can be negative.  If this causes problems with the algorithm, the procedure corrects itself and changes the sign (i.e. sometimes a positive value will cause an illegal negative to be generated inside the procedure, but the algorithms know how to correct for this).  You will see a message to that effect at the beginning of the on-screen data generation.

At this point the algorithm begins to generate the various frequency spectra.  The spectrum header provides information about what is happening:
First it shows the interval formed by the pitches of the Gen Dyad, its name and its ratio;  
continuing with LP = 7.10 and UP = 9.04  the program writes  interval = octave and tt  whose ratio = 2.828427

next it will show your choice of algorithm, as the number you typed and the full equation itself that is about to be executed.    1. fN = .......  (if you chose algorithm n.1)

The next information lines will be repeated for each of the frequency spectrum generations.
First, it writes the LP you chose in 8.pc form and then its equivalent in hertz; and the same for the UP.

Then the SBLU = X.0Y where X is the SBL or spectrum position of LP and Y is the SBU for UP.  X will be constant for all the spectra generated while Y goes progressively from X+1 up thru 8, as explained before.
This is followed by the Add Hz and the Multiply Factor required by the algorithm.  If you wrote aNum you will see that number as the Add Hz followed by the Multiply factor calculated by the algorithm;  or if you wrote mNum you will see the Add Hz calculated by the algorithm followed by number you input as the Mult factor.

then follows the 8 hz values for the SBLU (the comment "for nosc = 8" is shorthand for "with 8 oscils, the frequency spectrum is..")

The frequencies are listed in their generated positions, 1 thru 8

1. Frequency value = f0 the bottom hz ... f0 is the starting frequency for each algorithm and was calculated by the procedure based on the input data.
2. Frequency value -> Ratio to Previous Hz  tra A and B = TTT semitones
    the resultant ratio is between ("tra" is italian for between.. shorter word!) the nearest equal tempered scale ratios A and B   and this Ratio is equal to that number TTT of semitones above or below the previous frequency.  This last datum is extremely useful in getting a sense of the sound that is produced by a collection of frequencies that are not related to each other by whole numbers of semitones.  If the resultant ratio is exactly an equal tempered ratio (or very close to it) the program will write that.
  
3. thru 8. are in the same format as 2.  The ratios and semitone differences are always with respect to the previously generated frequency.  If the frequencies do NOT increase or decrease regularly, it won't be immediately apparent that, for example, component n.2 might actually be between component n.5 and 6.  This happens rather often.  I have not implemented a sort routine on the basis of absolute frequency values.   One of these days....

     In INHNTRVL the program pauses and waits for you to hit a key before proceeding to the next spectrum calculated on the basis of SBU being incremented by 1 (i.e. if you started with SBL = 3, the first SBU was 4, the next spectrum is based 
on SBU = 5).       
     The score data version, INHNTRVD will ask if you want to make a M30 i5nhd score card.  This refers to my MUSIC30 orchestra that uses these routines as part of an instrument.  As mentioned before, the csound score data format is identical and you need only adapt this p-fields in my score to your own orchestra format.  The score card will have the 8.pc for the LP, the >interval< formed by UP, in 8.pc format (not the UP 8.pc datum) the algorithm number and the MULT factor, whether calculated or user input.  All of these are in various p-fields of the MUSIC30 instrument.
   If you don't want the score card to be generated, hit 'n' twice (or rather hit 'n' and any other key to continue, so a flick of the finger-tip on a double n does the trick).  If you hit 'y' to generate the score card, and it is the FIRST time you call for the score card, you will get further prompts:  first you must input the name of the file where the score cards are to be written (either a new file or for appending to an old file), then you are asked for pn.nf which is my shorthand for "PartialNumber.FunctionNumber", all in on data field.  I generate each of these frequencies on partial pn of function nf; a function n. 31 might contain ONLY the 6th, 13th and 19th partials, so I program my additive synthesis instrument to play EACH frequency of this spectrum on, for example, 6.31, partial 6 of F31.  This produces an additional thickening of "inharmonicity" when all played together.  You need to fill in some number at this prompt even if you don't use it.
   If this is NOT the first time you hit 'y' at the "make M30 score card" prompt, then the program writes another score card without asking for any further input.  Hit any key to continue.

The above sequence continues until SBU has finished at 8.  The program then asks if you want do another run, and you have several options:  N exits from the program. Y returns you to the menu from which you choose another algorithm.  S means SAME algorithm; or you can input another algorithm choice if you memorized the menu (better to go thru Y).  If you hit S, you will do another run of the same algorithm, and you will be asked if you want the same pitches as well.  If Y, you will only need to input the SBL of LP and the m or a factor.  If N, you will start by inputting new 8.pc pitch values.

That's it.  There are more comments on added features and practical tips scattered around the other documentation.

When you exit, if you've created a complete data file, you will find it in the inhntrvl directory;  if you've created some score cards, that file will be there as well.  n.b. you CAN create a score file WITHOUT creating a complete data file.
Not recommended, however, for practical purposes.
 


if using this with M30 or Csound (gen21 or inhntrvl30): 
     pos choice is declare M find A, neg choice is declare A find M
     if choice is x.y rather x.0 (or -x.y instead of -x.0) then the generated
     array is left as HZ rather than the default Sampling Increment.
     CSound probably wants to read HZ so use x.y or -x.y where 'y' is
     any non zero digit.

================================================================
Two of the algorithms, n.7 and n.8, have been re-worked to accept GENERATING TRICHORDS.  These are in INHNTRIC.exe and INHNTRID.exe.  The two programs are identical except for the capacity of INHNTRID to optionally generate score cards, like INHNTRVD.

  The prompts are the same or similar to INHNTRVL, you input the trichord (LP, CP and UP) pitches in 8.pc notation, whichever pitches can be input as negative will be shown.  By supplying three pitch information, the algorithm can calculate BOTH the MOD factor and the ADD hz, you are not prompted for either of them.  Variety can be obtained by manipulating the declared position of the pitches: as before, the Lower, Center and Upper pitches need NOT be the Lowest, Middle and Highest frequency of the trichord.  LP can be the middle frequency, UP can be the lowest frequency, CP can be the highest frequency, and other manipulations.  This provides useful varietiy with the same trichord.  (That is the meaning of the rather cryptic message that appears concerning SBLU = sbu.sbl or sbc.sbu etc.)

For algorithm 7, the necessary restriction is automatically programmed into the procedure:  Whatever frequency is declared as LP, it MUST be SBL = 1, the starting frequency f0 must be LP (again, regardless of actual frequency).  The other two pitches, CP and UP can be in any position in the spectrum, even reversing their order... i.e. SBC = 4, SBU = 3.

For algorithm 8, the restriction is that the three SB positions in the frequency spectrum, SBL, SBC and SBU, MUST be contiguous, i.e. SBC =  SBL + 1, and SBU = SBC + 1.  Again you can juggle the frequency values so that the SBL is either the middle or highest frequency, etc.  If the 3 positions are not contiguous, you will not generate the correct frequency components; but interestingly if you keep SBC and SBU contiguous, but SBC NOT next to SBL, you will lose the original frequency values for CP and UP at positions SBC and SBU, but the interval ratio between the new CP and UP will be exactly the same as the original generating trichord CP UP.  Very useful.

=======================================================================================================


     Here are the algorithms currently available.  This is the same menu that appears at the start of each run in INHNTRVL.EXE
 
"given M find A mode" means the composer supplies the MULT fac, the alogrithm calculates the Add hz;  
and vice versa for "given A find M mode".

Only Proc 7 & Proc 8 accept reflected (negative) LP, -8.pc.  If you input negative 8.pc for any other proc, the algorithm continues as if it were positive.

             MULTIPLY then ADD

   1.  fN = f0*M^N + A*N  -> no restrictions
   11. fN = f(N-1)*M^N + A*N -> ONLY in given M find A mode

   2.  fN = f0*N^M + A*N -> Stretch Factor proc  no restrictions
   22. fN = f(N-1)*N^M + A*N -> limited to sbu = sbl + 1 ALWAYS, 
                                 i.e. 2.03 3.04 4.05  etc.  expands (nice)
     n.b. this expander is much more gradual than the ones below
  these work correctly ONLY with sbl > 1 and xx & yy > 0;  can be fractions 
   3.  fN = f0*M^N + A*X -> X = N+xx/N+yy 
   33. fN = f0*M^N + A*N^X -> X = N+xx/N+yy 

   34. fN = f0*M^N + A^X - not implemented yet 
   35. fN = f0*N^M + A^X - not implemented yet    

   4.  fN = f0*M^N + A*N^M -> ONLY in given M find A mode


             ADD then MULTIPLY

 for 5,6 in given A find M mode, sbl can ONLY be 1 (i.e. f0 is LP).  it will 
be set to 1 automatically in this mode.

   5.  fN = M^N*(f0 + A*N)
   55. fN = M^N*(f(N-1) + A*N) -> limited to sbu = sbl + 1 ALWAYS, 
                                 i.e. 2.03 3.04 4.05  etc.  expands 

   6.  fN = N^M*(f0 + A*N) -> Stretch Factor proc
   61. fN = N^M*(f(N-1) + A*N) -> limited to sbu = sbl + 1 ALWAYS, 
                                 i.e. 2.03 3.04 4.05  etc. expands

   65. fN = f(N-1)*(N^M + A*N) -> limited to sbu = sbl + 1 ALWAYS, 
                                 i.e. 2.03 3.04 4.05  etc. expands
   66.  fN = f0*(N^M + A*N)  various sequences, mostly getting smaller

   7.  fN = f0*(M + A*N) -> all OK, but watch the range of M & A
    for small LP and large U, A can become negative and mess up; very
    effective for low LP, tipo 6.00, sbl = 1, intrvl = 3.02, a = 12 - 30;
    yields mult facs tra 20 & -120 ca. and irreg. interval patterns
          this procedure accepts reflected LP (negative 8.pc)

   77. fN = f0*(M^N + A*N)  -> another sort of Stretch Fac proc,
 but in given M find A mode the results are identical to n.1.. go figger.
 In given A find M, you can only have NL = 1, always, and the algorithm sets 
 that for you automatically.  Also: since there is a subtraction that causes
 the algorithm to tilt with log of a negative value, the A value is 
 automatically made >negative< which gets some wildly varying interval 
 patterns.  To give a positive S, write a negative value, but should be very 
 close to 0, like .1 or so else once the log(negVal) tries to go, results are 
 zeroed.  

   8.  fN = f(N-1)*(M + A*N) -> usually expanding intervals going up..
 this is limited to sbu = sbl + 1 ALWAYS, i.e. 2.03 3.04 4.05  etc.
 using A find M gets huge hz values; use VERY small A and small intervals.
 best seems to be with smallish M (1.1 to 1.8 range) and in 4.05 on up 
 position (esp. with wider intervals like 1.11) so that the gen dyad ntrvl
 is the widest or next to widest in the succession.  small intervals can
 start at 2.03 position.. very good for mn3 mj4 with ntrvl expansion patterns.
     this procedure accepts reflected LP (negative 8.pc)

   88.  fN = M * f(N-1)^2/f(N-2)  -> M is a true interval compander
     The intervals between successive f(N)'s expand ( M > 1 ) or
     contract ( M < 1 );  the other hz depend on the size of the dyad
     interval and position.  You easily get large intervals in early
     N's (large "negative" hz)contracting toward a middle pair (the dyad)
     and then expanding immediately.  Algorithm fai-da-te the kind of
     internal interval patterns.

   9.  fN = M^N*(f0 + A*N^M) -> ONLY in given M find A mode

