Adjustable window objects:
math/sine window.axo
math/sine disto window.axo
math/trapezoidal window.axo
math/sine window.axo
math/sine disto window.axo
math/trapezoidal window.axo
Hey, I'm trying to use the"euclid length" object, and I can't adjust the notes field. I've tried using the arrows, typing into it, and using a "i radio 8 h" object to set it, but no go. Any ideas, or is it broken?
Thanks for the great work! Your other euclid objects work great, but I would like something I can change live. (There's no way to change a number box externally is there?)
Karl
That's strange, i just tried using the object and it behaves fine.
As for the live editability unless you want to use presets there's no way to edit but using the mouse.
I can make another version of the object with inlets, if you need it
sptnk/looper/play.axo
sptnk/looper/pos.axo
sptnk/looper/record.axo
sptnk/looper/protect.axo
sptnk/looper/endpos bpm.axo
sptnk/looper/pos2phase.axo
sptnk/looper/pos2ppq.axo
Help file: 4x8bit looper.axh
These objects take advantage of arm functions to write 4 tracks (based on 8-bit packets) on a 32 bit table.
This allows, using all 8 MB of sdram memory, approx 43 seconds per track of playback (for a total of 172 seconds of playback)
The principle behind it:
A 32 bit variable looks something like this: 11001010 11101001 01000111 00001001 (That's -890681591 in binary).
You can think a 32 bit number as an array of 4 8-bit numbers, in this case word1 = 11001010 = ; word2 = 11101001 = -54; word3 = 01000111 = 100; word4 = 00001001 = 9.
It is then possible to use a 32bit table, which is simply a big collection of 32bit variables, to store 4 tracks.
The headroom for such 8-bit tracks is of course much smaller compared to 16bit or 32 bit tracks, but my aim was to obtain a cheap sounding looper (for a higher quality one i'd reccomend checking rbrt's one).
Quickstart: load a table/alloc 32b sdram, call it whatever you want. You can calculate the maximum recording length (per track, in seconds) dividing size by 48000.
Load the other objects in the series, patch them up and write in their boxes the name of the 32bit table.
looper/pos: Pos output provides a driving counter for looper/play and looper/record . The counter increments of 1 for each s-rate cycle, without skipping numbers. This is required to avoid horrible sounds to be recorded. The counter loops around start and end position.
The start and end position are outputted by startpos and endpos outlets.
Play inlet makes the counter go. If play goes to zero, the counter resets. You can pause the playback with hold inlet.
Soo..
Play = 1 Hold = 0 -> counter goes
Play = 1 Hold = 1 -> counter pauses
Play = 0 Hold = 0/1 -> counter stays stopped and goes back to 0
You can do further operations on the loop: multiply it by a fraction (which is numerator/ denominator) and offset it by a factor (mulstart)
looper/protect:
Generates an input for the looper/record object's protect inlet.
You can connect ctrl/toggle objects to i1, i2, i3 and i4 inlets. When an input is activated, the corresponding track is protected from editing.
For example if you protect tracks 1 and 3, the output is -16711936, which corresponds to binary 11111111 00000000 11111111 00000000 .
You can see that ones mean protected, and zeros mean unprotected (so tracks 2 and 4 will be edited, while 1 and 3 will be left untouched).
There are 4 displays to show which track is protected and which is not.
You can override this object and provide a specialized bitmask to distort the sound.
looper/record
Allows to record 4 tracks in the 32 bit table. The track inputs are w1, w2, w3, w4, they are saturated to normal range. Pos must be connected to looper/pos object, in order to avoid clicking.
Mode input must be connected to a ctrl/i radio 8 object or something like that (ctrl/i, sel/sel i ... etc )
When mode is set to 0 no input is recorded
Mode = 1 erases the table at current position
Mode = 2 overwrites the table
Mode = 3 overdubs the table (sums input and table value)
Mode = 4 overdubs the table and halves the value (so you can avoid clipping)
Protect allows to protect some bits of the table (and therefore not edit/erase them)
looper/play:
reads the table at pos position and outputs 4 tracks. You should connect pos to looper/pos object, however you can provide a phase input with an lfo object to play back at different speeds.
looper/length bpm:
Allows to generate a correct length number for looper/pos object.
You can insert a bpm value up to decimal precision, and specify the number of quarters for the loop.
There are two displays in the object: length outputs the approximate length (in seconds) of the loop. Warning warns you if the calculated endpos is bigger than the table length.
The object outputs also the number of quarters of the loop. (will be used to generate 24ppq and 4ppq sync signals)
looper/pos2phase:
Takes in input position, startpos and endpos of the loop and outputs a phasor wave (k-rate) that goes from 0 to 2^27. Can be used as a position reference, or to drive other objects.
looper/pos2ppq:
Kinda like the previous object (same inlets), but outputs a position in 24ppq or 4ppq, to sync other objects to the looper.
Performance considerations:
The help file for the objects (which is a more or less functional looper by itself) uses 7% dsp and the block length of the patch is 7620 (although i expect these numbers to rise with a more populated object pool).
At 88 bpm you can record 64 quarters (16 bars) of music. 4 tracks mono or 2 tracks stereo. The theoretical dynamic range, however is 49.92 dB
For comparison, rbrt's 4 slot loopstation uses 15% dsp load, and the block length of the patch is 16740 (however the patch is much more complex and crammed of logic objects).
Recording at 16bit allows for half of the length, though with 98.08 dB theoretical dynamic range (which really cuts down noise and gives life to transients).
Now that I look, I can't find the module I was thinking of. I thought you had a Euclidean with an int. input for number of notes, but I don't see it now. Sorry for the trouble.
But, on the other hand, I would love to have a Euclidean with inputs for total steps and notes, that can be changed during performance. That would be really super!
Great job with the new looper too - can hardly wait to try it out!
Karl
In the next days i'm gonna be updating the topology of the looper patch, in order to make it more solid (i'm also working on a quantizer object, which needs these edits).
To do this i had to change some objects: in particular the looper/endpos bpm, which will become looper/length bpm and will lose the startpos and endpos outlets (substituted by a length outlet).
The looper/pos object will be changed too: it will no longer have startpos and endpos as inputs, but as outputs, and will take length as input.
This will break patches.
If you have already used such objects and don't want to update patches, you can convert all looper objects to patch/object. (click on the arrow -> embed as patch/object)
I'm sorry for this inconvenience, but i hope to extend the functionalities of the looper
(also this update will benefit the looper/pos2phase and looper/pos2ppq objects)
Man I just went through this with another user. I think it is not a good idea to make that drastic changes to objects.
Anyway, it is of course your choice, but I really dont think it is good practice, unless something is totally off in the object, something that might be misleading or not working.
My issue was that inputs had been renamed and also a parameter had been renamed. Which resultet in all input connections was lost and the parameter that had been changed lost its values.
Why not just make a new version with those features?
Not a good practice, i know, but it's an important change that will benefit patches in terms of functionalities(with the new objects you will be able to make odd time loops, for example), stability and, to some extent, cpu load.
Also, these are all objects that are meant to work together, so it won't be hard to patch em up back again, with the aid of the help patch.
Also i published something like 6-7 objects in two days. While i had in mind what the end goal was i still did not know how to implement it correctly, and in the making of the more advanced objects i recognized the need for a better and more solid implementation.
Since i had some problems with my axocomputer, i won't be publishing those changes for a while (more time for users to read this and take precautions).
I'll be here for troubleshooting after the update, so don't worry too much!
Coool. Sounds like you put some thought into it
Anyway, because I experienced this a few times, I started copying the objects that I use the most to my own library and use them from there. This eliminate the problem.
Anyway, thank you for the warning
yeah, without going too off topic....
changing interfaces and behaviour is a 'fact of life' with any software development (=custom objects/subpatches).
the developer needs to move forward, and even if they create a new object (v2) so dont break existing ones, they will probably not want to maintain the old one ... so the user in the end, has to move to v2.
Johannes and I have talked about this quite a bit, in the more 'generic' case , as its also a potential issue with factory objects, some of this was discussed here : https://sebiik.github.io/community.axoloti.com.backup/t/object-lifecycle/1629/3
really its more of a 'general problem' we need to solve.... you can't prevent change, but we can manage it better.
personally, Im thinking
a) using the fact that git IS a version control system, i.e. even if a current version of an object is change, git still has the old version.
b) simplifying 'embedding' e.g. having a 'freeze patch' concept, where all objects/subpatches are 'frozen/embedded' into a patch. (it can later be 'unfrozen') ... a bit like how in ableton you can 'collect resources' for a project.
anyway, we still need to work it out... but I think as the user base and community library grows it becomes a more 'pressing' problem.
yes!
So if I change the code inside my/object , will that also break patches? can i edit the overview without breaking patches?
I do agree to a certain extend, progess will happen, But I also believe that the saying "why fix it if it aint broke" is really good one. I dont see any reason to change something that is not broke. If it is working, why do you want to change it? Why not only make a new one?
I do understand changing things from a developers perspective, but not from a user perspective. And I guess there are more users that developers, so please take user perspective into consideration too. I really dunt understand the arguments about maintaining old ones. I dont think this have been an issue in any cases in here yet with maintaining them. What do you mean by that. Updating SHA or similar? Can you give an example?
Like I said, if there is somethin to fix, fix it, if not leave them alone and add new objects instead. I really dont see why you would like to mess with stuff that is functionally working. The only thing that wil happen it that you will create a load of problems for the users...... Which could be solved by just making a new one instead of overwritting the old one. Problem solved! I strongly believe that stuff uploaded to the the com.lib, should be thought throug BEFORE uploading it to com.lib, so you dont make problems for the user later on. Differnet objects can be good for different cases.
But I guess I will just make my own copy of the com.lib on local disc. I do suspect this to become a big problem for users in the near future. 1 object have been changed, which broke A LOT of my patches. I think it is a serious issue. ANd this is basicly telling me: dunt trust the com.lib. Dont use objects form there. Copy them to own disc! I think it would be sad if the com.lib. has that tag on it.
Exactly! Be careful with what you do!
perhaps I explained this badly, developers do not change interfaces without good reasons, as they are well aware of the impact it has on users, so avoid as much as possible - so it not should not be a frequent occurrence.
back to axoloti, we of course manage this in the factory library (and firmware etc), but with a community library its up to individuals, and how they view the sharing of objects etc.
my comments was more, with a large code base its inevitable it will happen occasionally, so we need a way to deal with it, not really more or less than that.
as for why it change is inevitable, how its avoided, cost on maintenance, its a big topic, best discussed over beers
No, this is all fine
Mainly we are taking about deleting or renaming inlets/outlet ( or entire objects)
Of course there are also 'soft breaks' where you change an objects behavior, so the patch still compiles but doesn't behave/sound the same as before.
This is still from a user perspective 'bad' , and in some ways worst .. as it's not always obvious why their patch is not acting the same as before.
Again, I think this was discussed on the above link.
( I suggest any more discussion on this should move to that topic , it's a bit OT here)
Cool. That is great to hear. But in few days I noticed one object change, which has broke a lot of my patches and another user announced a future chance for an object. This is 2 cases in a couple of days, so I think we need to adress it soon. But yes true, there is a difference between factory library and community library. But still I think it is nice to have not rules, but guidelines of what is good practise.
Can we please do it en Belgium then, Johannes homebase? I love Belgium beers.........
@jaffasplaffa
You're right when you say that if something ain't broken it should not be changed. Also some time ago i stated that contributions should be regulated some way, in order to avoid object flooding and this kind of issues (i guess this makes me an hypocrite then)
What if we write some contributor guidelines? I mean not only a list of written rules, but some kind of Magna Carta Axolotum to be signed from contributors.
As for the technical aspects of object updating, i think i'll leave that to devs. To me a decent (but not excellent) solution could be some kind of "macro" function that embeds all community objects. No extra bloat on github, just on end user's hard disk
Haha, I dont consider you anything like that
Actually I last night I had similar thoughts about some objects I have made. I made new versions of it, and named them something else, that matches it its function better. And now I wonder if I should remove the old and upload the new ones. But I am not sure what to do right now, cause I dont want to break other peoples patches. So I totally understand the dillemma. Also adding new versions could potentially flood the comlib & Github server with loads of similar objects, with different names. So there are different things to consider.
Anyway, I think we should do some guidelines or atleast just have a discussion about it. I will open a new thread right away for this topic, so we dont flood you contribution page with this.
Synced!
The help patch for the looper object has been slightly modified too, hoping to make it clearer.
If anyone is getting errors, PM me and i'll help.