I do something simular with wavetables in the spirit of PPG or Waldorf synthesizers (stepping through a bunch of single cycle waves), its great in combination with the moog~ filter and it sounded well on a concert yesterday. There are two windows applications out there which can generate wavetables and I managed to run them on my Linuxbox with Wine. Its the freeware Tranzilon
http://www.xs4all.nl/~avg/tranzilon/info.html
and the shareware wave256 http://www.sonicspot.com/wave256/wave256.html
Opensource solutions would be cool but I dont know any, I guess a pd patch should be possible and I tried something in csound some years ago.
Cheers,
Malte
Malte Steiner a écrit :
I do something simular with wavetables in the spirit of PPG or Waldorf synthesizers (stepping through a bunch of single cycle waves), its great in combination with the moog~ filter and it sounded well on a concert yesterday. There are two windows applications out there which can generate wavetables and I managed to run them on my Linuxbox with Wine. Its the freeware Tranzilon
I didn't try this freeware, but it looks like very good, the info.html is explicitly show the fonctionning,then we could deduce how to proceed for doing something similar with this. Also I am not sure how one hundred of waveforms would be stored into the patch. Using one hundred of tables woild be the basic solution, but also a single table for storing them all could be enough. In all cases, DS will be usefull for manipulating waves by hand. Ciao, PC.
#N canvas 0 0 618 280 10; #X obj 85 115 noise~; #X text 121 13 waveshape morphing; #X obj 134 82 nbx 5 14 -1e+037 1e+037 0 1 empty empty Frequency 0 -6 0 10 -262144 -1 -1 1017 256; #X floatatom 131 183 5 0 0 0 - - -; #X obj 173 181 hsl 128 15 0 127 0 0 empty empty WaveShape -2 -6 0 8 -262144 -1 -1 0 1; #N canvas 0 0 450 300 (subpatch) 0; #X array $0-lfo3 10000 float 2; #X coords 0 1 10000 -1 100 50 1; #X restore 332 176 graph; #X obj 179 208 t b; #X obj 209 211 t b; #X obj 195 237 tabwrite~ $0-lfo3; #X msg 155 122 63; #X msg 157 103 0; #X msg 155 143 127; #N canvas 508 62 468 391 module3 0; #X obj 139 23 inlet~; #X obj 176 343 outlet~; #X obj 233 71 osc~; #X obj 232 50 / 100; #X obj 140 122 samphold~; #X obj 232 24 inlet; #X obj 283 23 inlet; #X obj 315 55 fade-morph 63 128; #X obj 176 234 +~; #X obj 176 267 +~; #X obj 324 106 fade-morph 0 126; #X obj 325 157 fade-morph -63 126; #X obj 242 160 *~ 0; #X obj 177 151 *~ 0; #X obj 234 209 *~ 1; #X text 327 36 Random; #X text 336 87 Square; #X text 335 136 Sinus; #X obj 252 264 t b; #X obj 220 144 -~; #X obj 216 120 <~ 0; #X obj 247 120 >~ 0; #X obj 248 295 tabwrite~ $0-lfo3-square; #X connect 0 0 4 0; #X connect 2 0 14 0; #X connect 2 0 20 0; #X connect 2 0 21 0; #X connect 3 0 2 0; #X connect 4 0 13 0; #X connect 5 0 3 0; #X connect 6 0 7 0; #X connect 6 0 10 0; #X connect 6 0 11 0; #X connect 6 0 18 0; #X connect 7 0 13 1; #X connect 8 0 9 0; #X connect 9 0 1 0; #X connect 10 0 12 1; #X connect 11 0 14 1; #X connect 12 0 8 1; #X connect 12 0 22 0; #X connect 13 0 8 0; #X connect 14 0 9 1; #X connect 18 0 22 0; #X connect 19 0 12 0; #X connect 20 0 4 1; #X connect 20 0 19 0; #X connect 21 0 19 1; #X restore 111 208 pd module3; #X msg 317 82 ; pd dsp 1; #X obj 319 47 loadbang; #X connect 0 0 12 0; #X connect 2 0 3 0; #X connect 3 0 12 1; #X connect 3 0 6 0; #X connect 4 0 7 0; #X connect 4 0 12 2; #X connect 4 0 8 0; #X connect 6 0 8 0; #X connect 7 0 8 0; #X connect 9 0 4 0; #X connect 10 0 4 0; #X connect 11 0 4 0; #X connect 12 0 8 0; #X connect 14 0 13 0;
Hello,
I didn't try this freeware, but it looks like very good, the info.html is explicitly show the fonctionning,then we could deduce how to proceed for doing something similar with this. Also I am not sure how one hundred of waveforms would be stored into the patch.
I didnt looked into your patch yet but usually these waveforms are stored in one table as one sample. Your tabread object should run through one waveform at a time, I have to look up how much bytes they are but assume 256, so it runs from 0 to 255 and to switch to another waveform you add n*256 where n is the waveformnumber. When you switch with a line object over several waveforms, you get the wonderful crude ppg sound but you should make sure that it goes only whole numbers without fractions so it really jumps a whole waveform each step. It can be done by sending the moving number through an int object.
Even in the boring rompler 'synthesizers' of the 90s all samples are usually stored in one big memorychunk. The Emu line of Proteus and Morpheus Synthesizers even let you change the wavestart, -end and loop settings beyond one sample borders so you can create rather sick material.
http://en.wikipedia.org/wiki/Wavetable
Cheers,
Malte Steiner media art + development -www.block4.com-
Malte Steiner a écrit :
I didnt looked into your patch yet but usually these waveforms are stored in one table as one sample.
Oops, fortunately you didn't looked into the patch, there was, again, a missing abstraction which is attached. It's a kind of autorange but that outputs values between zero and one for a given pair of input range. This abstraction permits to slide between waveforms by adding them progressively
Your tabread object should run through one waveform at a time,
So the functionning seems different because my patch is about getting the average between to successive waveshapes, instead of passing from one to another without transition.
I have to look up how much bytes they are but assume 256, so it runs from 0 to 255 and to switch to another waveform you add n*256 where n is the waveformnumber.
Good, then the amount of samples won't get truncated with using one hundred of different waveforms.
thanks, PC.
Cheers,
Malte
#N canvas 0 0 339 233 10; #N canvas 29 318 179 311 fade-morph 0; #X obj 42 8 inlet; #X obj 41 267 outlet; #X obj 42 114 change; #X obj 41 245 /; #X obj 42 157 -; #X obj 109 50 $2; #X obj 127 118 / 2; #X obj 42 178 abs; #X obj 42 200 -; #X obj 42 222 abs; #X obj 42 135 - $1; #X obj 42 30 t a b; #X obj 80 72 + $1; #X obj 42 91 clip $1; #X connect 0 0 11 0; #X connect 2 0 10 0; #X connect 3 0 1 0; #X connect 4 0 7 0; #X connect 5 0 6 0; #X connect 5 0 12 0; #X connect 6 0 4 1; #X connect 6 0 3 1; #X connect 6 0 8 1; #X connect 7 0 8 0; #X connect 8 0 9 0; #X connect 9 0 3 0; #X connect 10 0 4 0; #X connect 11 0 13 0; #X connect 11 1 5 0; #X connect 12 0 13 2; #X connect 13 0 2 0; #X restore 163 121 pd fade-morph; #X text 161 47 $2 = ending fade out; #X text 161 26 $1 = begining fade in; #X text 148 66 $2/2 = top level; #X text 86 44 inlet; #X text 72 189 outlet = value between 0 and 1; #X obj 163 94 inlet; #X obj 163 145 outlet; #X connect 0 0 7 0; #X connect 6 0 0 0;
Malte Steiner wrote:
I didnt looked into your patch yet but usually these waveforms are stored in one table as one sample. Your tabread object should run through one waveform at a time, I have to look up how much bytes they are but assume 256, so it runs from 0 to 255 and to switch to another waveform you add n*256 where n is the waveformnumber. When you switch with a line object over several waveforms, you get the wonderful crude ppg sound but you should make sure that it goes only whole numbers without fractions so it really jumps a whole waveform each step. It can be done by sending the moving number through an int object.
Here's a patch that does exactly this. 256 waveforms each 256 samples long.
When writing it I found a bug in wrap~ in pd-0.40-2 from Miller's site:
sig~ 1 wrap~ print~ -> 0
sig~ 0 wrap~ print~ -> 1
http://claudiusmaximus.goto10.org
#N canvas 10 18 454 378 10; #N canvas 0 0 293 526 $0-make-wavetables 0; #X obj 29 26 inlet; #X obj 29 59 bang; #X msg 29 88 256; #X obj 29 118 until; #X obj 29 147 f 0; #X obj 61 147 + 1; #X obj 60 169 mod 256; #X msg 29 225 256; #X obj 29 255 until; #X obj 29 284 f 0; #X obj 61 284 + 1; #X obj 60 306 mod 256; #X obj 29 422 pack f f; #X obj 29 198 t b f f; #X obj 29 332 t f f; #X obj 191 315 * 256; #X obj 171 416 +; #X obj 29 499 tabwrite $0-wavetable; #X obj 125 305 / 255; #X obj 29 359 / 256; #N canvas 523 553 450 300 $0-waveform 0; #X obj 27 33 inlet; #X obj 27 57 unpack f f; #X obj 27 262 outlet; #X text 34 105 phase; #X text 286 102 morph; #X obj 28 127 expr cos((1-$f2) * 5*tanh(1-$f1*2) + ($f2) * 5*cos(5*(1-$f1*2))) ; #X connect 0 0 1 0; #X connect 1 0 5 0; #X connect 1 1 5 1; #X connect 5 0 2 0; #X restore 29 468 pd $0-waveform; #X connect 0 0 1 0; #X connect 1 0 2 0; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 4 0 5 0; #X connect 4 0 13 0; #X connect 5 0 6 0; #X connect 6 0 4 1; #X connect 7 0 8 0; #X connect 8 0 9 0; #X connect 9 0 10 0; #X connect 9 0 14 0; #X connect 10 0 11 0; #X connect 11 0 9 1; #X connect 12 0 20 0; #X connect 13 0 7 0; #X connect 13 1 18 0; #X connect 13 2 15 0; #X connect 14 0 19 0; #X connect 14 1 16 0; #X connect 15 0 16 1; #X connect 16 0 17 1; #X connect 18 0 12 1; #X connect 19 0 12 0; #X connect 20 0 17 0; #X restore 78 65 pd $0-make-wavetables; #X obj 76 99 table $0-wavetable 65536; #X obj 56 37 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 78 37 loadbang; #X obj 85 258 +~; #X obj 85 309 hip~ 5; #X obj 84 333 *~ 0.1; #X obj 85 355 dac~; #X obj 260 60 metro 2000; #X obj 260 37 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1; #X obj 260 106 vline~; #X obj 273 134 wrap~; #X obj 259 155 -~; #X obj 141 236 samphold~; #X msg 290 273 ; pd dsp $1; #X obj 290 252 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1; #X obj 83 126 loadbang; #X obj 259 210 *~ 256; #X obj 260 176 max~ 0; #X text 321 135 bug: wrap~ 0 -> 1; #X text 313 177 bug workaround; #X obj 85 283 tabread4~ $0-wavetable; #X obj 84 203 phasor~; #X obj 84 184 mtof; #X floatatom 83 166 5 0 0 0 - - -; #X msg 83 146 48; #X obj 85 235 *~ 256; #X obj 143 330 / 100; #X floatatom 143 312 5 0 0 0 - - -; #X msg 260 83 255 1500 , 0 300 1600; #X connect 2 0 0 0; #X connect 3 0 0 0; #X connect 4 0 21 0; #X connect 5 0 6 0; #X connect 6 0 7 0; #X connect 6 0 7 1; #X connect 8 0 29 0; #X connect 9 0 8 0; #X connect 10 0 11 0; #X connect 10 0 12 0; #X connect 11 0 12 1; #X connect 12 0 18 0; #X connect 13 0 4 1; #X connect 15 0 14 0; #X connect 16 0 25 0; #X connect 17 0 13 0; #X connect 18 0 17 0; #X connect 21 0 5 0; #X connect 22 0 13 1; #X connect 22 0 26 0; #X connect 23 0 22 0; #X connect 24 0 23 0; #X connect 25 0 24 0; #X connect 26 0 4 0; #X connect 27 0 6 1; #X connect 28 0 27 0; #X connect 29 0 10 0;
On Sun, 2007-01-14 at 15:01 +0000, Claude Heiland-Allen wrote:
When writing it I found a bug in wrap~ in pd-0.40-2 from Miller's site:
sig~ 1 wrap~ print~ -> 0
as i would expect.
sig~ 0 wrap~ print~ -> 1
as i would expect, as well. where is the bug? am i missing something?
roman
Telefonate ohne weitere Kosten vom PC zum PC: http://messenger.yahoo.de
Roman Haefeli wrote:
On Sun, 2007-01-14 at 15:01 +0000, Claude Heiland-Allen wrote:
When writing it I found a bug in wrap~ in pd-0.40-2 from Miller's site:
sig~ 1 wrap~ print~ -> 0
as i would expect.
sig~ 0 wrap~ print~ -> 1
as i would expect, as well. where is the bug? am i missing something?
wrap~-help says:
----8<---- wrap~ gives the difference between the input and the largest integer not exceeding it (for positive numbers this is the fractional part). ----8<----
largest integer not exceeding 0 is 0, or?
largest integer not exceeding X is X when X is an integer, or?
it makes life simpler when
(x - (wrap~ x)) == x
when x is an integer, as there is no [int~] in Pd.
roman
Claude
On Mon, 2007-01-15 at 05:51 +0000, Claude Heiland-Allen wrote:
Roman Haefeli wrote:
On Sun, 2007-01-14 at 15:01 +0000, Claude Heiland-Allen wrote:
When writing it I found a bug in wrap~ in pd-0.40-2 from Miller's site:
sig~ 1 wrap~ print~ -> 0
as i would expect.
sig~ 0 wrap~ print~ -> 1
as i would expect, as well. where is the bug? am i missing something?
wrap~-help says:
----8<---- wrap~ gives the difference between the input and the largest integer not exceeding it (for positive numbers this is the fractional part). ----8<----
largest integer not exceeding 0 is 0, or?
largest integer not exceeding X is X when X is an integer, or?
exactly, and since [wrap~] gives you the difference between the largest integer not exceeding X and X, it will always give you 0, when X is an integer. the output of [wrap~] is always => 0 and < 1.
it makes life simpler when
(x - (wrap~ x)) == x
when x is an integer, as there is no [int~] in Pd.
i can't quite follow, what you mean hear. you CAN use [wrap~] to build your own [int~] (see attached patch).
roman
Hallo, Roman Haefeli hat gesagt: // Roman Haefeli wrote:
i can't quite follow, what you mean hear. you CAN use [wrap~] to build your own [int~] (see attached patch).
Well, the problem is, that this will give you "-1" if you apply it to [sig~ 0], whereas int(0) is 0 as is the equivalent message algorithm using [wrap] (see attached again).
Frank Barknecht _ ______footils.org_ __goto10.org__
On Mon, 2007-01-15 at 14:08 +0100, Frank Barknecht wrote:
Hallo, Roman Haefeli hat gesagt: // Roman Haefeli wrote:
i can't quite follow, what you mean hear. you CAN use [wrap~] to build your own [int~] (see attached patch).
Well, the problem is, that this will give you "-1" if you apply it to [sig~ 0], whereas int(0) is 0 as is the equivalent message algorithm using [wrap] (see attached again).
ah, i see. thank you for making this clear. obviously i cannot count to 1 ;-).
sig~ 0 wrap~ print~ -> 1
as i would expect, as well. where is the bug? am i missing
something?
of course, this looks also strange in my eyes. i was not reading carefully.
roman
___________________________________________________________ Der frühe Vogel fängt den Wurm. Hier gelangen Sie zum neuen Yahoo! Mail: http://mail.yahoo.de
On Mon, 2007-01-15 at 11:49 +0100, Roman Haefeli wrote:
the output of [wrap~] is always => 0 and < 1.
which is wrong, when the input is 0. i din't read carefully, sorry.
Telefonate ohne weitere Kosten vom PC zum PC: http://messenger.yahoo.de
On 15/01/2007, at 11.49, Roman Haefeli wrote:
exactly, and since [wrap~] gives you the difference between the
largest integer not exceeding X and X, it will always give you 0, when X is an integer.
That's how i read it too. But following that: If 0 (zero) is an
integer (it normally is, right?), then the largest integer not
exceeding 0 is 0, and the difference is 0-0=0. Problem being that
wrap~ of the signal 0 gives 1, not 0.
I'd like to know too, as i find the description from the help patch
confusing (when the input is integers). As i understand what wrap~
does (again, on the integer domain), it's like a function f: Z ->
{0,1} where f(N)=0 and f(Z\N)=1 (where N is the numbers 1,2,3,.. and
Z is the numbers ...,-1,0,1,...).
the output of [wrap~] is always => 0 and < 1.
Again, i agree that from the description it would make sense if that
intact was the output domain. But it doesn't match the experience
using wrap~.
On 15/01/2007, at 14.37, Steffen wrote:
On 15/01/2007, at 11.49, Roman Haefeli wrote:
exactly, and since [wrap~] gives you the difference between the
largest integer not exceeding X and X, it will always give you 0, when X
is an integer.That's how i read it too. But following that: If 0 (zero) is an
integer (it normally is, right?), then the largest integer not
exceeding 0 is 0, and the difference is 0-0=0. Problem being that
wrap~ of the signal 0 gives 1, not 0.I'd like to know too, as i find the description from the help patch
confusing (when the input is integers). As i understand what wrap~
does (again, on the integer domain), it's like a function f: Z ->
{0,1} where f(N)=0 and f(Z\N)=1 (where N is the numbers 1,2,3,..
and Z is the numbers ...,-1,0,1,...).the output of [wrap~] is always => 0 and < 1.
Again, i agree that from the description it would make sense if
that intact was the output domain. But it doesn't match the
experience using wrap~.
Can someone give an explanation of why wrap~ behaves as it does for 0
and negative integer signals?
If it is meant do behave like it does, i think it would make sense to
changed the help patch so it matches the behavior. - As the
functionality is described now, i find it expected that it works on
signals as wrap from zexy does on the numbers (when wrap from zexy is
called without arguments).
That said. Why does wrap~ of fx. the signal -0.99 return 0.00999999?
and wrap~ of fx. -5.99 return 0.0100002?
That said. Why does wrap~ of fx. the signal -0.99 return 0.00999999? and wrap~ of fx. -5.99 return 0.0100002?
It seems that the precision is low: if wrap~ outputs the difference with the signal and the greatest integer, not larger than it, for -0.99 it should return 0.01.
BTW, if one wants to get frac part of the signal, then with the current implementation of wrap~ (returning 1 for each non-positive integer)
[wrap~] | [wrap~]
should do the work: 0 for any integer and the frac part for any other number.
On 29/01/2007, at 17.22, Denis Trapeznikoff wrote:
That said. Why does wrap~ of fx. the signal -0.99 return 0.00999999? and wrap~ of fx. - 5.99 return 0.0100002?
It seems that the precision is low: if wrap~ outputs the difference
with the signal and the greatest integer, not larger than it, for
-0.99 it should return 0.01.
Yes, exactly. I just wondered how-come it wasn't precise.
BTW, if one wants to get frac part of the signal, then with the
current implementation of wrap~ (returning 1 for each non-positive
integer)[wrap~] | [wrap~]
should do the work: 0 for any integer and the frac part for any
other number.
Here it just swaps it, such that for non-positive integers returns 1,
as it with one wrap~ object does for non-negative integers.
I still don't understand how warp~ of non-negative integers signals
returns 1. The help files says one are to find the largest integer
not exceeding the signal, which for integers are the given integer it
self; then find the difference, which is 0; and then calculate
difference mod 1, that is 0 mod 1, which is 0. What am i missing?
Sorry, "reply" instead of "reply all" again.
Well, it seemed impossible to me, but here what I found in d_math.c (pd 0.40.0 or something, I'm a bit lazy to look for version):
static t_int *sigwrap_perform(t_int *w) { float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2); t_int n = *(t_int *)(w+3); while (n--) { float f = *in++; int k = f; if (f > 0) *out++ = f-k; else *out++ = f - (k-1); } return (w + 4); }
Here it definitely says: if f <= 0 then return f - ((int f) - 1) = f - (int f) + 1 = frac(f) + 1 which is 1 for each non-positive int, of course, and assumes float-to-int conversions (int k = f) take 'neares to zero' which seems a dangerous assumption for me (I guess, it should return frac(f) + 1, where 0<=frac<1 for each negative number; perhaps, some compiler flags fix it, it depends on compiler, but for integers the result is always 1). I think, the whole situation is worthy a bug report.