Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: foo_wave_seekbar (Read 815068 times) previous topic - next topic
0 Members and 2 Guests are viewing this topic.

foo_wave_seekbar

Reply #1775
^ I know that it needs to generate it first. Even then, my CPU is a Core i7 950. I don't think it's the issue. The songs were generally 3-5min long. I would have understoof if the track was 30min long, I think.

I discovered that when FLAC files doesn't have extra tag padding, it slows down the "first time" process. Quite strange.

foo_wave_seekbar

Reply #1776
The last time I benchmarked anything, my code added rather negligible time on top of raw decoding.
Run some benchmarks (with foo_benchmark or something) with just decoding, see what time it takes to decode a track.

There may be some overheads for stupid formats if they cannot cheaply determine the parameters I ask for before decoding, but you'd need an instrumented scanner to find that out.

The underlying cause here is most probably you rewriting your whole collection. Doing so tends to cause severe file fragmentation, and as non-interactive decoding speed is sequential, fragmentation kills.
Stay sane, exile.

foo_wave_seekbar

Reply #1777
Uh, is it possible to entirely hide bar (filling the the bar with some color for example) if the height (or width) of the element is less than _number_?

 

foo_wave_seekbar

Reply #1778
If you use the Direct3D frontend, you can modify the pixel shader to add an if-branch on the size of the window. When I manage to dig out my testbed installation, I can give it a shot.
Stay sane, exile.

foo_wave_seekbar

Reply #1779
If you use the Direct3D frontend, you can modify the pixel shader to add an if-branch on the size of the window. When I manage to dig out my testbed installation, I can give it a shot.

Yeah I'm using D3D frontend, but I'm not really familiar with it, so help would be appreciated.

foo_wave_seekbar

Reply #1780
Hi everybody,

I have used Propheticus and derty2 code (pages 79 and 80 of this topic : http://www.hydrogenaud.io/forums/index.php?showtopic=63984 ) for changing my Waveform Seekbar, but it doesn't seem to adjust/center automatically to the height allowed to the component.



What part of the code should I tweak so the waveform is automatically centered, whatever the height of the component ?

Thanks in advance.

EDIT : the problem seems to be ReplayGain related : apparently the lower the track gain, the lower the waveform :

Track gain = -1.61 dB :


Track gain = -6.00 dB :


Track gain = -12.71 dB :


Three funny facts as you can see :
1. When the track gain is close to zero (first image), the waveform seems to "get out" of the component space
2. When the track gain becomes very low (third image), the waveform seems to be "compressed" vertically without ever getting out of the component space
3. The "inside waveform" (the darker/grey-ish orange) doesn't seem to be affected, it seems to be always centered. Here's a good example (-4.54 dB) where the "outside waveform" (orange) goes slightly up and the "inside waveform" remains centered :

foo_wave_seekbar

Reply #1781
It's possible that the code used is affected by the removal of floating point pixel formats many versions ago. Or it may be that their replaygain code is defective.
Try skimming ahead from those pages and see if you find any fixes to their code, the names seem familiar.

Otherwise, I might take a look at it if the mystical "free time" happens, but don't bet on it.
Stay sane, exile.

foo_wave_seekbar

Reply #1782
Thanks Zao. Here's what I have done so far :
- I have skimmed the other topic from page 79 on, and I haven't found any fix
- I have posted in the other topic, hoping that Propheticus or derty2 would see my post (no answer yet)
- Oh, and BTW I have foobar 1.3.2 with Waveform Seekbar 0.2.45.

If somebody here is willing to have a look, here are several codes that seem to be affected by exactly the same problems.
If it can be of any help, the first code didn't have any problem with my previous Waveform Seekbar version (which was an old one : 0.2.10). So maybe it has something to do with the floating point stuff. I have no idea.
The second and third code are both taken from the other topic(pages 79 and 80).

Code: [Select]
Texture1D tex : WAVEFORMDATA;
Texture2D seekTex < string filename = "seekbar.png"; >;

SamplerState sTex
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Clamp;
};

struct VS_IN
{
float2 pos : POSITION;
float2 tc : TEXCOORD0;
};

struct PS_IN
{
float4 pos : SV_POSITION;
float2 tc : TEXCOORD0;
};


float4 backgroundColor : BACKGROUNDCOLOR;
float4 highlightColor  : HIGHLIGHTCOLOR;
float4 selectionColor  : SELECTIONCOLOR;
float4 textColor      : TEXTCOLOR;
float cursorPos        : CURSORPOSITION;
bool cursorVisible    : CURSORVISIBLE;
float seekPos          : SEEKPOSITION;
bool seeking          : SEEKING;
float4 replayGain      : REPLAYGAIN; // album gain, track gain, album peak, track peak
float2 viewportSize    : VIEWPORTSIZE;
bool horizontal        : ORIENTATION;
bool shade_played      : SHADEPLAYED;

PS_IN VS( VS_IN input )
{
PS_IN output = (PS_IN)0;

float2 half_pixel = float2(1,-1) / viewportSize;
output.pos = float4(input.pos - half_pixel, 0, 1);
if (horizontal)
output.tc = float2((input.tc.x + 1.0) / 2.0, input.tc.y);
else
output.tc = float2((-input.tc.y + 1.0) / 2.0, input.tc.x);

return output;
}

float4 bar( float pos, float2 tc, float4 fg, float4 bg, float width, bool show )
{
float dist = abs(pos - tc.x);
float4 c = (show && dist < width)
? lerp(fg, bg, smoothstep(0, width, dist))
: bg;
return c;
}

float4 grayscale( float4 color )
{
return color.r * 0.3 + color.g * 0.59 + color.b * 0.11;
}

float4 sepia( float4 color )
{
float4 weight;
weight.r = 0.3;
weight.g = 0.59;
weight.b = 0.11;
weight.a = 0;

float4 adjust;
adjust.r = 0.098039215686275;
adjust.g = -0.050980392156863;
adjust.b = -0.26274509803922;
adjust.a = 0;

float intensity = dot(color, weight) ;
color = intensity + adjust;
return saturate(color);
}

float4 contrast( float4 color, float strength )
{
return saturate((color - 0.5) * strength + 0.5);
}

float4 played( float pos, float2 tc, float4 fg, float4 bg, float alpha)
{
float4 c = bg;
if (pos > tc.x)
{
#if 0
c = contrast(c, fg.r * 2);
c = lerp(c, sepia©, fg.g);
c = lerp(c, grayscale©, fg.b);
#else
c = grayscale©;
//c = sepia©;
#endif
}
return c;
}

float4 evaluate( float2 tc, float border )
{
// alpha 1 indicates biased texture
float4 minmaxrms = tex.Sample(sTex, tc.x);
minmaxrms.rgb *= pow(10,(replayGain.g) / 20) * 2; //use track gain
minmaxrms.rgb -= 0.5 * minmaxrms.a;
minmaxrms.rgb *= 1.0 + minmaxrms.a;

float belowWave = tc.y + border - minmaxrms.r;
float aboveWave = tc.y - border - minmaxrms.g;
float factorWave = min(abs(belowWave), abs(aboveWave));
bool insideWave = (belowWave > 0 && aboveWave < 0);

float diffRms = abs(tc.y) - border - minmaxrms.b;
float factorRms = abs(diffRms);
bool insideRms = diffRms < 0;

float factor = insideRms ? (1.0 - 0.5 * saturate(factorRms / border / 2)): 1.0;
factor = insideWave ? (factor * saturate(factorWave / border / 2)) : 0.0;

float4 wave = lerp(backgroundColor, textColor, factor);

return saturate(wave);
}

float4 PS( PS_IN input ) : SV_Target
{
float dx, dy;
if (horizontal)
{
dx = 1/viewportSize.x;
dy = 1/viewportSize.y;
}
else
{
dx = 1/viewportSize.y;
dy = 1/viewportSize.x;
}
float seekWidth = 2.5 * dx;
float positionWidth = 2.5 * dx;

float4 c0 = evaluate(input.tc, 2.5 * dy);
if (shade_played)
c0 = played(cursorPos, input.tc, highlightColor, c0, 0.3);
c0 = bar(cursorPos, input.tc, selectionColor, c0, positionWidth, cursorVisible);
c0 = bar(seekPos,  input.tc, selectionColor, c0, seekWidth,    seeking      );
return c0;
}

technique10 Render10
{
pass P0
{
SetGeometryShader( 0 );
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}

technique Render9
{
pass
{
VertexShader = compile vs_2_0 VS();
PixelShader = compile ps_2_0 PS();
}
}

Code: [Select]
texture tex : WAVEFORMDATA;
   
    sampler sTex = sampler_state
    {
        Texture = (tex);
        MipFilter = LINEAR;
        MinFilter = LINEAR;
        MagFilter = LINEAR;
     
        AddressU = Clamp;
    };
   
    struct VS_IN
    {
        float2 pos : POSITION;
        float2 tc : TEXCOORD0;
    };
   
    struct PS_IN
    {
        float4 pos : SV_POSITION;
        float2 tc : TEXCOORD0;
    };
   
   
    float4 backgroundColor : BACKGROUNDCOLOR;
    float4 highlightColor  : HIGHLIGHTCOLOR;
    float4 selectionColor  : SELECTIONCOLOR;
    float4 textColor      : TEXTCOLOR;
    float cursorPos        : CURSORPOSITION;
    bool cursorVisible    : CURSORVISIBLE;
    float seekPos          : SEEKPOSITION;
    bool seeking          : SEEKING;
    float4 replayGain      : REPLAYGAIN; // album gain, track gain, album peak, track peak
    float2 viewportSize    : VIEWPORTSIZE;
    bool horizontal        : ORIENTATION;
    bool flipped          : FLIPPED;
    bool shade_played      : SHADEPLAYED;
   
    PS_IN VS( VS_IN input )
    {
        PS_IN output = (PS_IN)0;
   
        float2 half_pixel = float2(1,-1) / viewportSize;
        output.pos = float4(input.pos - half_pixel, 0, 1);
   
        if (horizontal)
        {
            output.tc = float2((input.tc.x + 1.0) / 2.0, input.tc.y);
        }
        else
        {
            output.tc = float2((-input.tc.y + 1.0) / 2.0, input.tc.x);
        }
   
        if (flipped)
            output.tc.x = 1.0 - output.tc.x;
   
        return output;
    }
   
    float4 bar( float pos, float2 tc, float4 fg, float4 bg, float width, bool show )
    {
        float dist = abs(pos - tc.x);
        float4 c = (show && dist < width)
            ? lerp(fg, bg, smoothstep(0, width, dist))
            : bg;
        return c;
    }
   
   
    float4 evaluate(float4 bg, float4 fg, float factor)
    {
            return saturate(lerp(bg, fg, factor));
    }
   
    float4 played( float pos, float2 tc, float4 bg, float factor)
    {
            float4 c = bg;
            if (pos > tc.x)
            {
                    c = evaluate(backgroundColor, highlightColor, factor);
            }
            return c;
    }
   
    float RMSfactor( float2 tc, float border )
    {
            float4 minmaxrms = tex1D(sTex, tc.x);
   
            minmaxrms.rgb -= 0.1 * minmaxrms.a;
            minmaxrms.rgb *= 0.8 + minmaxrms.a;
         
            float belowWave = tc.y + border - minmaxrms.r;
            float aboveWave = tc.y - border - minmaxrms.g;
            float factorWave = min(abs(belowWave), abs(aboveWave));
            bool insideWave = (belowWave > 0 && aboveWave < 0);
       
            float diffRms = abs(tc.y) - border - minmaxrms.b;
            float factorRms = abs(diffRms);
            bool insideRms = diffRms < 0;
       
            float factor = insideRms ? ( 1 + 0.2 * saturate(factorRms / border / 2)): 1.0;
            factor = insideWave ? (factor * saturate(factorWave / border / 1)) : 0.0; //1 = max sharp
       
            return factor;
    }
   
    float4 PS( PS_IN input ) : SV_Target
    {
            float dx, dy;
            if (horizontal)
            {
                    dx = 1/viewportSize.x;
                    dy = 1/viewportSize.y;
            }
            else
            {
                    dx = 1/viewportSize.y;
                    dy = 1/viewportSize.x;
            }
            float seekWidth = 2.5 * dx;
            float positionWidth = 2.5 * dx;
   
            float factor = RMSfactor(input.tc, 2.5 * dy);
   
            float4 c0 = evaluate(backgroundColor, textColor, factor);
            if (shade_played)
                    c0 = played(cursorPos, input.tc, c0, factor);
            c0 = bar(cursorPos, input.tc, selectionColor, c0, positionWidth, cursorVisible);
            c0 = bar(seekPos,  input.tc, selectionColor, c0, seekWidth,    seeking      );
            return c0;
    }
   
    technique10 Render10
    {
        pass P0
        {
            SetGeometryShader( 0 );
            SetVertexShader( CompileShader( vs_4_0, VS() ) );
            SetPixelShader( CompileShader( ps_4_0, PS() ) );
        }
    }
   
    technique Render9
    {
        pass
        {
            VertexShader = compile vs_2_0 VS();
            PixelShader = compile ps_2_0 PS();
        }
    }

Code: [Select]
texture tex : WAVEFORMDATA;

sampler sTex = sampler_state
{
Texture = (tex);
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;

AddressU = Clamp;
};

struct VS_IN
{
float2 pos : POSITION;
float2 tc : TEXCOORD0;
};

struct PS_IN
{
float4 pos : SV_POSITION;
float2 tc : TEXCOORD0;
};


float4 backgroundColor : BACKGROUNDCOLOR;
float4 highlightColor : HIGHLIGHTCOLOR;
float4 selectionColor : SELECTIONCOLOR;
float4 textColor : TEXTCOLOR;
float cursorPos : CURSORPOSITION;
bool cursorVisible : CURSORVISIBLE;
float seekPos : SEEKPOSITION;
bool seeking : SEEKING;
float4 replayGain : REPLAYGAIN; // album gain, track gain, album peak, track peak
float2 viewportSize : VIEWPORTSIZE;
bool horizontal : ORIENTATION;
bool flipped : FLIPPED;
bool shade_played : SHADEPLAYED;

PS_IN VS( VS_IN input )
{
PS_IN output = (PS_IN)0;

float2 half_pixel = float2(1,-1) / viewportSize;
output.pos = float4(input.pos - half_pixel, 0, 1);

if (horizontal)
{
output.tc = float2((input.tc.x + 1.0) / 2.0, input.tc.y);
}
else
{
output.tc = float2((-input.tc.y + 1.0) / 2.0, input.tc.x);
}

if (flipped)
output.tc.x = 1.0 - output.tc.x;

return output;
}

float4 bar( float pos, float2 tc, float4 fg, float4 bg, float width, bool show )
{
float dist = abs(pos - tc.x);
float4 c = (show && dist < width)
? lerp(fg, bg, smoothstep(0, width, dist))
: bg;
return c;
}


float4 evaluate(float4 bg, float4 fg, float factor)
{
return saturate(lerp(bg, fg, factor));
}

float4 played( float pos, float2 tc, float4 bg, float factor)
{
float4 c = bg;
if (pos > tc.x)
{
c = evaluate(backgroundColor, highlightColor, factor);
}
return c;
}

float RMSfactor( float2 tc, float border )
{
float4 minmaxrms = tex1D(sTex, tc.x);

minmaxrms.rgb -= .1 * minmaxrms.a;

//- - - - - CHANGES THE OVERALL WAVE SIZE IN THE PANEL - - - - - - - -
//minmaxrms.rgb *= 0.8 + minmaxrms.a; <<<<<backup original
minmaxrms.rgb *= 0.95 + minmaxrms.a;

float belowWave = tc.y + border - minmaxrms.r;
float aboveWave = tc.y - border - minmaxrms.g;
float factorWave = min(abs(belowWave), abs(aboveWave));
bool insideWave = (belowWave > 0 && aboveWave < 0);

float diffRms = abs(tc.y) - border - minmaxrms.b;
float factorRms = abs(diffRms);

//- - - - - ENABLE/DISABLE THE INSIDE WAVE - - - - - - - -
// [TO DISABLE: bool insideRms = 0;] [TO ENABLE: bool insideRms = diffRms < 0; <<<<<backup original]
//bool insideRms = diffRms < 0;
//bool insideRms = (belowWave > 0 && aboveWave < 0);
bool insideRms = (diffRms > 0 && diffRms < 0);

//- - - - - CHANGES LOOK OF INSIDE WAVE - - - - - - - -
//float factor = insideRms ? ( 1 + 0.2 * saturate(factorRms / border / 2)): 1.0; <<<<<backup original
float factor = insideRms ? ( 6 * saturate(factorRms / border / 20)): 10.0;

//- - - - - CHANGES LOOK OF OUTSIDE WAVE & PANEL BACKGROUND - - - - - - - -
//factor = insideWave ? (factor * saturate(factorWave / border / 1)) : 0.0; <<<<<backup original
factor = insideWave ? (factorRms * 6.0 + 0.8 * saturate(factorWave / border / 0.5)) : 0.0;

//return factor; <<<<<<backup original
return insideWave - saturate(factorWave);
}

float4 PS( PS_IN input ) : SV_Target
{
float dx, dy;
if (horizontal)
{
dx = 1/viewportSize.x;
dy = 1/viewportSize.y;
}
else
{
dx = 1/viewportSize.y;
dy = 1/viewportSize.x;
}
float seekWidth = 2.5 * dx;
float positionWidth = 2.5 * dx;

float factor = RMSfactor(input.tc, 2.5 * dy);

float4 c0 = evaluate(backgroundColor, textColor, factor);
if (shade_played)
c0 = played(cursorPos, input.tc, c0, factor);
c0 = bar(cursorPos, input.tc, selectionColor, c0, positionWidth, cursorVisible);
c0 = bar(seekPos, input.tc, selectionColor, c0, seekWidth, seeking );
return c0;
}

technique10 Render10
{
pass P0
{
SetGeometryShader( 0 );
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}

technique Render9
{
pass
{
VertexShader = compile vs_2_0 VS();
PixelShader = compile ps_2_0 PS();
}
}

foo_wave_seekbar

Reply #1783
See all those parts where it works with minmaxrms? In all places, they've fucked up the unbias operation.

In the first one, RG adjustments are done before unbiasing.
In the second one, the factors used have been messed with.
In the third one, heaven knows.

The thing is that in the past I had two main ways of moving data from the program to the shader.
  • an 8-bit unsigned texture that had values that ended up between 0.0 and 1.0 in the shader, where 0.0 was negative fullscale and 1.0 was positive fullscale.
  • a floating point texture that had real numbers that mapped -1.0 thru 1.0 to digital fullscale.


The 8-bit kind needs a shift and a scale to turn the range of (0.0, 1.0) into (-1.0, 1.0). The way the shader knows if this should be done is the 'alpha' component of minmaxrms.
If alpha is one, we subtract 0.5 (getting us the range (-0.5, 0.5)) and multiply by two (getting us (-1.0, 1.0)).
If alpha is zero, we subtract 0 (doing nothing) and multiply by one (doing nothing), getting us the (-1.0, 1.0) we wanted all along.

This step should unconditionally be done in any shader with the value sampled from the texture. After you've got the proper fullscale range, you can then scale/shift/RG/mutilate all you want.

The reason why this surfaces more often now is because in some version inbetween the one you mentioned and now, I removed the floating point texture kind, only having 8-bit RGB. The shaders were already broken in the past on low-end video cards, but few noticed.
Stay sane, exile.

foo_wave_seekbar

Reply #1784
To be fair, I just hacked together some code I found somewhere and adjusted certain parameters so it looked like I wanted it to. Probably very specific to my situation, replaygain settings and other factors.
I have moved on to someone else's code that creates a soundcloud'esque waveform since then.

@Zao, sorry for causing you support questions due to old hacky code

WCS13, try this:
Code: [Select]
texture tex : WAVEFORMDATA;
 
sampler sTex = sampler_state
{
    Texture = (tex);
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
 
    AddressU = Clamp;
};
 
struct VS_IN
{
    float2 pos : POSITION;
    float2 tc : TEXCOORD0;
};
 
struct PS_IN
{
    float4 pos : SV_POSITION;
    float2 tc : TEXCOORD0;
};
 
 
float4 backgroundColor : BACKGROUNDCOLOR;
float4 highlightColor  : HIGHLIGHTCOLOR;
float4 selectionColor  : SELECTIONCOLOR;
float4 textColor      : TEXTCOLOR;
float cursorPos        : CURSORPOSITION;
bool cursorVisible    : CURSORVISIBLE;
float seekPos          : SEEKPOSITION;
bool seeking          : SEEKING;
float4 replayGain      : REPLAYGAIN; // album gain, track gain, album peak, track peak
float2 viewportSize    : VIEWPORTSIZE;
bool horizontal        : ORIENTATION;
bool flipped          : FLIPPED;
bool shade_played      : SHADEPLAYED;
 
PS_IN VS( VS_IN input )
{
    PS_IN output = (PS_IN)0;
 
    float2 half_pixel = float2(1,-1) / viewportSize;
    output.pos = float4(input.pos - half_pixel, 0, 1);
 
    if (horizontal)
    {
        output.tc = float2((input.tc.x + 1.0) / 2.0, input.tc.y);
    }
    else
    {
        output.tc = float2((-input.tc.y + 1.0) / 2.0, input.tc.x);
    }
 
    if (flipped)
        output.tc.x = 1.0 - output.tc.x;
 
    return output;
}
 
float4 bar( float pos, float2 tc, float4 fg, float4 bg, float width, bool show )
{
    float dist = abs(pos - tc.x);
    float4 c = (show && dist < width)
        ? lerp(fg, bg, smoothstep(0, width, dist))
        : bg;
    return c;
}
 
 
float4 evaluate(float4 bg, float4 fg, float factor)
{
        return saturate(lerp(bg, fg, factor));
}
 
float4 played( float pos, float2 tc, float4 bg, float factor)
{
        float4 c = bg;
        if (pos > tc.x)
        {
                c = evaluate(backgroundColor, highlightColor, factor);
        }
        return c;
}
 
float RMSfactor( float2 tc, float border )
{
        float4 minmaxrms = tex1D(sTex, tc.x);
 
        minmaxrms.rgb -= 0.5 * minmaxrms.a;
minmaxrms.rgb *= 1.0 + minmaxrms.a;
     
        float belowWave = tc.y + border - minmaxrms.r;
        float aboveWave = tc.y - border - minmaxrms.g;
        float factorWave = min(abs(belowWave), abs(aboveWave));
        bool insideWave = (belowWave > 0 && aboveWave < 0);
   
        float diffRms = abs(tc.y) - border - minmaxrms.b;
        float factorRms = abs(diffRms);
        bool insideRms = diffRms < 0;
   
        float factor = insideRms ? ( 1 + 0.2 * saturate(factorRms / border / 2)): 1.0;
        factor = insideWave ? (factor * saturate(factorWave / border / 1)) : 0.0; //1 = max sharp
   
        return factor;
}
 
float4 PS( PS_IN input ) : SV_Target
{
        float dx, dy;
        if (horizontal)
        {
                dx = 1/viewportSize.x;
                dy = 1/viewportSize.y;
        }
        else
        {
                dx = 1/viewportSize.y;
                dy = 1/viewportSize.x;
        }
        float seekWidth = 1 * dx;
        float positionWidth = 1 * dx;
 
        float factor = RMSfactor(input.tc, 2.5 * dy);
 
        float4 c0 = evaluate(backgroundColor, textColor, factor);
        if (shade_played)
                c0 = played(cursorPos, input.tc, c0, factor);
        c0 = bar(cursorPos, input.tc, selectionColor, c0, positionWidth, cursorVisible);
        c0 = bar(seekPos,  input.tc, selectionColor, c0, seekWidth,    seeking      );
        return c0;
}
 
technique10 Render10
{
    pass P0
    {
        SetGeometryShader( 0 );
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}
 
technique Render9
{
    pass
    {
        VertexShader = compile vs_2_0 VS();
        PixelShader = compile ps_2_0 PS();
    }
}

foo_wave_seekbar

Reply #1785
Heh, it's ultimately my fault as I didn't comment nor move the code out into a separate 'unbias' function when writing the original effect.
If all you see as a mortal is a bunch of numbers, it's instinct to twiddle them until it looks neat.
Stay sane, exile.

foo_wave_seekbar

Reply #1786
Thanks Zao and Propheticus for your help. It's much appreciated.

Propheticus, your new code works : it's the tweaked version of your own code, which corresponds to the 2nd codebox among the 3 I provided.
I see the two changes you've made, unless I'm wrong of course ( minmaxrms.rgb -= 0.5 * minmaxrms.a; AND minmaxrms.rgb *= 1.0 + minmaxrms.a; )

I'd like to tweak the 2 other codeboxes I provided, but as they seem to be coded differently that simple change won't work, and as a mere mortal I wouldn't dare mess with such dark magic.
Could somebody please tweak them, so we can have all 3 of them working ?

Thanks again.

foo_wave_seekbar

Reply #1787
I indeed only fixed my own screwup. Here's 1 and 3:
1
Code: [Select]
Texture1D tex : WAVEFORMDATA;
Texture2D seekTex < string filename = "seekbar.png"; >;

SamplerState sTex
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Clamp;
};

struct VS_IN
{
float2 pos : POSITION;
float2 tc : TEXCOORD0;
};

struct PS_IN
{
float4 pos : SV_POSITION;
float2 tc : TEXCOORD0;
};


float4 backgroundColor : BACKGROUNDCOLOR;
float4 highlightColor  : HIGHLIGHTCOLOR;
float4 selectionColor  : SELECTIONCOLOR;
float4 textColor      : TEXTCOLOR;
float cursorPos        : CURSORPOSITION;
bool cursorVisible    : CURSORVISIBLE;
float seekPos          : SEEKPOSITION;
bool seeking          : SEEKING;
float4 replayGain      : REPLAYGAIN; // album gain, track gain, album peak, track peak
float2 viewportSize    : VIEWPORTSIZE;
bool horizontal        : ORIENTATION;
bool shade_played      : SHADEPLAYED;

PS_IN VS( VS_IN input )
{
PS_IN output = (PS_IN)0;

float2 half_pixel = float2(1,-1) / viewportSize;
output.pos = float4(input.pos - half_pixel, 0, 1);
if (horizontal)
output.tc = float2((input.tc.x + 1.0) / 2.0, input.tc.y);
else
output.tc = float2((-input.tc.y + 1.0) / 2.0, input.tc.x);

return output;
}

float4 bar( float pos, float2 tc, float4 fg, float4 bg, float width, bool show )
{
float dist = abs(pos - tc.x);
float4 c = (show && dist < width)
? lerp(fg, bg, smoothstep(0, width, dist))
: bg;
return c;
}

float4 grayscale( float4 color )
{
return color.r * 0.3 + color.g * 0.59 + color.b * 0.11;
}

float4 sepia( float4 color )
{
float4 weight;
weight.r = 0.3;
weight.g = 0.59;
weight.b = 0.11;
weight.a = 0;

float4 adjust;
adjust.r = 0.098039215686275;
adjust.g = -0.050980392156863;
adjust.b = -0.26274509803922;
adjust.a = 0;

float intensity = dot(color, weight);
color = intensity + adjust;
return saturate(color);
}

float4 contrast( float4 color, float strength )
{
return saturate((color - 0.5) * strength + 0.5);
}

float4 played( float pos, float2 tc, float4 fg, float4 bg, float alpha)
{
float4 c = bg;
if (pos > tc.x)
{
#if 0
c = contrast(c, fg.r * 2);
c = lerp(c, sepia( c ), fg.g);
c = lerp(c, grayscale( c ), fg.b);
#else
c = grayscale( c );
//c = sepia( c );
#endif
}
return c;
}

float4 evaluate( float2 tc, float border )
{
// alpha 1 indicates biased texture
float4 minmaxrms = tex.Sample(sTex, tc.x);
//minmaxrms.rgb *= pow(10,(replayGain.g) / 20) * 2; //use track gain
minmaxrms.rgb -= 0.5 * minmaxrms.a;
minmaxrms.rgb *= 1.0 + minmaxrms.a;

float belowWave = tc.y + border - minmaxrms.r;
float aboveWave = tc.y - border - minmaxrms.g;
float factorWave = min(abs(belowWave), abs(aboveWave));
bool insideWave = (belowWave > 0 && aboveWave < 0);

float diffRms = abs(tc.y) - border - minmaxrms.b;
float factorRms = abs(diffRms);
bool insideRms = diffRms < 0;

float factor = insideRms ? (1.0 - 0.5 * saturate(factorRms / border / 2)): 1.0;
factor = insideWave ? (factor * saturate(factorWave / border / 2)) : 0.0;

float4 wave = lerp(backgroundColor, textColor, factor);

return saturate(wave);
}

float4 PS( PS_IN input ) : SV_Target
{
float dx, dy;
if (horizontal)
{
dx = 1/viewportSize.x;
dy = 1/viewportSize.y;
}
else
{
dx = 1/viewportSize.y;
dy = 1/viewportSize.x;
}
float seekWidth = 2.5 * dx;
float positionWidth = 2.5 * dx;

float4 c0 = evaluate(input.tc, 2.5 * dy);
if (shade_played)
c0 = played(cursorPos, input.tc, highlightColor, c0, 0.3);
c0 = bar(cursorPos, input.tc, selectionColor, c0, positionWidth, cursorVisible);
c0 = bar(seekPos,  input.tc, selectionColor, c0, seekWidth,    seeking      );
return c0;
}

technique10 Render10
{
pass P0
{
SetGeometryShader( 0 );
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}

technique Render9
{
pass
{
VertexShader = compile vs_2_0 VS();
PixelShader = compile ps_2_0 PS();
}
}
( c ) without spaces gets replaced by a ©. That's why I added the spaces. @forum: stop screwing with code inside a codebox!

3
Code: [Select]
texture tex : WAVEFORMDATA;

sampler sTex = sampler_state
{
Texture = (tex);
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;

AddressU = Clamp;
};

struct VS_IN
{
float2 pos : POSITION;
float2 tc : TEXCOORD0;
};

struct PS_IN
{
float4 pos : SV_POSITION;
float2 tc : TEXCOORD0;
};


float4 backgroundColor : BACKGROUNDCOLOR;
float4 highlightColor : HIGHLIGHTCOLOR;
float4 selectionColor : SELECTIONCOLOR;
float4 textColor : TEXTCOLOR;
float cursorPos : CURSORPOSITION;
bool cursorVisible : CURSORVISIBLE;
float seekPos : SEEKPOSITION;
bool seeking : SEEKING;
float4 replayGain : REPLAYGAIN; // album gain, track gain, album peak, track peak
float2 viewportSize : VIEWPORTSIZE;
bool horizontal : ORIENTATION;
bool flipped : FLIPPED;
bool shade_played : SHADEPLAYED;

PS_IN VS( VS_IN input )
{
PS_IN output = (PS_IN)0;

float2 half_pixel = float2(1,-1) / viewportSize;
output.pos = float4(input.pos - half_pixel, 0, 1);

if (horizontal)
{
output.tc = float2((input.tc.x + 1.0) / 2.0, input.tc.y);
}
else
{
output.tc = float2((-input.tc.y + 1.0) / 2.0, input.tc.x);
}

if (flipped)
output.tc.x = 1.0 - output.tc.x;

return output;
}

float4 bar( float pos, float2 tc, float4 fg, float4 bg, float width, bool show )
{
float dist = abs(pos - tc.x);
float4 c = (show && dist < width)
? lerp(fg, bg, smoothstep(0, width, dist))
: bg;
return c;
}


float4 evaluate(float4 bg, float4 fg, float factor)
{
return saturate(lerp(bg, fg, factor));
}

float4 played( float pos, float2 tc, float4 bg, float factor)
{
float4 c = bg;
if (pos > tc.x)
{
c = evaluate(backgroundColor, highlightColor, factor);
}
return c;
}

float RMSfactor( float2 tc, float border )
{
float4 minmaxrms = tex1D(sTex, tc.x);

minmaxrms.rgb -= 0.5 * minmaxrms.a;
minmaxrms.rgb *= 1.0 + minmaxrms.a;

float belowWave = tc.y + border - minmaxrms.r;
float aboveWave = tc.y - border - minmaxrms.g;
float factorWave = min(abs(belowWave), abs(aboveWave));
bool insideWave = (belowWave > 0 && aboveWave < 0);

float diffRms = abs(tc.y) - border - minmaxrms.b;
float factorRms = abs(diffRms);

//- - - - - ENABLE/DISABLE THE INSIDE WAVE - - - - - - - -
// [TO DISABLE: bool insideRms = 0;] [TO ENABLE: bool insideRms = diffRms < 0; <<<<<backup original]
//bool insideRms = diffRms < 0;
//bool insideRms = (belowWave > 0 && aboveWave < 0);
bool insideRms = (diffRms > 0 && diffRms < 0);

//- - - - - CHANGES LOOK OF INSIDE WAVE - - - - - - - -
//float factor = insideRms ? ( 1 + 0.2 * saturate(factorRms / border / 2)): 1.0; <<<<<backup original
float factor = insideRms ? ( 6 * saturate(factorRms / border / 20)): 10.0;

//- - - - - CHANGES LOOK OF OUTSIDE WAVE & PANEL BACKGROUND - - - - - - - -
//factor = insideWave ? (factor * saturate(factorWave / border / 1)) : 0.0; <<<<<backup original
factor = insideWave ? (factorRms * 6.0 + 0.8 * saturate(factorWave / border / 0.5)) : 0.0;

//return factor; <<<<<<backup original
return insideWave - saturate(factorWave);
}

float4 PS( PS_IN input ) : SV_Target
{
float dx, dy;
if (horizontal)
{
dx = 1/viewportSize.x;
dy = 1/viewportSize.y;
}
else
{
dx = 1/viewportSize.y;
dy = 1/viewportSize.x;
}
float seekWidth = 2.5 * dx;
float positionWidth = 2.5 * dx;

float factor = RMSfactor(input.tc, 2.5 * dy);

float4 c0 = evaluate(backgroundColor, textColor, factor);
if (shade_played)
c0 = played(cursorPos, input.tc, c0, factor);
c0 = bar(cursorPos, input.tc, selectionColor, c0, positionWidth, cursorVisible);
c0 = bar(seekPos, input.tc, selectionColor, c0, seekWidth, seeking );
return c0;
}

technique10 Render10
{
pass P0
{
SetGeometryShader( 0 );
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}

technique Render9
{
pass
{
VertexShader = compile vs_2_0 VS();
PixelShader = compile ps_2_0 PS();
}
}

foo_wave_seekbar

Reply #1788
BTW Zao, I have a question/request :

Right now Waveform Seekbar works as follows :
- When foobar starts : show nothing
- When a song is selected : show nothing
- When a song is played : show the waveform
- When a song is selected while a song is being played : stick to the waveform of the song that's being played
- When a song is stopped : keep showing the waveform of the song that was played, even if another song was/is selected

Could Waveform Seekbar be modified to function as follows ?
- When foobar starts : show nothing
- When a song is selected : show the waveform (including calculating it if it's not in the database)
- When a song is played : show the waveform
- When a song is selected while a song is being played : stick to the waveform of the song that's being played
- When a song is stopped : show the waveform of the selected song, even if the selected song is not the one that was played

This could be optional of course : there could be a checkbox in the preferences to switch between that mode and the usual mode.

Zao, what do you think ?


foo_wave_seekbar

Reply #1790
wcs13: There's a lot of obvious features that could be implemented with ease if the codebase hadn't been horrible. This is one of those that would be hard as it currently stands, as all information flow is arranged around the currently playing track.

w00w000: I saw you the first few times, and took a look or two at it. That may be somewhere between easy and hard to do, but as it currently stands, I don't trust the code to make a release unless I really have to work around a serious bug. 
Stay sane, exile.

foo_wave_seekbar

Reply #1791
i agree, not urgent, probably can wait another year.
just didn't sure after noreply you care about intuitive improvements or just interesting for being around.
but if need beta testing, feel free to reply my email at 24.11.2012 13:42 GMT. no probs

foo_wave_seekbar

Reply #1792
Zao, I totally understand. The codebase has certainly been horrible and it would need some serious rewriting, since I've read you many times say it since 2010.

Nearly 5 years have passed now since the first version of your wonderful component, so I think that a rewriting would be in order to celebrate them.
I know : you don't have time... I totally get it, since that is also what you've been saying for the last 5 years.
And yet you have managed to find some spare time to get out dozens of new (minor but new) releases for all of us to enjoy.
And of course we all thank you for that.
So maybe it's not really that you don't have time (in 5 years every single soul on Earth has time), but that the task may seem too long/difficult to actually start dealing with it.
And I understand it too, because it's human nature and we would probably all do the same in your position. 

So here's what I suggest : just stop pushing out new minor releases, and start rewriting it once and for all. after 5 years and 72 topic pages, I think such an awesome component really deserves it.
Besides, you'll see that once you have started doing it, it will all look easier than now. A mountain can seem long and difficult to climb, until you've actually started climbing it.
What do you think ? Good idea, right ?...

(please don't kill me  )

foo_wave_seekbar

Reply #1793
Heh, as you can find if you dig hard enough, I've speculated about what a proper remake would entail.

Replacing programmable shaders with something more building-block like for the mortal user; storing of waveforms near the audio files; incremental display of waveforms for streaming audio; display of tracks for non-playing songs; and a service that renders waveforms for other interested components, like playlist or properties.

Lots of fun stuff, and as with everything else, completely soul-draining once you run into limitations of the Windows platform instead of the actual thing you wanted to do.

And yes, the "no time" excuse is indeed wearing thin, but I feel like I've been burned out for half a decade now.
Stay sane, exile.

foo_wave_seekbar

Reply #1794
hey take it easy, no need to rewrite from the ground up or stopped/selected waveform showing, storing waveforms near audio files etc..
ie. i dont store waveforms at all, every track recreated all the time from scratch. it's all rare using situation like showing waveform of streams (and not a "seekbar" job at all).
but when it's paused and stopped and you want to play from some part or again current track showing, it's intuitive to click on a waveform to start play.
instead of seekbar from the box (which i dont have at all) the hand want to double click on a waveform, very logical..
let it make "waveform seekbar" be real advanced 'seekbar', and not just waveform visualization for show. Or next good step to rename it2: foo_waveform_visualisation.dll then..

peace!

foo_wave_seekbar

Reply #1795
Zao, I understand what you mean about Windows platform limitations. And you certainly know that subject much better than us.
Which means that you could easily write down the specs for a rewritten Waveform Seekbar component, and say "this can be done", "this can be done", "uh, this will be tricky because of Windows", etc..
So ultimately you could easily decide which features you should implement or not in the rewritten component.

The rewritten component doesn't have to be perfect and include everything that all of us (including yourself) have been dreaming of for the last 5 years.
But either way it will be so much better than the current Waveform Seekbar (which is already very good) that it will completely justify the rewriting process.
I'm sure you believe it too.

So here's another suggestion : why not start a preliminary thread about the features that you would like to implement in a rewritten component ?
It could be a thread like this foobar2000 thread : http://www.hydrogenaud.io/forums/index.php...st&p=525549
People could contribute with their own ideas, but ultimately you would decide on what should be implemented or not.
Maybe that would motivate you, because let's face it : that's what you need to start working on it, right ?

There are other threads that could/should already have been started. Like a thread for people to share their own waveforms / codes / tips / etc. instead of polluting this thread. It could be a thread like this foobar2000 thread : http://www.hydrogenaud.io/forums/index.php?showtopic=58574 . The same thing could be said about other components like WSH panel component, where it's very difficult to find panel codes since they're buried in that huge thread when they could be nicely displayed in a specific thread, with screenshots, etc... Anyway. 

foo_wave_seekbar

Reply #1796
Back to topic, and to the unbias operation suggested by Zao in page 69 : http://www.hydrogenaud.io/forums/index.php...mp;#entry864358
Basically as Zao (and Propheticus by PM) said, we can take a waveform code in the frontend settings, find the
minmaxrms.rgb -= 0.5 * minmaxrms.a;
minmaxrms.rgb *= 1.0 + minmaxrms.a;


and add this afterwards (if not present already) :
minmaxrms.rgb *= 2.0;
if (replayGain.g != -1000) {
minmaxrms.rgb *= pow(10,(replayGain.g) / 20); //use track gain
} else if (replayGain.r != -1000) {
minmaxrms.rgb *= pow(10,(replayGain.r) / 20); //use album gain
}


We can then play with the overall height by changing the minmaxrms.rgb *= 2.0; value.

However, this is not the result I'd like to achieve, because with this code all the waveform heights remain relative (smaller waveforms remain smaller than the bigger waveforms). I can provide examples if needed.
What I want is that ALL waveforms have the SAME max height inside my component's space (in other words, have them occupy the maximum possible space without clipping).
Can this be achieved, and how ?

Thanks !

foo_wave_seekbar

Reply #1797
There are two semantics you can use. They have the largest sample value in the Y component and the lowest sample value in the X component. Z probably contains the largest RMS value.
CHANNELMAGNITUDE contains the values for the current channel being drawn.
TRACKMAGNITUDE contains the most significant values from all channels.

You can either shift and rescale to fit the window to the range of [X,Y], or rescale to fit the range of [-abs(max(X,Y)),abs(max(X,Y))], give or take some signs.
If you want to promote touching the edge, you should probably not involve RG.
Stay sane, exile.

foo_wave_seekbar

Reply #1798
Thanks Zao. You have understood what I want !
And I totally agree that RG should not be involved, since the purpose here would be "touching the edge" for the largest sample value (be it positive or negative) of every waveform. So I will gladly remove the previous RG code.
I just put it in my previous post for info purposes, since it had suggested previously (by you in this topic and by Propheticus by PM). But like I said it's not what I would like (Propheticus, I hope you understand better now, thank you).

Since I only have one waveform ("mix-down to mono" enabled) I guess I would have to use CHANNELMAGNITUDE and the range of [-abs(max(X,Y)),abs(max(X,Y))] . So far I think I understand.

However like I said previously, I'm not a dev and I'm not familiar with such coding language / dark magic.
So could you or somebody else provide the tiny bit of code necessary to achieve this ? I believe it would be helpful to many others besides me.
It's probably trivial to the point that you haven't bothered writing it, but I really could use that bit of help here. Thank you !

PS : I can report upon success (with screen caps) if somebody's interested.

foo_wave_seekbar

Reply #1799
foosion, that's cool, i will get a look..