• myQwil

    @shreeswifty For potpourri, try this out: lyonpotpourri.zip

    posted in extra~ read more
  • myQwil

    Just thought I'd point out that the difference between mod and % is how they handle negative values.

    posted in technical issues read more
  • myQwil

    This library overrides Pd's f, i, and binop objects to give them a couple of extra features:

    • A creation arg that ends with an exclamation point tells the object to loadbang the result. The loadbang occurs either upon instantiation or when a patch initially opens, depending on which version of Pd you're running.
      Some examples:
      • [ f 5! ] outputs 5 as a loadbang
      • [ - 8! ] sets the 2nd inlet to 8 and outputs -8 as a loadbang, since the calculation would be 0 minus 8.
      • [ + 1 2 ] sets the 1st and 2nd inlets respectively
        • sending a bang to the 1st inlet would output 3
      • [ / 1 4! ] outputs 0.25 as a loadbang
    • Binop objects also have the following additional methods:
      • [ f2 $1 ( - sets the 2nd inlet.
      • [ . $1 ( - sets the 2nd inlet and outputs the result of the calculation.

    Note: Older versions of Pd don't support the overriding of built-in objects, so for the sake of backward compatibility, the objects have an additional creator method with the general rule being to put a grave accent ( ` ) in front of the object's name (ex: [`f ], [`+ ], [`- ], etc. )

    blunt.zip

    posted in extra~ read more
  • myQwil

    Did you get this working? I have a very quick and dirty solution for you. pd-lib-builder takes care of just about everything when you run make but you'll still need to link Helmholtz and helmholtz~ together manually. It'll probably look something like this:

    g++ -static-libgcc -static-libstdc++ -shared -Wl,--enable-auto-import "C:\Program Files/Pd/bin/pd.dll"    -o helmholtz~.dll helmholtz~.o Helmholtz.o
    

    That's pretty much all pd-lib-builder, with the one manual part being the Helmholtz.o at the end of the statement.

    Anyways, here's a zip of that project folder, where you'll also find a 64-bit build. I haven't really played around with it much but it seems to be working just fine.

    helmholtz~.zip

    Just as an addendum, you can probably get pd-lib-builder to link the files on its own by removing helmholtz~.cpp from class.sources and adding:

    make-lib-executable = yes
    lib.setup.sources = helmholtz~.cpp
    

    posted in extra~ read more
  • myQwil

    They act similar to delay and line objects, but when they're in the middle of a delay or a ramp, the message "pause" will act as a toggle between pausing and resuming.

    The delay object, delp, has two additional outlets. The remaining time passes through the 2nd outlet whenever a pause occurs, and the toggle's current state passes through the 3rd outlet.

    These objects all use timers to calculate their remaining time and ramp state, which means that linp will be precise regardless of what its time grain is set to. On the other hand, it also means that linp~ will sound inaccurate if there's any discrepancy between your audio server's sample rate and pd's sample rate because discrepancies of that kind, in general, result in the audio's timing being either too fast or too slow in relation to Pd's system timing.

    Included is an example where these objects help with playback control, with linp displaying the remaining time, linp~ handling the fade-out effect, and delp triggering the fade-out and end of playback.

    delp-linp.zip

    posted in abstract~ read more
  • myQwil

    @alfonso.santimone Sorry it took so long. I finally got around to making win64 builds of my externals. They're all up on my Github page but here's gme(s)~ for the sake of convenience:

    gme.zip

    posted in extra~ read more
  • myQwil

    @deframmentazione-geometrica It looks like your select box is trying to prevent repeat values from getting through, so when random outputs the same value as it did previously, select will keep telling random to produce another value until it's different, then it'll assign that to the single number box on the right. The two number boxes at the bottom will retain the duplicate value and continue to reassign the value to each other until it's caught by the stack overflow error.

    Then again, how everything plays out will depend on whether you create the select box before or after creating the looped number boxes at the bottom, because that'll determine what gets triggered first. If you create the select box last, then the number boxes at the bottom will change and it may never even get to the number box on the right.

    posted in technical issues read more
  • myQwil

    MSYS2 is the new standard last time I checked. You can follow along with the purr data build guide to guarantee the right dependencies get installed. You only need to go as far as step 4, and you can also skip the inno setup if you're just building externals.

    https://git.purrdata.net/jwilkes/purr-data#windows-32-bit-using-msys2

    I went ahead and built plaits for 32-bit pure data. Hopefully that works for you.

    plts~.zip

    When building it, I needed to change one thing in the Makefile. See that line where it says:

    cflags = -DTEST -Wno-unused-local-typedefs -I./
    

    That doesn't work. -I./ needs to be changed to the absolute path that your plaits project happens to be in. For example, mine looked like this:

    cflags = -DTEST -Wno-unused-local-typedefs -I/c/Users/myQwil/Desktop/pd-plaits-master
    

    posted in extra~ read more
  • myQwil

    @seb-harmonik.ar No, I'm not the creator of the gme library. There's a lot about its behaviour that I don't fully comprehend at this point. One of the first issues I came across was the instant fade. Another was that it would come to a full stop after maybe 2 repetitions or so. I've tried preventing these issues by changing the original code in as minimal a way as possible but there are probably further changes that could make it run more smoothly in pd. Again, the only reason I added that ifndef clause is because it's what worked for me personally. I wanted it to behave the same way across multiple platforms in such a way that it repeated the song forever, leaving the stopping of the track up to the patch itself.

    In gme.zip you should see the folder gme-diff. It contains whatever changes I made to the original code. If you're building your own version of gme, you'll need to incorporate those changes to see where I'm coming from. Either way, it's worth knowing that it behaves differently on your end. What OS are you using, by the way?

    posted in extra~ read more
  • myQwil

    @seb-harmonik.ar That was there because that same issue would happen to me, but under different circumstances depending on if I was using linux or windows. I believe I was using ubuntu studio 64-bit.

    posted in extra~ read more
  • myQwil

    Hi @alfonso-santimone, at this point, none of my externals are built for win64, but I'll look into making those builds

    posted in extra~ read more
  • myQwil

    I've noticed that pd-vanilla and purr-data currently handle pointers differently, making the is.pd object work in pd-vanilla, but not purr-data. I've created another pd-native variation of the external [is] that works in both purr-data and pd-vanilla.

    While the route object in pd-vanilla can detect pointers as a type of symbol, in purr-data, a pointer is detected as a list by the symbol object, but not detected as a list by the route object. So if an atom passing through [route list] gets sent to the rejection outlet, then later reveals to have a string value of "list" when sent to a [symbol] object, we can assume that that atom is a pointer.

    is.pd

    posted in extra~ read more
  • myQwil

    You can also debug with VSCode, which is something I recently just tried out for the first time. You'd need to install the VSCode extension C/C++, then you'd build pd-vanilla based on the instructions given on pd's website and the INSTALL.txt file, and using the --enable-debug option.

    Then open the pure-data folder in VSCode, either by navigating to that folder in a terminal and typing code . or by right-clicking the folder and selecting "Open With->VSCode"

    Then in VSCode, you switch to the debug pane and from a drop-down at the top of the pane, click "Add Configuration" and after selecting a config preset, a file called launch.json will pop up. You'll need to specify where the binary is. In my case, the location was:
    "program": "/home/myqwil/Documents/pure-data/bin/pd",

    Then lastly, and maybe there's a better way of doing this last part but the quick and easy way is just to inject your external into some part of pd's code, change the setup function so that it's static, and make sure the setup function gets called at some point, usually the setup calls are kept inside of one function at the very end of a .c file. Then it's just a matter of adding your breakpoints and re-building pd when changes are made.

    posted in technical issues read more
  • myQwil

    Works very much the same as trigger except that when you use 'a' for creation arguments, lists that consist of only 1 atom will output as the atom itself and not as a list. This also includes pointers. You'll notice that with trigger, a pointer will output as a list, which makes it difficult to type-check.

    The [unpak] object had a similar problem where it would output lists instead of raw atom values, and that has also been changed with unpak's latest update.

    EDIT: I've made it so that floats default to anything outlets and no creation args defaults to 2 anything outlets.

    x.zip

    posted in extra~ read more
  • myQwil

    Similar to [pack ] and [unpack ] but instead of the default atom type being a float, the default type is anything.

    Also comes with a new creation arg 'a' for anything. Numbers and unrecognized types will also default to anything.

    For strict type checking, use f(loat), s(ymbol), and p(ointer).
    The pak object will also store unrecognized types as symbols and interpret 'b' as a 'bang' symbol.

    You can send lists to any of the additional pak inlets and it will store the list values with the inlet as the starting point. For example, sending the message [foo bar 3 baz( to the 2nd inlet of [pak 1 2 3 4] would result in the list: 1 foo bar 3

    The example includes another object called [x ], which is a kind of trigger object that dehusks lists that consist of only 1 element when you use 'a' or nothing for creation args. For pd-vanilla users, the example also requires zexy's [demux].

    You can also use "." to skip inlets and assign only specific ones.
    For example, sending the message [. . 123( would assign 123 to the 3rd inlet and leave the first two values the same as they were. You can send these messages to any inlet.
    The skip arg feature only applies to list and anything type messages, so if you really want to, you can still assign a single period to an inlet by sending it as a symbol.

    There are two more objects [@pak] / [@unpak] - reverse pak/unpak, which output the lists in reverse order.

    Strict-type error messages are muted by default and to unmute them, you need to send [mute 0( to the 1st inlet. The number sent to mute acts as a bit mask for the inlets, so when a bit is turned on, the associated inlet will output error messages.

    pak-unpak.zip

    posted in extra~ read more
  • myQwil

    @ingox I recently made a slight change to how the c external works and went ahead and made the same change to your pd external. I just needed to include the rejection outlet of the left route object. is.pd

    posted in extra~ read more
  • myQwil

    Neat! I've used route with custom messages, but it didn't occur to me that it could also be used as a type checker.

    posted in extra~ read more
  • myQwil

    Returns a boolean 1 or 0 if the value sent to the 1st inlet matches the type specified in the creation arg or 2nd inlet.

    You can set the type to be matched against either as a creation argument or with the message [type $1(, or by sending to the 2nd inlet either the type name or an example of the atom whose type you want matched against.

    EDIT: the "type" method needed a bug fix. The help file has also been slightly altered:

    EDIT2: Now the type can be virtually anything, rather than one of 5 possible types. This allows us to check for specific messages. For example, sending the message [foo 1 2 3( to the object [is foo] will return true.

    EDIT3: Defaults to float if no creation argument given. Also added a pointer example to the help file.

    EDIT4: A memory-freeing method was necessary to clear the proxy inlet.

    is.zip

    posted in extra~ read more
  • myQwil

    Allows you to play various game music formats, including:

    AY - ZX Spectrum/Amstrad CPC
    GBS - Nintendo Game Boy
    GYM - Sega Genesis/Mega Drive
    HES - NEC TurboGrafx-16/PC Engine
    KSS - MSX Home Computer/other Z80 systems (doesn't support FM sound)
    NSF/NSFE - Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)
    SAP - Atari systems using POKEY sound chip
    SPC - Super Nintendo/Super Famicom
    VGM/VGZ - Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro

    The externals use the game-music-emu library, which can be found here: https://bitbucket.org/mpyne/game-music-emu/wiki/Home

    [gme~] has 2 outlets for left and right audio channels, while [gmes~] is a multi-channel variant that has 16 outlets for 8 voices, times 2 for stereo.
    [gmes~] only works for certain emulator types that have implemented a special class called Classic_Emu. These types include AY, GBS, HES, KSS, NSF, SAP, and sometimes VGM. You can try loading other formats into [gmes~] but most likely all you'll get is a very sped-up version of the song and the voices will not be separated into their individual channels. Under Linux, [gmes~] doesn't appear to work even for those file types.
    Luckily, there's a workaround which involves creating multiple instances of [gme~] and dedicating each one to a specific voice/channel. I've included an example of how that works in the zip file.

    Methods

    • [ info ( - Post game and song info, and track number in the case of multi-track formats
      • this currently does not include .rsn files, though I plan to make that possible in the future. Since .rsn is essentially a .rar file, you'll need to first extract the .spc's and open them individually.
    • [ path ( - Post the file's full path
    • [ read $1 ( - Reads the path of a file
      • To get gme~ to play music, start by reading in a file, then send either a bang or a number indicating a specific track.
    • [ goto $1 ( - Seeks to a time in the track in milliseconds
      • Still very buggy. It works well for some formats and not so well for others. My guess is it has something to do with emulators that implement Classic_Emu.
    • [ tempo $1 ( - Sets the tempo
      • 0.5 is half speed, while 2 is double. It caps at 4, though I might eventually remove or increase the cap if it's safe to do so.
    • [ track $1 ( - Sets the track without playing it
      • sending a float to gme~ will cause that track number to start playing if a file has been loaded.
    • [ mute $1 ... ( - Mutes the channels specified.
      • can be either one value or a list of values.
    • [ solo $1 ... ( - Mutes all channels except the ones specified.
      • it toggles between solo and unmute-all if it's the same channel(s) being solo'd.
    • [ mask ($1) ( - Sets the muting mask directly, or posts its current state if no argument is given.
      • muting actually works by reading an integer and interpreting each bit as an on/off switch for a channel.
      • -1 mutes all channels, 0 unmutes all channels, 5 would mute the 1st and 3nd channels since 5 in binary is 0101.
    • [ stop ( - Stops playback.
      • start playback again by sending a bang or "play" message, or a float value
    • [ play | bang ( - Starts playback or pauses/unpauses when playback has already started, or restarts playback if it has been stopped.
      • "play" is just an alias for bang in the event that it needs to be interpreted as its own unique message.

    Creation args

    Both externals optionally take a list of numbers, indicating the channels that should be played, while the rest get muted. If there are no creation arguments, all channels will play normally.

    Note: included in the zip are libgme.* files. These files, depending on which OS you're running, might need to accompany the externals. In the case of Windows, libgme.dll almost definitely needs to accompany gme(s)~.dll
    Also, gme can read m3u's, but not directly. When you read a file like .nsf, gme will look for a file that has the exact same name but with the extension m3u, then use that file to determine track names and in which order the tracks are to be played.

    gme.zip

    posted in extra~ read more
  • myQwil

    This is a spiritual successor to amPd. It's much more stable and has many more features than amPd:

    • reads/writes metadata to/from patches. This is done by storing the info in the form of comments, in a canvas called [pd meta] or [pd info]. If no such canvas exists, foobar will add it in the top left-hand corner of your patch.

    • comes with a Win32 Dialog UI element, containing sliders, toggles, buttons, and edit-text/button combos to send messages to your patch.

      • foobar looks in your patch for a canvas called [pd mix] and uses the parameters of whatever sliders, bang objects, or toggles it finds there to give your UI controls similar functionality.

    How playback works

    • libpd sends a 1 to vol, then a bang to play.
      • Generally this is where, in your patch, you have an [r play] hooked up to your metro, and an [r vol] connected to a [*~ ] before your output reaches [dac~].
    • the length of the song is arbitrarily set by the user.
      • This affects the trackbar's cursor visibility and ability to set a position.
      • If the length is 0, there will be no trackbar cursor. Otherwise, the cursor, when moved, will send its position in seconds to pos. From there, it's up to your patch to take that information from [r pos] and work it into song events.
    • The patch will not actually stop and move on to the next track until libpd receives a bang from [s stop].

    How the mixer works

    • all mixer controls go inside of [pd mix]
    • horizontal and vertical sliders are turned into slider controls in the UI element
      • labels assigned to sliders in the patch become labels for the UI element's slider controls. The same applies for send symbols.
      • min and max values of sliders on the UI element work in integers only, so if you want a gradual shift from, say, 0 to 1, write "gradient" in the slider's receive symbol, and the slider's range will be broken down into roughly 200+ individual steps.
      • there are currently 7 sliders in the UI element
    • bang objects with no label become simple buttons in the UI
      • their send symbols will be reflected in the button's name and they will send a bang when clicked.
      • there are currently 3 buttons
    • bang objects with a label assigned become message buttons
      • these have an edit text field associated with them, where you can type out any message you want and send it to the destination.
      • the bang's label is placed inside of the edit text field as a suggested message to send.
        • pure data strips commas out of labels, so I'm using apostrophes to denote where commas should go. ex: do this' then this
      • there are currently 2 message buttons, with the 'any' button being a potential 3rd.
    • a bang object with a label written in the format dest : msg will be assigned to the 'any' button.
      • the 'any' button has an editable destination field, giving you access to basically any receive symbol in your patch.
      • also substitutes as a third normal message button, when the other two are already in use
    • toggles become checkboxes
      • each checkbox can have a label and send symbol assigned to it
      • there are currently 4 checkboxes
    • right-clicking a track shows the context menu entry Pd Player -> Load mixer.
      • basically, you can load mixers of tracks not currently playing for some potentially interesting exchanges between patches. After loading the mixer, you still need to hit the Refresh button to show the changes.

    foo_pd's copy of libpd.dll contains only the externals that I needed to run the example patches. If you want your own patches to work with foo_pd, you might need to make another build using MSYS2. If you're not sure which objects aren't instantiating, foobar's console prints all of pd's messages while audio is being processed. I'll also add more externals over time.

    I'll be maintaining foo_pd at https://github.com/myQwil/foo_pd where you can also find the latest builds

    foo_pd.zip

    posted in libpd / webpd read more
Internal error.

Oops! Looks like something went wrong!