1 Signal[float] : FloatArray {
3 *sineFill { arg size, amplitudes, phases;
4 ^Signal.newClear(size).sineFill(amplitudes, phases).normalize
6 *chebyFill { arg size, amplitudes, normalize=true;
7 ^Signal.newClear(size).chebyFill(amplitudes, normalize); //.normalizeTransfer //shouldn't normalize by default!
9 *hammingWindow { arg size, pad=0;
11 ^this.newClear(size).fill(0.5).addSine(1, 0.39, -0.5pi);
13 ^this.newClear(size-pad).fill(0.5).addSine(1, 0.39, -0.5pi) ++ this.newClear(pad);
16 *hanningWindow { arg size, pad=0;
18 ^this.newClear(size).fill(0.5).addSine(1, 0.5, -0.5pi);
20 ^this.newClear(size-pad).fill(0.5).addSine(1, 0.5, -0.5pi) ++ this.newClear(pad);
23 *welchWindow { arg size, pad=0;
25 ^this.newClear(size).addSine(0.5, 1, 0);
27 ^this.newClear(size-pad).addSine(0.5, 1, 0) ++ this.newClear(pad);
30 *rectWindow { arg size, pad=0;
32 ^this.newClear(size).fill(1.0);
34 ^this.newClear(size-pad).fill(1.0) ++ this.newClear(pad);
42 fill { arg val; _SignalFill ^this.primitiveFailed }
43 scale { arg scale; _SignalScale ^this.primitiveFailed }
44 offset { arg offset; _SignalOffset ^this.primitiveFailed }
47 // Interpolating oscillators require wavetables in a special format.
48 // This method returns a wavetable in that format.
54 // Shaper requires wavetables without wrap.
55 // This method returns a wavetable in that format.
56 //To generate size N wavetable need N/2+1 signal values rather than N/2
57 //because Buffer's add_wchebyshev calculates N/2+1 values whilst
58 //Signal's _SignalAddChebyshev calculates N/2!
60 var newsig = Signal.newClear((this.size-1)*2);
68 newsig[index]= 2*cur -next;
69 newsig[index+1]= next-cur;
77 peak { _SignalPeak; ^this.primitiveFailed }
79 normalize { arg beginSamp=0, endSamp;
84 _SignalNormalizeTransferFn;
88 invert { arg beginSamp=0, endSamp;
92 reverse { arg beginSamp=0, endSamp;
96 fade { arg beginSamp=0, endSamp, beginLevel=0.0, endLevel=1.0;
102 ^this.primitiveFailed
105 zeroPad { arg minSize;
106 var size = max(minSize ? 0, this.size).nextPowerOfTwo;
107 ^this ++ Signal.newClear(size - this.size);
110 integral { _SignalIntegral; ^this.primitiveFailed }
111 overDub { arg aSignal, index=0;
113 // add a signal to myself starting at the index
114 // if the other signal is too long only the first part is overdubbed
115 ^this.primitiveFailed
117 overWrite { arg aSignal, index=0;
119 // write a signal to myself starting at the index
120 // if the other signal is too long only the first part is overwritten
121 ^this.primitiveFailed
124 play { arg loop=false, mul=0.2, numChannels=1, server;
126 buf = Buffer.alloc(server ? Server.default, this.size, numChannels);
127 buf.sendCollection(this, 0, 0.1, { buf.play(loop, mul); });
131 waveFill { arg function, start = 0.0, end = 1.0;
132 var i = 0, step, size, val, x;
134 // evaluate a function for every sample over the interval from
137 if (size <= 0, { ^this });
140 step = (end - start) / size;
141 while ({ i < size }, {
142 val = function.value(x, this.at(i), i);
149 addSine { arg harmonicNumber = 1, amplitude = 1.0, phase = 0.0;
151 ^this.primitiveFailed
153 sineFill { arg amplitudes, phases;
155 if (phases.isNil, { phases = #[0]; });
156 amplitudes.do({ arg amp, i; this.addSine(i+1, amp, phases @@ i) });
158 sineFill2 { arg list;
160 list.do({ arg item, i;
161 var harm, amp, phase;
162 # harm, amp, phase = item;
163 this.addSine(harm, amp ? 1.0, phase ? 0.0);
167 addChebyshev { arg harmonicNumber = 1, amplitude = 1.0;
169 ^this.primitiveFailed
171 chebyFill { arg amplitudes, normalize=true;
173 amplitudes.do({ arg amp, i; this.addChebyshev(i+1, amp); if(i%4==1,{this.offset(1)}); if(i%4==3,{this.offset(-1)}); }); //corrections for JMC DC offsets, as per Buffer:cheby
175 if(normalize,{this.normalizeTransfer}); //no automatic cheby
179 chebyFill_old { arg amplitudes;
181 amplitudes.do({ arg amp, i; this.addChebyshev(i+1, amp) });
182 this.normalizeTransfer
186 *fftCosTable { arg fftsize;
187 ^this.newClear((fftsize/4) + 1).fftCosTable
191 harm = this.size / ((this.size - 1) * 4);
192 this.addSine(harm, 1, 0.5pi);
195 fft { arg imag, cosTable;
196 // argCosTable must contain 1/4 cycle of a cosine (use fftCosTable)
197 // fftsize is the next greater power of two than the receiver's length
199 ^this.primitiveFailed
201 ifft { arg imag, cosTable;
202 // argCosTable must contain 1/4 cycle of a cosine (use fftCosTable)
203 // fftsize is the next greater power of two than the receiver's length
205 ^this.primitiveFailed
208 neg { _Neg; ^this.primitiveFailed }
209 abs { _Abs; ^this.primitiveFailed }
210 sign { _Sign; ^this.primitiveFailed }
211 squared { _Squared; ^this.primitiveFailed }
212 cubed { _Cubed; ^this.primitiveFailed }
213 sqrt { _Sqrt; ^this.primitiveFailed }
214 exp { _Exp; ^this.primitiveFailed }
215 //reciprocal { _Recip; ^this.primitiveFailed }
216 //midicps { _MIDICPS; ^this.primitiveFailed }
217 //cpsmidi { _CPSMIDI; ^this.primitiveFailed }
218 //midiratio { _MIDIRatio; ^this.primitiveFailed }
219 //ratiomidi { _RatioMIDI; ^this.primitiveFailed }
220 //ampdb { _AmpDb; ^this.primitiveFailed }
221 //dbamp { _DbAmp; ^this.primitiveFailed }
222 //octcps { _OctCPS; ^this.primitiveFailed }
223 //cpsoct { _CPSOct; ^this.primitiveFailed }
224 log { _Log; ^this.primitiveFailed }
225 log2 { _Log2; ^this.primitiveFailed }
226 log10 { _Log10; ^this.primitiveFailed }
227 sin { _Sin; ^this.primitiveFailed }
228 cos { _Cos; ^this.primitiveFailed }
229 tan { _Tan; ^this.primitiveFailed }
230 asin { _ArcSin; ^this.primitiveFailed }
231 acos { _ArcCos; ^this.primitiveFailed }
232 atan { _ArcTan; ^this.primitiveFailed }
233 sinh { _SinH; ^this.primitiveFailed }
234 cosh { _CosH; ^this.primitiveFailed }
235 tanh { _TanH; ^this.primitiveFailed }
236 distort { _Distort; ^this.primitiveFailed }
237 softclip { _SoftClip; ^this.primitiveFailed }
239 rectWindow { _RectWindow; ^this.primitiveFailed }
240 hanWindow { _HanWindow; ^this.primitiveFailed }
241 welWindow { _WelchWindow; ^this.primitiveFailed }
242 triWindow { _TriWindow; ^this.primitiveFailed }
244 scurve { _SCurve; ^this.primitiveFailed }
245 ramp { _Ramp; ^this.primitiveFailed }
247 + { arg aNumber; _Add; ^aNumber.performBinaryOpOnSignal('+', this) }
248 - { arg aNumber; _Sub; ^aNumber.performBinaryOpOnSignal('-', this) }
249 * { arg aNumber; _Mul; ^aNumber.performBinaryOpOnSignal('*', this) }
250 / { arg aNumber; _FDiv; ^aNumber.performBinaryOpOnSignal('/', this) }
251 mod { arg aNumber; _Mod; ^aNumber.performBinaryOpOnSignal('mod', this) }
252 div { arg aNumber; _IDiv; ^aNumber.performBinaryOpOnSignal('div', this) }
253 pow { arg aNumber; _Pow; ^aNumber.performBinaryOpOnSignal('pow', this) }
254 min { arg aNumber; _Min; ^aNumber.performBinaryOpOnSignal('min', this) }
255 max { arg aNumber; _Max; ^aNumber.performBinaryOpOnSignal('max', this) }
256 ring1 { arg aNumber; _Ring1; ^aNumber.performBinaryOpOnSignal('ring1', this) }
257 ring2 { arg aNumber; _Ring2; ^aNumber.performBinaryOpOnSignal('ring2', this) }
258 ring3 { arg aNumber; _Ring3; ^aNumber.performBinaryOpOnSignal('ring3', this) }
259 ring4 { arg aNumber; _Ring4; ^aNumber.performBinaryOpOnSignal('ring4', this) }
260 difsqr { arg aNumber; _DifSqr; ^aNumber.performBinaryOpOnSignal('difsqr', this) }
261 sumsqr { arg aNumber; _SumSqr; ^aNumber.performBinaryOpOnSignal('sumsqr', this) }
262 sqrsum { arg aNumber; _SqrSum; ^aNumber.performBinaryOpOnSignal('sqrsum', this) }
263 sqrdif { arg aNumber; _SqrDif; ^aNumber.performBinaryOpOnSignal('sqrdif', this) }
264 absdif { arg aNumber; _AbsDif; ^aNumber.performBinaryOpOnSignal('absdif', this) }
265 thresh { arg aNumber; _Thresh; ^aNumber.performBinaryOpOnSignal('thresh', this) }
266 amclip { arg aNumber; _AMClip; ^aNumber.performBinaryOpOnSignal('amclip', this) }
267 scaleneg { arg aNumber; _ScaleNeg; ^aNumber.performBinaryOpOnSignal('scaleneg', this) }
268 clip2 { arg aNumber=1; _Clip2; ^aNumber.performBinaryOpOnSignal('clip2', this) }
269 fold2 { arg aNumber; _Fold2; ^aNumber.performBinaryOpOnSignal('fold2', this) }
270 wrap2 { arg aNumber; _Wrap2; ^aNumber.performBinaryOpOnSignal('wrap2', this) }
271 excess { arg aNumber; _Excess; ^aNumber.performBinaryOpOnSignal('excess', this) }
272 firstArg { arg aNumber; _FirstArg; ^aNumber.performBinaryOpOnSignal('firstArg', this) }
274 == { arg aNumber; _EQ; ^aNumber.performBinaryOpOnSignal('==', this) }
275 != { arg aNumber; _NE; ^aNumber.performBinaryOpOnSignal('!=', this) }
277 clip { arg lo, hi; _ClipSignal; ^this.primitiveFailed }
278 wrap { arg lo, hi; _WrapSignal; ^this.primitiveFailed }
279 fold { arg lo, hi; _FoldSignal; ^this.primitiveFailed }
281 asInteger { _AsInt; ^this.primitiveFailed }
282 asFloat { _AsFloat; ^this.primitiveFailed }
283 asComplex { ^Complex.new(this, 0.0) }
291 performBinaryOpOnSignal { arg aSelector, aNumber; ^error("Math operation failed.\n") }
292 performBinaryOpOnComplex { arg aSelector, aComplex; ^aComplex.perform(aSelector, this.asComplex) }
293 performBinaryOpOnSimpleNumber { arg aSelector, aSimpleNumber; ^aSimpleNumber.perform(aSelector, this) }
296 Wavetable[float] : FloatArray {
297 // the only way to make a Wavetable is by Signal::asWavetable
299 ^this.shouldNotImplement(thisMethod)
302 ^this.shouldNotImplement(thisMethod)
305 *sineFill { arg size, amplitudes, phases;
306 ^Signal.sineFill(size, amplitudes, phases).asWavetable
309 //size must be N/2+1 for N power of two; N is eventual size of wavetable
310 *chebyFill { arg size, amplitudes, normalize=true;
312 ^Signal.chebyFill(size, amplitudes, normalize).asWavetableNoWrap; //asWavetable causes wrap here, problem
315 *chebyFill_old { arg size, amplitudes;
317 //this.deprecated(thisMethod, Buffer.findRespondingMethodFor(\cheby));
319 ^Signal.chebyFill(size, amplitudes).asWavetable; //asWavetable causes wrap here, problem
324 ^this.primitiveFailed
327 blend { arg anotherWavetable, blendFrac=0.5;
328 ^this.asSignal.blend(anotherWavetable.asSignal, blendFrac).asWavetable;
332 ^file.readAllSignal.asWavetable;
336 file = File.new(path, "wb");
338 file.write(this.asSignal);
342 //libMenuAction { arg names;
343 // this.plot(names.last);