00001 /* 00002 $Id: OscgafUGs.h 3449 2009-04-04 16:52:47Z leighsmith $ 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