about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/v2ch13/fourie.html
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
committerelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
commit562a9a52d599d9a05f871404050968a5fd282640 (patch)
tree7d3305c1252c043bfe246ccc7deff0056aa6b5ab /js/games/nluqo.github.io/~bh/v2ch13/fourie.html
parent5d012c6c011a9dedf7d0a098e456206244eb5a0f (diff)
downloadtour-562a9a52d599d9a05f871404050968a5fd282640.tar.gz
*
Diffstat (limited to 'js/games/nluqo.github.io/~bh/v2ch13/fourie.html')
-rw-r--r--js/games/nluqo.github.io/~bh/v2ch13/fourie.html853
1 files changed, 853 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/v2ch13/fourie.html b/js/games/nluqo.github.io/~bh/v2ch13/fourie.html
new file mode 100644
index 0000000..74ea2c4
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/v2ch13/fourie.html
@@ -0,0 +1,853 @@
+<HTML>
+<HEAD>
+<TITLE>Computer Science Logo Style vol 2 ch 13: Example: Fourier Series Plotter</TITLE>
+</HEAD>
+<BODY>
+<CITE>Computer Science Logo Style</CITE> volume 2:
+<CITE>Advanced Techniques</CITE> 2/e Copyright (C) 1997 MIT
+<H1>Example: Fourier Series Plotter</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../csls2.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/v2ch13.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../v2-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="https://people.eecs.berkeley.edu/~bh/v2ch12/v2ch12.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v2ch14/manual.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="https://mitpress.mit.edu/books/computer-science-logo-style-second-edition-volume-2">MIT
+Press web page for <CITE>Computer Science Logo Style</CITE></A>
+</TABLE></TABLE>
+
+<HR><P>Program file for this chapter: <A HREF="https://people.eecs.berkeley.edu/~bh/v2ch13/plot.lg"><CODE>plot</CODE></A>
+
+<P>A particular musical note (middle C, say) played on a piano and played
+on a violin sound similar in some ways and different in other ways.
+Two different notes played on the violin also have similarities and
+differences.  How do you hear which note is being played, and how
+do you know what instrument you're listening to?
+
+<P>To do justice to these questions would fill up an entire book.  For example,
+a piano produces sound when a felt-covered wooden hammer hits metal wires,
+or strings.  Each piano key controls one hammer, but each hammer may hit
+from one to three strings.  It turns out that the strings for a particular
+note are not tuned to exactly the same pitch.  Part of the richness of the
+piano's sound comes from the interplay of slightly different pitches making
+up the same note.
+
+<P>Another contributing factor to the recognition of different instruments is
+their differences in attack and decay.  Does the sound of a note start
+abruptly, or gradually?  The differences are not only a matter of loudness,
+though.  A few instruments start out each note with a very pure, simple tone
+like a tuning fork.  Gradually, the tone becomes more complex until it
+finally reaches the timbre you associate with the instrument.  But a bowed
+violin, a more typical example, starts out each note almost as a burst of
+pure noise, as the bow hits the strings, and gradually mellows into the
+sound of a particular note.  If you are experimentally inclined, try tape
+recording the same note as played by several instruments.  Then cut out the
+beginnings and ends of the notes, and retain only the middle section.  Play
+these to people and see how well they can identify the instruments, compared
+to their ability to identify the complete recorded notes.
+
+<P>
+
+For this chapter, though, I'm going to ignore these complications, and
+concentrate on the differences in the <EM>steady-state</EM> central part of a
+note as played by a particular instrument.  What all such steady
+musical sounds have in common is that they are largely <EM>
+periodic</EM>.  This means that if you graph the air pressure produced by the
+instrument over time (or the voltage when the sound is represented
+electrically in a hifi system), the same pattern of high and low pressures
+repeats again and again.  Here is an example.  In this picture, the motion
+of your eye from left to right represents the passing of time.
+
+<P><CENTER><IMG SRC="squig5.gif" ALT="figure: squig5"></CENTER>
+
+<P>
+
+The height of the squiggle on the page, at
+any particular moment, represents the sound pressure at that moment.  So
+what this picture shows is that there are many small up-and-down
+oscillations superimposed on one large, regular up-and-down motion.  (This
+one large oscillation is called the <EM>fundamental</EM> frequency.)  You can
+see that the entire picture consists of five repetitions of a smaller
+squiggle with just one of the large oscillations.
+
+<P>From what I've said about oscillations, you might get the impression
+that this is a picture of something like a foghorn or siren, in which
+you can hear an alternation of loud and soft moments.  But this is
+actually the picture of what sounds like a perfectly steady tone.
+The entire width of the page represents about one one-hundredth of
+a second.  There are a few hundred repetitions of the single large
+up-and-down cycle in each second of a musical note.  The exact number
+of repetitions is the <EM>frequency</EM> of the note,
+and is the same for every instrument.  For example, the note A above
+middle C has a pitch of 440 cycles per second, or 440 Hertz.
+
+<P>All instruments playing A above middle C will have a picture with
+the same fundamental frequency of 440 Hertz.  What is different from
+one instrument to another is the exact shape of the squiggle.  (By
+the way, the technical name for a squiggle is a <EM>waveform.</EM>  You
+can see the waveform for a note by connecting a microphone to an oscilloscope,
+a device that shows the waveform on a TV-like screen.)
+
+<P>Here is a picture of the simplest, purest possible tone:
+
+<P><CENTER><IMG SRC="sine5.gif" ALT="figure: sine5"></CENTER>
+
+<P>This is the waveform you'd get from an ideal tuning fork,
+with no impurities or bumps.  It is called a <EM>sine wave.</EM>  This
+particular kind of oscillation turns up in many situations, not just musical
+sounds.  For example, suppose you write a program that starts a turtle
+moving in a circle forever.
+
+<P><PRE>to circle
+fd 1
+rt 1
+circle
+end
+</PRE>
+
+<P>Think about the motion of the turtle, and concentrate only
+on its vertical position on the screen.  Never mind its motion from
+left to right.  The up-and-down part of the turtle's motion over time
+looks just like this sine wave.
+
+<P>This says more than simply that the turtle alternates moving up and
+down.  For example, the turtle's vertical motion might have looked
+like this over time:
+
+<P><CENTER><IMG SRC="tri5.gif" ALT="figure: tri5"></CENTER>
+
+<P>If
+this were the picture of the turtle's motion, it would mean that
+the turtle's vertical position climbed at a steady rate until it reached
+the top of the circle, then abruptly turned around and started down
+again.  But in fact what happens is that the height of the turtle
+changes most quickly when the turtle is near the &quot;Equator&quot;
+of its circle.  The turtle's vertical speed gets less and less as
+the turtle gets near the &quot;poles.&quot;  This speed change corresponds
+to the gradual flattening of the sine wave near the top and bottom.
+(You may find it confusing when I say that the turtle's vertical motion
+slows down, because the turtle's speed doesn't seem to change as it
+draws.  But what happens is that near the Equator, the turtle's speed
+is mostly vertical; near the poles, its speed is mostly horizontal.
+We aren't thinking about the horizontal aspect of its motion right
+now.)
+
+<P><CENTER><IMG SRC="motion.gif" ALT="figure: motion"></CENTER>
+
+<P>What makes sine waves most important, though, is that <EM>any</EM> periodic
+waveform can be analyzed as the sum of a bunch of sine waves of different
+frequencies.  (Sometimes an infinite number of since waves must be
+added together.)  The frequencies of the sine waves will always be
+multiples of the fundamental frequency.  This important mathematical
+result was discovered by the French mathematician
+Jean-Baptiste-Joseph Fourier (1768-1830).  The representation of
+a mathematical function as a sum of sine waves is called a <EM>
+Fourier series.</EM>
+
+<P>For example, when a violin plays A above middle C, the waveform that
+results will include a sine wave with frequency 440 Hertz, one with
+frequency 880 Hertz, one at 1320 Hertz, and so on.  Not all of these
+contribute equally to the complete waveform.  The <EM>amplitude</EM> of
+each sine wave (the amount of swing, or the vertical distance in the
+picture) will be different for each.  Typically, the fundamental frequency
+has the largest amplitude, and the others (which are called <EM>
+harmonics</EM> or <EM>overtones</EM>) have smaller amplitudes.  The
+precise amplitudes of each harmonic are what determine the steady-state
+timbre of a particular instrument.
+
+<P><H2>Square Waves</H2>
+
+<P>Two traditional musical instruments, the clarinet and the
+pipe organ, share a curious characteristic: their Fourier series
+contain only odd harmonics.  In other words, if a clarinet is
+playing A above middle C, the waveform includes frequencies of 440 Hertz,
+1320 Hertz (3 times 440), 2200 Hertz (5 times 440), and so on.  But the
+waveform does not include frequencies of 880 Hertz (2 times 440), 1760 Hertz
+(4 times 440), and so on.  (I'm oversimplifying a bit in the case of the
+pipe organ.  What I've said about only odd harmonics is true about each
+pipe, but the organ can be set up to combine several pipes in order to
+include even harmonics of a note.)
+
+<P>In recent times, a third musical instrument has come to share this
+peculiar Fourier series: the computer.  (Perhaps you were wondering
+where computers come into this.)  Today there are computer-controlled
+musical instruments that can generate
+any possible sound.  Musicians have even used computers to create
+new instrument timbres that are not possible with ordinary instruments.
+But the particular timbre that most people associate with
+computer music is the one produced by the simplest possible
+computer sound generator.  Instead of a steady oscillation in sound
+pressure, this simple device can only be on or off at a given moment.  The
+computer produces sound by flipping the device from on to off and back at a
+particular rate.  Such a device produces a <EM>square wave</EM>, like
+this:
+
+<P><CENTER><IMG SRC="square5.gif" ALT="figure: square5"></CENTER>
+
+<P>No sound that occurs in nature has a waveform that turns
+corners so abruptly.  But what is &quot;natural&quot; in nature isn't necessarily
+what's &quot;natural&quot; for a computer.  For many years, computer-generated
+music invariably meant square waves except in very fancy music research
+centers.
+
+<P>More recently, new integrated circuit technology has made
+it relatively inexpensive to equip computers with &quot;music chips&quot;
+that generate sine waves.  The stereotyped sound of computer music
+is becoming uncommon.  But I still find square waves fascinating
+for several reasons.
+
+<P>One place where square waves are still used is in the hifi magazines,
+in their tests of amplifiers.  The testing laboratories feed a square
+wave into an amplifier, and show oscilloscope pictures of the waveform
+going into the amp and the waveform coming out.  Here is an example:
+
+<P>
+<CENTER><IMG SRC="scope.gif" ALT="figure: scope"></CENTER>
+
+
+<P>The oscillation that is visible in the output near the corners of
+the input is called <EM>ringing</EM>.  A lot of ringing indicates that
+the amplifier doesn't have good high-frequency response.
+
+<P>Here is why a square wave is a good test of high frequencies:  The
+Fourier series corresponding to the square wave includes an infinite
+number of odd-harmonic sine wave components.  In other words, a perfect
+square wave includes infinitely high frequencies.  (In practice, the
+input picture isn't a perfect square wave.  You can see that the vertical
+segments aren't <EM>quite</EM> truly vertical, for example.)  No amplifier
+can reproduce infinitely high frequencies faithfully.  The result
+is that the output from the amplifier includes only some of the harmonics
+that make up the input.  It turns out that such a <EM>partial series</EM>,
+with relatively few of the harmonics included, produces a waveform
+in which the ringing phenomenon at the corners is clearly visible.
+
+<P>If you think about it, that's a bit unexpected.  Normally, the more
+harmonics, the more complicated the waveform.  For example, the simplest
+waveform is the one with only the fundamental, and no added harmonics.
+Yet, <EM>removing</EM> harmonics from the square wave produces a <EM>
+more</EM> complicated picture.  I like paradoxes like that.  I wanted
+to write a computer program to help me understand this one.
+
+<P>Before you can look into the square wave in detail, you have to know
+not only the fact that it uses odd harmonics, but also the amplitude
+of each harmonic.  A square wave with fundamental frequency <EM>f</EM>
+has this formula: <P><CENTER><IMG SRC="https://people.eecs.berkeley.edu/~bh/v2ch13/math1.gif" ALT="math display"></CENTER>
+<P>The dots at the end indicate that this series goes on forever.
+The amplitude of each sine wave is the reciprocal of the harmonic
+number (one divided by the number).
+
+<P>This project draws pictures of waveforms containing some number of
+terms of this series.  (Each sine wave is called a term.)  The program
+allows many different ways of controlling exactly what is drawn.
+
+<P>To start with something very simple, try this instruction:
+
+<P><PRE>plot 1
+</PRE>
+
+<P>The effect of this command is to draw one cycle of a pure
+sine wave:
+
+<P><CENTER><IMG SRC="plot1.gif" ALT="figure: plot1"></CENTER>
+
+<P>This
+is the first term of the series for the square wave.  Now try
+this:
+
+<P><PRE>plot 5
+</PRE>
+
+<P><CENTER><IMG SRC="plot5.gif" ALT="figure: plot5"></CENTER>
+
+<P>The
+input to <CODE>plot</CODE> is the harmonic number of the highest harmonic.
+In this example, we've drawn three sine waves added together: the
+fundamental, third harmonic, and fifth harmonic.
+
+<P>To see a plot looking somewhat more like the pictures in the amplifier
+tests, try
+
+<P><PRE>plot 23
+</PRE>
+
+<P><CENTER><IMG SRC="plot23.gif" ALT="figure: plot23"></CENTER>
+
+<P>This
+contains the first 12 odd harmonics.  (Remember to use an odd
+number as input, if you want to see something that looks like a square
+wave.)  You can see that the result still includes some oscillation
+in the horizontal sections, but does have an overall square shape.
+
+<P>A mediocre hifi amp has a frequency response that is good to about
+20,000 Hertz.  This is about the 45th harmonic of 440 Hertz.  To see
+how A above middle C would come out on such an amplifier, try
+
+<P><PRE>plot 45
+</PRE>
+
+<P><CENTER><IMG SRC="plot45.gif" ALT="figure: plot45"></CENTER>
+
+<P>There
+is still some ringing near the corners, but the middle of the
+horizontal segment is starting to look really flat.  A better amplifier
+might be good to 30,000 Hertz.  To see how that would look, try
+
+<P><PRE>plot 77
+</PRE>
+
+<P><CENTER><IMG SRC="plot77.gif" ALT="figure: plot77"></CENTER>
+
+<P>(The
+drawing of the picture takes longer when you use a larger input
+to <CODE>plot</CODE>, because the program has to calculate more terms of the series.)
+
+<P>So far, we have only changed one of the possible parameters controlling
+the waveform, namely the highest harmonic.  The program allows you
+to control several other elements of the picture.  For example, try
+this:
+
+<P><PRE>plot [maxharm 77 yscale 140 deltax 1]
+</PRE>
+
+<P><CENTER><IMG SRC="https://people.eecs.berkeley.edu/~bh/v2ch13/plot77big.gif" ALT="figure: plot77big"></CENTER>
+
+<P><CODE>
+Plot</CODE> takes one input, but this time the input is a list instead of
+a single number.  The members of the list are used as sort of &quot;sub-inputs.&quot;
+The odd-numbered members are the <EM>names</EM> of parameters,
+for which the even-numbered members provide <EM>values.</EM>
+
+<P><CODE>Maxharm</CODE> stands for &quot;maximum harmonic&quot;; it is the parameter you were
+setting when you used a single number as the input.  <CODE>Yscale</CODE> is an
+adjustment for the height of the plot.  (To &quot;scale&quot; a bunch of numbers
+means to multiply all of them by some constant value, the &quot;scale factor.&quot;)
+You may have noticed that as the
+number of harmonics has increased, the pictures have been getting smaller in
+the vertical direction; by increasing the value of <CODE>yscale</CODE> we can
+expand the height of the plot to show more detail.  Similarly, <CODE>deltax</CODE>
+allows us to show more horizontal detail, not by widening the picture but by
+computing the value for every dot.  Ordinarily, the program saves time by
+calculating every second dot.  This approximation is usually good enough,
+but sometimes not.  (<CODE>Deltax</CODE> means &quot;change in X.&quot;  Delta is the
+name of the Greek letter D (&Delta;), which mathematicians use to represent
+a small change in something.)
+
+<P>Here's another example:
+
+<P><PRE>plot [11 cycles 5]
+</PRE>
+
+<P><CENTER><IMG SRC="plot11by5.gif" ALT="figure: plot11by5"></CENTER>
+
+<P><CODE>Cycles</CODE> indicates
+the number of complete cycles you want to see.  By saying <CODE>cycles 5</CODE>
+in this example, I drew a picture like the ones near the beginning
+of this chapter, with five repetitions of the fundamental oscillation.
+
+<P>Notice also that we didn't have to say <CODE>maxharm</CODE>.  If a number
+appears in the input list where a name should be, it's automatically assigned
+to <CODE>maxharm</CODE>.
+
+<P><CODE>Plot</CODE> allows you to specify any of six parameters.  Each parameter
+has a <EM>default</EM> value, the value that is used if you don't say
+anything about it.  For example, the default value for <CODE>deltax</CODE> is 2.
+Here are all the parameters:
+
+<P><TABLE>
+<TR><TH>name<TH>default<TH>purpose
+<TR><TD>maxharm<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;highest harmonic number included in series
+<TR><TD>deltax<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;number of turtle steps skipped between calculations
+<TR><TD>yscale<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;75<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vertical motion is multiplied by this number
+<TR><TD>cycles<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;number of cycles of fundamental shown
+<TR><TD>xrange<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;230<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;highest X coordinate allowed
+<TR><TD>skip<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;number of harmonics skipped between terms
+</TABLE>
+
+<P>You've already seen what <CODE>maxharm</CODE>, <CODE>yscale</CODE>, <CODE>deltax</CODE>,
+and <CODE>cycles</CODE> are
+for.  Now I'll explain the others.
+
+<P><CODE>Xrange</CODE> is mainly changed when moving the program from
+one computer to another.  Each computer allows a particular number
+of turtle steps to fit on the screen in each dimension, horizontal
+and vertical.  <CODE>Xrange</CODE> is the largest horizontal position <CODE>plot</CODE>
+is allowed
+to use.  This is set a little below the largest possible X coordinate,
+just to make sure that there is no problem with wrapping around the
+screen.
+
+<P><CODE>Skip</CODE> is the number of harmonics skipped between terms.  To get odd
+harmonics, which we need for the square wave, we have to skip by 2
+each time, from 1 to 3, from 3 to 5, and so on.  Different values
+for <CODE>skip</CODE> will give very different shapes.
+
+<P>For example, if you are at all adventurous, you must have tried an
+even value of <CODE>maxharm</CODE> a while ago, getting a result like this:
+
+<P><PRE>plot 6
+</PRE>
+
+<P><CENTER><IMG SRC="plot6.gif" ALT="figure: plot6"></CENTER>
+
+<P>What
+you see is two cycles of an approximation to another shape, the
+<EM>sawtooth</EM>:
+
+<P><CENTER><IMG SRC="saw.gif" ALT="figure: saw"></CENTER>
+
+<P>Why
+two cycles?  Well, <CODE>plot 6</CODE> uses the
+second, fourth, and sixth harmonics.
+Supposing that the fundamental frequency is 440 again, this means
+that <CODE>plot</CODE> added frequencies of 880, 1760, and 2640 Hertz.  But these
+are also the fundamental, second harmonic, and third harmonic of 880
+Hertz.  By choosing only even harmonics, you've essentially chosen
+<EM>all</EM> the harmonics of <EM>twice the fundamental frequency</EM> you
+had in mind.  It is this doubling of the fundamental frequency that
+produces two cycles on the screen.  You could get one cycle of the
+same waveform by saying <CODE>plot [3 skip 1]</CODE>:
+
+<P><CENTER><IMG SRC="plot3skip1.gif" ALT="figure: plot3skip1"></CENTER>
+
+<P>You can see much more bizarre waveforms by using other values of <CODE>skip</CODE>.
+The best one I've found is <CODE>plot [16 skip 3]</CODE>:
+
+<P><CENTER><IMG SRC="plot16skip3.gif" ALT="figure: plot16skip3"></CENTER>
+
+<P>I
+chose a <CODE>maxharm</CODE> of 16 because it includes the fundamental plus five
+additional harmonics (4, 7, 10, 13, 16).  If I'd made <CODE>maxharm</CODE> 15 or
+17, I wouldn't have included the fundamental.
+
+<P><H2>Keyword Inputs</H2>
+
+
+
+
+
+<P>There are two different points of interest about this project.  One
+is the whole business of waveforms and Fourier series.  The second
+is the use of <EM>keyword</EM> inputs, which is the name for this system
+of giving information to <CODE>plot</CODE>.  The more usual style of Logo programming
+would have been to make <CODE>plot</CODE> a procedure with six inputs.  To draw
+a default graph, you would then have had to say
+
+<P><PRE>plot 5 2 75 1 230 2
+</PRE>
+
+<P>Since most of the time you want to use the default values
+for most of the inputs, all this typing would be an annoyance.  It
+would also be easy to make a mistake about the correct order of the
+inputs.  (This more usual Logo technique is called <EM>positional</EM>
+inputs.)  The combination of many necessary inputs with standard
+values for most of them makes the keyword technique appropriate here.
+It isn't always appropriate.  You wouldn't want to have to say
+
+<P><PRE>print item [index 2 list [vanilla chocolate strawberry]]
+</PRE>
+
+<P>because you have no trouble remembering which input to <CODE>item</CODE>
+is which, and you always want to provide both of them.
+
+<P>The procedure that interprets the keyword inputs is called <CODE>keyword</CODE>.
+<CODE>Keyword</CODE> was written to be a general tool, not limited to this particular
+program.  It takes two inputs.  The first is the input that you,
+the user, provide.  The second is a list of defaults.  When <CODE>plot</CODE> invokes
+<CODE>keyword</CODE>, the second input is this:
+
+<P><PRE>[maxharm 5 deltax 2 yscale 75 cycles 1 xrange 230 skip 2]
+</PRE>
+
+<P>This input tells <CODE>keyword</CODE> the names of all the keyword inputs
+as well as their default values.  It's in the same form as the actual
+input you give (a list of alternating names and values), and in fact
+<CODE>keyword</CODE> uses a single subprocedure, first to process the default list
+and then to process your input.
+
+<P><CODE>Keyword</CODE> is actually not <EM>perfectly</EM> general because it uses the
+assumption that all the values it gets are numeric.  The virtue of this
+assumption is that it allows <CODE>keyword</CODE> to recognize a number without a
+name as implicitly referring to the <CODE>maxharm</CODE> keyword.  (The name <CODE>
+maxharm</CODE> is not built into the procedure.  Instead, the first name in the
+list of default values is used.)  To use <CODE>keyword</CODE> in a context in which
+non-numeric words could be values as well as names, this assumption would
+have to be removed.
+
+<P>I didn't have keyword inputs in mind from the beginning.  When I started
+working on this project, the only input to <CODE>plot</CODE> was what I now call
+<CODE>maxharm</CODE>, the highest harmonic number to include.  All the other numbers
+were &quot;wired in&quot;; if I wanted to change something like what is now
+called <CODE>:xrange</CODE>, I'd edit all the procedures and change the numbers
+in the editor.
+
+<P>Editing all the procedures wasn't too difficult, since without the
+keyword-processing procedures everything fits in a single screenful.
+Changing the resolution (what is now <CODE>:deltax</CODE>) was a bit annoying,
+since I had to edit three different parts of the program.  (You can
+see that <CODE>:deltax</CODE> appears three times in the final version.)  When
+I finally got tired of that editing process, I decided to use keyword
+inputs.
+
+<P><H2>Making the Variables Local</H2>
+
+<P>The job of <CODE>keyword</CODE> is to create variables, one for each keyword,
+and assign a value to each variable.  If the user provides a value for
+a particular keyword, that's the value to use; if not, the default
+value is used.
+
+<P>When I first did this project, I wrote a version of <CODE>keyword</CODE> that
+creates global variables for the keywords:
+
+<P><PRE>to keyword :inputs :defaults
+if or (wordp :inputs) (numberp first :inputs) ~
+   [make &quot;inputs sentence (first :defaults) :inputs]
+setup.values :defaults
+setup.values :inputs
+end
+
+to setup.values :list
+if emptyp :list [stop]
+make first :list first butfirst :list
+setup.values butfirst butfirst :list
+end
+</PRE>
+
+<P><CODE>Keyword</CODE> checks for the special cases of a single number
+(as in <CODE>plot 5</CODE>) or a list beginning with a number; in either case,
+a new list is made with the first keyword (<CODE>maxharm</CODE>) inserted before
+the number.  Then the default values are assigned to all the keyword
+variables, and finally the user's values are assigned to whatever keywords
+the user provided, replacing the defaults.
+
+<P>Since these keyword variables are only used within the <CODE>plot</CODE> program,
+it would be cleaner to make them local to <CODE>plot</CODE>, just as ordinary
+positional inputs are automatically local to a procedure.  I could have
+had <CODE>plot</CODE> take care of this before calling <CODE>keyword</CODE>:
+
+<P><PRE>to plot :inputs
+local [maxharm deltax yscale cycles xrange skip]
+keyword :inputs [maxharm 5 deltax 2 yscale 75 cycles 1 xrange 230 skip 2]
+...
+</PRE>
+
+<P>but I thought it would be unaesthetic to have to type the
+names twice!  What I really want is for <CODE>keyword</CODE> to be able to
+make the variables local.  But I can't just say
+
+<P><PRE>to keyword :inputs :defaults
+<U>local filter [not numberp ?] :defaults</U>
+if or (wordp :inputs) (numberp first :inputs) ~
+   [make &quot;inputs sentence (first :defaults) :inputs]
+setup.values :defaults
+setup.values :inputs
+end
+</PRE>
+
+<P>because that would make the variables local to <CODE>keyword</CODE>
+itself, not to its caller, <CODE>plot</CODE>.  This is the same problem I had
+in writing <CODE>localmake</CODE> in Chapter 12, and the solution is the
+same:  Make <CODE>keyword</CODE> a macro!
+
+<P><PRE>.macro keyword :inputs :defaults
+if or (wordp :inputs) (numberp first :inputs) ~
+   [make &quot;inputs sentence (first :defaults) :inputs]
+output `[local ,[filter [not numberp ?] :defaults]
+         setup.values ,[:defaults]
+         setup.values ,[:inputs]]
+end
+</PRE>
+
+<P>Now it will be <CODE>plot</CODE>, instead of <CODE>keyword</CODE>, that creates the
+local variables and calls <CODE>setup.values</CODE>.
+
+<P><H2>Indirect Assignment</H2>
+
+<P>The actual assignment of values to the keywords is a good illustration of
+indirect assignment in Logo.  The instruction that does the
+assignment is this:
+
+<P><PRE>make first :list first butfirst :list
+</PRE>
+
+<P>Usually the first input to <CODE>make</CODE> is an explicit quoted word,
+but in this program the variable names are computed, not explicit.
+This technique would be impossible in most programming languages.
+
+<P><H2>Numeric Precision</H2>
+
+
+
+<P>It's important that the program computes the Fourier
+series starting with the higher harmonic numbers, adding in the fundamental
+term last.  Recall the formula for the series:
+<P><CENTER><IMG SRC="https://people.eecs.berkeley.edu/~bh/v2ch13/math1.gif" ALT="math display"></CENTER><P>
+The value of the sine function for each term is divided
+by the harmonic number of the term.  In general, this means that the
+terms for higher numbered harmonics contribute smaller values to the
+sum.
+
+<P>Theoretically, it shouldn't matter in what order you add up a bunch
+of numbers.  But computers carry out numeric computations with only
+a limited precision.  Usually there is a particular number of <EM>
+significant digits</EM> that the computer can handle.  It doesn't matter
+how big or small the number is.  The numbers 1234, 1.234, and 0.00000001234
+all have four significant digits.
+
+<P>To take a slightly oversimplified case, suppose your computer can
+handle six significant digits.  Suppose that the value of the fundamental
+term is exactly 1.  Then the computer could add 0.00001 to that 1
+and get 1.00001 as the result.  But if you tried to add 0.000001 to
+1, the result (1.000001) would require seven significant digits. 
+The computer would round this off to exactly 1.
+
+<P>Now suppose that the 23rd term in some series is 0.000004, the 24th
+term is 0.000003, and the 25th is 0.000002.  (I just made up
+these values, but the general idea
+that they'd be quite small is true.)  Suppose we are adding the terms
+from left to right in the formula, and the sum of the first 22 terms
+is 2.73.  Adding the 23rd term would make it 2.730004, which is too
+many significant digits.  This sum would be rounded off to 2.73 again.
+Similarly, the 24th and 25th terms would make absolutely no difference
+to the result.
+
+<P>But now suppose we add up the terms from right to left.  The sum of
+the 25th and 24th terms is 0.000005, and adding in the 23rd term give
+0.000009.  If we were to add this to 2.73 the result would be 2.730009.
+Although this is still too many significant digits, the computer would
+round it off to 2.73001.  The three terms at the end <EM>would</EM> make
+a small difference in the result.
+
+<P>In the square wave series, the successive terms get smaller quite
+slowly.  You'd have to add very many terms before the problem I'm
+describing would really be important.  But other series have terms
+that get smaller quickly, so that even for a small number of terms it's
+important to add in the smaller terms before the larger ones.
+
+<P>
+
+<P>By the way, the procedure <CODE>series</CODE> that computes the value of the
+series for some particular <CODE>x</CODE> value is written recursively, but
+its task is iterative.  I could have said
+
+<P><PRE>to series
+localmake &quot;result 0
+for [harmonic :maxharm 1 [-:skip]] ~
+    [make &quot;result :result + (term :harmonic)]
+output :result
+end
+</PRE>
+
+<P>but the use of <CODE>make</CODE> to change the value of a variable
+repeatedly isn't very good Logo style.  What I really want is an <EM>
+operation</EM> corresponding to <CODE>for</CODE>, analogous to <CODE>map</CODE> as the
+operation corresponding to <CODE>foreach</CODE>.  Then I could say
+
+<P><PRE>to series
+output accumulate &quot;sum [harmonic :maxharm 1 [-:skip]] [term :harmonic]
+end
+</PRE>
+
+<P>You might enjoy using the techniques of Chapter 10 to
+implement <CODE>accumulate</CODE>.
+
+<P><H2>Dynamic Scope</H2>
+
+<P>One final point about the programming style of this project has to
+do with the use of Logo's dynamic scope.  Every procedure has access
+to the variables of its superprocedures, and this project takes advantage
+of the fact.  Many people think it's better style if every procedure is given
+all the information it needs as inputs.  I didn't follow that rule
+in this project because, as I've said, many of the variables were
+invented late in the development process, and I did as little rewriting
+as possible.
+
+<P>For example, here is the procedure that computes one term of the
+Fourier series:
+
+<P><PRE>to term :harmonic
+output (sin :xscale * :harmonic * :x) / :harmonic
+end
+</PRE>
+
+<P>Of the three numbers that are used in this computation, <CODE>
+:xscale</CODE> is constant throughout the program, so it's not unreasonable for it
+to be used globally.  But <CODE>:x</CODE> changes for every point.  <CODE>X</CODE> is, in
+fact, a local variable, but it's local to <CODE>plot</CODE> rather than to <CODE>
+term</CODE>.
+
+<P>
+
+<P>Why does it matter?  One reason is that people find it easier to understand
+a program if it's made very clear where each variable gets its value.  In
+this example, it's easy to miss the fact that <CODE>x</CODE> is the index variable
+in a <CODE>for</CODE> loop.  The second reason is that as written, <CODE>term</CODE> can
+be used only within <CODE>plot</CODE>.  If we wanted to compute the value of a
+Fourier series for some reason other than plotting it, we couldn't easily
+use the same procedures.
+
+<P>I decided to leave the program as it is, instead of cleaning it up
+for publication, so that you could see an example of a style that,
+after all, Logo makes possible by choosing to use dynamic scope. 
+In some ways, this style is simpler than one in which each procedure
+would have several more inputs.  You can decide for yourself if you
+find it easier or harder to read the program this way, compared to
+the officially approved style:
+
+<P><PRE>to term :x :harmonic :xscale
+output (sin :xscale * :harmonic * :x) / :harmonic
+end
+</PRE>
+
+<P>In this version of the procedure, I've made <CODE>x</CODE> the first
+input to <CODE>term</CODE>.  This seems most natural to me, considering that <CODE>
+term</CODE>'s job is to compute an algebraic function of <CODE>x</CODE>.  The argument to
+a function is very naturally represented in a computer program as
+the input to a procedure.
+
+<P>All I've changed in <CODE>term</CODE> itself is the title line.  But of course
+the invocation of <CODE>term</CODE>, which is in the procedure <CODE>series</CODE>, must
+be changed also.  And to be consistent, <CODE>series</CODE> should get <EM>its</EM>
+needed values as explicit inputs, too:
+
+<P><PRE>to series :x :harmonic :skip :xscale
+if :harmonic &lt; 1 [output 0]
+output (term :harmonic)+(series :harmonic-:skip)
+end
+</PRE>
+
+<P>We're up to four inputs, and it'd be easy to get them out of
+order when <CODE>series</CODE> is invoked by <CODE>plot</CODE>.  You can see why
+&quot;inheriting&quot; variables from a procedure's caller can simplify its use.
+
+<P><H2>Further Explorations</H2>
+
+<P>The fact that each term in the series is divided by <CODE>:harmonic</CODE> limits this
+program to a particular family of waveforms, the family that includes
+square waves and sawtooth waves.  In general, real musical instruments
+don't have such regularity in the extent to which each term contributes
+to the sum.  For example, I started
+by saying that clarinets and pipe
+organs are made of odd harmonics, just as square waves are.  But clarinets
+don't sound like organs, and neither sound like square waves.  There
+is a family resemblance, but there are definite differences too. 
+The differences are due to the different &quot;weights&quot; that each instrument
+gives to each harmonic.
+
+<P>Instead of the <CODE>maxharm</CODE> and <CODE>skip</CODE>
+variables in the program as I've written
+it, you could have an input called <CODE>timbre</CODE> (a French word for
+the characteristic sound of an instrument, pronounced sort of like
+&quot;tamper&quot; with a B instead of the P) that would be a list of
+weighting factors.  The equivalent of <CODE>plot 5</CODE> would be this timbre
+list:
+
+<P><PRE>[1 0 0.3333 0 0.2]
+</PRE>
+
+<P>This list says that the fundamental has a weight of 1, the
+second harmonic has a weight of 0 (so it's not used at all), the third
+harmonic has a weight of 1/3, and so on.
+
+<P>The <CODE>timbre</CODE> version of the program would be perfectly general.  You
+could create any instrument, if you could find the right weighting
+factors.  But so much generality makes it hard to know where to begin
+exploring all the possibilities.  Another thing you could do would
+be to try different kinds of formulas for weighting factors.  For
+example, you could write this new version of <CODE>term</CODE>:
+
+<P><PRE>to term :harmonic
+op (sin :xscale * :harmonic * :x)/(:harmonic * :harmonic)
+end
+</PRE>
+
+<P>What waveforms would result from this change?
+
+<P>If you're really interested in computer-generated music, you'll want
+to hear what these waveforms sound like.  Unfortunately, it's hard
+to do that with the standard sound generators in personal computers,
+which allow little or no control of timbre.  But if you have one
+of the computer-controllable musical instruments that have become
+available recently, you may be able to program them to reproduce
+the timbre of your choice.
+
+<P>On the other hand, you can hear the effect of different waveforms
+without a computer if you visit the <A HREF="http://www.exploratorium.edu/">Exploratorium</A>
+in San Francisco,
+the world's best museum.  Among their exhibits are several that let
+you experiment with different ways of generating sounds.  One of these
+exhibits is a machine that does audibly the same thing we've been
+doing graphically, adding up selected harmonics of a fundamental pitch.
+If you don't live near San Francisco, the Exploratorium is well worth
+the trip, no matter how far away you are!
+
+<P>
+<TABLE width="100%"><TR><TD><A HREF="../v2-toc2.html">(back to Table of Contents)</A>
+<TD align="right"><A HREF="https://people.eecs.berkeley.edu/~bh/v2ch12/v2ch12.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v2ch14/manual.html"><STRONG>NEXT</STRONG></A>
+</TABLE>
+
+<P><H2>Program Listing</H2>
+
+<P>As mentioned in the text, the appropriate value of <CODE>xrange</CODE> may be
+different depending on which computer you're using.
+
+<P><P>
+<P><PRE>
+to plot :inputs
+keyword :inputs ~
+        [maxharm 5 deltax 2 yscale 75 cycles 1 xrange 230 skip 2]
+localmake "xscale :cycles*180/:xrange
+splitscreen clearscreen hideturtle penup
+setpos list (-:xrange) 0
+pendown
+for [x :deltax [2*:xrange] :deltax] ~
+    [setpos list (xcor+:deltax) (:yscale * series :maxharm)]
+end
+
+;; Compute the Fourier series values
+
+to series :harmonic
+if :harmonic < 1 [output 0]
+output (term :harmonic)+(series :harmonic-:skip)
+end
+
+to term :harmonic
+output (sin :xscale * :harmonic * :x) / :harmonic
+end
+
+;; Handle keyword inputs
+
+.macro keyword :inputs :defaults
+if or (wordp :inputs) (numberp first :inputs) ~
+   [make "inputs sentence (first :defaults) :inputs]
+output `[local ,[filter [not numberp ?] :defaults]
+         setup.values ,[:defaults]
+         setup.values ,[:inputs]]
+end
+
+to setup.values :list
+if emptyp :list [stop]
+make first :list first butfirst :list
+setup.values butfirst butfirst :list
+end
+</PRE><P>
+
+
+
+
+<P><A HREF="../v2-toc2.html">(back to Table of Contents)</A>
+<P><A HREF="https://people.eecs.berkeley.edu/~bh/v2ch12/v2ch12.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v2ch14/manual.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>