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 819752 times) previous topic - next topic
0 Members and 2 Guests are viewing this topic.

Re: foo_wave_seekbar

Reply #2000
I have update the bump map effect to use a fine grained normal estimation. The two functions below demonstrate the old and new approach.
Code: [Select]
float3 getWaveformNormalCoarse(float2 tc, float heightScale) {
float height = evaluateHeight(tc) * heightScale;
return normalize(float3(ddx(height), ddy(height), 1.0));
}

float3 getWaveformNormalFine(float2 tc, float heightScale) {
float dx = 1/viewportSize.x;
float dy = 1/viewportSize.y;
float height = evaluateHeight(tc) * heightScale;
float heightX = evaluateHeight(float2(tc.x + dx, tc.y)) * heightScale;
float heightY = evaluateHeight(float2(tc.x, tc.y + dy)) * heightScale;
return normalize(float3((height - heightX) / dx, (height - heightY) / dy, 1.0));
}

Before: using ddx/ddy

After: using finite differences manually and 3x (horizontal) multisampling

Note that I also changed the light color to make it saturate into white. The code for the multisampling is not shown in the code snippet above.

Re: foo_wave_seekbar

Reply #2001
@Just_Addict

Thanks a lot for your new "prototypes". I've not seen time scales implemented before, indeed interesting. And of course thanks for the set of gimmicks fx you recently published.
Sadly, I simply can't figure out how to get the time axis/scale function integrated in your gimmicks set.
It's not a problem to copy the function itself but to get the return value (c0) evaluated is beyond me.
Hopefully you would be so kind to explain how (or perhaps – if the function is 'mature' – integrate it in the gimmicks set)?
Glad you like it :) that function is indeed part of the next update of the gimmicks set. Which hopefully will get updated this week.

PS. BTW. If anyone uses the scrolling option and found it slightly stuttering. go to
File > Preferences > Advanced > Tools > Waveform seekbar and raise the update percentage. Best to try  in steps of say 5 or 10% until it becomes fluent.

Re: foo_wave_seekbar

Reply #2002
^Ah, good news. I'll keep my clumsy fingers from your code in the meantime. ;D

(Written before your edit)

Re: foo_wave_seekbar

Reply #2003
I improved the previewer slightly
[...]
You probably are aware of this already, the resize cursor doesn't show when hovering the borders (it can resize, it's just the cursor that don't change) and when I minimize to the taskbar it always dies on Win10

Re: foo_wave_seekbar

Reply #2004
Wasn't aware of minimize problem.

sbs-v3 has that fixed, the resize cursor fixed, and (shouldn't matter much now) wall time from program start instead of since system boot.
Stay sane, exile.

Re: foo_wave_seekbar

Reply #2005
cool! Thanks :) but you lost me at 'wall time'?

Re: foo_wave_seekbar

Reply #2006
I think Zao refers to how the value for the REALTIME semantic is computed.

Re: foo_wave_seekbar

Reply #2007
Right, time as counted by a clock mounted on your wall.
Stay sane, exile.

Re: foo_wave_seekbar

Reply #2008
I'm running into an odd situation where component and previewer are disagreeing with each other. In fact they are of opposite opinion.

... how to explain this in short.... images may be the best way...
But first a bit of background. I have a scale function that uses either replaygain scaling or magnitude scaling. Which of the two it uses is controlled by either conditional defines or if both methods end up included, the absence or presence of replaygain info.
In this case the magnitude scaling method is the only one getting used and included. I could post the function but it's a direct copy of your magnitude scaling example so I'm skipping that for the moment.

Now, since magnitude scaling changes the y component of the passed texcoord, I use a copy of the current texcoord to determine where static stuff is involved (e.g. grid, time scale, etc)... and that is also the thing here where the disagreement between component and previewer originates.

on the left, my editor with the previewer below, on the right the component editor with output below.
In both editors the code in question is in the red box. Both editors contain the exact same code (copied straight from external editor to component editor). Originally the first two calls used a dummy texcoord variable because at first I passed the unscaled copy

As you will probably have guessed, this is part of one of your outline functions.

Since the outline function retrieves it's own samples, I needed it to scale those so that minmaxrms values of each would be scaled equally with the one used to draw the regular waveform.  That is, when replaygain scaling is used.  To make it also work with magnitude scaling I originally passed an unscaled texcoord copy, until I realized that I didn't need to and could just pass the properly magnitude-scaled texcoord and be done with it. However, I had forgotten to change the sample_line function to replace the texcoord variable with a dummy in the third call to the scale function

The code in above screenshot is deliberately creating a logic error by re-using the same tc variable to show how component and previewer disagree when using magnitude scaling (where left,mid,right arguments are ignored). Originally I passed in the unscaled copy of the current texcoord and used dummy tc variables in the first two scale calls. In the above screenshot the component perfectly shows the effect of this progressive scaling effect of 3 successive calls with the same variable by sending the top outline skyrocketing and the bottom outline plummeting like a ton of bricks. The previewer however disagrees.

When I corrected the logic error this is what happened in both previewer and component, each next image has one of the tc variables replaced by a dummy variable.
 

As you can see, the previewer scales the outline up/downwards, but the component does the exact reverse, both however place it correctly when all three texcoord variables are replaced with dummies (since the texcoord is already properly before it was passed to the outline function)

If needed I can put it together in a small sample effect, but am reluctant to post flawed code that might start to go floating around.

With all logic errors removed, both previewer and component agree again, but it looks as if the previewer has a misplaced sign somewhere if it reacts in the opposite way...

Re: foo_wave_seekbar

Reply #2009
Congratulations, my head now hurts trying to read that. :)
A lot of the variables I pass into the effect in the previewer are made up and may not align with what the seekbar proper produces, particularly around replaygain and magnitude information.

Track/channel magnitude is just hardcoded to -1 to +1 in the previewer, so that's utterly unreliable.
Stay sane, exile.

Re: foo_wave_seekbar

Reply #2010
haha :) I'm making _your_ head hurt?well, that's a change  :) Usually I'm the one cringing when trying to understand what something does.

Ok :) Well as long as they both react correct without the presence of logic errors it's fine by me.

Re: foo_wave_seekbar

Reply #2011
It's been a while now...  Just wanted to report that everything is working for me using the latest versions.  Thank you Zao and kode54.

Re: foo_wave_seekbar

Reply #2012
I'm back here with the same issue, as it hasn't been resolved last time.

Here's a chilled out, relatively quiet track's waveform generated by your plugin. It's called Roger Sanchez - Morning Prayer:


And here is a track with a heavy bassline called Cirez D - In The Reds:


The waveform generated for a loud track is much worse in terms of readability than the one of a calm track. When the heavy track drops, all you see is a wide rectangle. I know nothing about mathematics, but it seems like a scaling issue. Please fix.

The frontend I'm using:
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;
float3 track_magnitude : TRACKMAGNITUDE;

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( float2 tc, float cursorPos )
{
// alpha 1 indicates biased texture
float4 minmaxrms = tex1D(sTex, tc.x);
minmaxrms.rgb -= 0.5 * minmaxrms.a;
minmaxrms.rgb *= 1.0 + minmaxrms.a;

if (replayGain.g != -1000) {
minmaxrms.rgb *= pow(10,(replayGain.g) / 25) * 1.6; //use track gain
} else if (replayGain.r != -1000) {
minmaxrms.rgb *= pow(10,(replayGain.r) / 25) * 1.6; //use album gain
}

float below = tc.y - minmaxrms.r;
float above = tc.y - minmaxrms.g;
float factor = min(abs(below), abs(above));
bool outside = (below < 0 || above > 0);
bool inside_rms = abs(tc.y) <= minmaxrms.b;
bool played = cursorPos < tc.x;
float4 inside_color = played ? textColor : highlightColor;
float4 bgColor = backgroundColor;


float4 wave = outside
? bgColor
: inside_color
;

return saturate(wave);
}

float4 reflect_evaluate( float2 tc, float cursorPos)
{
float baseline = -1.0/3.0;
float low_unscale = 3.0/2.0;
float high_unscale = 3.0/4.0;
bool mirrored = tc.y < baseline;
if (mirrored) {
tc.y = baseline - tc.y;
tc.y = tc.y * low_unscale;
}
else {
tc.y = tc.y - baseline;
tc.y = tc.y * high_unscale;
}
float mag = max(-track_magnitude.r, track_magnitude.g);
if (mag > 0.95) {
tc.y = lerp(0, mag/0.95, tc.y);
}
float boost = mirrored ? 1.3 : 1.0;
float gradient = lerp(0.7, 1.0, tc.y);
return boost * gradient * evaluate(tc, cursorPos);
}

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.3 * dx;

float4 c0 = reflect_evaluate(input.tc, cursorPos);
c0 = bar(cursorPos, input.tc, selectionColor, c0, positionWidth, cursorVisible);
c0 = bar(seekPos, input.tc, selectionColor, c0, seekWidth, seeking );
return c0;
}

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


Re: foo_wave_seekbar

Reply #2013
It's likely that your track is brickwalled from the source. It takes a single sample at fullscale within a bucket to peg the whole bucket to the boundary.

The only thing in the component that can be limiting is that it ignores content outside of fullscale (-1.0 to +1.0) due to the texture format used, but if your content is that clipped, you're in for a bad time as it hits the output.
Stay sane, exile.

Re: foo_wave_seekbar

Reply #2014
It's likely that your track is brickwalled from the source. It takes a single sample at fullscale within a bucket to peg the whole bucket to the boundary.

The only thing in the component that can be limiting is that it ignores content outside of fullscale (-1.0 to +1.0) due to the texture format used, but if your content is that clipped, you're in for a bad time as it hits the output.
No, every single track that is "loud" looks like this. This is not an issue with a single track. Just see it for yourself please.

Re: foo_wave_seekbar

Reply #2015
My claim wasn't that your particular track was broken. My claim was that if you have tracks that are mostly fullscale, you're going to get a predominantly fullscale result.

As mentioned before, the analysis considers every single sample in the slice to determine the extents. I have considered other functions that consider outliers but do not give them extreme importance, but that relies on unbiased songs with a lot of fiddling for low amplitudes.

If you have a case where it misinterprets source audio beyond what's described, feel free to show this with Audacity and a way to get files that reproduce the problem without searching the net for some random release that may or may not reproduce the problem. I've been down that route when someone reports a bug with some obscure weeaboo track no-one can spell, from any number of sources.

The promise of the component was never to give a "true picture" of the song, as you are asking it to interpret many millions of samples into 2048 slices. If you have a better function to determine "min" and "max" when doing such a drastic reduction that works across all forms of songs, including chiptunes and with slice sizes between a few dozen and few hundred thousand samples, feel free to suggest it.
Stay sane, exile.

Re: foo_wave_seekbar

Reply #2016
Please have a look at the waveform generated by zippyshare for the same heavy track I posted above:


As you can see, it scales properly. I admire your work, but this is a major oversight, the extents calculation seems to be off. If you load it in Audacity, what you need is to discard the dark blue waveform, take the light blue waveform, and stretch it. Same thing goes for tracks that are very quiet. They should have their waveform scaled to fill the space vertically.

Re: foo_wave_seekbar

Reply #2017
As you can see, it scales properly. I admire your work, but this is a major oversight, the extents calculation seems to be off. If you load it in Audacity, what you need is to discard the dark blue waveform, take the light blue waveform, and stretch it.

Zippyshare doesn't "scale properly". It calculates RMS. The light blue waveform in Audacity also displays RMS: http://manual.audacityteam.org/man/audacity_waveform.html --
Quote
The dark blue part of the waveform displays the tallest peak in the area that pixel represents. At default  zoom level Audacity will display many samples within that pixel width, so this pixel represents the value of the loudest sample in the group.
The light blue part of the waveform displays the average RMS (Root Mean Square) value for the same group of samples. This is a rough guide to how loud this area might sound, but there is no way to extract or use this RMS part of the waveform separately.

Same thing goes for tracks that are very quiet. They should have their waveform scaled to fill the space vertically.
Why do you think that it should be scaled? Simply because you prefer it?

Re: foo_wave_seekbar

Reply #2018
Quote
Why do you think that it should be scaled? Simply because you prefer it?
For the sake of visibility. It's a suggestion, don't get all feisty. The plugin could incorporate an option for that. Besides, a guy asked for it before me.

Re: foo_wave_seekbar

Reply #2019




There's two factors to interpreting a song. There's the algorithm that reduces a song down into sequences of min/max/RMS values, and there's the display of that cooked data.

You can alter the display to take things like the maximum song amplitude into consideration, as well as honor ReplayGain information which will help you scale the displayed waveform.

There is nothing I can do centrally to get a song that "fills the space" well, as tastes vary greatly. My defaults are set so that you see the waveform, and if you want something fancier, you have RMS and other measures to customize via effects.

All the three images above are from almost the same base data, the bottom two is from foo_wave_seekbar with the default D3D effect and the soundcloudish one you embedded. The topmost one is from a different visualiser which has a bit harsher detail and a slightly larger supporting dataset.
Stay sane, exile.

Re: foo_wave_seekbar

Reply #2020
One of the major points of the programmable effects in the D3D9 mode is that a user can customize the look and interpretation of the source data if they can squint at shaders and hack around a bit, or get someone that understands shaders to do it for them.

There's so many interpretations and so much vagueness in what you suggest that I cannot come up with an algorithm by myself to capture it all. Checkboxes are not free.
Stay sane, exile.

Re: foo_wave_seekbar

Reply #2021
Ok my friend, it was worth a try. I will use the effect with visible RMS. Great work, maybe consider my thoughts for the v2.

Re: foo_wave_seekbar

Reply #2022
with all due respect but if all of your loud tracks look like that Cirez D track then you've got a load of tracks that are clipped and no amount of coding is going to rectify that.

Simply ignoring the parts that Audacity shows in dark blue is just fooling yourself. You might as well plug both ears with soundproof cotton wool to get the same effect audibly....

PS. The component was never meant as analytical tool. At best you get a representation of what a full blown professional analyzer will display.

Re: foo_wave_seekbar

Reply #2023
Just_Addict: Be optimistic, maybe it's just very dynamically compressed? Looking at the first (minibar) waveform, there's still a wee bit of headroom, not quite clipped. No-one needed those low-order bits anyway.

bpp: You have indeed deduced what I was about to recommend as a concrete solution, use the RMS measure if you want something a bit more representative of the "energy" of the signal, as that's literally what that computes.
Stay sane, exile.

Re: foo_wave_seekbar

Reply #2024
@Zao

Correct me if I am wrong, but from all my experimenting with replaygain scaling I never could get anywhere with (replayGain.g != -1000). And as far as I know, that is no longer a valid check.


EDIT: BTW. Eric Prydz - Cirez D In the Reds according to Audacity.... wouldn't call this very dynamic compressed...