MusicKit  0.0.0
OscgafUGs.h
00001 /*
00002   $Id$
00003   
00004   Defined In: The MusicKit
00005   Description:
00006      OscgafUG, superclass for OscgafUG (non-interpolating or "drop-sample") and 
00007    OscgafiUG (interpolating or "high-quality")
00008 
00009    - from dsp macros /usr/lib/dsp/ugsrc/oscgaf.asm and oscgafi.asm 
00010    (see source for details).
00011 
00012        OscgafUG<a><b><c><d>, where <a> is the output space, <b> is the
00013     amplitude input space, <c> is the increment input space, and <d> is
00014     the table space.
00015     
00016        OscgafUG is a class of lookup-table unit generators which includes
00017     patchpoint arguments for amplitude and frequency control.  That is,
00018     those parameters are intended to be determined by the output of some
00019     other unit generator, such as AsympUG.  See the example synthpatch
00020     FmExamp.m for an example of the use of Oscgaf.
00021     
00022        Amplitude control is straightforward.  The output of OscgafUG is
00023     simply the value of the lookup table times whatever comes in via the
00024     ampEnvInput patchpoint.  Frequency control is more complicated. The
00025     signal needed for freqEnvInput is not actually the frequency in Hertz, 
00026     but the phase increment, which is the amount the lookup table index changes
00027     during each sample.  This number depends on the desired frequency, the
00028     length of the lookup table, the sampling rate, and a constant called
00029     MK_OSCFREQSCALE. MK_OSCFREQSCALE is a power of two which represents
00030     the maximum possible increment.  Input to freqEnvInput must be divided
00031     by this number in order to insure that it remains in the 24-bit signal
00032     range.  The signal is then scaled back up by this number within
00033     Oscgaf, with a possible additional scaling by the incRatio (see
00034     below).
00035     
00036        A method called incAtFreq: has been provided which takes all the
00037     above factors into account and returns the increment for a given
00038     frequency.  The lookup table must be set first, via the -setTable:
00039     method, since the length of the table must be known to perform the
00040     calculation.  If more than one Oscgaf is to be controlled by the same
00041     increment envelope signal (such as in a typical FM patch), they can
00042     have different frequencies by using the -setIncRatio: method.  Since
00043     the input increment signal is scaled by MK_OSCFREQSCALE*incRatio
00044     within Oscgaf, the resulting frequency will be correspondingly
00045     changed.  The incRatio defaults to 1.0.
00046     
00047        The increment scaler can be set directly with -setIncScaler:. This
00048     simply sets the increment scaler to the value you provide, ignoring
00049     MK_OSCFREQSCALE, incRatio, etc.
00050     
00051        OscgafUG is a non-interpolating oscillator. That means that its
00052     fidelity depends on the size of the table (larger tables have lower
00053     distortion) and the highest frequency represented in the table. For
00054     high-quality synthesis, an interpolating version with the same methods,
00055     OscgafiUG, is preferable.
00056     However, an interpolating oscillator is also more expensive. OscgafUG
00057     is useful in cases where density of texture is more important than
00058     fidelity of individual sounds.
00059 
00060   Original Author: David A. Jaffe
00061 
00062   Copyright (c) 1988-1992, NeXT Computer, Inc.
00063   Portions Copyright (c) 1994 NeXT Computer, Inc. and reproduced under license from NeXT
00064   Portions Copyright (c) 1994 Stanford University.
00065   Portions Copyright (c) 1999-2001, The MusicKit Project.
00066 */
00067 // classgroup Oscillators and Waveform Generators
00131 #ifndef __MK_OscgafUGs_H___
00132 #define __MK_OscgafUGs_H___
00133 
00134 #import <MusicKit/MKUnitGenerator.h>
00135 
00136 @interface OscgafUGs: MKUnitGenerator
00137 {
00138     double _reservedOscgaf1;
00139     double incRatio;    /* optional multiplier on frequency Scale */
00140     double _reservedOscgaf2;
00141     id _reservedOscgaf3;
00142     int tableLength; /* Or 0 if no table. */
00143 }
00144 
00151 +(BOOL)shouldOptimize:(unsigned) arg;
00152 
00159 + (int) defaultTableLength: (id) anObj;
00160 
00168 -setIncScaler:(int)aScaler;
00169 
00178 -setPhase:(double)aPhase;
00179 
00188 -setAmpInput: (id) aPatchPoint;
00189 
00195 -setOutput: (id) aPatchPoint;
00196 
00209 -setIncInput: (id) aPatchPoint;
00210  /* Set frequency envelope input to specified patchPoint. Note that OscgafUG  
00211    implements a multiplicative frequency envelope. The actual phase increment 
00212    is the value of the signal received via aPatchPoint multiplied by the 
00213    IncScaler. To get the proper increment value for a certain frequency, e.g, 
00214    for use in a frequency envelope generator writing to the incEnvInput, 
00215    see "incAtFreq:" below. */
00216 
00226 -(double)incAtFreq:(double)aFreq;
00227 
00239 -setIncRatio:(double)aRatio;
00240 
00271 -setTable:anObj length:(int)aLength;
00272  /* 
00273    Sets the lookup table of the oscillator.
00274    anObj can be a MKSynthData object or a MKWaveTable (MKPartials or MKSamples).
00275 
00276    First releases its claim on the locally-allocated MKSynthData, if any. 
00277    (see below).
00278 
00279    If anObj is a MKSynthData object, the MKSynthData object is used directly.
00280 
00281    If anObj is a MKWaveTable, the receiver first searches in its MKOrchestra's
00282    shared object table to see if there is already an existing MKSynthData based 
00283    on the same MKWaveTable, of the same length, and in the required memory
00284    space. Otherwise, a local MKSynthData object is created and installed in the
00285    shared object table so that other unit generators running simultaneously 
00286    may share it. (This is important since DSP memory is limited.) 
00287    If the requested size is too large, because there is not sufficient DSP
00288    memory, smaller sizes are tried. (You can determine what size was used
00289    by sending the tableLength message.)
00290    
00291    Note that altering the contents of a MKWaveTable will have no effect once it 
00292    has been installed, even if you call setTable:length: again after 
00293    modifying the MKWaveTable. The reason is that the Orchestra's shared data
00294    mechanism finds the requested object based on its id, rather than its
00295    contents.
00296 
00297    If anObj is nil, simply releases the locally-allocated MKSynthData, if any. 
00298    If the table is not a power of 2, returns nil and generates the error
00299    MK_ugsPowerOf2Err. 
00300  */
00301 
00302 
00308 - setTable: (id) anObj;
00309 
00316 -setTableToSineROM;
00317 
00343 -setTable:anObj length:(int)aLength defaultToSineROM:(BOOL)yesOrNo;
00344  /* This method is provided as a convenience. It tries to do 'the right thing'
00345    in cases where the table cannot be allocated. 
00346 
00347    If the table can be allocated, it behaves like setTable:length:. If the
00348    table cannot be allocated, and the table memory space of the receiver is Y,
00349    sends [self setTableToSineROM]. 
00350    
00351    A common use of this method is to pass YES as the argument defaultToSineROM
00352    only if the SynthPatch is beginning a new phrase (the assumtion is that it 
00353    is better to keep the old wavetable than to use the sine ROM in this case).
00354    Another use of this method is to specifically request the sine ROM by 
00355    passing nil as anObj. If the sine ROM is used, the aLength argument is
00356    ignored.
00357    
00358    Errors:
00359    If anObj is not nil and the sine ROM is used, generates the error 
00360    MK_spsSineROMSubstitutionErr. If sineROMDefaultOK is YES but the 
00361    receiver's table memory space is X, the error MK_spsCantGetMemoryErr 
00362    is generated.
00363  */   
00364 
00365 
00372 -setTable: anObj defaultToSineROM:(BOOL)yesOrNo;
00373 
00378 - (unsigned) tableLength;
00379 
00384 -(double)incRatio;
00385 
00394 -runSelf;
00395 
00400 -idleSelf;
00401 
00402 @end
00403 
00404 #endif