home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 202.lha / FFT / fft.doc < prev    next >
Encoding:
Text File  |  1988-12-28  |  14.0 KB  |  351 lines

  1.                                FFT.HMSL
  2.  
  3. version 1.0
  4. September 19, 1988
  5.  
  6.  
  7. INTRODUCTION
  8.  
  9.      FFT stands for Fast Fourier Transform.  There are a variety of ways to
  10. describe what a Fourier Transform is and what it does.
  11. I'll stick to a purely musical description, specifically:
  12. what a Fourier Transform does to a sound sample.
  13. The FFT accepts a sequence of sample points as input, and outputs
  14. the energies contained in its partials.  A single FFT tells you nothing about
  15. how a sound changes over time, only that its first partial has "this" much
  16. power, its second "this" much, its third "that" much, etc.  Timbres are
  17. completely describable in terms of how much energy is contained in the
  18. various partials.
  19.      However, most sounds change considerably from start to finish.  The
  20. strategy, then, is to do a sequence of small FFT's on little chunks of the
  21. sample, maybe 32 points at a time.  This 32 point spread is called a "window".
  22. The window scoots along the sample, taking FFT's at every stop.  What you're
  23. finally left with is a nice report of how each partial of the original sound
  24. changed over time.  This is what the routine FFT.H does.
  25.      An inverse Fourier Transform does the opposite: it recombines all the
  26. partials into a single sound sample.  This is done by the routine IFFT.H
  27.      The power of these two routines is dramatic.  After doing an FFT.H on
  28. a sound, you can go in and change partials around: delete some, invert others,
  29. reverse them, draw your own, write routines to generate or alter them in
  30. ways that God never intended.  Then run the IFFT.H routine to recombine them,
  31. and listen to your new sound!  Or create sounds from scratch by using IFFT.H
  32. alone.
  33.  
  34. ************************** RUNNING THE CODE ******************************
  35.  
  36.          PLEASE DO THE TUTORIAL BEFORE YOU TRY THIS SECTION!!!!!!!!
  37.  
  38. 1) Get HMSL up and running.
  39.  
  40. 2) INCLUDE 4th:FFT/FFT.HMSL  ( read file READMEFIRST about renaming disk. etc)
  41.    If your version of JForth is v1.2, edit the file X*.ASM and remove the
  42.    HASH.ON and HASH.OFF lines before you do this.
  43.  
  44. 3) Load up a sample into any OB.SAMPLE like this:
  45.    " MY-SOUND-FILE" LOAD: SAMPLE-IN
  46.    I instantiated two sample objects: SAMPLE-IN and SAMPLE-OUT in this file.
  47.    Use them for convenience only; the code doesn't rely on them.
  48.  
  49. 4) Now type INIT.FFT.HMSL (you only have to do this step once, even if you
  50.    load other samples later)
  51.  
  52. 5) To run the FFT routine, type:
  53.    SAMPLE-IN FFT.H
  54.  
  55. 6) wait a while (roughly 12 seconds for a sample with 2048 points)
  56.  
  57. 7) get the shape editor up by typing HMSL, and you'll see two objects
  58.    in there called MAGNITUDES and PHASE INDICES.  MAGNITUDES is the shape
  59.    which contains the amplitudes of the various partials.  Flip through
  60.    the dimensions.
  61.    PHASE INDICES might look a bit anti-intuitive.  Its even numbered
  62.    dimensions store phase angle information in terms of index values to
  63.    a trig lookup table instead of in terms of degrees.  This is done so 
  64.    for speed, and is extremely necessary.
  65.    Odd numbered dimensions contain -1's and 0's, which store the signs of
  66.    some values needed for the IFFT.
  67.    Hit the close box to get back.
  68.  
  69. 8) To run the inverse FFT routine, instantiate a target sample: let's say
  70.    OB.SAMPLE SAMPLE.OUT
  71.    and type:
  72.    SAMPLE-OUT IFFT.H
  73.  
  74. 9) wait a while.
  75.  
  76. 10) listen to the result   START: SAMPLE-OUT
  77.  
  78. IMPORTANT:
  79. If you look through the source code, you'll see that the FFT.H and IFFT.H
  80. routines don't necessarily expect OB.SAMPLE's.  You can pass them OB.ARRAY's
  81. if you care to.  The data width of the object you pass it is also variable,
  82. so any of you who have routines for loading samples from external samplers
  83. should bear this in mind.
  84.  
  85. *************************** CHANGING PARAMETERS *****************************
  86.  
  87.      As mentioned above, a "window" creeps over your sample, taking FFT's as 
  88. it goes. The size of the window defaults to 32, which you can change with 
  89. SET.WINDOW.SIZE ( size -- ).  Just don't try any size that's not a power
  90. of 2.  Use 2, 4, 8, 16, 32, 64, 128, or 256.  I've never tried values that 
  91. aren't in this list, but I'm not too curious about what would happen to tell you
  92. the truth.  
  93. The FFT presumes that the width of the window = width of the lowest period
  94. in the sample.
  95. At 10k sample rate, window size of 32 means the lowest frequency you can 
  96. resolve is about 312 Hz.  A window size of 64 means you can do pretty well 
  97. down to around 156 Hz.  The tradeoff: The wider the window, the coarser
  98. the detail of spectral change over time.  On the other hand, a narrow window
  99. will yield few partials.  The number of partials generated equals half the
  100. window size.  You'll get 16 partials with a 32 wide window. 
  101.  
  102.     The amount of the sample you want to work with can be set with
  103. SET.SAMPLE.SIZE ( size -- ).  It defaults to 2048. This means you'll be running
  104. the FFT on the first 2048 values of your input sample, and that your output
  105. sample will be allocated a size of 2048.  If your input sample has more
  106. than 2048 points, the rest will be ignored, if it has less, the surplus will 
  107. be padded with zeros.  The input sample will be unharmed in any case.
  108.      
  109.  
  110. *************** A LITTLE MORE ON MAGNITUDES and PHASE-INDICES ***********
  111.  
  112.     The number of dimensions in these shapes correspond to the number of 
  113. partials generated by the FFT.  This number depends on the window size.  
  114. A window 64 wide will generate 32 partials (half).  
  115. MAGNITUDES would in this case have 33 dimensions; one for each partial
  116. and an extra dimension that stores a very important value: 
  117. the WINDOWSIZE/2+1st "partial". 
  118. PHASE-INDICES will have 64 dimensions: two for each of 32 partials 
  119. ( one to hold the index to a sine lookup table, one to hold on to the 
  120. sign of the real component generated by the FFT).  
  121. The number of elements (MANY:) in these two shapes will equal the sample 
  122. size you set divided by the window size.  
  123. Looking at MAGNITUDES in the shape editor means you can click through the 
  124. partials and see how the magnitude of that partial changes over the course 
  125. of the sample.  You can and should mess with them.  Same with
  126. PHASE-INDICES: each even numbered dimension will show you how the phase
  127. relationships of the sample's partials change over time, while the odd
  128. numbered dimensions hold 0 or -1, used for IFFT.
  129.  
  130. ********************************* TOOLS **************************
  131.  
  132.  To get some nice tools to make your acoustic debauchery faster and easier,
  133.  
  134. INCLUDE FFT.TOOLS
  135.  
  136. Here's a glossary of words contained in this file
  137.  
  138.  
  139. COMPARE.THEM ( start -- )
  140.   testing only.  Prints values from SAMPLE-IN and SAMPLE-OUT starting at 
  141.   start, continuing until terminal hit.  Used to compare original sample 
  142.   with sample after FFT.H and IFFT.H
  143.  
  144.  
  145. ENV-TEMPLATE
  146.   This is not a word, this is an OB.SHAPE used to generate n-stage magnitude
  147.   envelopes.  It has two dimensions.  Dimension 0 is an increasing series
  148.   of values, and should not be altered unless low-to-high ordering is preserved.
  149.   Dimension 1 contains "magnitude" values.  The "shape" of this dimension
  150.   is used to carve out a nearly identical profile in any dimension of
  151.   MAGNITUDES.
  152.   see STAGE.ENVELOPE, FILL.DIM.ENV
  153.  
  154. FILL.DIM.ENV ( dimension -- )
  155.   Creates a new set of points in selected MAGNITUDES dimension.  Uses INTERP
  156.   between values in ENV-TEMPLATE. 
  157.   example:
  158.    5 FILL.DIM.ENV  
  159.    takes the current n-stage envelope prescribed by ENV-TEMPLATE and leaves 
  160.    the fifth MAGNITUDE dimension filled with values that follow the profile
  161.    of ENV-TEMPLATE.
  162.  
  163. FILL.DIM.MAG  ( value dim -- )
  164.  Fills magnitude values of a given partial with given value.
  165.  
  166.  
  167. FILL.DIM.PHASE  ( value dim -- )
  168.  Fills phase values of a given partial with given value.
  169.  
  170.  
  171. INIT.INSTRUMENTS ( -- )
  172.   Used for testing.  Loads the object SAMPLE-IN into INS-AMIGA-1
  173.   and SAMPLE-OUT into INS-AMIGA-2.  Puts TUNING-EQUAL into these instruments.
  174.  
  175.  
  176.  
  177. PLAY.BOTH ( end-note start-note -- )
  178.   Used for testing.  Plays SAMPLE-IN and SAMPLE-OUT alternately up selected
  179.   range of notes by NOTE.ON:ing INS-AMIGA-1 and INS-AMIGA-2
  180.   INIT.INSTRUMENTS first.  
  181.  
  182. PLAY.OUT ( end-note start-note -- )
  183.   Used for testing.  Plays SAMPLE-IN up selected
  184.   range of notes by NOTE.ON:ing INS-AMIGA-2
  185.   INIT.INSTRUMENTS first.
  186.  
  187. PLOT.M ( -- )
  188.   Plots contents of MAGNITUDES in mountain-style graph.  Only plots
  189.   50 elements, so if MAGNITUDES has, say, 200 elements, PLOT.M will plot
  190.   every 4th.
  191.   Frequency increases left to right, time axis increases "away" from you.
  192.   Magnitude is vertical.
  193.  
  194. PLOT.FIRST.50 ( -- )
  195.   Plots first 50 elements of MAGNITUDES.
  196.   A nice detailed look at the attack portion of your sound.
  197.  
  198. STAGE.ENVELOPE ( #stages -- )
  199.   Sets up how many stages in magnitude envelope.  Initializes ENV-TEMPLATE.
  200.   Initializes all with value 30.
  201.   example:
  202.    10 STAGE.ENVELOPE
  203.    sets up a 10 point envelope that you can edit and apply to any MAGNITUDE 
  204.    dimension with FILL.DIM.ENV
  205.  
  206.  
  207. ZERO.DIM.MAG  ( dim# -- )
  208.   zeros out all magnitude values of a given partial 
  209.   same as 0 dim# FILL.DIM: MAGNITUDES.
  210.  
  211.  
  212. ZERO.ALL.MAG ( -- )
  213.   zeros out all magnitude values of all partials.
  214.  
  215.  
  216. ZERO.DIM.PHASE  ( dim# -- )
  217.   zeros out all phase values of a given partial 
  218.  
  219.  
  220. ZERO.ALL.PHASE
  221.   zeros out all phase values of all partials.
  222.  
  223.  
  224.  
  225.  
  226. **************************  A QUICK TUTORIAL ******************************
  227.  
  228. We'll run various routines on the sample P2.  This sound, by the way, is
  229. the second note of the Indonesian Pelog scale, as sampled from an instrument
  230. I borrowed from Gamelan Son of Lion (NYC based new music group).
  231.  
  232. Load up HMSL and CD 4th:fft ( read file READMEFIRST about renaming disks, etc)
  233.  
  234. 1) INCLUDE FFT.HMSL
  235.    If your version of JForth is v1.2, edit the file X*.ASM and delete the
  236.    HASH.ON and HASH.OFF lines before you do this.
  237.  
  238. 2) INCLUDE FFT.TOOLS
  239.  
  240. 3) " P2" LOAD: SAMPLE-IN
  241.  
  242. 4) INIT.FFT.HMSL
  243.  
  244. 5) SAMPLE-IN FFT.H
  245.    That should take less than 12 seconds.
  246.  
  247. 6) HMSL
  248.    Look through the MAGNITUDES dimensions.  All have a tendency to slope down
  249.    because the sound fades out.  Notice dimension 11.  Large values there.
  250.    That's the "ching" of the mallet.  A high bright partial.  Want a better
  251.    view? Close the HMSL screen and type:
  252.  
  253. 7) PLOT.M
  254.    This is a "mountain graph" of MAGNITUDE values.  There's  a long smooth
  255.    ridge far left.  That's the lowest partial of the sound.  There's another
  256.    ridge around the middle of the screen.  That's a higher partial (the 6th).
  257.    See that nice big peak far right?  That's the high "ching"!
  258.  
  259. 8) GR.CLOSECURW closes the graphing window.
  260.  
  261. 9) Now let's recombine all the partials to resynthesize a sample.
  262.    SAMPLE-OUT IFFT.H
  263.    That should take less than 10 seconds.
  264.  
  265. 10) SAMPLE-OUT now contains the resynthesized data, and you can play it like 
  266.     any other sample. Compare SAMPLE-IN with SAMPLE-OUT:
  267.     40 35 PLAY.BOTH
  268.     You hear that SAMPLE-OUT is noisier and shorter than SAMPLE-IN.
  269.  
  270. 11) Use SET.SAMPLE.SIZE ( size -- ) to change how much of the sample is being 
  271.     used.  (The size defaulted to 2048 when you INIT.FFT.HMSL'ed.) 
  272.     type: 
  273.     6000 SET.SAMPLE.SIZE
  274.       Now try, just as before:
  275.       SAMPLE-IN FFT.H
  276.       SAMPLE-OUT IFFT.H
  277.       40 35 PLAY.BOTH
  278.       You'll note that the resynthesized sample is longer. Try typing:
  279.       MANY: SAMPLE-OUT .
  280.       It's not 6000, is it?  That's because SET.SAMPLE.SIZE divides your request
  281.       by the current window size and dumps the remainder.  Remember that the
  282.       window scans your sample end-to-end, and a fraction of a window is
  283.       a meaningless thing to subject to an FFT.
  284.  
  285. 12) Use SET.WINDOW.SIZE ( size -- ) to change the size of the window.  As 
  286.     mentioned above, this will increase or decrease the number of partials
  287.     generated (#partials=half-of-window-width).
  288.     type:
  289.     64 SET.WINDOW.SIZE
  290.     Now do your FFT.H and IFFT.H, and use PLAY.BOTH to compare the input
  291.     sample with the resynthesized sample.  Enter the shape-editor by typing
  292.     HMSL and look through the MAGNITUDE dimensions.  Notice that there are
  293.     32 partials this time, but that there is a loss of profile detail.  
  294.     The bigger the window, the less it will be able to track fine changes in 
  295.     the source sample.  
  296.     As was mentioned above, a window size that is not a power of 2 is 
  297.     meaningless.  Use 2, 4, 8, 16, 32, 64, 128, or 256 as arguments to
  298.     SET.WINDOW.SIZE.
  299.     
  300. 13) Now to edit partials for resynthesis.  
  301.     First, reset window size to 32 and sample size to 2048.  
  302.     Run the FFT.H on SAMPLE-IN.
  303.     You now have 16 partials to play with.  We'll establish a, say, ten-stage
  304.     envelope and use this to carve out magnitude profiles of selected 
  305.     partials.  Set up the envelope:
  306.     10 STAGE.ENVELOPE
  307.     You'll want to be able to edit it with the mouse, so type:
  308.     ENV-TEMPLATE ADD: SHAPE-HOLDER
  309.  
  310. 14) Type HMSL to enter the editor, and flip through until you see and select
  311.     ENV-TEMPLATE.
  312.     You'll see that dimension 0 is a rising line.  Leave it alone.  These
  313.     are index values to MAGNITUDES.  
  314.     Flip to dimension 1.  It's named AMP for AMPlitude.  Make sure your 
  315.     SET MODE is on REPLACE.  Go ahead and chisel out a profile.  Don't
  316.     set values too high.  I find that even very small values have a great 
  317.     effect (around 10-20).  Exit the editor.
  318.  
  319. 15) Type PLOT.M (not necessary, but a good demo)
  320.     Apply the envelope to the, say, thirteenth partial by typing:
  321.     13 FILL.DIM.ENV
  322.     PLOT.M again.  See what you just did?
  323.  
  324. ***  Go back and forth between steps 14 and 15 as often as you like. ***
  325.  
  326. 16) Finally, do a SAMPLE-OUT IFFT.H and listen to it. 
  327.     You should be able to get some extremely interesting sounds this way.
  328.  
  329.  
  330. **************************** END OF TUTORIAL ****************************
  331.  
  332. General notice to users:
  333.  
  334. Anyone who can make this thing faster and more accurate, please contact me. 
  335.  
  336. This code is free and in the public domain.  Please pass on the origin of
  337. the included sample P2 along to anyone you give it to.  If you change the
  338. source code, please comment, date, and sign your handiwork before you 
  339. upload it somewhere or otherwise pass it on.
  340.  
  341. Feel free to call or write for support, but don't feel snubbed if it takes
  342. a day or two for me to return your call.
  343.  
  344. Nick Didkovsky
  345. 171 east 99th street #2O
  346. NYC NY 1OO29
  347. (212) 369-1733
  348.  
  349. Great thanks to Robert Marsanyi who helped inestimably during the great
  350. "HMSL Blowout, Summer '88"  This code would not exist without him.
  351.