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

foo_wave_seekbar

Reply #1400
I just updated to the most recent version of Foobar (from 1.2.3) and then updated wave seekbar along with it.  It was working perfectly before but now it won't load when I try reinstalling it.  I get this:

"Failed to load DLL: foo_wave_seekbar.dll
Reason: This component is missing a required dependency, or was made for different version of foobar2000."

Help, please?

*EDIT*
So right after I posted I thought "maybe I should read the OP in case there's something there."  Turns out there was and I installed the visual studio update.  Guess I should do that first, next time.

Great component, though!  When it wasn't working and I played music with the normal seekbar it felt like something was missing.  Great to have it back.

/edit

foo_wave_seekbar

Reply #1401
Quote
Versions starting from 0.2.35 require the Visual Studio 2012 Update 1 (x86) runtime installed. If you're the kind of person who for some reason cannot run the installer, as a fallback solution you can put in the msvcr110.dll and msvcp110.dll from this download location manually in your PATH or in the foobar2000 application directory. Note that if you put them in the foo_wave_seekbar directory, they will be removed whenever the component is updated.

You're not the first, and will definitely not be the last
Stay sane, exile.

foo_wave_seekbar

Reply #1402
Hello

First of all, thank you for this great plugin. I used it for over a year now and i was always fully satisfied.

But I began to apply the ReplayGain to the MP3s today and now I get very small wave forms.
Is there any way to "add" gain to the wave form?

I hope you understand what I mean.

Thanks in advance

foo_wave_seekbar

Reply #1403
loiparty - what frontend do you use? D3D9? If D3D9 what script do you use? If the one submitted in this thread by derty2, then you have to disable part responsible for applying ReplayGain to waveform. I use default script for D3D9 and all my tracks are RaplayGained and all waveforms are OK. By default, this component don't use ReplayGain and thus waveforms remain untouched, so they shouldn't be small.

EDIT:
@Andreasvb: OMG... I forgot about it... Irreversible mistake. But how he could do this with foobar? I RG'd all my mp3 files and I even don't know how to RG them permanently in other way than reencoding them with Converter - still after sucessful scanning and proper applying RG as tags...

foo_wave_seekbar

Reply #1404
I guess he applied it to the MP3 data itself.
Windows 10 Pro x64 // foobar2000 1.3.10

foo_wave_seekbar

Reply #1405
Tools like MP3gain do a decent work of applying RG by mucking with frame attenuation or something, but I'd expect that the tool would obliterate or recompute actual RG tags if so.

loiparty: Do you have a sample pair of files (of some freely available content) which demonstrate the problem? It's hard to suggest a solution if we don't know what you've done to it and the tags.

I can't say I've ever heard of any temporary or permanent RG adjustment resulting in low amplitudes unless you've manually altered the reference level.
Stay sane, exile.

foo_wave_seekbar

Reply #1406
Hi, thanks for the fast replies.


I altered the mp3 files like that: Right Click on the track (with RG info) -> ReplayGain -> Apply track ReplayGain to MP3 data

I use the newest version of the plugin and D3D with the standard source code.
Im sure there is a simple solution like adding 7dB or so, but i just dont find the method where i have to add it.

To the mp3 in this screenshot i added a RG of -8 dB

foo_wave_seekbar

Reply #1407
Citing the commit for Expose peak information to effect
Quote
The shader semantics "CHANNELMAGNITUDE" and "TRACKMAGNITUDE" are
float4:s representing the amplitude of the current channel and the whole
track.

R is the minimum amplitude, G is the maximum amplitude, B is the highest
RMS value, A is 1.0 if the data is present.

This can be used to rescale the vertical texcoord to display a scaled
and displaced range, ensuring that the edges of the display are
peak-to-peak.

In most effects, add something akin to the following at the top next to
all the other semantics:
float4 chan_mag : CHANNELMAGNITUDE;
float4 track_mag : TRACKMAGNITUDE;


Add something akin to the following in the main PS function:
input.tc.y = (input.tc.y + 1)/2 * (chan_mag.g - chan_mag.r) + chan_mag.r;

This will map the range [-1,1] to [min_peak,max_peak].

Other effects are possible, like a symmetric scale by the largest
absolute value:
input.tc.y = input.tc.y * max(abs(chan_mag.r), abs(chan_mag.g));

This will map the range [-1,1] to [-largest_peak,largest_peak].

This will scale the waveform to fit the window, regardless of the presence of RG values or not in the metadata.
If you want to adapt to replaygain, there's a different set of variables to adjust by.
Stay sane, exile.

foo_wave_seekbar

Reply #1408
Thank you very much

I just found out myself 

New Screenshot

foo_wave_seekbar

Reply #1409
loiparty - so you've made a mistake - you've altered data instead of adding a tag if I'm not wrong...

foo_wave_seekbar

Reply #1410
EpicForever: It's not always a mistake to do gain adjustments on MP3 frames. It's common if you have a portable player that does not understand ReplayGain and beats transcoding the content.

However, if all you use is players that understand ReplayGain, there's not much point in mutating the files themselves as the players can apply the gain on the fly when decoding if instructed to do so.
Stay sane, exile.

foo_wave_seekbar

Reply #1411
What Zao said.

My car radio doesnt understand ReplayGain and I dont want to turn the volume up and down for every song

foo_wave_seekbar

Reply #1412
I'm not quite sure, whether it's related to the new fb2k or the new waveform version, but today I recognized that the seekbar seems to ignore negative replay gain values (or, at least takes only its absolute value). As I'm scaling my waveform by replay gain values, the seekbar appears overscaled. (To be more precise: I'd like to display two waveforms over another, displaying the scaled and the original waveform, as well)

Here's the code of my seekbar.fx file which has worked fine before:

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 faded_bar( float pos, float2 tc, float4 fg, float4 bg, float width, bool show, float vert_from, float vert_to )
{
float dist = abs(pos - tc.x);
float fluff = smoothstep(vert_from, vert_to, abs(tc.y));
float4 c = show
? lerp(fg, bg, max(fluff, smoothstep(0, width, dist)))
: bg;
return c;
}

// #define BORDER_ON_HIGHLIGHT

float4 played( float pos, float2 tc, float4 fg, float4 bg, float alpha)
{
float4 c = bg;
float2 d = 1 / viewportSize;
if (pos > tc.x)
{
#ifdef BORDER_ON_HIGHLIGHT
if (tc.x < d.x || tc.y >= (1 - d.y) || tc.y <= (2 * d.y - 1))
c = selectionColor;
else
#endif
c = lerp(c, fg, saturate(alpha));
}
return c;
}

float4 evaluate( float2 tc )
{
// alpha 1 indicates biased texture
float4 minmaxrms = tex1D(sTex, tc.x);
float4 minmaxrms2 = tex1D(sTex, tc.x);

if (replayGain.g != -1000 && replayGain.g < -2.2)
{
float temp = pow(10,(replayGain.g + 2.2) / 20.0);
minmaxrms.rgb *= temp; //use track gain
        }
if (replayGain.g != -1000 && replayGain.g > -2.2)
{
float temp = pow(10, (replayGain.g + 2.2) / 20.0);
minmaxrms2.rgb *= temp;
}
minmaxrms.rgb -= 0.5 * minmaxrms.a;
minmaxrms2.rgb -= 0.5 * minmaxrms2.a;
minmaxrms.rgb *= 1.0 + minmaxrms.a;
minmaxrms2.rgb *= 1.0 + minmaxrms2.a;
float below = tc.y - minmaxrms.r;
float above = tc.y - minmaxrms.g;
float below2 = tc.y - minmaxrms2.r;
float above2 = tc.y - minmaxrms2.g;
float factor = 1.5*min(abs(below), abs(above));
float factor2 = 1.5*min(abs(below2), abs(above2));
bool outside = (below < 0 || above > 0);
bool outside2 = (below2 < 0 || above2 > 0);
bool inside_rms = abs(tc.y) <= minmaxrms.b;

#if 1
float4 bgColor = backgroundColor;
#else
float a = viewportSize.x / viewportSize.y;
float2 aspect = horizontal ? float2(a, 1) : float2(1/a, 1);
float2 tcBg = float2(tc.x, -tc.y / 2 + 0.5) * aspect;
float4 bgColor = tex2D(sTexBg, tcBg);
#endif

float4 wave = (outside && outside2)
? backgroundColor
: (wave = (!outside2 && outside)
? (replayGain.g < -2.2
? lerp(bgColor, selectionColor, 2.0 * factor2 )
: lerp(bgColor, highlightColor, 3.0 * factor2) )
: (replayGain.g < -2.2
? lerp(bgColor, textColor, 6.0 * factor )
: lerp(bgColor, textColor, 6.0 * factor) )
);
// lerp(bgColor, textColor, 5.0 * factor2);
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 = 1.5 * dx;
float positionWidth = 1.5 * dx;

float4 c0 = evaluate(input.tc);
c0 = bar(cursorPos, input.tc, selectionColor, c0, positionWidth, cursorVisible);
c0 = bar(seekPos,  input.tc, selectionColor, c0, seekWidth,    seeking      );
if (shade_played)
c0 = played(cursorPos, input.tc, highlightColor, c0, 0.3);
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_3_0 PS();
}
}

foo_wave_seekbar

Reply #1413
Same issue for me.
As I'm scaling my waveform by replay gain values, the seekbar appears overscaled.

Only occurred in the latest release.

C.
PC = TAK + LossyWAV  ::  Portable = Opus (130)

foo_wave_seekbar

Reply #1414
The worst thing about being the sole developer on a project is that you don't have anyone else to blame but yourself. 
Should be fixed in 0.2.38, it turns out that I forgot to call the function I had moved the RG update code to.
Stay sane, exile.

foo_wave_seekbar

Reply #1415
The worst thing about being the sole developer on a project is that you don't have anyone else to blame but yourself. 

Zao, get one of these

C.
PC = TAK + LossyWAV  ::  Portable = Opus (130)

foo_wave_seekbar

Reply #1416
The worst thing about being the sole developer on a project is that you don't have anyone else to blame but yourself. 


to be fair, your update didn't kill any kittens and if people are that unhappy, they can always ask for a refund. 

foo_wave_seekbar

Reply #1417
Zao, I have a suggestion, to make sure the database is always up to date, without having to do wholesale re-scans:

Component checks if there's a waveform in database.
1) If yes, it loads it -- then goes to (3)
2) If no, it scans and loads (done).
3) It then scans in background and if there's a difference between old scan and new scan it replaces the old scan with the new and refreshes / loads the new one while playing.

Since this would just be a matter of seconds and small degrees (minor replaygain shift etc..) the change while playing would be minor.
Seems a decent way to keep the DB up to date.

What do you think? Or does it do this already?

C.
PC = TAK + LossyWAV  ::  Portable = Opus (130)

foo_wave_seekbar

Reply #1418
scanning again to check if it's different would be just as much overhead as scanning on every play and not keeping a cache of previous results.

foo_wave_seekbar

Reply #1419
Yes, it would. But I don't think it's really going to stress a modern CPU.
If this was an option, I'd select it. The difference between this and just scanning without a cache is that there's no delay offering up the waveform for pre-scanned tracks.

C.

EDIT: Additionally, because there would already be a waveform to load, the "background check" scan could be super-low priority.
PC = TAK + LossyWAV  ::  Portable = Opus (130)

foo_wave_seekbar

Reply #1420
Zao, I have a suggestion, to make sure the database is always up to date, without having to do wholesale re-scans:

Component checks if there's a waveform in database.
1) If yes, it loads it -- then goes to (3)
2) If no, it scans and loads (done).
3) It then scans in background and if there's a difference between old scan and new scan it replaces the old scan with the new and refreshes / loads the new one while playing.

Since this would just be a matter of seconds and small degrees (minor replaygain shift etc..) the change while playing would be minor.
Seems a decent way to keep the DB up to date.

What do you think? Or does it do this already?

C.

No, it doesn't do this already for many fine reasons.

One would be that I've made the assumption that most people never mutate the audio stream of their music. The analysis scans at full scale, no RG is applied during the process so traditional changes in RG values do not matter. As for people who use MP3Gain-like tools, one'd expect that they'd generate and modify tracks once, as the computed RG for something doesn't really change.

One would be that a scan is not invisible. It has to open and pretty much lock the file for the duration, wreaking all havoc on other plugins and core parts that want to fiddle with the track being played.

One would be that I don't have any way to prioritize tracks outside of the rudimentary and fairly broken method of letting VIP tracks be processed before touching any queued regular tracks. This doesn't extend much at all to multiple tiers of tasks, especially as they're not pre-emptable.

In the end, it's all about weighing the complexity involved (and how hard it will break things implementing it) to the value it adds (off-by-default, only applies to a very odd subset of the community).
Stay sane, exile.

foo_wave_seekbar

Reply #1421
carpman: Do you have some particular use case in mind where you'd have unpredictable and recurring modifications of the underlying audio stream data?
Stay sane, exile.

foo_wave_seekbar

Reply #1422
The worst thing about being the sole developer on a project is that you don't have anyone else to blame but yourself. 
Should be fixed in 0.2.38, it turns out that I forgot to call the function I had moved the RG update code to.


Thank you! Works now as expected.

 

foo_wave_seekbar

Reply #1423
carpman: Do you have some particular use case in mind where you'd have unpredictable and recurring modifications of the underlying audio stream data?
The RG algorithm provides a decent approximation, but I very often have to manually edit the album gain for collections of music (plus occasional edits and repairs). Once edited I have to re-"extract signature". This can happen quite a bit especially if I'm putting stuff together.

This is the point: Unless you keep track of what you've changed and force an "extract signature" at the time of changing it, you have to rescan the whole collection if you want to be sure each waveform is accurate, and that can take quite a while. I'd simply prefer this was done on an ongoing basis.


EDIT:

Perhaps a better way to put it is this:

I have a collection of about 10,000 tracks.
Let's say 2 weeks ago I altered the RG of 5 tracks, but I can't remember which tracks I altered.
That basically means I can't "trust" ANY waveform I see. It's a data integrity issue.

I'm making it sound way more important than it is ... but you see the point?
What I'm suggesting is ....
/EDIT

similar in some ways to the verify integrity of tracks during playback that Peter recently implemented (it's an option, for those that want it).

C.
PC = TAK + LossyWAV  ::  Portable = Opus (130)

foo_wave_seekbar

Reply #1424
I have one good reason to add mechanism proposed by carpman as an "advanced config option": Editing cue sheets. I buy music on Juno and Beatport and sometimes I got tracks like Dinka's "Hotel Summerville" album or Stan Kolev's "Grace Light" album. They contain all tracks mixed together in one file. I have to edit cue sheets manually for them. Before cue sheet is finished I edit split points many times - automatic waveform refreshment would be very useful if it could be enabled just for cue sheet editing session.