[sharing for requesting help] trying to make a feedback delay network in gen~
Feedback delay network is documented here : https://ccrma.stanford.edu/~jos/cfdn/Feedback_Delay_Networks.html
It seems to be like a lot of delay lines in parallel that are fed back into each other.
My skills in math/dsp are limited, so i assumed that the matrix at the top of the figure "Order 3 Feedback Delay Network." is just meaning that all sounds are summed up. But maybe i’m wrong ?..
There is a really cool fdn~ object in PureDatak, i’m trying to "replicate" it in gen~.
Of course as the pd one has inners guts that create (nearly) any number of delay lines, it’s not the same, but it still can be cool i think.
I’m not sure how to do this. Is it like this ?
----------begin_max5_patcher---------- 3643.3oc6c08bihiD+4j+JnbcaU2sUFunOQb08vbOeOdOt0TovFYOrKFbA3L Y1s18u8SHAXHAkHxGNst61shGa.a9oepoU2sZ052u9pUaJuWVuJ3uG7yAWc0 ue8UWoOT6Atp6yWs5Px8aySp0W1pMGSZ19UY0paLmLKUe3xM+xmDh9CVb5P4 olbYi96f5Np4PMe+nzbCWUmsuHIeUvW5t.8OcVw9aqjaaLWCCQVGdS.iSVyt I.iEseJlsNb3KotWYE82pv9ClbPeSVkJOTVWdpHcspUn98W0d9+35qae4FGa xxeKMY6eNWCFOeCtGEaJqRkUaKyKqLslv1Fw4WPiZFyz14TSqEIZuXJq8CTq Mc7KnkUH+lpcz2HZj2quyqNFjUzHqNVlmzjUVLSKGQo8GcWYQy.c+OqxTcny RJXaRAqtQ82Pap8mqN62zmDgWGZmdD31SGvYZIDAu8Ub3H5YBwGgPrn3VhOh DgI712InS6Clvmnw2YYUGK1QiJblkKuSVU2xOmu5qVkb73nCe0nuRK2+KF.w uY3PYElCgFNTk7tr9uezvQSpTs+FUi+TkgpuWvWYNop+959uZO4fPDM6vB0b DU+OTwH5QIarOub6uJSGIxp5dNJKxJNVIqkEMlt+wmNUtK4Tdysy2MM876R1 Js9kmUj4pU6qxRKKZAwjuY6g6ucpFm9QADabiQeEEIGm4KWqZGmp2jT0xqax kijFUB8kk4SO0PWo5YmjhrCIMxlLCXwgC+nYGNVodJYxMRVjn9M9Z81px77I +Tlyb2LmIU0auU9srzlup+sFSkpKO6XeWvpANJMaurtY5wZR1WO8HSzrOVLb rRgIG+oTNLUAwOodrY7IFoYfL9316nsNJw75H1kWpzcOzaaWQgMkEXl9wAjP qRU8rAapxBK5SupWmZ2yYu8T4ukGjKKrPl3WJYheJxbhB2WBWJPZtjFq4x3G p388kK2Vd3fR0zrj4+3SAMeMqNXe1cx5fRkh3zJ0asIpxsSuokaj+qjrlr+c SpcZdLQsqZ+loOAublkhizjImZHXymPOE0htLhoMAaB1YiGouKhoaRJ12Jp9 pe1mP35G2Mp.b4Y+KDoV0Ym0A0fhYG2kZSM.48Qo5qhSoF6svZI03nY0ALw. LANjvi6M6JbMFo9x7IFfMi87WlNBkDV5AYccq0g15Cv.rOv3TTntOPfed8vW H456j2erJ3urCE7ipWwAetdaRdR0gxTY.xF+FBN90nEFGoMY.EwtriyYZJ1X KjaCJMmTSjVPgFpcI.y5e8IjZl7HsYzWsolWLKjpOcvlERBPZhTGI29DZXuq 6PwbymfLIvzdSDdj8l.hLaBxa+ear4KdDCxyxl27VnYCgz+CkCuAN9IWG1.C 0gMPBSPJ3Q.ZXCT3KdXCSqBXiZnua1ZquIc8VYBtyDQ3BHhywyJOqvV3azXp 87yyP0kmp112Z5BISvT7kJqaxJFht2Oe1Dr.zjK7qYooSillI.T0sgyJ0cKz WJjwNi4GcceXPdAHFHjbKjwN.YLbHY7iXOKPl.KL6hjQ6XY.AyHWgLbDMHN+ .HENhFgKQ0LP3YWwLBPXl3gxFjkn1.HinHbkmQ9m77LMtWFlC9x0im11U0I2 ISuUcKTlXdaRSSU1lSMFi+FOiyu1oV84m51ELeiyBhm3la6ltOubSRd2brO7 cmYZMu9LI91jjC054ucWvtzMa+0eHOM3G1MShNvCWZdNXMaWrjiCHGxwgnPS LHMQ5EEeAxAj7r5lcmJJj4C9dOgWDuY7R6c5UvMbApMJ3bxSSMn2dIm1rBPK 3jmNCCwh+PkbhEZBIBQVy4QTT7kU7Y7T.PoqmSDhBBBhqbjG0QPljC3sUFZ5 zUelfRk4IeWKBUG7WqSNbLWVeSvg1+RtOfGFFp9veaNZisTZqmDdzLTuH1RG 7UNNbPbBiBe6oK8TgVmmkNaFFR4upbKqV1nfm590Omj533DF9zogWL2HVfDi Z5bSxUgG8UGHR1vuUkp2oQVcqI8eljfhuWxU6jxzMIa+054nO5GgnSjITYLj dh24nKtPC9MWnIbcb7SIxz2jIHyDzpkVh4eXBKurw3IrO7w36URKhFTReAGn eurXtz9E+1YS3Cy.Z2YFNSLxxPB6YHEuNYVogcykhV2gfYx2Ad7zjYcR1lnS zj9WPuKY8J5+m0q+uUVupUQGjV88uIaBBsLsSQnK8DRhd1IjDarVggWGgnDF qOa4Gqu3CK2qNjceGmZiQCAGiRwqwBlx2JEqJzSv6iGU5CKqD9QSHMhsPmLL 3nSl5RZ4yPtZ.MV740svSymnKJehX1HTB7dhmGMPnBRjYETANBkZiPoviPom kPElbdEfDJwFgxfGgpriYfP0WNDITrMBkCOcnh3y5PiE.kPskFWrH3QnpgzG HTSxbAPB0lYnLA7HTx4AkhL4GK7HTgM9LFdFgJNqBMhxVinXAFCQSmrslJ3. zxdNu0IIbLUQpDJfIUtMREdNfRYn0Q8RpHAfIUa13ygmSSJG4WqbAkhPJuOi iALoZyNeNAfN1GdlTEP9wea15ygmySsgucfT4PVR0l89b34.EIdjjJCxRp1r 4mCOmnHQijTIfTR0j2.TJpMCAPrfO2OguAnfOaVNwA0G04+lEZ+k6pEyo0kz R+60zeYxJAVrYkZRbHHrHNLhBK7rRCEqiwU6ZzlFQGlp.eJRrvyeBRWzWGM2 KdTjXovyqWRWvBUZmALgZy5LJ7BKCtK1VXNjITaVlQgWfCwcyfEh.YB0lUYT 3YUFlfWGq9OgdznPHyp1BGKEdNPzlUZ8rJUDAXV0VLYovyUWTDevFJd351bD HR3SgjkBuXxfXZgSba0ajRiALoZKjrT3E8PEe1FRVsfpxsI3xo1r0mBPGnTl P0lTPwbEohn.lTsZuO7bfBotj9PxPhg7S+1r4m.Omnh4m4TAjETsY1OAd9QI FImxAobpI+UaypWDydcXCfNTYV.NXSnTL4aIHRc0QDJ0NgBPGpLkLarYATBS BkXmPAnuT8EAW.KghsSnvyOJLtKT9.VBEYmPI.za+tpXYz4hkOzHzP6DJ.cf xLmSHNbkPisym.z4otxrpolWKP.jOE.p30977Y2JRwrMP.R9LxdUcLFfALoa UfCW4Stc9DdtKg5lr9P3JeZ2IIbD.iSh37.QfjNs6hDFdtHgBMkOE3JcZ2AI L7bPpaNlgqvocuivvy6nHyt4DbkMs6ZDFdtFY1VPLKpOvwlcI7j0kaNNDfqy mtcdLcLQLdvCNFkZmQQ.b8QqUbRMtbBTFkXmQA3JN2X1IMBxxnXqLJBfI4un ayDf.XFEYmQY.bonY1uK51EPgIiFZmQ4.bcnYjQI.VFM1NgFAv0flQDsy2SN DITgcBU.v0eV21rAAtDZjcBEfKRZiUnDAfkP41IT34sT2RtgDQgKgZ2cIDFf q4LpoB9ECWB0t2RH34sDwjAyDJfkPs6rDBfqgICSRv.VB0tuR.bILYHRBBZB nOyB1U.v5b14btiQgaN2YnU60LR.tJ6Lqn1Xn8H+qe4O+eOq9Yd7ZJVvXhVc ygfaEPmUXcV..nQCw8KGhtc2dr.Lx7pFpUl7EGHvvWQgQan3mFgOW1odbIn1 MktuOa4gQNto9va26jXvXiHhuDLSgAlYKAyDXfY5RvL1u1.yzXF4WaHeZLCj MCLzBvbres+k0BYAL1l3hW.ji7qc1tVHygAjWxXfvXHP7RFBDFi.hWxHfvX. P7RF.D6WaFlbvrWXF4pdYp2sq+FAmc10YrE9IvLBNXl3gXF6gXF4eXN1Co4P +CyB+CxQ9Gj49GjY9Gj8vQ.8vA.8ww+7OH6YCkvVR7WfgQyzX+CxB+CxQ9Gj 49GjYdGjYH+iko9GjI9Gjw9Gj8PYY+a.ah+MfMw+Fv1+Pb6d4fSgKhIfElcJ dQrHfAZWblhALoCmBZKiALP6RvAXTfAZWBBCi.KP6j9NfIR6R743HXgYWBCJ ODVX1knMyhA1Cgtvy.SamKZn4.SYmKJn4.SWmK5m4XXgYWljJFfvryAPBP11 wVBlARbxoKAyvHGd3jkfYXjpTb7RvLLxHMNZIXFFI9GObIXFF4WIKdIXFFow JaQxyB+ZLEHYKpyX1CG6FRASxYLG4gXl6gXl4gXl5gXl3e1OCI8yTODyDODy XODyHODygdHlcM7FHPAYWhhDEVP1kf0Qg0Z5vkXhRfkrrKgdlH.EjcIB+TJn frKSjBk.JH6x7UQwfBxtLThv+VDXLfsv0bRwLvzx4hlYJvjMbQ0LMBVX1okN JGTX1kLQhx7tk65aEIG7kqOeD8qlVgFiiJSPFLOs7.kmcmb89jrh+rqj9r5t jpgZ8y4y9y3uzeAyUXVePQ.pqjV83RoTc19h1pGz32092t7xjl12jmU2LTuk ls3TwzEPoHd3Z8FLuYynhet5.YJMZxFY0sxhVdaT8cZZUCB2cv5j6jo2lzzT ks4Ti776p66v65sUbS9IY4tA4fdofQ2y7xh8OI+M4pq+ZYUyLW9bWaOMFNy4 NnZVsm6S5svi4NehVJfO6YyJxZZKpSZBNbbgVZzEcRcQ0Me2vmzqGKD9hj7Z Y4SYyHTMrIHYutSMe06R+SZplaUe+axlU1jBOKfMeEpZ9RBntNTwMUUUziKE fyTQp5XD8ULsJTYHnGpXoildbBjNYXOKZSvSrA4wpRdrZjG0g4JdPwNfGAdr uK.AOWH9YpuM1T+KtX.ZpW.VvyCQ86If3tHQyubRzO3V8g+D1z5elSwb6cEO rXXwOTWvyCHw2U7vc.OzKW+0zZzzGe+E1kmuPuT9wL.axwi2Iqp69M0PQYww uTpMIfei9iYElOpsXXUk7tr9qORejjJ039MpA8OUYr53dAe00s2m+35+CI7R Pr. -----------end_max5_patcher-----------
Noone, really ? :/…
is that topic complicated for everyone, or am i really on that much of a bad track ?..
your patch seems simple enough, but i’m not sure if it really follows the math described at the jos link… so i’m trying to read and understand that link at my leisure(it does seem a bit more complicated at first glance), and if i eventually figure something helpful out, will certainly post here, as i find this thread very interesting.
in the meantime, here’s a bump to help get anyone else’s advice :)
(also, if anyone here had the c source code for the puredata fdn~ object and felt like attaching just that here(i couldn’t find just the one file very easily without the rest of the whole source distro) or could link to that specific file on sourceforge, might help alot… but just an idea… sorry in advance for my ignorance about getting pd-source-code :p)
fdn~ is inside the creb lib http://sourceforge.net/projects/pure-data/files/libraries/creb/
or here http://zwizwa.be/darcs/creb/
Also FWIW Pluggo for Live has a Feedback Network patch you might want to look at.
- This reply was modified 3 months by Rick.
@raja : i’m trying to translate the fdn~ from Pd to max also, see that thread : http://cycling74.com/forums/topic/trying-to-compile-only-2-errors-left/
but probably better not start from there, i completely bonked the source. The only useful things i learned with that so far is that -it seems possible, and -you need to enforce the variant -fnested-functions in the "other c flags" field.
@Rick : let me link to the fdn~ source direclty, if i may ! http://zwizwa.be/darcs/creb/modules/fdn~.c and didn’t know that pluggo thing
there is also an example of feedbak delay network inside a reverb in gen~, in the example/gen folder. it’s the gigaverb~. From that and other sources, i inferred that the math for feedback delay networks includes substracting some of the delay lines, and adding others and feed a different result in each feedback delay line, and maybe calculating feedback coefficients a little more carefully. So there is math needed and that simple attempt certainely is not close to that.
(i try a lot.)
- This reply was modified 3 months by vichug.
At first, got pretty far porting the fdn~.c source to msp. Actually heard the reverb sound, with damping capabilities and such… really nice.
But it kept crashing when i sent it a ‘reset’ message, so i kept working on it, eventually breaking so many goddamned things, i can’t tell where i’m at anymore(at least, now, i got it so it doesn’t crash on instantiation …but it makes no sound anymore :p).
Some veteran can probably take the .c file here and figure it out in seconds, but I might resist more torment for a bit :D
Sorry(but attached here is however far i got… at least some things specific to max are already in place there: instead of free/memset/etc. there’s sysmem_newptr/etc., floats are all changed to doubles(i think… though i might’ve changed em back and lost track by now :p), arguments are taken in using A_GIMME(rather than individual floats)…. probably many other things… worked on this for the past 18 hours to no avail.)
You’re doing gods work again, raja.
wow. thanks a lot … incidentally, i was working on it *a little* yesterday, and weeell i didn’t even think about memset to system_newptr etc… now that i look at your source it seems a looot more work than what i had anticipated T_T
if i may allow myself some questions…
* you added fonction declarations for all the functions, is that just cleaner programming method or required in Max vs not in Pd ?
* you removed all the "static" casting (if i understand well, those things are called typecasting right ?..) of functions, i don’t understand why there where "static" to begin with…
* i don’t understand when you need to use
* You melted together the fdnctl and fdn struct, is that required for Max vs Pd ? or again cleaner (or your prefered) programming workflow ?
I’m no expert and this is just one exercise I thought would get me back into coding mspmexternals in C, but I’m very rusty… Will do my best to explain:
- ‘static’ simply declares anything as global, but only within the .c file within which it appears. You normally don’t need it for anything but the class name(ex: ‘static t_class fdn_class’) and you don’t really need it there either(but I guess it can be safer in general(?)…) depends on how unique or generic your naming schemes are…
- ‘double’ and ‘t_double’ are essentially the same everywhere, but the ‘t_…’ versions of things are type-definitions which typecast to something assured to be the same size on all machines… I’ve never been entirely clear on this difference… But, I think it has to do with the fact that certain data formats have different byte/word lengths to their binary equivalents on different architectures, and the typecasting ‘t_..’ versions make sure they are always the same(for example ‘t_float’ will always be a 32-bit float and ‘t_double’ will always be a 64-bit float no matter how architectures and operating systems change in the future, and no matter their differences now too…)
- re: function declarations, I always thought this is just how C works: you need a declaration called a ‘function prototype’ before all functions so that the compiler knows what functions it can expect to look for(I think this is why you can write all functions in any order you choose after that)… In PD, it could be that they put the function prototypes in a separate definition file, or maybe I’m missing something else…. ;p
- melting the structs together: haha, no not required as far as I know, but when I can’t trace problems very well, I end up trying to make the code look more like regular max/MSP objects(most of which only use one structure). Furthermore, in PD, just like in Max5 and earlier(32-bit versions), you used to pass the input signals along with samprate info. and reference to object itself all in one proxy-like thing from the DSP method but you could send whatever you wanted in place of the exact object struct reference(you can see there in the original PD version’s c-file, within the function ‘fdn_dsp’, he passes the address of the fdnctl structure: "&x->x_ctl" instead of the main object structure). In Max’s newer dsp64 method, this may still be possible, but since we get a pointer to the main object’s structure itself, I figured I’d just melt them together for convenience of direct references in my DSP method(in a more recent version I reseparated the structs again, but in my perform routine, instead of pulling from the main object’s struct, I added this line: "t_fdnctl *ctl = &x->x_ctl" thus making it work more like the original PD code…)
Basically this part of the work was simply not knowing what was going wrong with crashes at first and guessing that the object struct might simplify things. Later, I found out that the crashes were more due to my way of initializing the newly created sysmem_newptr memory(when you use ‘for’ instead of ‘memset’, you don’t need to account for the bit-size of the data being stored… no need to use ‘sizeof’ there… At first, I did so and when this would initialize memory outside the range I wanted, it ended up ‘corrupting the heap’(<-that was my main error log with every crash). Having figured that out more recently(not uploaded here), I’ve returned to separate structures again since that had nothing to do with any problem, hehe :p
Incidentally, I also tried returning memory management to the original malloc/memset/free way, and that works fine too(slowly I’ve figured out the crashes, and I’m realizing that my main prob with sound is probably directly in the perform routine, or in some silly small mistake I’ve made somewhere initializing DSP… But I’m taking a small break now, because debugging this stuff is so much harder than in gen~ or even in some coding environs like supercollider, and it can get a bit overwhelmingly irritating, teeeheeee! >;D)
edit: duh… i should’ve just used ‘sysmem_newptrclear’ :p will try later:
Anyways, hope that helps a bit for now… will keep at it from time to time.
…also… some thoughts on doing this in gen~ since this thread was originally about that:
-it’s very possible to do basic variations of the idea on this page:
seems to me though, this(particularly the J.Stautner and M.Puckette paragraph) is also important gound for understanding that:
-there’s even variations of the feedback delay network idea in the gen~ examples(freeverb and gigaverb… though, i must admit i haven’t studied them extensively)
-i have to study the pd version of fdn~ more, but it seems possible and easier in gen~ to do that exact idea if you don’t try to incorporate some of the messaging to change internal states like ‘lines’ message(which changes the number of delay lines/’order’(very possible in gen~ if you have an absolute max of lines to begin with but not as efficient…(?)))
there are also efficient c tricks i don’t know yet about implementing in gen~(it’s possible codebox/genexpr can work with hexadecimal(?)), for example, this line ensures no matter what order(#-of-delay-lines) the user sets the object to, it will always be a multiple of 4:
int order = argc & 0xfffffffc;
(hence Tom Schouten’s comment in dutch: "veelvoud van 4"(‘multiple of 4′) in the original c file ;D)
and finally, i barely understand the equation for the first order IIR filter, but then to get to the difference equation is amazing… must learn math better :p
furthermore, it’s used to setup the gain coefficients but not at sample-rate… so… there would be some need to think more about messages/params to gen~ separately(or maybe i’m just whining to myself :p)
…and i didn’t mention what causes the object to output no sound now because i have no clue… but soon, because it’s safer to dereference an msp object’s struct entirely within its perform_routine before the vector is parsed sample-by-sample(before ‘for’ or ‘while’ loop),..i might try more of that…
the original PD code doesn’t do this entirely, these lines in particular:
cvec = ctl->c_vector[ctl->c_curvector]; lvec = ctl->c_vector[ctl->c_curvector ^ 1]; ctl->c_curvector ^= 1;
nice ! thanks for the infos.
re:functions declarations , from what i understood one needs to declare a function before it is used in another function – but the header lines are only a direct reference to the definition, so it counts as declaration (the compiler sees the header, then looks for function def in the code i guess, before going to next header) ; in the end if you define all the functions before they are used it should be fine ? :)
And i completely get the "overwhelmingly irritating" part, although it will be a delight to know about your progression in this thing ;D
in the end if you define all the functions before they are used it should be fine ?
ya, exactly. i just reread the relevant info. in Eric Lyon’s book, the compiler assumes all functions will return an ‘int’. this is why the ‘main’ function doesn’t require a prototype(the compiler uses function prototypes to do argument checking(type and number-of), ‘main’ has no arguments and returns an ‘int’). prototypes might not always be necessary but are particularly required for max external code.
boy do i feel stupid.
i had a typo in the "fdn_dsp64" method… for the symbol there i wrote "dspadd64" where it should’ve been "dsp_add64"(with an underscore… and xcode doesn’t show warnings because it’s a symbol particular to the max api)
so now i’ve got the object fully working…
but just a warning: seems a bit volatile in terms of how easily the delay lines blow up when changing ‘hi’ and ‘lo’.
keep the volume low until you get a feel for how fast it can change. also keep the volume low when using the ‘lines’ message or when reinstantiating the object with new arguments.
(use the ‘print’ message to see how the internal states of the object change after messaging…)
some notes on what i did and other things:
so i tried changing the arguments for functions which matched messages all to ‘t_float’, this didn’t change anything, but then finally, while i left everything else at t_double, i changed the maximum buffer size(2nd argument to object) to register as a float argument instead of double("t_float maxbufsz;") and this improved the response of the ‘hi’/'lo’ messages to the object in general(whereas before i did this, the ‘hi’/'lo’ messages would cause a more abrupt/noisy change and i don’t think that’s how the original object was supposed to sound… nice to figure out this added detail at the last minute :).
ok then. attached here(for 64-bit max6 on osx only… someone else can take the .c code from here to windows, etc…). enjoy :)
this is greater than awesome thanks so much !! soooooo cool !!!
lin and exp seem to work as they should here !
^oh nice! Bonus win, haha, glad to hear they work too. You’re welcome. Thanks for giving me a good way to refresh my amateur external/c-coding chops. It’s a nice feeling to get it working :)
ha, another stupid mistake on my part (so sorry!)
in the .c file the fdn_setupdeline method should have this CLAMP instead:
sum += CLAMP( (int)(length[t-1] * scale), 0, mask);
(in my previous attachment, the max reach of clamp is set to ‘mask-sum’… ugh…)
you’ll want to change that(…or change the code to the original PD version there…) and recompile, i will avoid polluting the forum with more attachments :p
…but you’ll pollute us with attachments once things start working out, right?
@awetterbergpostcybercitydk aka Wetterberg
Not exactly: there are no serious crashy bugs anymore, and the object is behaving nicely(my previously posted error is a fix folks can perform themself, it doesn’t hurt to leave it as is in my last attachment, but the clamp change I mentioned will give the hi/lo settings to the object overall a bit more range…)…
But ya, as of my last attachment("FDN4MSPOSX.zip") things are all working out nicely…(check out the external(OSX) if ya haven’t already, there’s a helpfile in there to make it a lil easier. It’s all done :)
My effort here was just to make it easier for us to look at fdn~ in max(it’s more for purposes of vichug’s thread of inquiry, not so much a full on developer-style release to the public). I don’t want to make it too easy for people to take Tom Schouten’s brilliant fdn~ code without being pushed a lil to study it. So the last correction I mentioned keeps this MSP port imperfect until folks themselves try to correct and compile it their self.
I pray it does not upset you: think of it like this is my way of keeping it on the point of getting to know Schouten’s code rather than making it easy to just rip and use it.
It comes from my experience in a previous life… So please, grab a cup of tea and a bag of popcorn and I shall tell you a little story:
You see, i existed as a humble Japanese sword-smith, around the time of Tokugawa shogunate in a small temple known as ‘Sainenji’. I had perfected my master’s patient practice of folding steel into the finest blades by a process which kept the blades hot during the manufacturing process for weeks on end(this had the effect of reducing small fractures that can sometimes occur during the natural air cooling process when the steel has not been folded over and over at least 100 times yet).
Over the course of weeks, we would fold the steel over and over, each blade had to be folded at least 1000 times to ensure the greatest strength. During the course of my training as apprentice and later as an accomplished swordsmith, myself and my fellow craftsman as well as some of the monks at the temple would talk about life, and we would observe the slow processes which would unfold in all aspects of nature.
At one point we had crafted approximately 500 swords all kept within our unlocked workshop. One night while we were all at meditation, a local gang of ninjas crept in and stole the surplus of swords we had kept laying around. They later used them against us, slaying many of my own friends and family in front of me, all with swords I had painstakingly crafted with my own hands. And as the blood of my kin spattered across my stunned face, i saw it as if in slow motion: how long it can take to create something like life itself, and yet how quickly something can be used to destroy, especially if the pain of creation is not appreciated first hand by experience. These ninjas slaughtered pregnant women and small children without a second thought, they were trained merely to appreciate the efficacy with which they could kill. If they had experienced the beauty of time as it unfolded with each new fold of steel that went into the strength of their weaponry, if they had experienced the joy and friendships that surrounded the temple as we worked peacefully to perfect a craft which was more about the function of grace and courage in human movement as it finds a relationship with the math behind the gravity and momentum of a sword, rather than how easily it can be used to end a life, they would not have killed my people so quickly, so cold heartedly.
And so it is true to this day: I wear the imperfections of my creations like a bleeding heart on my shoulder, to help point the way to true experience, the kind gained by sacrifice, empathy, and arduous toil and painful struggle! So that no one can take for granted what it means to truly—-
Nah fuck it, I’m just bullshitting >;D
But seriously though, give the correction a shot and compile it yourself, and if you have probs, let me know again here and I’ll attach it myself with the latest small correction I mentioned :)
For the honor and glory of Tom Schouten, the master samurai swordsmith whose original brilliance is the sole provision for our enlightenments here!
You make me become more puzzled about fdn.
So you’re saying every samouraï should be a swordsmith as well ? >:D
On a more related note, i noticed that when i try something like
lin 32 10 1015, or anything with a long delay line, it doesn’t seem to work well. Well i’m not sure how it should work, but sound fades all of a sudden. Is it related to the clamp mistake you were talking about ? It’s a behaviour that i encountered in PD as well. If this is a mistake in the original PD external, it could be maybe worht it to send the updated version to the pd list or whatever ?
hm just gave a look at original pd c file and they don’t have this ClAMP function, neither the typo you made. But maybe adding a clamp would be beneficial for the pd version too ? maybe the clamping would be necessary for the bug i’m talking about too ?
- This reply was modified 2 weeks by vichug.
^ya, the clamp is added by me to avoid the error message about ‘instability’ after that which would happen more easily without the clamp in place(I don’t like to leave things easily unstable so I added clamp). You can take it out entirely and it would be more close to the original PD.
I don’t know about ‘lin’ and ‘exp’ messages. I didn’t change em at all. If it works the same in PD that’s probably how it works… These messages basically use 3 arguments to determine the number of delay lines, the minimum delay line length, and the maximum length(‘lin’ will create lengths in a linear fashion, ‘exp’ will create them exponentially related…). The two length arguments are in milliseconds.
If you take out the clamp I added it might improve, you might try that before sending to the PD list… But if you’re saying it works this way in PD, it could be that this is just how it works… (Only other prob I could imagine is maybe in your Lin message, creating 32 lines might be too much? Doesn’t seem like too much to me, but I haven’t really done enough A/B comparisons of the PD version with this one to say for sure…)
It does appear that the original fdn~ was not entirely finished:
There is also the ‘prime number’ calculation code which is near the top of the original PD .c code. This was commented out in the PD and never used so I simply left it out. I believe he was making this to be able to calculate better lengths(look at the fdn_new method in his original .c file, you’ll notice under the "/*preset*/" comment area, he initializes the first four delay lines with prime number lengths(29, 31, 37, 67)….)
If this were also added properly(I don’t understand it fully), it might also improve the same behavior you’re noticing.
Anyways, hope that helps make some more sense out of it, I’ll leave it for you to decide whether or not to connect with the Pd community about it(I don’t think my clamp is the only way to protect against the instability that was left in there, so you might experiment more first… But… It seems because PD is developed voluntarily/open-source there are sometimes these things left in the code that are either incomplete or cause instability(like this one where it could be trying to access memory outside of range if left without my clamp addition)).
"…should be a swordsmith as well?"
Yes, yes I am. In this day and age, if you had to make every bullet you shot at another person from scratch, you’d think twice more before wasting them so easily on any frivolous kills.
Every digital-artist should be a developer/programmer as well :)