• Products
    • Isadora
    • Get It
    • ADD-ONS
    • IzzyCast
    • Get It
  • Forum
  • Help
  • Werkstatt
  • Newsletter
  • Impressum
  • Dsgvo
  • Press
  • Isadora
  • Get It
  • ADD-ONS
  • IzzyCast
  • Get It
  • Press
  • Dsgvo
  • Impressum

Navigation

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Popular
    • Tags

    Using Shader with Audio Input?

    How To... ?
    2
    2
    34
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D
      dexamusx last edited by

      Looking to use the audio feature in the linked GLSL shader and really struggling. Can anyone help me understand how to use this shader with Isadora's audio features? I

      I've linked the Shader and attached my current patch. The cue I'm working on though is only Q4. Any help would be appreciated

      Shader: https://www.shadertoy.com/view...

      Device: Omen Laptop running Windows 11
      Patch: vinyljournal2.izz

      DusX 1 Reply Last reply Reply Quote 0
      • DusX
        DusX Izzy Guru @dexamusx last edited by

        @dexamusx

        Shadertoy intakes audio at video textures, and currently Isadora has no way to convert audio to a video texture. 

        So I converted this shader to use 5 fft inputs as seen below (I am not sure this looks right, since this effect would not run for me on shadertoy).

        the updated code:

        // ------------------------------------------------------------
        // Audio-reactive circular visualizer
        // Converted from texture-based audio input to 5 numeric bands
        //
        // Suggested Isadora inputs:
        //   fft0   = 0 Hz
        //   fft94  = 94 Hz
        //   fft188 = 188 Hz
        //   fft281 = 281 Hz
        //   fft375 = 375 Hz
        //
        // Expected input range: 0.0 to 1.0
        // ------------------------------------------------------------
        // If needed for Isadora custom controls, you can adapt these comments
        // to the exact syntax expected by the GLSL Shader actor.
        //
        // ISADORA_FLOAT_PARAM(fft0, f000, 0.0, 1.0, 0.0, "FFT 0 Hz");
        // ISADORA_FLOAT_PARAM(fft94, f094, 0.0, 1.0, 0.0, "FFT 94 Hz");
        // ISADORA_FLOAT_PARAM(fft188, f188, 0.0, 1.0, 0.0, "FFT 188 Hz");
        // ISADORA_FLOAT_PARAM(fft281, f281, 0.0, 1.0, 0.0, "FFT 281 Hz");
        // ISADORA_FLOAT_PARAM(fft375, f375, 0.0, 1.0, 0.0, "FFT 375 Hz");
        // ISADORA_FLOAT_PARAM(audioGain, gain, 0.0, 3.0, 1.0, "Audio gain");
        uniform float fft0;
        uniform float fft94;
        uniform float fft188;
        uniform float fft281;
        uniform float fft375;
        uniform float audioGain;
        // ------------------------------------------------------------
        // Utility: sample a pseudo-spectrum from the 5 numeric bands
        // ------------------------------------------------------------
        float SampleAudioSpectrum(float normPos)
        {
            normPos = clamp(normPos, 0.0, 1.0);
            // Apply overall gain and clamp
            float b0 = clamp(fft0   * audioGain, 0.0, 1.0);
            float b1 = clamp(fft94  * audioGain, 0.0, 1.0);
            float b2 = clamp(fft188 * audioGain, 0.0, 1.0);
            float b3 = clamp(fft281 * audioGain, 0.0, 1.0);
            float b4 = clamp(fft375 * audioGain, 0.0, 1.0);
            // 5 points distributed evenly across 0..1:
            // 0.00, 0.25, 0.50, 0.75, 1.00
            if (normPos <= 0.25)
            {
                float t = normPos / 0.25;
                return mix(b0, b1, t);
            }
            else if (normPos <= 0.50)
            {
                float t = (normPos - 0.25) / 0.25;
                return mix(b1, b2, t);
            }
            else if (normPos <= 0.75)
            {
                float t = (normPos - 0.50) / 0.25;
                return mix(b2, b3, t);
            }
            else
            {
                float t = (normPos - 0.75) / 0.25;
                return mix(b3, b4, t);
            }
        }
        float GetIntensityInRange(float beginNorm, float endNorm, float incrementSize)
        {
            if (incrementSize <= 0.0) return 0.0;
            float range = endNorm - beginNorm;
            if (range <= 0.0) return 0.0;
            float result = 0.0;
            float sampleCount = 0.0;
            // Fixed maximum iterations for GLSL compatibility
            for (int i = 0; i < 64; i++)
            {
                float lookupCoord = beginNorm + float(i) * incrementSize;
                if (lookupCoord >= endNorm) break;
                result += SampleAudioSpectrum(lookupCoord) * 2.0;
                sampleCount += 1.0;
            }
            if (sampleCount <= 0.0) return 0.0;
            return result / sampleCount;
        }
        float GetCornerIntensity(vec2 fragCoord, float checkDist, vec2 corner, float beginSample, float endSample)
        {
            float distanceN = 1.0 - (clamp(distance(fragCoord, corner), 0.0, checkDist) / checkDist);
            float intensity = GetIntensityInRange(beginSample, endSample, 0.05);
            float color = distanceN * intensity;
            return color;
        }
        bool IsWithin(float val, float minVal, float maxVal)
        {
            return val >= minVal && val <= maxVal;
        }
        vec4 innerColour     = vec4(0.0,   168.0, 181.0, 255.0) / 255.0;
        vec4 outerRingColour = vec4(119.0, 72.0,  152.0, 255.0) / 255.0;
        vec4 highsColour     = vec4(243.0, 174.0, 75.0,  255.0) / 255.0;
        vec4 lowsColour      = vec4(222.0, 67.0,  131.0, 255.0) / 255.0;
        void mainImage(out vec4 fragColor, in vec2 fragCoord)
        {
            fragColor = vec4(0.0, 0.0, 0.0, 1.0);
            // Normalized pixel coordinates (from 0 to 1)
            vec2 uv = fragCoord / iResolution.xy;
            float smallestDimen = min(iResolution.x, iResolution.y);
            vec2 halfDimen = iResolution.xy * 0.5;
            float halfSDimen = smallestDimen * 0.5;
            vec2 centerOffset = fragCoord - halfDimen;
            vec2 nOffset = centerOffset / halfSDimen;
            float fragAngle = atan(centerOffset.y, centerOffset.x);
            float fragAngleDegrees = fragAngle * 180.0 / 3.14159;
            float overAllPulse = GetIntensityInRange(0.0, 0.3, 0.05);
            float pixelDistanceToCenter = distance(fragCoord, halfDimen);
            float idealRingDistance = halfSDimen * 0.8;
            float ringDistance = idealRingDistance + (halfSDimen * overAllPulse * 0.2);
            float pixelRingDist = abs(ringDistance - pixelDistanceToCenter);
            const float ringWidth = 20.0;
            float outerRingIntensity = 1.0 - (pixelRingDist / ringWidth);
            if (IsWithin(outerRingIntensity, 0.0, 1.0))
            {
                outerRingIntensity *= sin(fragAngle * 3.0 + iTime) * 0.5 + 0.5;
                fragColor += outerRingIntensity * outerRingColour;
            }
            // --- Inner ring
            // Start = close to center, End = going further away
            float innerRingEnd = ringDistance - ringWidth * 0.5;
            float lookupAngle = mod(fragAngleDegrees + 180.0, 360.0);
            float pixelLookupIndex = lookupAngle / 360.0;
            float pixelLookupColor = SampleAudioSpectrum(pixelLookupIndex) * 2.0;
            float pulseA = (sin(fragAngle * 3.0 + iTime) * 0.5 + 0.5) * 0.2;
            float pulseB = (cos(fragAngle * 6.0 - iTime * 1.5) * 0.5 + 0.5) * 0.2;
            float pulse = 0.1 + pulseA + pulseB;
            float innerRingStart = innerRingEnd * (1.0 - pixelLookupColor - pulse);
            float innerRingLength = max(innerRingEnd - innerRingStart, 0.0001);
            float innerRingFragProgress = (pixelDistanceToCenter - innerRingStart) / innerRingLength;
            float innerRingIntensity = innerRingFragProgress;
            if (pixelDistanceToCenter < innerRingStart || pixelDistanceToCenter > innerRingEnd)
                innerRingIntensity = 0.0;
            // Inner ring separators
            float angleMod = mod(fragAngleDegrees, 3.0);
            if (IsWithin(angleMod, 0.0, 1.0))
                innerRingIntensity = 0.0;
            fragColor += innerColour * innerRingIntensity;
            // Corners
            float topRightIntensity = GetCornerIntensity(fragCoord, smallestDimen, iResolution.xy, 0.3, 0.65);
            float topLeftIntensity = GetCornerIntensity(fragCoord, smallestDimen, vec2(0.0, iResolution.y), 0.0, 0.25) * 2.0;
            if (topRightIntensity > 0.0)
            {
                fragColor += highsColour * topRightIntensity;
            }
            if (topLeftIntensity > 0.0)
            {
                fragColor += lowsColour * topLeftIntensity;
            }
            // Background spectrum wash:
            // original shader used texture(iChannel1, vec2(uv.x, 0.25)).x
            float texIntensity = SampleAudioSpectrum(uv.x);
            fragColor += lowsColour * texIntensity;
            fragColor.rgb = clamp(fragColor.rgb, 0.0, 1.0);
        }

        🎛️ TroikaTronix Professional Services
        https://troikatronix.com/professional-services

        🎫 Support Tickets
        https://support.troikatronix.com/support/tickets/new

        💻 Add-ons
        https://troikatronix.com/add-ons/?u=dusx

        🧪 GitHub Projects
        https://github.com/rwebber

        🖥️ Win11 | i7 | RTX 4070 | 32GB RAM | Ontario, Canada

        1 Reply Last reply Reply Quote 1
        • First post
          Last post