• ddw_music

    @gentleclockdivider This is becoming perhaps a bit heated, unnecessarily?

    I guess part of the confusion is that there are two purposes being discussed. One is display ("show all incoming midi notes that make up the chord"). The other is performing the notes as audio.

    whale-av is correct that if you want to play the notes audibly, it's easier not to pack the note numbers into a single list.

    • Note performance, approach 1: Notes come in --> play them polyphonically.
    • Note performance, approach 2: Notes come in --> pack the note numbers into a list --> unpack the list --> play the notes polyphonically.

    whale-av was trying to caution you against the second approach for audio performance. Those comments were not addressing the problem of display.

    For display, I gave you a couple of examples (btw those examples were mine, not whale-av's, proper credit), so that problem is solved, I think.

    max msp has a dedicated object for exactly that , says enough .

    As shown, it's possible to do using core Pd objects.

    If you replace the [notein] at the top with a pair of inlets (note number and velocity), and put an outlet at the end, you can save it as an abstraction and then you have a dedicated object. You could even add a list box in a graph-on-parent zone and get built-in display.

    hjh

    posted in technical issues read more
  • ddw_music

    @lacuna said:

    Indeed, stairs require lowered anti-aliasing filtering at the output.

    There used to be CD players boasting of "8x (or 16x) oversampling" DACs.

    They would do exactly what you're seeing here: 1. Zero-order hold the 44.1 kHz samples up to 352.8 kHz or 705.6 kHz. 2. Then, the final filter could be a gentle rolloff at a much lower order, rather than a very tight, high-order 20k - 22.5k filter.

    But does always any DAC need filtering, even for sines below Nyquist??

    If there's a zero-order hold, then yes, you do need to filter away the sharp corners. The added samples extend the frequency range above the original Nyquist -- but the zero-order hold does not accurately reflect the original signal. The sharp corners introduce high frequency energy that couldn't possibly exist at the original sample rate. It is necessary to remove those.

    Reconstructing the signal from the samples could be done in a way other than upsampling and filtering. Sinc interpolation convolves the samples against a band limited impulse (band limited impulse = (sin x) / x except y = 1 when x = 0), and this can reconstruct the original signal at any time resolution, without filtering. But it's expensive, compared to upsample-and-filter.

    hjh

    posted in technical issues read more
  • ddw_music

    And the overlapping-notes approach. This one updates the list for every note on/off.

    pd-updating-note-list.png

    24-0302-updating-note-list.pd

    [pd delete] is basically:

    newlist = List.new;
    i = 0;
    while(i < list.size) {
        if(list[i] != notenum) {
            newlist.add(list[i]);
        };
        i = i + 1;
    };
    return newlist;
    

    (Or in SuperCollider, list = list.select(_ != notenum) :grin: )

    hjh

    posted in technical issues read more
  • ddw_music

    Here's a pure-vanilla simple threshold (like quickthresh but simpler).

    pd-quickthresh.png

    24-0302-quickthresh.pd

    The threshold is currently hard-coded in the [moses] and [delay] objects. You could add a control to change it.

    hjh

    posted in technical issues read more
  • ddw_music

    In addition to time thresholding, you could also look for overlapping notes -- if you get 5 note-ons without any matching note-offs, then all 5 notes are held together = chord.

    So which would you prefer?

    hjh

    posted in technical issues read more
  • ddw_music

    @whale-av said:

    @ddw_music Even in extended I never had it working as [pop] never existed.

    :laughing: A case could be made for removing cruft from public releases.

    Thanks for the tips -- in this case I'll just rearrange it around radio buttons instead. Then I could just have the end user run it in PlugData and get ELSE for free.

    hjh

    posted in technical issues read more
  • ddw_music

    https://puredata.info/docs/ListOfPdExternals/ shows only one match for "menu": iemlib/popup.

    However the object can't be instantiated:

    1. Create [declare -lib iemlib -path iemlib] -- this appears to be fine.
    iemlib (1.22-1) library loaded!   (c) Thomas Musil Jul  7 2023 : 18:09:03
       musil@iem.at iem KUG Graz Austria
    
    1. Create [popup]
     pop 6 17 0 0 play_cmd play_cmd play_cmd 82 9 192 17 -225280 -1109 -260818 0 5 open rewind start stop quit
    ... couldn't create
     pop 7 14 0 0 empty empty empty 50 7 0 10 -262144 -1 -1 0 1 pop
    ... couldn't create
    help-popup.txt: can't open
    help-popup.txt: read failed
    

    Before logging an issue on their repository, I wondered if anyone knows some backstory? Is this library maintained? There seems to be a reference to a "pop" object, which doesn't exist...?

    hjh

    posted in technical issues read more
  • ddw_music

    Good tips from both @jameslo and @manuels, thanks :+1:

    EDIT: FWIW, I think I'll go with else/player~. My initial attempt with it overcomplicated things because I was expecting to have to manage sample rates myself, but... it handles all of that automatically. Thanks for the suggestion!

    hjh

    posted in technical issues read more
  • ddw_music

    I was hoping to build a variable-speed sound file streamer abstraction -- like readsf~ but with a rate inlet (particularly for correcting a mismatch between the file's sample rate and the DSP sample rate).

    I was hoping to do it like this:

    • Allocate an array with x frames.
    • Upon "cue," load x/2 frames at the beginning of the array.
    • When playback takes off from frame 0, load the next x/2 frames into the second half of the array.
    • When playback crosses the halfway point, load the 3rd x/2 chunk into the beginning of the array.
    • At this point, then, a phasor can just read forward through the array, and loop back to the beginning. At every half-transition, load data into the half of the array that isn't being played.

    I quickly run into gaps in soundfiler's interface.

    • "-maxsize" resizes the target array -- there appears to be no way to load partially into an array.
    • There also doesn't seem to be any way to read starting at index 'a' in an array. "-skip" will skip frames from the file, but there isn't a flag for where to start putting data into the array. (Compare SC, with parameters fileStartFrame, numFrames and bufStartFrame for the buffer read message.)

    This was to distribute a multichannel fixed-media work. I was thinking Pd because the download size is small. But I think I'm going to have to take this back to SuperCollider because there's a VDiskIn built-in -- can just use it, not spend time hacking it.

    In any case... are there any workarounds for those two limitations? (I guess I would need two arrays -- I was hoping to avoid that because switching the table name sample-synchronously also sounds a little bit tricky.)

    hjh

    posted in technical issues read more
  • ddw_music

    @gentleclockdivider said:

    It's only skipped for cosinesum (lower table ) and not the sinesum (upper table) , the screesnhot shows the first partal for sinesum and a DC constant for cosinesum

    This means that the cosinesum preserves the zero-frequency component, while sinesum skips the zero-frequency component.

    sin(0x) == 0, so there is no need to keep it.

    cos(0x) == 1, so if it's skipped, then it becomes impossible to synthesize a wavetable that has a DC offset.

    That's probably the reason for the different behavior. It's a bit surprising but not unreasonable.

    hjh

    posted in technical issues read more
  • ddw_music

    Wouldn't it be

    expr~ max( min($v1, $v2), $v3 )

    If v1 is the signal, v2 is the upper limit and v3 is the lower limit. (If v2 is the lower limit, then exchange mac and min in the formula.)

    hjh

    posted in technical issues read more
  • ddw_music

    @jameslo said:

    [text] loads the commas and treats the new lines as whitespace

    IIRC there is a flag that specifies whether newlines should advance to the next line, or if a semicolon is required to break lines. The default requires semicolons.

    I forget whether this is a property of the [text define] object or of the "read" message, but I'm sure it's documented in [text] help.

    hjh

    posted in technical issues read more
  • ddw_music

    @gentleclockdivider said:

    SUre it sends a bang when the file has audio on it till the end .
    When there is only audio at the beginnng ( by stopping the recording before the buffer is full ) it will not send a bang .

    It should send the bang when it reaches the end of the entire array (including silence).

    You seem to be expecting that the array will automagically remember how much time you recorded into it. It doesn't. You'll have to create your own logic in the patch to keep track of the recording time and use that for playback.

    hjh

    posted in technical issues read more
  • ddw_music

    Per https://opensoundcontrol.stanford.edu/spec-1_0.html , 'h' is the type tag for 64 bit big-endian two’s complement integer. Probably [oscparse] simply doesn't implement it.

    ... in which case, try mrpeach. (Though, come to think of it, what would Pd do with a 64-bit integer? It can't be squished down into a 32-bit float. Even a 64-bit float would be able to keep only 53 bits' worth of precision, or 54 if you count the sign bit. So it would be helpful to know what data the app is sending in this format.)

    hjh

    posted in technical issues read more
  • ddw_music

    Spaces must be escaped.

    spectral vocoder.wav = not ok

    spectral\ vocoder.wav = should be ok

    hjh

    posted in technical issues read more
  • ddw_music

    FWIW -- Pd's native interface for sound files is difficult. While that's consistent with the "minimal core" philosophy, I find it annoying enough to work with that I would sometimes be tempted to avoid using sound files just because of rebuilding basic functionality.

    For example, a couple of factors that haven't been mentioned in this thread yet:

    • What if the sound file is at a different sample rate from the audio system?
    • Also, audio engineering 101, every audio segment hitting the speakers should have an envelope, even if it's just a trapezoidal envelope with a very short attack and release. Otherwise you will get clicks at every splice point. This means, then, using two players and toggling between them (because the ideal splice is a short crossfade, not a jump cut).

    A while back, I made a set of abstractions to simplify these problems. Using those, this is how I would do it.

    pd-segmenter.png

    24-0210-segmenter.pd

    Here, the logic is:

    • Choose a random duration.
    • Choose a random direction, +1 or -1.
    • Random starting position is chosen based on dur * direction.
      • Random range is 0 to (soundfile dur - abs(dur)).
      • Then, if dur is negative, we have to shift the entire random range up, by subtracting the negative number.
    • Then the endpoint in the sound file is start + (dur * direction). Backwards playback is start > end.
    • Last, toggle 0 or 1 to choose one of two sound file players.

    monofile and sf-play~ are abstractions of mine. sf-play~ uses cyclone. Note that cyclone's play~ claims to take time indices in ms, but it doesn't compensate for sample rate. My abstraction does this automatically -- ms go in, ms come out.

    YMMV but I find working with sound files is much easier when the programming interface is more usable.

    hjh

    posted in technical issues read more
  • ddw_music

    @raynovich said:

    Thank you! 1 sample. seems pretty amazing. Thanks though

    A feed-forward unit generator should have zero samples latency. It gets samples in, processes them, and outputs them with no delay (unless delay is its job).

    FWIW though, I was just trying to do a quick demo, and else.gain~'s messaging interface is really quite inscrutable. It's fine if I manually move the slider, but what if you want to initialize by loadbang? I just cannot get that to work.

    You could just use a [*~] instead.

    hjh

    PS the demo:

    pd-gain~.png

    posted in technical issues read more
  • ddw_music

    @manuels said:

    @ddw_music Thanks for the link! Should probably read the SC forum more often ... This is indeed an exact explanation for what's going on in my version of the filter:...

    I thought it might :laughing: I suspect that a number of ELSE signal objects are cribbed from SC, or cribbed from the same source of DSP formulas that SC cribs from (e.g, [resonant~] vs SC's Ringz -- note that both reflect a standard DSP algorithm, which also appears in Faust as pm.modeFilter if my memory is correct). Wouldn't surprise me at all if lop2~'s behavior is identical to RLPF's.

    I ended up just switching my synths to use BLowPass because the result was more musically useful to me, even if mathematically "warped."

    hjh

    posted in technical issues read more
  • ddw_music

    Here's a thread from the SuperCollider forum that is related to, or perhaps precisely answers, your question. My understanding of it is fairly superficial though.

    https://scsynth.org/t/rlpf-vs-blowpass-blowpass-seems-better/2627

    hjh

    posted in technical issues read more
Internal error.

Oops! Looks like something went wrong!