• weightless

    @RandLaneFly Hi, I'll do my best to give you some replies:

    • yes, offset just adds a fixed frequency in hertz regardless of the ratio or the note played. It's useful if you want to use an operator as an LFO;
    • I used clip because the patch can receive values from external messages from the parent patch, the clip avoids unwanted values whatever you send to it. It's got to do with the GUI of the patch rather than with the synth itself;
    • here is pphasor~.pd, it's just a phasor with sample accurate phase reset to be able to sync the operators accurately. I adapted it from some old patch I found, but I can't remember what I've changed to be honest. It only replaces phasor~ so you'd still need cos~ afterwards;
    • about wrap~ and cos~: in a normal situation, where you do phase modulation with phasor and cos~, you don't need wrap~ because cos~ already wraps whatever phase it receives, even if it's outside the 0..1 range. In this case, instead of cos~, I used a table to store the waveform. Two reasons for this: 1) I wanted to be able to change the resolution of the sine and 2) I wanted to be able to use other waveforms other than a sine wave. Having said that, if your phase (after being scrambled around by all the modulators acting on it) has to address a table, you need it to be within the range of that table, otherwise you would be addressing points that are outside of the table (which would result in silence). This is why the phase is wrap~ped to the 0..1 range, and then multiplied by the length of the table in samples (4096 in this case);
    • I don't understand what you mean by:

    @RandLaneFly said:

    But I take it after that it's sending out the phases to the tables, what is the purpose of the line being formed and sent into the right inlet?

    The tabread4~ object is your output waveform for this specific operator you're looking at. Afterwards it's multiplied by the envelope (received on the right inlet of the *~ object), and then it's sent to the output (aka, what you hear) and to the phase tables.

    • If by "the math in the table patch" you mean the fexpr~ object, that is exactly the same as found in the thread I mentioned in the first post. It averages the last two samples in order to filter very high, harsh frequencies in the feedback path. It's possible that FM8 uses a different filter, which would result in a different sound, but I have no way of knowing that.

    I'm afraid the only resource I used for making this mess of a patch was that single thread about feedback, and then I expanded it for multiple operators. I very much like how it sounds, but it's incredibly expansive with polyphony, and on my computer 3 operators seem to be the limit, I wanted to try six but could never manage.

    posted in abstract~ read more
  • weightless

    @dadasane Here is the sampler I mentioned. I left it before finishing it but it kind of works like a hardware sampler would in principle. Open sampler16~-help.pd, load and play an audio file in the yellow abstraction on top (this would be the equivalent of your live input, you can connect an adc~ there as well). Then on the purple abstraction click the red R button, this records 1 second of the live input with the specified bitrate (you can change both length and bitrate in the number boxes). I suppose you can add the samplehold~ mechanism to reduce the sample rate as well as the bitrate. Once you see the updated waveform you can play it like a sampler. Might not be what you were after, but I like how it sounds.
    I hope I've included all abstraction to make it work, let me know if something is missing. You also need shadylib for the envelope.
    sampler16~.zip

    posted in technical issues read more
  • weightless

    @dadasane Why not load the sample in an array, play it through the sample rate/bit depth reduction and record the output into another array, and then have the sampler read that instead of the original sample? I made a sampler like that once and it sounds interesting, it might not be exactly what you're after but you could try it all the same. Another important thing is to use [tabread~] instead of [tabread4~] for more crunchiness.

    I'm not sure how you would do it faster than realtime but for short samples of a few seconds it shouldn't be a big issue, and you can save the aliased samples as well.

    posted in technical issues read more
  • weightless

    @DizeHD If the last object is a signal object, you need to use [outlet~] instead.

    posted in technical issues read more
  • weightless

    @boonier said:

    How would this work in the context of [savestate] - the text files would be loaded into each instance of the abstraction individually, or as one global preset load?

    They would be loaded only in the instance of the abstraction on which you save the presets. Think of it this way: the abstraction contains a [text] object, and you save its state (ie, the text it contains, whether it's a set of presets or a poem) which can be different for each instance of the abstraction. I can't see any advantages with this approach, but it may work for you.

    posted in abstract~ read more
  • weightless

    @boonier I haven't had time to think about it, but in fact my feeling is that it wouldn't have any advantages at all. With presets you have to chose when to save a new one, compared to saving the "state" in which the abstraction was when you saved and closed the patch. At that point, I think it's more efficient if the presets are stored in text files so that they can be shared by all instances of the abstraction.

    posted in abstract~ read more
  • weightless

    @djpersonalspace By the same token, this produces a triangle wave:
    Screenshot 2019-10-11 at 12.31.40.png
    How bizarre!

    posted in technical issues read more
  • weightless

    @rotho In Pd vanilla [text] could do it I think. [text search] is not very versatile but there are workarounds. For example, if you have one line of text for each file, and each field is a fixed tag (first field: filename, second field: key, third field: bpm etc), you can do searches with [text sequence] followed by list split, select etc.
    Hope that makes sense.

    posted in technical issues read more
  • weightless

    @zxcvbs Hi, yes I realise the patch is very counterintuitive, I'll do my best to try and explain what's going on. Let's forget about polyphony and consider one voice.
    The PMops abstraction is the single voice, inside it are the three operators (PMop, both badly named sorry) and the tables subpatch. The basic structure of each operator could be reduced to the simple:
    Screenshot 2019-09-01 at 10.48.46.png
    but the +~ object, instead of receiving the phase from a fixed modulator, it receives it from a table. Each operator has its own table, so operator 1 receives the phase from tabreceive~ $0-phase1 which is connected to +~.
    At the same time (to populate those tables), the output from cos~ of each operator is sent to all tables, how much of the signal goes to each is decided in the modulation matrix.
    The reason I decided for this arrangement is because this way each operator can send its phase to any operator, including itself (feedback). As explained in the first post, feedback has to be done with the operator working at block~ 1 in order to sound good, but if an operator receives the feedback every sample (block~ 1) but to that you add the phase of the other modulators every 64 samples (the default block size), the result sounds bad. This is the reason I used this mess of tables, to have an FM-8 style modulation matrix.
    If you want to implement hard-coded algorithms, the same thing can be done without tables, patching each algorithm in its own abstraction or subpatch and switch between them as @whale-av suggested in your thread. Plus I see none of your algorithms have feedback, so they don't even need to run at block~ 1, and therefore the approach with tables is really not necessary.
    Hope this clarifies things a bit.

    posted in abstract~ read more

Internal error.

Oops! Looks like something went wrong!