Skip to main content

Topic: foo_wave_seekbar (Read 535476 times) previous topic - next topic

0 Members and 2 Guests are viewing this topic.
  • rokkokko
  • [*]
Re: foo_wave_seekbar
Reply #2050
I've been observing when it happens and I do not see a pattern, but there is a pattern in how it happens. This is the queue after it got stuck the last time:


The tracks on top and bottom are the ones that I played most recently, and the scanning didn't work. The one in the middle, however, is a track that I played about half an hour ago (in a continuous playlist), and its waveform as well as those of the tracks before and after (until the previously mentioned two) were scanned without a problem.

That means that there is a track in the "jobs" table that has already been scanned, which might be the root of the problem. How that happens though, I don't have any idea.

  • Zao
  • [*][*][*][*][*]
  • Developer (Donating)
Re: foo_wave_seekbar
Reply #2051
Jobs are read out from the database on startup, and persisted at shutdown. I'm not sure whether jobs that are "stuck" are collected, it depends on how they've broken the workers.

What kind of format is the first and last song in that list? At least for the first one, it looks like it has no extension.
Zao shang yong zao nong zao rang zao ren zao.
To, early in the morning, use a chisel to build a bathtub makes impatient people hot-tempered.

  • Typhoon859
  • [*][*]
Re: foo_wave_seekbar
Reply #2052
Any possibility it can look ahead for songs being streamed (rather than being played local) to generate the waveform?  That would be really great!  Thanks for all the hard work.

  • rokkokko
  • [*]
Re: foo_wave_seekbar
Reply #2053
Pretty much all of my library is mp3, including these two, the exxtension is just cut off.

  • Zao
  • [*][*][*][*][*]
  • Developer (Donating)
Re: foo_wave_seekbar
Reply #2054
Any possibility it can look ahead for songs being streamed (rather than being played local) to generate the waveform?  That would be really great!  Thanks for all the hard work.
This has been suggested in the past and isn't really possible in the current architecture. The component is designed around tracks that can be opened separately and with fixed duration. The only way to get samples out of a currently playing song would be if I had a DSP or visualisation stream service, which would grab samples as they're produced.

This would be different enough from the current component that it's pretty much a separate UI element all-together.
Zao shang yong zao nong zao rang zao ren zao.
To, early in the morning, use a chisel to build a bathtub makes impatient people hot-tempered.

  • Typhoon859
  • [*][*]
Re: foo_wave_seekbar
Reply #2055
Any possibility it can look ahead for songs being streamed (rather than being played local) to generate the waveform?  That would be really great!  Thanks for all the hard work.
This has been suggested in the past and isn't really possible in the current architecture. The component is designed around tracks that can be opened separately and with fixed duration. The only way to get samples out of a currently playing song would be if I had a DSP or visualisation stream service, which would grab samples as they're produced.

This would be different enough from the current component that it's pretty much a separate UI element all-together.

Ah, I see, so in effect it is possible but not with how it was currently coded.  Alright then, well I appreciate the consideration nonetheless!

  • juniiflow
  • [*][*]
Re: foo_wave_seekbar
Reply #2056
Anyway to extract the settings and colors?

  • Zao
  • [*][*][*][*][*]
  • Developer (Donating)
Re: foo_wave_seekbar
Reply #2057
The settings are stored per-instance in the manner that Default UI and Columns UI prescribes.
You can use whatever functionality they offer to export/clone instances to preserve your settings.

For this reason, I have not bothered to implement explicit import/export as that requires the importing code to be aware of the meddling of mortals in the exported data.
Zao shang yong zao nong zao rang zao ren zao.
To, early in the morning, use a chisel to build a bathtub makes impatient people hot-tempered.

  • Charlatan
  • [*]
Re: foo_wave_seekbar
Reply #2058
Is there any way to export the database as images en masse as JPG or PNG? I've been trying to create waveforms for my music library for a while now to no avail.

  • Zao
  • [*][*][*][*][*]
  • Developer (Donating)
Re: foo_wave_seekbar
Reply #2059
Currently? No.
Technically? Yes.
Will I get around to doing it? Unlikely.

I'd have to figure out how to name the files if generating external names for them. If they're going into tags, I'd have to smack you over the fingers with a ruler, and then figure out what tag to bloat with them.

What kind of use case do you have for this? It's a bit complicated with CUEs and archives and all the other silly formats fb2k can feed me.
Zao shang yong zao nong zao rang zao ren zao.
To, early in the morning, use a chisel to build a bathtub makes impatient people hot-tempered.

  • Charlatan
  • [*]
Re: foo_wave_seekbar
Reply #2060
I'd be giving them the same filenames as the source audio and saving/moving them all to the relevant album folders. It's for use with a program called Rainmeter, mostly for aesthetics but it also means I can keep foobar minimised and still navigate lengthy tracks by their waveforms (which I've done before, but it seems the program I used to generate waveform images last time does not play nicely with Windows 10).

Anyway, I appreciate the reply. It's remarkable that you're still actively supporting this.

  • Zao
  • [*][*][*][*][*]
  • Developer (Donating)
Re: foo_wave_seekbar
Reply #2061
What frontend are you using? It's somewhere between slightly painful and very painful to implement based on the frontend used. I used to have a dev-grade screenshot function implemented, you know. Got rid of it because it required too much customizable UI to be usable by meatbags.

Not saying that I'm going to do anything of this, but you got me thinking about it. Sadly everything is gated by that the current codebase and tech used is a steaming pile of  :-X .
Zao shang yong zao nong zao rang zao ren zao.
To, early in the morning, use a chisel to build a bathtub makes impatient people hot-tempered.

  • Charlatan
  • [*]
Re: foo_wave_seekbar
Reply #2062
(Apologies for the delayed reply. A very busy weekend just concluded.)

I'm using the Direct3D 9.0c frontend. I like to think of myself as a fairly high-tier meatbag, but a meatbag all the same.

Re: foo_wave_seekbar
Reply #2063
Is there anythink can do to make the waveform bigger when the song is very low at volume?

Example: Marker is to big for waveform

  • Last Edit: 26 February, 2017, 07:51:37 PM by foobaraddicted

  • Shinsekai
  • [*][*]
Re: foo_wave_seekbar
Reply #2064
Is there anythink can do to make the waveform bigger when the song is very low at volume?

Example: Marker is to big for waveform
I'm using 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;
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.4; //use track gain
} else if (replayGain.r != -1000) {
minmaxrms.rgb *= pow(10,(replayGain.r) / 25) * 1.4; //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/100.0;
float low_unscale = 3.0/3.7;
float high_unscale = 3.0/3.7;
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.26 : 1.26;
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 = 3.0 * 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();
}
}
Here's another:
https://hydrogenaud.io/index.php/topic,77490.msg920510.html#msg920510

Make sure your files have ReplayGain info.
| TAK pMax | QAAC ~ 192 kbps |

Re: foo_wave_seekbar
Reply #2065
thank you

Re: foo_wave_seekbar
Reply #2066
It works, but now it looks not as smooth as before. Is there some kind of anti aliasing on the default style?

  • evesira
  • [*]
Re: foo_wave_seekbar
Reply #2067
Is there any chance you'd add an option to just completely disregard cache and recompute the waveform on every play?

I'm a music composer/producer, so I make changes to files a lot. In a peak work time I could be editing and playing several different wave files a minute, where the waveform should change significantly and I want to eyeball check that turned out properly. So even though it's quick to go and delete wavecache.db or do rescan all waveforms, that adds up quick.

Processors are fast enough now anyway that I'd rather have it recompute the waveform every time (< 1 second on my machine for a 10 min song) than have to go delete the .db file (10 seconds with voidtools everything search) every time. I've even searched some kind of software or Windows trick to delete that file every time Foobar is run, but alas can't find a clean way to do that.

Of course ideally there'd be some super quick check to see if the file had changed, but I saw you mentioned that a checksum or similar would take just as long as computing the waveform. What about using the Windows "date modified" property?

  • Zao
  • [*][*][*][*][*]
  • Developer (Donating)
Re: foo_wave_seekbar
Reply #2068
I thought I had such a thing already, but it seems like I conflated some other features.

There's an advanced configuration to always refresh waveforms in response to an user-initiated rescan, you might be able to bind a hotkey to that or manually invoke a scan in the context menu with that.

I'm not quite sure how much the display part would cache the old waveform, the whole component is kind of written assuming that tracks are immutable.

foo_wave_minibar has similar attitudes to things, I'm not quite sure which component would be easiest to hack this into.

The problem with testing modification times is that there's a whole bunch of inputs that aren't directly file-based, like CUE sheets. At the moment I don't have to care much at all about the input path given to me, looking at files would mean that I'd have to figure out what the input path actually means and if the input would be deferring to other files.
Zao shang yong zao nong zao rang zao ren zao.
To, early in the morning, use a chisel to build a bathtub makes impatient people hot-tempered.

  • evesira
  • [*]
Re: foo_wave_seekbar
Reply #2069
I thought I had such a thing already, but it seems like I conflated some other features.

There's an advanced configuration to always refresh waveforms in response to an user-initiated rescan, you might be able to bind a hotkey to that or manually invoke a scan in the context menu with that.

I'm not quite sure how much the display part would cache the old waveform, the whole component is kind of written assuming that tracks are immutable.

foo_wave_minibar has similar attitudes to things, I'm not quite sure which component would be easiest to hack this into.

The problem with testing modification times is that there's a whole bunch of inputs that aren't directly file-based, like CUE sheets. At the moment I don't have to care much at all about the input path given to me, looking at files would mean that I'd have to figure out what the input path actually means and if the input would be deferring to other files.

So I tried binding a hotkey to the "Rescan All Waveforms" function, and in my testing it seemed to function just like deleting the wavecache.db file. It doesn't seem to pull any of the old waveform from the cache, and seems to recompute the whole thing. So this will work for me, thank you! I have to press the hotkey to clear the cache then a hotkey to restart the song, but that is still way faster than having to manually delete the file.

I'm not sure what you mean regarding the modification times though. When you say "a whole bunch of inputs", do you mean the info about the file that Foobar is passing you? If so, doesn't Foobar pass you any info like the modification date?

  • Zao
  • [*][*][*][*][*]
  • Developer (Donating)
Re: foo_wave_seekbar
Reply #2070
One such input is standalone CUE sheets. Properties in foobar2000 has a "Last modified" field that only indicates seems to indicate when the CUE sheet was changed, not the file it references.

In the case with a regular boring file track, I may be able to query information from what I think is the file, I cannot tell what input will handle a particular file.

It's nice that you found a workflow that seems to work.
Zao shang yong zao nong zao rang zao ren zao.
To, early in the morning, use a chisel to build a bathtub makes impatient people hot-tempered.

  • evesira
  • [*]
Re: foo_wave_seekbar
Reply #2071
Ah okay, I just don't know enough about this to understand the cue sheet stuff.

But yeah if you looked into doing the file modification date, or some kind of faster checksum-like heuristic, I bet a lot of people would be really appreciative. Hell, even if you just had an option to ignore the cache completely, that would be great. I don't know how your code is set up, but maybe it would even be as simple as skipping out of the code that loads stuff from cache, and going straight to your function to compute the new waveform and then display it etc.

Also props for still supporting an extension you made 7 years ago, and promptly too. Thanks for your help.

  • Zao
  • [*][*][*][*][*]
  • Developer (Donating)
Re: foo_wave_seekbar
Reply #2072
Ooh, ooh, I completely forgot about tags. Tag updates tend to change the file and would ensure that I can't really have a modification test on by default. Checksums of the whole file, even if restricting to single-file inputs, would mismatch even if just things like tags differed.

I would love to implement a mode that would attempt to have as little persistent storage as possible but everything throughout the component is designed to not do anything if the waveform remains the same. Changing those things would be quite risky with regards to component stability.

The unreleased "minibar" is so close but not quite there in this regard, as it has two distinct databases. One on-disk for songs in the media library and one in memory that gets discarded on foobar2000 restart for all other songs. I made some speculative changes to it to see if I could get it to always refresh but even that had a bit of safety code in place.

Sorry to let you down, but there's no half-hour-hack I can do to deliver this :)
Zao shang yong zao nong zao rang zao ren zao.
To, early in the morning, use a chisel to build a bathtub makes impatient people hot-tempered.

Re: foo_wave_seekbar
Reply #2073
Hi guys,

I am a long time user of foobar2000 and the amazing waveform seek-bar plug-in.  I have a quick question, is there any way to scale the horizontal axis, and have the waveform scroll along. Ideally with the current position centred in the display?

I ask as for long tracks 10mins+ the waveform becomes on big block. For example as seen in the Image : The Bucketheads - The Bomb (Original Mix) 14:49s



Apologies if this has already been asked, I am new too the forum. (I did have a good search)

Thanks

Ben

  • Zao
  • [*][*][*][*][*]
  • Developer (Donating)
Re: foo_wave_seekbar
Reply #2074
Mrbencow007: This has indeed been requested in the past and cannot be done in a satisfactory manner with the current design.

The reason for this is that at analysis time I extract the rough shape of the whole song into 2048 bins of min/max/rms data. The longer the song, the more samples cover each bin, and the min/max is more certain to be extreme; this is why your song is a bit more brickwalled than shorter songs.

While you can kind of approximate scrolling by adjusting coordinates in the effect code, the data that it works with is still severely undersampled and would just be the same brickwall, stretched out.

In order to have satisfactory scrolling, you'd have to have a finer subdivision in the analysis step, something which this incarnation of the design cannot do, it has a hard assumption of 2048 datapoints as that was a sweet spot of disk usage vs. typical screen sizes at the time.

This isn't something I aim to change over time either, my minimalistic internal version of the component has the same assumptions but a 4k set of datapoints.
Zao shang yong zao nong zao rang zao ren zao.
To, early in the morning, use a chisel to build a bathtub makes impatient people hot-tempered.