{"id":75,"date":"2023-09-09T06:48:02","date_gmt":"2023-09-09T13:48:02","guid":{"rendered":"https:\/\/rabiensoftware.com\/?p=75"},"modified":"2023-09-09T15:35:56","modified_gmt":"2023-09-09T22:35:56","slug":"gin-juce","status":"publish","type":"post","link":"https:\/\/rabiensoftware.com\/index.php\/2023\/09\/09\/gin-juce\/","title":{"rendered":"Gin &#038; Juce"},"content":{"rendered":"<h3>Introduction<\/h3>\n<p>Over the past 13 years as an independent contractor I&#8217;ve worked on JUCE based projects for companies like Intel, reFX, QSC, Neyrinck Audio and Tracktion. During this time I&#8217;ve had to solve the same problems multiple times, so I came up with <a href=\"https:\/\/github.com\/figbug\/gin\">Gin<\/a>, a collection of classes and utilities that compliment JUCE and allow me to work faster. Some parts of Gin have been well tested widely deployed in popular plugins, others are for my personal projects or ideas that went nowhere. Unfinished classes are marked with a comment, but feel free to ask me if something is &#8216;production ready&#8217; before you use it. The following sections will cover some of what&#8217;s in Gin and why you might want to use it. This is not a complete list, but just the highlights, please see the <a href=\"https:\/\/figbug.github.io\/Gin\/annotated.html\">online documentation<\/a> for a full list.<\/p>\n<h3>Licensing<\/h3>\n<p>I&#8217;m not a lawyer or a master of Open Source licenses, but the intention is that for anybody who has a license to use JUCE (either GPL3 or Commercial) and also use Gin free or charge and without restrictions. Therefore I&#8217;ve released Gin under the BSD license. As parts of Gin are derivates of JUCE, you also need to abide by JUCE&#8217;s license terms. Gin also includes 3rd party code (either BSD, MIT or similar license). I have left the authors original copyright notifications in these files.<\/p>\n<p>While I do not require your changes to be shared back to the main branch, it is appreciated. If you fixed bugs or have new features, please open a pull request.<\/p>\n<h3>Example Code<\/h3>\n<p>The Gin repository include a <a href=\"https:\/\/github.com\/FigBug\/Gin\/tree\/master\/examples\/Demo\">Demo Application<\/a> that uses as many classes as possible with visual demos. There is also a <a href=\"https:\/\/github.com\/FigBug\/Gin\/tree\/master\/examples\/Synth\">Synth Demo<\/a> that is a basic subtractive synth.<\/p>\n<h3>gin<\/h3>\n<p>The core gin module only depends on <strong>juce_core<\/strong> and <strong>juce_data_structures<\/strong> and is designed to be used from command line apps as well a GUI apps and plugins.<\/p>\n<h5>Catenary<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-81 aligncenter\" src=\"https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-300x182.png\" alt=\"\" width=\"300\" height=\"182\" srcset=\"https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-300x182.png 300w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted.png 576w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/>A catenary is the shape a wire, cable, rope etc. makes when it hangs. This class is useful for drawing wire connections in a modular synth. Note that in this class the y axis inverted compared to the y axis in <strong>juce::Graphics<\/strong> so you will need to invert the y coordinates.<\/p>\n<h5>Ellipse<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-82 size-medium\" src=\"https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-1-300x229.png\" alt=\"\" width=\"300\" height=\"229\" srcset=\"https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-1-300x229.png 300w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-1-768x587.png 768w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-1.png 924w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/>This class provides a set of functions to fine where lines intersect ellipses, points on ellipses, points inside and outside ellipses. Along with <strong>Catenary<\/strong> it can be useful for drawing wires with rounded ends.<\/p>\n<h5 class=\"p1\">DownloadManager<\/h5>\n<p class=\"p1\">DownloadManager is useful for downloading multiple files in the background. Maximum number of concurrent downloads and retry limits can be set. Supports gzip compressed downloads, which JUCE doesn&#8217;t automatically support on Windows.<\/p>\n<h5 class=\"p1\">EquationParser<\/h5>\n<p class=\"p1\">EquationParser takes strings like &#8220;6 * 3 + 5&#8221; and calculates the resulting value. Supports variables, constants, and functions. Parsing is cached and stored in byte code, so it is very fast if only variables change between evaluations. Based on <a href=\"https:\/\/beltoforion.de\/en\/muparser\/\">muParser<\/a>.<\/p>\n<h5 class=\"p1\">FileSystemWatcher<\/h5>\n<p class=\"p1\">FileSystemWatcher monitors the file system for changes to files, much more efficient than polling for changes. Useful for file browsers to know when to refresh or watching for new presets and samples in a plugin. Supports Windows, macOS &amp; Linux.<\/p>\n<h5 class=\"p1\">RIFFParser<\/h5>\n<p class=\"p1\">RIFFParser parses files like WAV and AVI that are based on the RIFF format. Useful for getting metadata chunks that aren&#8217;t supported by the JUCE WavAudioFormat. Used internally by the free function <strong>gin::getWavetableSize()<\/strong>.<\/p>\n<h3>gin_dsp<\/h3>\n<p><strong>gin_dsp<\/strong> is split into DSP algorithms and Components which are used to display the output of or control those algorithms.<\/p>\n<h5>ADSR<\/h5>\n<p>A simple linear ADSR, best used as a modulation source.<\/p>\n<h5>AnalogADSR<\/h5>\n<p>A analog style ADSR based on the algorithm from Will Pirkle&#8217;s book. Much better for controlling auto levels than the other ADSR.<\/p>\n<h5>AudioEquationParser<\/h5>\n<p>Similar to the <strong>gin::EquationParser<\/strong>, this subclass adds audio related functions. And since these functions have state, they aren&#8217;t true functions without side effects anymore. However, it does let the user type things like <em><strong>(hp12(inL, 5000, 0.707) + hp12(inR, 5000, 0.707))<\/strong><\/em> and it will filter the left and right channels and add them together. Since there is state, make sure you have a separate\u00a0<strong>gin::AudioEquationParser\u00a0<\/strong>for the left and right channel. For an example of how this can be used, see the <a href=\"https:\/\/github.com\/FigBug\/slPlugins\/blob\/master\/plugins\/Maths\/Source\/PluginProcessor.cpp\">Maths<\/a> plugin.<\/p>\n<h5>AudioFifo<\/h5>\n<p>A simple wrapper around <strong>juce::AbstractFifo<\/strong>, that lets you push and pop from a\u00a0<strong>juce::AudioSampleBuffer<\/strong>.<\/p>\n<h5>BandLimitedLookupTable<\/h5>\n<p>A collection of lookup tables for an oscillator, with a different lookup table for every few notes. This allows the oscillator to play back notes without aliasing. The tables can either be created from functions like saw, triangle, since, square and pulse. Or they can be loaded from a single cycle wave file, and then the higher frequencies will be removed with an FFT. These tables are used by the\u00a0<strong>gin::StereoOscillator \u222band gin::WTOscillator<\/strong>.<\/p>\n<h5>DelayLine<\/h5>\n<p>Simple delay with multiple tabs. Either linear or Lagrange interpolation.<\/p>\n<h5>Dynamics<\/h5>\n<p>Compressor, limiter, expander and gate based on Will Pirkle&#8217;s book.<\/p>\n<h5>EQ<\/h5>\n<p>Bundles up a number of filters to make it easy to have multi channel, multi band EQ.<\/p>\n<h5>Filter<\/h5>\n<p>Bundles up a number of SVF filters to have multichannel filters with either 12 or 24 dB slope.<\/p>\n<h5>GateEffect<\/h5>\n<p>Tracegate style effect<\/p>\n<h5>LFO<\/h5>\n<p>Oscillator with 17 different waveforms, great as a modulation source.<\/p>\n<h5>MidiFifo<\/h5>\n<p>If your plug-in has latency, and you need to keep the midi in sync with the audio, then a\u00a0<strong>gin::MidiFifo <\/strong>will do just that.<\/p>\n<h5>Modulation<\/h5>\n<p>Audio modulation, for a chorus or phaser etc<\/p>\n<h5>StereoOscillator<\/h5>\n<p>Audio rate oscillator with sine, saw, ramp, square, pulse and noise waves. Uses <strong>gin::BandLimitedLookupTables\u00a0<\/strong>to avoid aliasing.<\/p>\n<h5>VoicedStereoOscillator<\/h5>\n<p>A template class that can take an Oscillator and add multiple voices, detune and spread.<\/p>\n<h5>PlateReverb<\/h5>\n<p>An implementation of the classic plate reverb algorithm described by Jon Dattorro.<\/p>\n<h5>ResamplingFifo<\/h5>\n<p>An audio fifo where you push ay one sample rate and pop at another. Uses <a href=\"http:\/\/www.mega-nerd.com\/SRC\/\">SecretRabbitCode<\/a> internally.<\/p>\n<h5>SampleOscillator<\/h5>\n<p>Not really an oscillator, but it plays audio files at various pitches, so it can be used to create a sample based instrument.<\/p>\n<h5>Synthesiser<\/h5>\n<p>A subclass of <strong>juce::MPESynthesiser\u00a0<\/strong>but with much better voice handling. Adds fast kill support so there are no clicks when you run out of voices. Supports mono, legato, glissando and portamento. Number of voices can be changed with just a parameter, rather than having to construct and delete\u00a0<strong>Voice\u00a0<\/strong>objects.<\/p>\n<h5>ValueSmoother<\/h5>\n<p>A value smoother that only works on values between 0.0 and 1.0, but smooths at a fix rate, rather than a fixed time from current value to new value.<\/p>\n<h5>WTOscillator<\/h5>\n<p>Wave table oscillator with formant and bend phase distortion. Uses <strong>gin::BandLimitedLookupTables\u00a0<\/strong>to avoid aliasing.<\/p>\n<h5>TriggeredScope<\/h5>\n<p>Triggered Scope that it can be set to start on a rising or falling signal. This makes it extremely useful for very zoomed-in waveform viewing.<\/p>\n<h5>WavetableComponent<\/h5>\n<p>Draws a sweet 3D looking wavetable.<\/p>\n<h3>gin_graphics &amp; gin_webp<\/h3>\n<p>The\u00a0<strong>gin_graphics<\/strong> module extends the <strong>juce_graphics<\/strong> module<strong>\u00a0<\/strong>with 2 new image file formats: webp and bmp.<\/p>\n<p>There are also several free functions for applying image effect to\u00a0<strong>juce::Image<\/strong> including vignette, sepia, soften, sharpen, game, contrast, brightness, stack blur, higher quality <a href=\"https:\/\/github.com\/avaneev\/avir\">AVIR<\/a> resampling, Photoshop inspired blend modes.<\/p>\n<h3>gin_gui<\/h3>\n<p>The\u00a0<strong>gin_gui\u00a0<\/strong>module extends <strong>juce_gui_basics<\/strong> with the following new classes:<\/p>\n<h5><strong>ComponentViewer<\/strong><\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-88 size-medium\" src=\"https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-4-300x230.png\" alt=\"\" width=\"300\" height=\"230\" srcset=\"https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-4-300x230.png 300w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-4-1024x785.png 1024w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-4-768x589.png 768w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-4.png 1372w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>A useful tool for debugging, however the mouse over components to get the name, class, size, hierarchy, etc. Superseded by <a href=\"https:\/\/github.com\/sudara\/melatonin_inspector\">Melatonin Inspector<\/a>.<\/p>\n<h5>MapViewer<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-89 size-medium\" src=\"https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-5-300x210.png\" alt=\"\" width=\"300\" height=\"210\" srcset=\"https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-5-300x210.png 300w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-5-1024x718.png 1024w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-5-768x539.png 768w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-5-1536x1077.png 1536w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-5-2048x1437.png 2048w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-5-1540x1080.png 1540w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Display an OpenStreetMap zoomable and scrollable map.<\/p>\n<h5 class=\"p1\">FilePropertyComponent \/ ColourPropertyComponent<\/h5>\n<p class=\"p1\"><strong>juce<span class=\"s1\">::<\/span>PropertyComponent <\/strong>subclasses for File and Colour<\/p>\n<h5 class=\"p1\">CoalescedTimer<\/h5>\n<p>A way to combine <strong>juce::Timers\u00a0<\/strong>to ensure all timers with the same rate trigger at the same time. Usually for making sure all Component update from the same 60 Hz timer for example.<\/p>\n<h5 class=\"p1\">ElevatedFileCopy<\/h5>\n<p>For macOS and Windows, all the user to copy files into folders that require admin access.<\/p>\n<h5>Layout<\/h5>\n<p>This class probably deserves it&#8217;s own article. Allows Component layouts to be set from json, supports hot reloading to build layouts at runtime. Component positions are set by name, x, y, width and height. Functions are available to get the positions of other components. <strong>gin::EquationParser <\/strong>is used internally so mathematical expressions are supported. Square brackets can be used to layout several components at once.<\/p>\n<p>The following code does the layout for components name <strong>lfo1<\/strong>, <strong>lfo2<\/strong> and <strong>lfo3<\/strong>. The y position for lfo1 is <em>prevB()+1<\/em> while lfo2 and lfo3 use <em>prevY()<\/em> for their y position. All other coordinates are the same for each. If you are using this class with gin_plugin, each knob, select or switch component will be named after the short name of the parameter it is controlling.<\/p>\n<pre>{ \"id\": \"lfo[1..3]\", \"x\": 0, \"y\": \"prevB()+1,prevY()\", \"w\": 280, \"h\": 163, \"children\":\r\n  [\r\n    { \"id\": \"Sync\", \"x\": 0, \"y\": 23, \"w\": 56, \"h\": 70 },\r\n    { \"id\": \"Beat\", \"x\": \"prevR()\", \"y\": 23, \"w\": 56, \"h\": 70 },\r\n    { \"id\": \"Rate\", \"x\": \"prevX()\", \"y\": 23, \"w\": 56, \"h\": 70 },\r\n  ] \r\n},<\/pre>\n<p>For full examples see <a href=\"https:\/\/github.com\/FigBug\/Organ\/blob\/master\/plugin\/Source\/ui.json\">Organ<\/a> or <a href=\"https:\/\/github.com\/FigBug\/Wavetable\/blob\/master\/plugin\/Resources\/layout.json\">Wavetable<\/a>.<\/p>\n<h5 class=\"p1\">AsyncDownload<\/h5>\n<p>Downloads on a background thread, but until the similar juce functionality, doesn&#8217;t do the DNS lookup on the main thread, which can lock up your UI.<\/p>\n<h3>gin_location<\/h3>\n<p>This is a work in process module for getting the current location from the device GPS. It is nowhere near ready for use.<\/p>\n<h3>gin_metadata<\/h3>\n<p>Loads EXIF, IPTC, XMP, and comment metadata from JPEG and PNG images. If you are displaying a JPEG that came from a camera, you&#8217;ll need to get the orientation metadata to ensure the image is displayed the correct way up. GPS location, focal length, aperture, ISO may also be useful to know.<\/p>\n<h3>gin_network<\/h3>\n<h5>SecureStreamingSocket<\/h5>\n<p>A drop in replacement for <strong>juce::StreamingSocket<\/strong> but it supports SSL.<\/p>\n<h5>WebSocket<\/h5>\n<p>Webscocket client, supports HTTPS thanks to <strong>gin::SecureStreamingSocket<\/strong><\/p>\n<h3>gin_plugin<\/h3>\n<p>This module really needs an article on it&#8217;s own. It provides subclasses of<strong> juce::AudioProcessor<\/strong>, <strong>juce::AudioProcessorParameter<\/strong> and <strong>juce::AudioProcessorEditor\u00a0<\/strong>that make it much faster and easier to get started writing a effect or synth plugin. Preset loading and saving is handled. The editor has a titlebar for loading \/ saving presets and a patch browser. The plugin editor layout can either be done via json or snapped to a large grid.<\/p>\n<p>See the <a href=\"https:\/\/github.com\/FigBug\/slPlugins\/tree\/master\/plugins\/HugeGain\">HugeGain<\/a> plugin for a simple example, or <a href=\"https:\/\/github.com\/figbug\/wavetable\">Wavetable<\/a> for a full featured synth.<\/p>\n<p>The following code:<\/p>\n<pre>PluginEditor::PluginEditor (PluginProcessor&amp; p)\r\n    : gin::ProcessorEditor (p), proc (p)\r\n{\r\n    for (auto pp : p.getPluginParameters())\r\n    {\r\n        ParamComponent* pc;\r\n\r\n        if (pp-&gt;isOnOff())\r\n             pc = new Switch (pp);\r\n        else\r\n             pc = new Knob (pp);\r\n\r\n        addAndMakeVisible (pc);\r\n        controls.add (pc);\r\n     }\r\n     setGridSize (6, 1);\r\n}\r\n\r\nvoid PluginEditor::resized()\r\n{\r\n    gin::ProcessorEditor::resized();\r\n\r\n    componentForId (PARAM_GAIN_L)-&gt;setBounds (getGridArea (1, 0));\r\n    componentForId (PARAM_GAIN_S)-&gt;setBounds (getGridArea (2, 0));\r\n    componentForId (PARAM_GAIN_R)-&gt;setBounds (getGridArea (3, 0));\r\n    componentForId (PARAM_CLIP)-&gt;setBounds (getGridArea (4, 0));\r\n}<\/pre>\n<p>Creates the following UI:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-85\" src=\"https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-2-300x147.png\" alt=\"\" width=\"300\" height=\"147\" srcset=\"https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-2-300x147.png 300w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-2-768x376.png 768w, https:\/\/rabiensoftware.com\/wp-content\/uploads\/2023\/09\/Pasted-2.png 784w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>The <strong>gin::Parameter <\/strong>class supports optional smoothing to avoid zipper effect. Modulation via <strong>gin::ModMatrix<\/strong>.<\/p>\n<p>Setting up the parameters is as follows:<\/p>\n<pre>gainl = addExtParam (PARAM_GAIN_L, \"Left\", \"\", \"dB\", {-100.0f, 100.0f, 0.0f, 5.0f}, 0.0f, 0.1f);\r\ngains = addExtParam (PARAM_GAIN_S, \"Both\", \"\", \"dB\", {-100.0f, 100.0f, 0.0f, 5.0f}, 0.0f, 0.1f);\r\ngainr = addExtParam (PARAM_GAIN_R, \"Right\", \"\", \"dB\", {-100.0f, 100.0f, 0.0f, 5.0f}, 0.0f, 0.1f);\r\nclipp = addExtParam (PARAM_CLIP, \"Clip\", \"\", \"\", { 0.0f, 1.0f, 1.0f, 1.0f}, 1.0f, 0.1f, onOffTextFunction);\r\n\r\ngainl-&gt;conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); };\r\ngains-&gt;conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); };\r\ngainr-&gt;conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); };<\/pre>\n<p>And then the process block function is as follows, doing it sample by sample if smoothing is currently active or by blocks if parameters have changed recently:<\/p>\n<pre>void PluginProcessor::processBlock (AudioSampleBuffer&amp; buffer, MidiBuffer&amp;)\r\n{\r\n    int numSamples = buffer.getNumSamples();\r\n\r\n    if (isSmoothing())\r\n    {\r\n        int pos = 0;\r\n\r\n        while (pos &lt; numSamples)\r\n        {\r\n            auto workBuffer = sliceBuffer (buffer, pos, 1);\r\n\r\n            workBuffer.applyGain (0, 0, 1, gainl-&gt;getProcValue (1));\r\n            workBuffer.applyGain (1, 0, 1, gainr-&gt;getProcValue (1));\r\n            workBuffer.applyGain (gains-&gt;getProcValue (1));\r\n\r\n            pos++;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        buffer.applyGain (0, 0, numSamples, gainl-&gt;getProcValue (numSamples));\r\n        buffer.applyGain (1, 0, numSamples, gainr-&gt;getProcValue (numSamples));\r\n        buffer.applyGain (gains-&gt;getProcValue (numSamples));\r\n    }\r\n\r\n    if (clipp-&gt;getUserValue() != 0.0f)\r\n        clip (buffer, -1.0f, 1.0f);\r\n}<\/pre>\n<p>There are also numerous components for the plugin editor including LFO display, envelope display, patch browser, mod matrix, modulation source draggers, step lfo editor. The Wavetable synth uses no custom components, other than <strong>gin<span class=\"s1\">::<\/span>ParamBox <\/strong>subclasses to group components, everything else is from Gin.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/FigBug\/Wavetable\/raw\/master\/Screenshots\/Screenshot1.png\" alt=\"Screenshot 1\" \/><\/p>\n<h3>Conclusion<\/h3>\n<p>That is a high level overview of the Gin library. In future posts, I&#8217;ll give into some of the classes in more detail. If you have any questions or bugs, join the <a href=\"https:\/\/github.com\/FigBug\/Gin\/discussions\">discussion<\/a> or <a href=\"https:\/\/github.com\/FigBug\/Gin\/issues\">issues<\/a> on GitHub or ask on my <a href=\"https:\/\/discord.gg\/hCbpasqQ\">Discord<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Over the past 13 years as an independent contractor I&#8217;ve worked on JUCE based projects for companies like Intel, reFX, QSC, Neyrinck Audio and Tracktion. During this time I&#8217;ve had to solve the same problems multiple times, so I came up with Gin, a collection of classes and utilities that compliment JUCE and allow&hellip; <br \/> <a class=\"read-more\" href=\"https:\/\/rabiensoftware.com\/index.php\/2023\/09\/09\/gin-juce\/\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":95,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8,6,7],"tags":[5,4,3],"class_list":["post-75","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dsp","category-gin","category-programming","tag-dsp","tag-gin","tag-juce"],"_links":{"self":[{"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/posts\/75","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/comments?post=75"}],"version-history":[{"count":12,"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/posts\/75\/revisions"}],"predecessor-version":[{"id":96,"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/posts\/75\/revisions\/96"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/media\/95"}],"wp:attachment":[{"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/media?parent=75"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/categories?post=75"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rabiensoftware.com\/index.php\/wp-json\/wp\/v2\/tags?post=75"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}