LI7XI / AudioAnalyzerDocs

Documentations for AudioAnalyzer Plugin.
0 stars 0 forks source link

Unclear parts of the documentation #1

Open d-uzlov opened 3 years ago

d-uzlov commented 3 years ago

One issue to discuss everything that's difficult to understand in current version of documentation.

Click to expand >Channels are present in the audio device(?) From .txt: "list of channels that this processing must process ~~of~~ **_if_** they are present in the audio device". I guess I should have paid more attention to typos. Sorry. In case this is still not clear: I wanted to say that `Channels` option specifies all possible channels that this Process can use, but if some of them aren't present in the audio device (for example, 2.0 headphones don't have Center, LFE, Back and side channels) they won't be present in the Process. --- >TargetRate(Optional): Specify the sample rate of the processed audio stream.(?) What are the issues with this option? --- >Todo: "process description" term still not clear "process description" is exactly 4 options: Channels, Handlers, TargetRate and Filter. It wasn't intended to have any more meaning than this. >Specify description of a sound handler.(?) As with "process description", it's just a set of options. --- >UnusedOptionsWarning >Todo: Can it be renamed to LogErrors? also is the syntax correct? It only affects options that the plugin didn't read. Other log messages are not suppressed with `UnusedOptionsWarning`. For example, if you write `Processing-proc2=channels auto | handlers wave | speed fast`, then there will be a log message `Processing proc2: unused options: [speed]`, and `UnusedOptionsWarning=false` will make such log messages to disappear. Intended usage of this option is to clear the log when you, for some strange reason, have some unused options that you don't want to delete. For me this mostly happens when I want to disable some option, but I don't want to delete it. So I can temporarily rename `filter` to `filter1`, and it won't be parsed. --- >Threading >Policy: Specify the way the plugin will work. I don't know what happened here, but `UiThread` and `SeparateThread` are values of option `Policy`, but they are for some reason formatted as separate options. >Means that each process(?) will create its own working thread. No, there will be only one background thread, that will process everything. --- >OnDeviceDisconnected >Device that was being captured is not in exclusive mode(?). "Device that was being captured is ~~not~~ **_now_** in exclusive mode". I'm sorry, I'm very bad at typos. >OnDeviceListChange >Device was disabled or disconnected.(?) >Or disconnected? what's the diffrence between this and OnDeviceDisconnected event? OnDeviceDisconnected is called when the device you are using was disconnected from the plugin. Nothing to do with the device physical disconnection, it's just that plugin can no longer connect to it. In fact, IIRC, OnDeviceDisconnected is only called when the plugin become disconnected from the device. When one device is disconnected but another is available, then plugin seamlessly switches to that second device and only onDeviceChange is called. OnDeviceListChange is called when _any_ device changed. Changes include, for example, when user pulled the headphone jack from the PC. When OnDeviceDisconnected is called, then OnDeviceListChange is also likely to be called, but it's not guaranteed, and it doesn't work the other way around. ---

There are also several notes, that start with "TODO". I'm not sure if these notes are simply for the future or if these notes require some explaining, like above.

d-uzlov commented 3 years ago

Few more from skin-setup page

Click to expand >Todo: Does the handlers arrangement matter? (in performance and output quality). What do you mean by handler arrangement? Order of options doesn't matter. How handlers are chained matters a lot, and this must be a part of discussion on handler chains/trees/graphs, which I have yet to write. --- >So to tell the Child measure which value to read data from, we use an option called ValueID. > >In this option specify which handler to read data from. >It can be any handler, But you should always use the last handler specified in the process description. In our case it would be >MainMapper. It's not that you should "always" use the last handler, it's that in many cases that makes the most sense. However, there are cases when it's useful to take values from other handlers. For example, Loudness example skins use both last and next to last handler values.
LI7XI commented 3 years ago

I'm not sure if these notes are simply for the future or if these notes require some explaining.

To be explained, and rewritten if necessary.

Click to expand! >They won't be present in the Process. Therefore they can't be used? what the plugin will do if unavailable channel was used? is there a fallback? >What are the issues with this option? For the end user (the ones who's going to use the plugin), what does it mean to them? I mean 'the processed audio stream' part, is it correct? >Todo: "process description" term still not clear. I mean, is it more like process setup? like process initialize? and how the process is going to capture audio? I don't know how to explain this and at same time it's not that important, because it will make more sense when reading other options (handler types, etc...). >As with "process description", it's just a set of options. I'll use this to explain handlers in depth in another page. >So I can temporarily rename filter to filter1, and it won't be parsed. That's smart lol, i'll probably add it to Tips section. >I don't know what happened here, but UiThread and SeparateThread are values of option Policy, but they are for some reason formatted as separate options. I thought indenting them will only make visual noise since they are only a part of one parameter (`Policy`). If UiThread is used then SeparateThread and other otions are not used, and vice versa. >No, there will be only one background thread, that will process everything. UiThread or SeparateThread? I was talking about SeparateThread because that's how it's explained. Kinda confusing.😅 >"Device that was being captured is not now in exclusive mode". >I'm sorry, I'm very bad at typos. Don't worry about that, i understand your meaning, but what is exclusive mode? that's what i meant. Should i link it to an article? a wiki page? >OnDeviceDisconnected is called when the device... I'll add this as a note.
LI7XI commented 3 years ago

Few more from skin-setup page.

Click to expand! >What do you mean by handler arrangement? The handlers chain, if ValueTransformer came before TimeResampler or vice versa, will it make any difference in performance or in the output? >How handlers are chained matters a lot, and this must be a part of discussion on handler chains/trees/graphs, which I have yet to write. Sure, also we should point out that first handler of any process must be one of the following types: Loudness, FFT, Peak, RMS, Spectrogram, Waveform Maybe i'll update the examples to contain all possible types, right now RMS type is missing. >It's not that you should "always" use the last handler, it's that in many cases that makes the most sense. >However, there are cases when it's useful to take values from other handlers. For example, Loudness example skins use both last and next to last handler values. I know, i did this in my own skins. But i can't find a good way to explain it. TwT
d-uzlov commented 3 years ago
Click to expand >Therefore they can't be used? what the plugin will do if unavailable channel was used? is there a fallback? When you query anything from the channel that is not available, you will get 0 as a value. Handlers that draw images will draw an empty image one time. Also no error log messages will be generated when you query channel that should be processed, but it is not present in current device channel setup. While if you query channels that aren't present in Processing channel list, then there will be a log message. --- >TargetRate >For the end user (the ones who's going to use the plugin), what does it mean to them? For user this option mostly means that they can shoot themselves in the foot if they change it. I mean, almost nobody needs frequencies above 22 kHz, and almost everybody needs frequencies below 22 kHz, so changing this will only make things worse. But if somebody _really needs_ wider or narrower frequency range, then they can use this option. >I mean 'the processed audio stream' part, is it correct? Well, it depends on how you define "processed audio stream" term. It's about the state of the audio stream before giving the stream to handlers. After _all_ the processing you have the values of handlers, which have almost nothing to do with the sampling rate. Technically, sampling rate change is done before applying filters, but I believe that such small details make absolutely no difference. --- > > Todo: "process description" term still not clear. > > I mean, is it more like process setup? like process initialize? and how the process is going to capture audio? > > I don't know how to explain this and at same time it's not that important, because it will make more sense when reading other options (handler types, etc...). I think that these are very technical details. They could only be helpful if someone were to change the source code. It's description. Like, there are meters' and measures' descriptions in the rainmeter. This plugin has processing and handler descriptions. They have different syntax, but semantically they are the same. As with rainmeter descriptions, they are declarative, not imperative, so it doesn't matter to user how they are handled inside the plugin. --- > > No, there will be only one background thread, that will process everything. > > UiThread or SeparateThread? Rainmeter has the UI thread. Almost everything in rainmeter is done in this thread, and this is not how things should be. UI thread should only be responsible for the UI. I believe that every plugin (at least those that do more complex things than custom "a+b" calculation) should use background threads. When background thread is created, then it's update rate must be specified. By the way, `WarnTime` is used regardless of the `Policy` value. It's only `UpdateRate` that doesn't apply to UI thread because it's rainmeter that manages updates in this thread. --- >Don't worry about that, i understand your meaning, but what is exclusive mode? that's what i meant. Exclusive mode is when some application gets an exclusive ownership of the audio device. When device is in exclusive mode, no other application can connect to device. Exclusive mode is intended to be used by specialized audio applications, to reduce latency. Maybe some of the users will have some applications that will steal the audio device from the plugin, and it won't work, so it's worth mentioning such possibility. But exclusive mode is not related to this plugin in any other way, and using or not using it is up to user to decide. I believe that discussion of when and whether to use exclusive mode should be part of documentation of the programs that use it. >Should i link it to an article? a wiki page? I don't know. Most users probably don't know what it is, so maybe it's a good idea to add a link to some explanation, but I don't know where to. In `OnDeviceDisconnected` this was mentioned because it's a rare callback with mostly defined set of causes. --- >The handlers chain, if ValueTransformer came before TimeResampler or vice versa, will it make any difference in performance or in the output? Well, from my experience, most impact to performance comes from number and size of fft-transforms (controlled by BinWidth and OverlapBoost in FFT handler). Everything else might affect performance but won't make that big of a difference. Though, since TimeResampler produces different amount of data from what it receives, it's probably possible to kill the performance by setting Granularity too low. There will certainly be changes in the output. Speaking of "ValueTransformer vs TimeResampler", TimeResampler applies low-pass filter to values. If there are some non-linear changes in values, then results will be different. Example of this can be seen on "Curve Tester" skin. ---

But i can't find a good way to explain it. TwT

I would say that it almost never makes sense to query raw data from handlers that produce it. Usually raw data is very inconvenient to work with. This mostly applies to FFT results, and intermediate FFT-chain handlers (like BandResampler). Handlers like loudness and peak have transforms option, and ValueTransformer can sometimes be used to transform already useful data, like I did with Loudness example skins.

LI7XI commented 3 years ago
Click to expand >For user this option mostly means that they can shoot themselves in the foot if they change it. >But if somebody really needs wider or narrower frequency range, then they can use this option. I should add more warnings lmao. But why is that? is it because changing the TargetRate causes more CPU usage for no affect on processed audio? --- >Well, it depends on how you define "processed audio stream" term ... almost nothing to do with the sampling rate. I suggest we make another page under plugin structure section, to explain how the audio is processed from the beginning (capturing sound from audio device) to the handlers. Not sure if such thing is necessary since no one might be interested in knowing, so i'll think of this as a future work. For now, i'll brain storm until i find a good way to describe it. The explaining (the one above) is for those who wanna change this option. >I think that these are very technical details. They could only be ... to user how they are handled inside the plugin. I agree, it will make sense to users when they dive into the docs. --- >Rainmeter has the ... be specified. I thought the plugin will create a thread for each process of `Processing=Proc1 | Proc2 | Proc3`. Because in my visualizer, i experimented with making a process for each colored layer. When i used only one process of `type fft` then inherited other bands for each layer from it, CPU usage was low. But when i made a process for each layer (or even on same process but when using fft type in more than one handler) The CPU usage doubles on every layer i add. >By the way, WarnTime is used regardless of the Policy value. It's only UpdateRate that doesn't apply to UI thread because it's rainmeter that manages updates in this thread. I'll fix that! --- >I don't know. Most users probably don't know what it is, so maybe it's a good idea to add a link to some explanation. Actually your explanation was quite comprehensive, i'll just add it to the docs. >but I don't know where to. In OnDeviceDisconnected this was mentioned because it's a rare callback with mostly defined set of causes. Simply there, in `OnDeviceDisconnected` option, i won't try to bring too much attention to it but i'll mention it there. --- >It's probably possible to kill the performance by setting Granularity too low. Actually there is a memory-leak followed by a crash that happens when Granularity is set to invalid value. I mostly do this: Granularity [#UpdateRate], but at some point i forgot and commented out UpdateRate variable, and my laptop (4Gb ram) lagged for solid 20 minutes. Another time when i first experimented this option, i don't remember what i did but similar thing happened. Shouldn't there be a fallback? like if the arg is invalid then log a warning and use a default value. I wanted to create an issue about this, should i? >There will certainly be changes in the output. Last thing, is there a suggested way of how these handlers should be arranged? I mean if someone used `type fft`, then `BandResampler`, what should be next? any other type or specific types would be a better fit? And does this apply to other main types? RMS, Loudness, etc... --- >Like I did with Loudness example skins. Then i'll create an example for this use case, this way users will know that they can do this.
d-uzlov commented 3 years ago
Click to expand > But why is that? is it because changing the TargetRate causes more CPU usage for no affect on processed audio? Increasing TargetRate above 44100 could in some cases significantly increase CPU load without any difference in the result. Even if it would be, like, from 0.5% to 3%, I don't think it's good. Though in case of using images, it could be from 30.5% to 33%, because transferring images through windows filesystem is times more expensive than [my] typical handler setup. Decreasing TargetRate below 44100 will affect results, and it's probably not the result users need. If target rate is 8000, then any sounds above 4000 Hz won't be detected, and why could you need that when your ears clearly hear them? --- > > I think that these are very technical details. They could only be ... to user how they are handled inside the plugin. > > I agree, it will make sense to users when they dive into the docs. It's not only that. The beauty of declarative languages is that it doesn't matter. I could completely change how it works, and it will still work, and probably even without any noticeable changes in performance. Describing such details only makes sense in the context of certain version (well, not even version, certain build) of the application (dll, library, etc.). --- > I thought the plugin will create a thread for each process of `Processing=Proc1 | Proc2 | Proc3`. > Because in my visualizer, i experimented with making a process for each colored layer. > > When i used only one process of `type fft` then inherited other bands for each layer from it, CPU usage was low. > But when i made a process for each layer (or even on same process but when using fft type in more than one handler) The CPU usage doubles on every layer i add. Every processing is handled separately. So if two processings have FFT handler, then FFT will be calculated two times. But it will be done in one thread, one after another. --- > Actually there is a memory-leak followed by a crash that happens when Granularity is set to invalid value. > I mostly do this: Granularity [#UpdateRate], but at some point i forgot and commented out UpdateRate variable, and my laptop (4Gb ram) lagged for solid 20 minutes. > > Another time when i first experimented this option, i don't remember what i did but similar thing happened. > Shouldn't there be a fallback? like if the arg is invalid then log a warning and use a default value. Interesting. I was able to reproduce it, I will look into it. > I wanted to create an issue about this, should i? You can. Well, I already know about it. But it would increase activity in the repository, so why not. --- > Last thing, is there a suggested way of how these handlers should be arranged? > I mean if someone used `type fft`, then `BandResampler`, what should be next? any other type or specific types would be a better fit? > And does this apply to other main types? RMS, Loudness, etc... Well, the bare minimum in my opinion is: FFT → BandResampler → BandCascadeTransformer → ValueTransformer BandCascadeTransformer is not needed when you don't use FFT cascades. Though, I don't see why someone wouldn't want to use them. Value transformer is here because you certainly need at least to transform values to decibels. TimeResampler is needed when you have issues with too many or too few data. Through if something is updating very slowly, then I would argue that you probably have set some option to unnecessary high values, but that's what my plugin is all about: providing good default values and a way to shot yourself in the foot, just to make sure that if someone need something unusual there is a way to do it. It kinda can replace OverlapBoost option from FFT: both don't produce any new data, just interpolate existing data. Though TimeResampler and OverlapBoost work very differently, and I didn't experiment on this. And OverlapBoost should at least be 2, because of window function. Also TimeResampler is very-very much needed when your values are updating too fast. Because in that case you might not notice it visually but you will be loosing some transient data. How could you know that your data is updating too fast? Easy: update rate of FFT can be calculated from it's options (though, if it's just OverlapBoost too high then you should just lower it, but if it's high BinWidth then TimeResampler is the way to go), update rate of Loudness, Peak and RMS handlers are literally its options. Oh, I forgot that TimeResampler also applies low-pass filtering on its values (like attack and decay options from AudioLevel). Previously there were another handler for this, which I now considering as legacy, because in some cases it worked very badly. If you just think that your values are not smooth enough then TimeResampler is the thing you need. It's convenient to use ValueTransformer in the end of any handler chain (of handler tree). Just convenient. Technically you could use ValueTransformer inside your handler chain. For example, if you want to use TimeResampler for low-pass filtering, then values in decibels will be changing _fast_, because while difference between 0.95 and 0.96 is small both in linear and in logarithmic spaces, difference in 0.1 and 0.01 is very small in linear space but gigantic after transformation to decibels. If you don't want that, you could place your ValueTransformer before TimeResampler. Will it be better? No, it will be different. I prefer my values crystal sharp, maybe someone will like them smooth. Kinda the same thing happens with BandResampler. It samples values in linear space, then down in the handler chain this gets transformed into decibels, and transitions seem very different. Though, there is a problem: BandCascadeTransformer was not written to handle decibel values, and it probably won't work properly. But if there weren't such problems, then you could use ValueTransformer before BandResampler to get different results on interpolation. Simple handlers, like loudness, are mostly independent. ValueTransformer is convenient to use when you want to do some transfornations, but all of them have Transform option, so in the simple case you don't need anything additional.
LI7XI commented 3 years ago
Click to expand Notes above will help me a lot to explain certain parts of the docs, i'll consider adding them. Thanks! --- >I don't see why someone wouldn't want to use them. I don't, as far as i know they are used to increase resolution in low frequencies, and since i only use a range between 20 to 110Hz i don't think i need them. >Value transformer is here because you certainly need at least to transform values to decibels. I still don't understand transformation part that well, both in syntax and usage. I need to dig more into that.
Click to expand >TimeResampler is needed when you ... but if it's high BinWidth then TimeResampler is the way to go). Umm, i guess i messed up. It's long topic to explain but i'll do my best. First Check this [video](www.youtube.com/watch?v=1eGaaXooSsk&t=100s) You see these options? i tried to replicate them. So far i succeeded, i used TimeResampler as Audio Offset and that worked. But when it came to the resolution or the quality of the bands, i had to set the BinWidth to something like 3.1, and overlapBoost to something like 60, and i did this for each layer. Why is that? because i want something like Audio Duration, but it's not easy to replicate. You see.. (and this is kinda a feature request) if it's possible to do something like CubicInterpolation slider and my problem would be solved, and i don't need to create a new fft type for each layer to cook my CPU. Something similar can be done using kaiser window function with something like kaiser[2] for layer 1, kaiser[3] for layer 2 and so on. But window function is only available when creating an fft type handler, this is why i create a new process for each layer in first place. Another way is to use UniformBlur, actually this is the key for making the visualizer look exactly like i wanted, but increasing this will remove some resolution, in the sense of: if the beat is so fast it can't be visualized probably. Kinda hard to explain without examples. I thought RadiusAdaptation would do the trick but this doesn't work at all, i don't know why but no matter how much i increase it or decrease it, it doesn't make any change, even when increasing or decreasing UniformBlur Radius, still nothing happens. (Actually i don't understand how RadiusAdaptation works.) So i can't blur values for each layer to make them wider. visualization won't look as good All what i mentioned above doesn't cause too much CPU usage (when testing, the plugin alone for 120 bands uses around 3-4% of CPU), until i started using the "new fft process for each layer" method, the usage doubles on every layer i add, aside from the shape meters i used. If this won't cause you a trouble and you have enough time, could you take a look at it? my skin suit is still WIP but i can upload a copy if needed. P.S This is how my setup looks like: ```ini ; never mind Main and the ones that start with av/sd, they are used to control the zoom effect and meters/measures update rate in idle state. Processing-Main=channels auto | handlers Main, AVresampler, AVmapper, SDmapper, AVFinalOutput, SDFinalOutput, L1Ringsfft, L2Ringsfft, L1Ringsresampler, L2Ringsresampler, L1Ringsmapper, L2Ringsmapper, L1Ringsfilter, L2Ringsfilter, L1RingsFinalOutput, L2RingsFinalOutput | filter none ; ------------------------------------------------------------------------ ; ------------------------------------------------------------------------ Handler-L1Ringsfft=type fft | binWidth [#QualitySteps] | overlapBoost [#OverlapBoost] | cascadesCount 1 | windowFunction kaiser[2] Handler-L2Ringsfft=type fft | binWidth [#QualitySteps] | overlapBoost [#OverlapBoost] | cascadesCount 1 | windowFunction kaiser[3] ; ------------------------------------------------------------------------ Handler-L1Ringsresampler=type BandResampler | source L1Ringsfft | bands linear (90+1) [#FreqMin] [#FreqMax] | cubicInterpolation true | minCascade 0 | maxCascade 0 Handler-L2Ringsresampler=type BandResampler | source L2Ringsfft | bands linear (72+1) [#FreqMin] [#FreqMax] | cubicInterpolation true | minCascade 0 | maxCascade 0 ; ------------------------------------------------------------------------ Handler-L1Ringsmapper=type ValueTransformer | source L1Ringsresampler | transform db map[from ([#MaxDB]) : ([#MinDB])] clamp Handler-L2Ringsmapper=type ValueTransformer | source L2Ringsresampler | transform db map[from ([#MaxDB]) : ([#MinDB])] clamp ; ------------------------------------------------------------------------ Handler-L1Ringsfilter=type TimeResampler | source L1Ringsmapper | attack [#L1RingAttack] | decay [#L1RingDecay] | Granularity ([#ActiveUD]) Handler-L2Ringsfilter=type TimeResampler | source L2Ringsmapper | attack [#L2RingAttack] | decay [#L2RingDecay] | Granularity ([#ActiveUD]) ; ------------------------------------------------------------------------ Handler-L1RingsFinalOutput=type UniformBlur | source L1Ringsfilter | Radius ([#Smoothness]/1) | RadiusAdaptation [#RadiusAdaptation] Handler-L2RingsFinalOutput=type UniformBlur | source L2Ringsfilter | Radius ([#Smoothness]/1.25) | RadiusAdaptation [#RadiusAdaptation] ``` Bands are calculated using lua script, they are lowered in background layers because it helps performance, also they won't be that noticeable.
--- >It's convenient to use ... don't need anything additional. While this is so important in some cases, it can't be summarized in 1 or 2 lines in the docs. So can we suggest a way on how to arrange handlers? Like in fft case, tell users to do: FFT → BandResampler → BandCascadeTransformer → ValueTransformer. Also is it okay to follow this even when removing something (e.g BandCascadeTransformer)?
LI7XI commented 3 years ago

Btw could you check this?

Source=ID id_string Todo: Check examples validity.

d-uzlov commented 3 years ago
Click to expand > I don't, as far as i know they are used to increase resolution in low frequencies, and since i only use a range between 20 to 110Hz i don't think i need them. These are _**the**_ low frequencies. Actually, as low as they get in generic discussions, because humans tend to have very poor hearing below 20-30 Hz, so in many places frequencies below 20 Hz aren't even considered theoretically usable despite some people hearing them. You example is probably the case where you could lower `TargetRate` because you don't need the standard frequencies, but FFT that draws anything detailed below 100 Hz will still update very rarely. Though, if your main use case is to use very few bands, like below 10, then yeah, you don't need detailed information, so you could make FFT update at high rate without loosing on visible quality, and then you don't really need FFT cascades. >It's long topic to explain but i'll do my best. I will look into it later. In the meantime, create an issue for it. I don't know yet, but this seems like something that can't be discussed in a few phrases, so it would be better to have it in a separate thread. Also, include in that issue some picture comparison of how it should look and how it looks right now, please. It's hard to me to understand what is wrong in your case by just verbal description. > While this is so important in some cases, it can't be summarized in 1 or 2 lines in the docs. > So can we suggest a way on how to arrange handlers? > > Like in fft case, tell users to do: FFT → BandResampler → BandCascadeTransformer → ValueTransformer. > Also is it okay to follow this even when removing something (e.g BandCascadeTransformer)? BandCascadeTransformer does literally nothing except uniting cascades. You don't need it when cascades aren't used. But if cascades are used, then this handler is required: without it only the first (the fastest and simultaneously the least detailed cascade) would be shown in spectogram or in spectrum skins. Peak, RMS and Loudness are independent, they don't really need other handlers unless you wan't to do something specific. The only thing that is almost always needed is to transform to decibels (and maybe mapping to range [0, 1] because rainmeter meters work best when values are in this range), and in these handlers that can be done with their transform option. > Btw could you check this? > > > Source=ID id_string > > Todo: Check examples validity. 1. You are missing a colon after "ID". 2. In the current last available build of the plugin specifying certain device doesn't work. I have already fixed it but I didn't release a new version of the plugin since then. Actually, I didn't expect that someone would use current version because I didn't announce its release anywhere.
LI7XI commented 3 years ago
Click to expand >These are the low frequencies. I'm laughing so hard right now lmao, i thought it's the opposite. Does it mean now i should use BandCascadeTransformer? >You example is probably the case where you could lower TargetRate because you don't need the standard frequencies. How much is lower? 12000 or 8000? >Though, if your main use case is to use very few bands, like below 10 I use around 90 to 150 bands. when using high bands count like 150 or 180 then i see there is a noticeable delay, to avoid it i either increase the BinWidth or the OverlapBoost, most of the time increasing BinWidth tend to be more effective. >please. It's hard to me to understand what is wrong in your case by just verbal description. Sure! I'll prepare them then create that issue. >BandCascadeTransformer ... or in spectrum skins. The very last thing, what is a cascade? as in audio terms. >You are missing a colon after "ID". `Source=ID; 5f23ab69-6181-4f4a-81a4-45414013aac8` ? >In the current last available build of the plugin specifying certain device doesn't work. I have already fixed it but I didn't release a new version of the plugin since then. Actually, I didn't expect that someone would use current version because I didn't announce its release anywhere. How does this compare to the current docs? And i found your plugin while scrolling through plugins section in the forum. When you announced version 1.0 and 1.1
LI7XI commented 3 years ago

And UnusedOptionsWarning=false will make such log messages to disappear.

What kind of messages will still be logged even when UnusedOptionsWarning=false ?

LI7XI commented 3 years ago

Btw is it okay to compare some options to AudioLevel? that way it would be easier to explain.

d-uzlov commented 3 years ago
Click to expand > I'm laughing so hard right now lmao, i thought it's the opposite. > Does it mean now i should use BandCascadeTransformer? Mm. Probably? I don't know. FFT cascades will give you fast response in low frequencies while retaining detailed picture with delayed data. It won't really update the fine details any faster, but rough details will show almost immediately. > How much is lower? 12000 or 8000? Generally speaking, to retain all the information about frequencies from 0 to F, it's necessary and sufficient to have sampling rate 2×F. However, due to the need to limit the frequencies before resampling and the lack of an ideal solution to this problem, there will be some distortion near Nyquist frequency (the F I mentioned above, or the half of the sampling rate), so it's better to leave some slack. How much? I dunno, noticeable distortion starts at about 0.95×F, so it _should_ be safe to set TargetRate to 2×F/0.9. So if you are only interested in frequencies 20-110, then TargetRate about 244 should be okay. But don't use it blindly, test it. > I use around 90 to 150 bands. when using high bands count like 150 or 180 then i see there is a noticeable delay, to avoid it i either increase the BinWidth or the OverlapBoost, most of the time increasing BinWidth tend to be more effective. Increasing BinWidth gives you natural increase in update speed but you are loosing details. So, more throughput, less latency. OverlapBoost just adds interpolation to the results. You get more throughput, but the latency stays the same, which might be an issue. >The very last thing, what is a cascade? as in audio terms. There is no such audio term :P It's something that's made up by me. I haven't really seen it discussed anywhere. I believe I have seen some notes about something similar, but I don't remember seeing any detailed description of anything like this. So. In the plugin one cascade is a result of processing audio wave with _some_ sampling rate. Next cascade is the same, but with sampling rate cut in half. This means that this next cascade will update 2x slower but will have 2x more details in low frequencies after FFT. Because the first cascade updates relatively fast, the final data can also update relatively fast. However, this "fast" data doesn't have much details in low frequencies, so it must me combined with "slower" data from further cascades. BandCascadeTransformer takes data from all cascades and unites them in _some_ way. There is no "right" way to do this, only many "wrong" ways with varying results. Maybe the word "cascade" is not suitable here, but I didn't come up with anything better. > > You are missing a colon after "ID". > > `Source=ID; 5f23ab69-6181-4f4a-81a4-45414013aac8` ? 1. Colon, as in `:`, not a semicolon. 2. Device IDs are opaque. There is no syntax for it, it's just a string that you can get from the system. If you modify it in any way, it won't be a device ID anymore. It's not a requirement of my plugin, it's a requirement of Windows. That's why I wrote that id_string **_must_** be obtained from section variables using LUA. In the section variables there is a well-defined place where you can get device ID string. On my system device ID right now looks like this: `{0.0.0.00000000}.{134d7830-179e-4748-9861-37967e8bda9e}` It doesn't mean that on your system it will look the same, or that it can't change with a single windows update. So, for me valid option syntax is something like this: `Source=ID: {0.0.0.00000000}.{134d7830-179e-4748-9861-37967e8bda9e}` P.S. Though, it's very unlikely to change. It's just that Windows API gives no guarantees. > How does this compare to the current docs? IIRC, if the syntax is not as in documentation, you will get a log warning, and if the syntax is right, then it would be like there is no such device — as if you didn't connect your headphones, because the plugin messed up the ID string while reading it. > What kind of messages will still be logged even when `UnusedOptionsWarning=false` ? Um, _everything_ else? There are probably many dozens, if not hundreds, of log messages, and all of them are not affected by this option. Examples: many independent issues with Windows audio system API, unknown values of options, invalid values of options, there are zero audio devices in the system, current device is unavailable, etc. This list is not exhaustive, of course. You can write something incorrectly and look at the log window for concrete examples. >Btw is it okay to compare some options to AudioLevel? that way it would be easier to explain. Sure.
d-uzlov commented 3 years ago

Maybe i'll update the examples to contain all possible types, right now RMS type is missing.

Oh, by the way, I didn't have any example for RMS because it's kinda useless for me. In AudioLevel plugin RMS is used to measure loudness, but AudioAnalyzer now have a dedicated Loudness handler, that, IMO, works much better, than RMS. But since Loudness handler is not an RMS, and someone could potentially need exactly RMS, I didn't remove it from documentation. But RMS has no intended uses, it's just there for people who know what they are doing.

LI7XI commented 3 years ago

Oh, by the way, I didn't have any ... they are doing.

After i add it to the docs, should i label it as deprecated?

d-uzlov commented 3 years ago

After i add it to the docs, should i label it as deprecated?

I don't know. There is nothing wrong with it (unlike the things that I have marked deprecated and removed from documentation), it's just it's not the best choice for a loudness meter, and I don't know if it has some good applications.

LI7XI commented 3 years ago
Click to expand >FFT cascades will give you fast response in low frequencies while retaining detailed picture with delayed data. It won't really update the fine details any faster, but rough details will show almost immediately. That's great, i should give it a try. >Increasing BinWidth gives you natural increase in update speed but you are loosing details. I don't know if i was clear or not but with increasing BinWidth i meant the resolution, the smaller the BinWidth is the more res you get, that's what i meant. >which might be an issue. Nope it's fine, since i got the look i want, just wanted it to look smoother. >Maybe the word "cascade" is not suitable here, but I didn't come up with anything better. I got the idea, a similar explanation would be.. cascades are frames of processed values, and these values are calculated the way you explained above. Correct? QwQ >Colon, as in :, not a semicolon. Sorry, i'm used to code javascript lol. >So, for me valid option syntax is something like this: Source=ID: {0.0.0.00000000}.{134d7830-179e-4748-9861-37967e8bda9e} I needed this example to add to the docs. Next i'll show them how to generate this using section vars, and provide them a code in tips and code snippets discussion. >IIRC, if the syntax is not as in documentation, you will get a log warning, and if the syntax is right, then it would be like there is no such device — as if you didn't connect your headphones, because the plugin messed up the ID string while reading it. I'll test it out before writing. >You can write something incorrectly and look at the log window for concrete examples. Or just in short, this option will hide the errors generated only by doing this: `Processing-ProcessName=channels auto | handlers wave | speed fast` Or this: `SomeUndocumentedOption=Something` ? >it's just it's not the best choice for a loudness meter, and I don't know if it has some good applications. I'll mention that it's preferred to use Loudness meter. Since it has almost everything RMS provides.
d-uzlov commented 3 years ago

I got the idea, a similar explanation would be.. cascades are frames of processed values, and these values are calculated the way you explained above. Correct? QwQ

Yeah, something like this.

Or just in short, this option will hide the errors generated only by doing this: Processing-ProcessName=channels auto | handlers wave | speed fast Or this: SomeUndocumentedOption=Something ?

I would love to be able to also catch unknown options on the global rainmeter lever, but rainmeter API doesn't have a way to enumerate all options in a measure, so things like SomeUndocumentedOption=Something aren't accessible to plugins.

LI7XI commented 3 years ago

I would love to be able to also catch unknown options on the global rainmeter lever, but rainmeter API doesn't have a way to enumerate all options in a measure, so things like SomeUndocumentedOption=Something aren't accessible to plugins.

Oh, so for now that option only hides Processing-ProcessName=channels auto | handlers wave | speed fast errors?

d-uzlov commented 3 years ago
> Oh, so for now that option only hides `Processing-ProcessName=channels auto | handlers wave | speed fast` errors? Yes. --- > > Processing-ProcessName > > and handlers that draw images will draw an empty image for one time then stop updating. "Stop updating until this channel is available (can happen if your audio device settings change, of when plugin connects to another device)". Without this notice it looks like they will be dead forever. > Add possible channels list. If this is a question for me, then list of available channel values is at the end of "03. Syntax.txt" file. --- > Even a small increase, like from 0.5% to 3%, I don't think it's good. I don't know if I should point out grammar mistakes in this issue, but you are missing a verb in the first part if the sentence. Also, "KHz" is conventionally written as kHz. SI prefixes are sometimes strange. --- > Threading By the way, I still insist that `UpdateRate` and `WarnTime` are options of `Threading`, and not values of `Policy` option. The way it is written looks confusing, because description doesn't match real syntax. --- > > OnDeviceDisconnected > > Attempt to connect to this device ended with some unknown error. Plugin was disconnected for unknown reason. If connection didn't happen in the first place, OnDeviceDisconnected won't be called. Also > You are capturing data from default device, then onDeviceDisconnected is called when all devices has been disconnected, so there is no default device anymore. It's probably better to rewrite it, now it is hard to read. Maybe something like "Plugin was capturing a default device, and all devices of that type became unavailable". --- > > OnDeviceListChange > > In fact, if i remember correctly, Interesting wording for a documentation :P You may delete this, I checked the sources and this seems to be true.
d-uzlov commented 3 years ago

For the Child measure page

>Getting processed audio data and return it as a ranged number (e.g from 0 to 1) to be used in your skin. I believe that there should either be "Getting processed audio data and return it as a number **_without limited range_** to be used in your skin" or the word "range" should not appear here. Now it sounds like it's impossible to get numbers without limits. Also, it would be better to say, that Child measure can be used for "Providing access to values of handlers in Parent measure", because it's unclear where it returns data to. From the user perspective measure itself doesn't return data, it provides data. --- >>Processing > >But you have to specify it only if parent measure has several processings with same handler, so that HandlerName doesn't uniquely identify the handler(?, after the 'so that' part). What are the issues with this? Wording is a bit awkward, because you added "but" without modifying the rest of the sentence, but the example below that phrase perfectly illustrates "after the 'so that' part". >This will make sense when we explain ValueID option. There is no `ValueID` option in the current version of the plugin. Well, at least it's not documented. --- >An example of a value index would be a band in handler of type fft. A bit of pickiness. You can say either "a bin from FFT" or "a band from BandResampler" or from BandCascadeTransformer. Words 'bin' and 'band' are only applicable in certain cases. Generally, without the context where the data is from, an index is just an index. Though, if you have chain "FFT→BandResampler→ValueTransformer", then you know ValueTransformer transforms data that originated from BandResampler so you can say that you are indexing bands. >Is this option always avaliable in every child measure? What if ValueID was set to Loudness handler type, and this option was set to other than 0? will the child still retrieve values? If index is out of range then measure will get 0.0 as a value. For handlers with a single value any index except for 0 will be out of range. --- > >Transform > >; Lets say you are getting a value in range [0 to 1] from a handler >Transform=map[0, 100] clamp >; Will convert it to range from 0 to 100 No, this will convert to range from 0 to 100 and then clamp the values to range from 0 to 1. So most values will likely become 1. >Does this option follows the same syntax as the one in ValueTransformer handler type? Yes. >Is the syntax correct? ~~Syntax is _correct_ (in the sense that this is a valid transformation description) but, as I said few lines above, it doesn't do what you wanted it to.~~ After second reading, syntax is not quite correct. Also, apparently I can't read and/or think. Sorry. But let's continue this discussion later. >or we should discuss that after writing transformation docs? Yeah, probably after this. --- >>StringValue > >; (?, is explanation correct?) Yeah, kinda correct. In fact, when StringValue is Number, then plugin tells rainmeter "I don't have a string value", and rainmeter uses number as a string value. But it's a technical detail, for user there is no difference. >What if both of StringValue=String and ValueID=HandlerName was specified? Well, nothing unusual will happen. Child measure always have some number value (if valid options are specified, then it will get it from a handler, otherwise it will be zero). Child measure always have some string value (either value duplicating the number value or some real string). See [rainmeter docs](https://docs.rainmeter.net/manual/variables/section-variables/#Colon) to learn about number and string variables if measures.
LI7XI commented 3 years ago
Click to expand! >Stop updating until this channel is available. Added and committed. >(can happen if your audio device settings change, of when plugin connects to another device)". What is "can happen"? and will it happen in regular Rainmeter update cycle? I mean, if the plugin reconnected to that device, everything will go back to normal? without skin refresh? >Without this notice it looks like they will be dead forever. Which notice? a message in logs? --- >If this is a question for me, then list of available channel values is at the end of "03. Syntax.txt" file. It was a Todo, already committed. :) --- >I don't know if I should point out grammar mistakes in this issue, but you are missing a verb in the first part if the sentence. Tbh this slows me down a lot when writing, there is an extension that checks for spell errors in vscode, but it does that for the whole document, not just raw text, so all the examples will have red underline which is a bit annoying. The plan was after i finish writing, i start rechecking every page, for spell mistakes, missing links, etc.. Btw, if possible, can i add you as a project member? just to correct minor mistakes, and i'll take care of actual writing. --- >By the way, I still insist that UpdateRate and WarnTime are options of Threading, and not values of Policy option. The way it is written looks confusing, because description doesn't match real syntax. I know i know, i forgot to correct this. P.S Done. --- >Maybe something like "Plugin was capturing a default device, and all devices of that type became unavailable". Done. Although it's still not clear for me, but gives enough insight to know the issue. --- >Interesting wording for a documentation :P >You may delete this, I checked the sources and this seems to be true. Done. I thought the word "Recall" is not as common as "Remember" lol.
LI7XI commented 3 years ago

For the Child measure page

Still WIP, i'll look into this soon.

LI7XI commented 3 years ago

By the way, I still insist that UpdateRate and WarnTime are options of Threading, and not values of Policy option. The way it is written looks confusing, because description doesn't match real syntax.

But UpdateRate can't be used without SeparateThread parameter, that's why i left them in same place.

d-uzlov commented 3 years ago

What is "can happen"? and will it happen in regular Rainmeter update cycle? I mean, if the plugin reconnected to that device, everything will go back to normal? without skin refresh?

In the current version of the plugin this happens automatically when possible. No skin refresh required. Else there wouldn't be these callbacks.

Which notice? a message in logs?

I meant notice in the documentations, the one I suggested to add.

Btw, if possible, can i add you as a project member? just to correct minor mistakes, and i'll take care of actual writing.

Yeah, sure. Though I wouldn't rely on myself to find all mistakes.

Although it's still not clear for me, but gives enough insight to know the issue.

Well, if you have speakers and headphones, and you have set Source=defaultoutput, then if you pull the headphone jack from the PC, the plugin will automatically connect to speakers. But you you then also pull speakers jack, there will be no audio devices available, and onDeviceDisconnected will be called.

But UpdateRate can't be used without SeparateThread parameter, that's why i left them in same place.

There are a lot of options that are not compatible with each other (although most of them are deprecated so they aren't in the documentation). It doesn't mean that some values for these options should be considered independent options. I believe that having a warning about UpdateRate not having an effect is enough. Also, I would not say that "nothing matters unless Policy is set to SeparateThread". I would say that "if Policy is set to UiThread then UpdateRate (only specifically UpdateRate) doesn't matter, because it is controlled by rainmeter".

The main issue fro me is that syntactically there are options and there are value. Documentation is there to tell the user that he should write Policy <value for policy> | UpdateRate <value for update rate>, and not Policy UpdateRate (but now according to indentation this is a valid value for Threading option).

LI7XI commented 3 years ago

I meant notice in the documentations, the one I suggested to add.

Oh, a notice in logs window, got it.

Though I wouldn't rely on myself to find all mistakes.

It's my job to find these, you are a reviewer. \( ̄︶ ̄\)

Well, if you have ... will be called.

Added as an example and committed.

But now according to indentation this is a valid value for Threading option.

That's a horrible error lol, definitely not what i meant.

I fixed them in this commit.

LI7XI commented 3 years ago

For the Child measure page.

Click to expand! >Now it sounds like it's impossible to get numbers without limits. Removed. But the transformations actually do this, i mean when you clamp values in range [0, 1] or [0, something]. P.S We will wait transformations docs before discussing this. >Also, it would be better to say, that Child measure can be used for "Providing access to values of handlers in Parent measure", because it's unclear where it returns data to. From the user perspective measure itself doesn't return data, it provides data. Yeah, i think the word "return" is more like a technical term. --- >Wording is a bit awkward, because you added "but" without modifying the rest of the sentence, but the example below that phrase perfectly illustrates "after the 'so that' part". I changed it a bit and removed "so that HandlerName doesn't uniquely identify the handler(?, after the 'so that' part).". Since examples explained it perfectly. >There is no ValueID option in the current version of the plugin. Well, at least it's not documented. Yeah i didn't find docs for it, although it's still working. Since it's deprecated i better not mention it in first place, i'll update the examples in the skin setup page. --- >If index is out of range then measure will get 0.0 as a value. For handlers with a single value any index except for 0 will be out of range. I added examples. Btw, in future, can you make this something like, if `HandlerName=ThisHandlerTypeDoesNotProvideIndexing` then automatically ignore the `Index` option and set it to 0? --- >See rainmeter docs to learn about number and string variables if measures. I never used section variables except when using Lua scripts inside the skin. So i'm planning to document Section Variables discussion first, and experiment with it before finishing `StringValue` and `InfoRequest` options. That way i can write with confidence when making examples about it.
d-uzlov commented 3 years ago

There is no ValueID option in the current version of the plugin. Well, at least it's not documented.

Yeah i didn't find docs for it, although it's still working.

It's not really deprecated, it's just renamed to HandlerName. If HandlerName option is empty, then ValueID is used, to keep compatibility with old skins.

Btw, in future, can you make this something like, if HandlerName=ThisHandlerTypeDoesNotProvideIndexing then automatically ignore the Index option and set it to 0?

Yeah, why not.

I never used section variables except when using Lua scripts inside the skin.

As far as I know, in some places in the rainmeter different values of measures are used. Like, Calc measure uses number value when using its inner syntax for formulas. Most meters also use number value. Generally speaking, I suspect that most rainmeter users don't know that number value and string value are separate, and one measure can have both. Most people just write [&MeasureName] for everything. That's why there is a StringValue=Number option, to allow people to use numbers with without a deep dive into rainmeter section variables system.

LI7XI commented 3 years ago

That's why there is a StringValue=Number option, to allow people to use numbers with a deep dive into rainmeter section variables system.

StringValue=Number Will make this Child measure provide the retrieved String value of handler as a Numerical value.

Correct? If yes, i feel like that sentence is a bit long and takes time to understand.

d-uzlov commented 3 years ago

Correct? If yes, i feel like that sentence is a bit long and takes time to understand.

Not quite.

the retrieved String value of handler

Generally handlers only have numeric values in the first place. The only "string values" you can get from handlers are from section variables. Maybe it would be better to say by default string value is a number, and that StringValue=Info replaces that number with a result of section variable resolve.

LI7XI commented 3 years ago

Maybe it would be better to say by default string value is a number, and that StringValue=Info replaces that number with a result of section variable resolve.

Hmm.. Is it necessary to mention it in first place? I thought it's important so i added it. But since it doesn't make a difference for the users then we can remove it all together. And we can find a simpler phrase for Number parameter.


Btw can you check Child measure page? i finished documenting it. Except transformations, StringValue and InfoRequest options.

d-uzlov commented 3 years ago

This will make sense when we explain HandlerName option.

Maybe we should rearrange options, so that HandlerName is before Processing option. I think for the reader it would make more sense to have a reference to something they have already read than to something in the future.


Note that Child measure can only listen to one Channel at a time. Not documented, is it correct?

Yeah, things like Channel=FL, Right are not allowed.


HandlerName option used to be called ValueID. It's preferred to use HandlerName Since ValueID is kept just for compatibility with old skins.

I'm not sure if it's worth writing about deprecated options. If someone creates a skin, I think it would be better to only use "modern" options. But I don't have a strong options about this, choose what you like.


An example of a value index would be: ... ...

I don't think these are good examples. First of all, for me it was just a little bit hard to read, and also by separating indices on bin and band values it kinda implies (though not really) that other handlers don't have indices.

I would write something like this:

Many handlers produce arrays of data, and the Index option specifies the index of value in that array. For example: Generally, only handlers that transform data from FFT produce arrays of data (Like, if you have handler chain FFT → BandResampler → ValueTransformer → TimeResampler, then all four of these will make data arrays). Independent handlers (like Loudness) usually produce only one value, so any index except for 0 will be invalid.

P.S. It's not not directly related, but it's better to try not to use examples with directly getting data from FFT, because its size is dynamic, so anything that gets data from an FFT handler will be unreliable.

LI7XI commented 3 years ago

Maybe we should rearrange options, so that HandlerName is before Processing option. I think for the reader it would make more sense to have a reference to something they have already read than to something in the future.

~On the other hand this might be confusing, all of a sudden HandlerName option comes out without knowing how it...~ After thinking, you are right. But to be honest i don't know how to link them together this way, a rewrite is needed.


But I don't have a strong options about this, choose what you like.

There was a reason why i mentioned it, but i forgot it lol. I removed it for less visual noise.


P.S. It's not not directly related, but it's better to try not to use examples with directly getting data from FFT, because its size is dynamic, so anything that gets data from an FFT handler will be unreliable.

I removed old examples and used yours.

LI7XI commented 3 years ago

Now Child measure page (except transformations) is completed. Only few checks are needed for StringValue and InfoRequest options.

d-uzlov commented 3 years ago

i don't know how to link them together this way, a rewrite is needed.

I suggest the following: Place Processing right after HandlerHame, so that they are linked by placing on the page.

Processing

Name of the process to get data from. (!)this option is optional Child measure gets data from specific handler. Usually it's enough to specify HandlerHame option to find a handler. However, it's allowed to have one handler description be used in several processes. In such case each of the processes will have its own copy of such handler, so to HandlerHame alone is ambiguous. Processing option allows to resolve this ambiguity. ! here goes example

On the other hand... I'm thinking if I should specifically forbid using the same handler in several processings, just to make it less confusing to the user. It's not that useful after all.

d-uzlov commented 3 years ago

StringValue

Number: Will make this Child measure provide the retrieved String values of handler as a numerical value.(Correct?)

You make it sound like it will use section variable value (from InfoRequest) as a number value. Actually, that's an interesting idea, but that's not true for current version of the plugin and that's probably not what you wanted to say. I would rephrase it as "String value of the measure will match its number value" or "Measure won't have a separate string value".

Example ; Will make this Child measure provide the following: Realtek High Definition Audio

I think we should make clear that this is an example

… provide the name of current audio device, for example: Realtek High Definition Audio


Example

Variable=[InfosMeasure] ; Makes the value of that variable the name of the current Audio Device. ; As example: Realtek High Definition Audio

Though it will work as you explained, this is technically not correct. In rainmeter variable don't resolve its values. So if you write Variable=[InfosMeasure] then the value of the variable will be [InfosMeasure], and only in the place where you use this variable it will be transformed into some real value, like "Realtek High Definition Audio". And by that point the value of [InfosMeasure] may have changed. Rainmeter variables are kinda strange. I think it would be better to use a [!log] call as an example.

d-uzlov commented 3 years ago

By the way. I don't remember if I have specified anywhere what allowed symbols for handler names are. Like, if user is allowed to use special symbols in names. You have recently read the major part of the documentation. Do you remember anything like this?

LI7XI commented 3 years ago
Click to expand! >Place Processing right after HandlerHame, so that they are linked by placing on the page. >Name of the process ... goes example Done. >I'm thinking if I should specifically forbid using the same handler in several processings, just to make it less confusing to the user. It's not that useful after all. Good idea. --- >I would rephrase it as "String value of the measure will match its number value" or "Measure won't have a separate string value". I tried to avoid the word "match" because it does not give much context. >Measure won't have a separate string value. While this is true, explaining this will cause confusion. I suggest: - `Number`: This Child measure will provide the value retrieved from the handler in `HandlerName` option. - `Info`: This will (ignore?) `HandlerName` option and make this Child measure provide the information specified in `InfoRequest` option. --- >I think we should make clear that this is an example. I agree but i want users to know that they can use the child measure as a data provider. Like they can do `Var=[ChildMeasure]` or `SomeAction=[!SetOption SectionName OptionName [&ChildMeasure]` I shouldn't worry about this and just mention this possibility in Tips discussion right? --- >I think it would be better to use a [!log] call as an example. I did this in Section Variables discussion. I thought about doing it here, but `[!Log]` is a bang, it needs `OnUpdateAction` in a measure or `OnRefreshAction` in rainmeter section to use it. So i thought using it as a variable in that example is enough. Also what if i did `Variable=[&InfosMeasure]`? the actual value of InfosMeasure should be assigned to `Variable` right? --- >Do you remember anything like this? I searched for the word "symbol" but didn't find any. But i remember you mentioned something about names somewhere. Users already know they shouldn't use except string, numbers and underscores, but we can add additional warnings if you want. In options like `Processing` and `Handlers` parameter.
LI7XI commented 3 years ago

Btw, here are few notes before releasing this plugin:

This can be improved to be like:

And after finishing the docs, we will be ready to distribute the plugin. ^^

d-uzlov commented 3 years ago
> * `Info`: This will (ignore?) `HandlerName` option and make this Child measure provide the information specified in `InfoRequest` option. It will not. Each measure in rainmeter has 2 values, and StringValue option changes only one if these. I believe that for people familiar with the concept of string value and number value this will be quite easy to understand. By the way, you can open rainmeter About window and go to "Skins" tab to see that actually a lot of measures have different string and number values. --- > i want users to know that they can use the child measure as a data provider It's fine. I'm only talking about lack of "for example" in the > ; Will make this Child measure provide the following: Realtek High Definition Audio --- > I thought about doing it here, but `[!Log]` is a bang, it needs `OnUpdateAction` in a measure or `OnRefreshAction` in rainmeter section to use it. I don't think that example of usage should always be the whole line. I think that `[!log [&HeyImAMeasure]]` would be enough. It can be used everywhere: on a timer, as a reaction to button press, etc. > So i thought using it as a variable in that example is enough. Also what if i did `Variable=[&InfosMeasure]`? the actual value of InfosMeasure should be assigned to `Variable` right? No. Variable will hold value `[&InfosMeasure]`. You can open rainmeter About window, go to "Skins" tab and see what values variables really have. As I said, variables are never solved. When they are used, all the math and measure values are solved, but not before. This leads to interesting effect, as you can set `variable=[&measure]` and call `[!log """[#variable]"""]` two times and it will give you two different results, if the measure changes its value between cals. "Makes the value of that variable the name of the current Audio Device" is not quite true because of this, despite result being technically the same. Oh, and by the way. >When they are used, all the math and measure values are solved, but not before They are solved not because they are used, but because the place where they are used substitutes math and references. But not all places do this. For example, measure String doesn't substitute some things. ```ini [www] measure=cals formula=1+2 [variables] q=(1+2) * [www] [qqq] measure=string string=[#q] ``` Value of `qqq` measure is `(1+2) * [www]`. My point is: variables in the rainmeter are **_tricky_**, and I wouldn't use them in such examples. They will most likely confuse users that aren't familiar with variables, and they aren't any better than examples without variable. --- >Users already know they shouldn't use except string, numbers and underscores, but we can add additional warnings if you want. In options like Processing and Handlers parameter. Yes, please. I checked the code, and I can't find any checks, so now simple names aren't enforced, and it's possible that there is nothing about it in the documentation. But it's quite important for theoretical compatibility in future versions.
d-uzlov commented 3 years ago

Memory leak: This is a big problem since it can happen for any mistake in parameters. It can be annoying if it happened while experimenting with plugin options for first time.

It will certainly be fixed.

Plugin=PluginName option: Right now we have to reference the plugin name + its version name (Plugin=AudioAnalyzer_1_1), while it can simply be Plugin=AudioAnalyzer.

We can rename it. Well, technically plugin name is just a file name. You can rename plugin file whenever you like, and use another name. I could rename the plugin on every release, if I wanted to.

But.

But there is a weight of backward compatibility upon my shoulders. There are skins that use this plugin. Skins, that will never ever be updated. And if some another skin uses the same plugin, then the plugin will be updated, and it will use the newest version. But if the plugin name will change, then old skins will forever use the old version. I don't want this. We could ask skin authors to include two plugins in their .rmskin packages: AudioAnalyzer and AudioAnalyzer_1_1. But I doubt anyone will do this. Ideally we would have a centralized plugin repository, and rainmeter would search for updated plugins there. But we don't have one, and I doubt it will be created in the next few decades. Also ideally we would have some guidelines on plugin names so nobody would name a plugin like me.

It was a very dumb decision to name the plugin like this. But I can not undo this without breaking compatibility with old skins.

P.S. Oh, cool, I have remembered that there once was a plugin named AudioAnalyzer. It had very different syntax, and all the skins using it would break if I were to name a new version just AudioAnalyzer (though, it's unlikely any skin uses it because it only existed few weeks before I replaced it with 1.1 version, but still). So it would have to be something like AudioAnalyzer2. If in any time in the future I will break the compatibility I will certainly rename the plugin. But for now I would like to leave the name as it is: it's dumb but it's tolerable.

P.P.S. It should have probably been a separate issue, and not in this repository, because people who have the same question will never find it here. But whatever.

Name: AudioAnalyzer (without version number or underscores)

Can't be. There is already another plugin with this name. Also, this is not a meta-info from plugin, it's just a file name of the plugin.

Version: 1.x.x (without 64 or 32 bit) Author: rxtd - 2021 © (the copyright symbol to look cool)

Yeah, good idea.

LI7XI commented 3 years ago
Click to expand >It will not. Each measure in rainmeter ... number values. I guess we should link to rainmeter docs where this is actually documented. Then we can say something like "child measure will have 2 values, 0.31 as a number, and '0.31' as a string", `StringValue=Info` will change the ''0.31' as a string' to the infos specified in `InfoRequest` option. --- >It's fine. I'm only talking about lack of "for example" in the > >>; Will make this Child measure provide the following: Realtek High Definition Audio Will be fixed. --- >I think that [!log [&HeyImAMeasure]] would be enough. It can be used everywhere: on a timer, as a reaction to button press, etc. I guess yeah, it would be clear since who will use this will go and check Section Variables page as well. It's well documented there. >You can open rainmeter About window, go to "Skins" tab and see what values variables really have. Yes i know that, but isn't it just for visualization? i mean it only shows that but when using the variable it will be replaced by the actual value. >My point is: variables in the rainmeter are tricky, and I wouldn't use them in such examples. They will most likely confuse users that aren't familiar with variables, and they aren't any better than examples without variable. I got you, actually i wanted to do the following, `OnRefreshAction=[!WriteKeyValue SectionName VarName [ChildMeasure] FilePath]`. And tell the user to refresh at least once again (we won't use OnRefreshAction event of course, just an example). Then we use that VarName in `Source` option as an example: `Source=ID [#VarName]`. I mean that should work right? --- >Yes, please. I checked the code, and I can't find any checks, so now simple names aren't enforced, and it's possible that there is nothing about it in the documentation. But it's quite important for theoretical compatibility in future versions. Sure, i'll look into it soon enough. --- >Ideally we would have a centralized plugin repository, and rainmeter would search for updated plugins there. But we don't have one, and I doubt it will be created in the next few decades. Long time ago i thought about coding this myself, but not just for plugins, for skins as well, so users can update there skins automatically without loosing settings or anything. But that's kinda tricky with skins, your skin should have an id and users shouldn't touch it at all (actually they won't touch it, no need in first place). --- I read your concerns about backward compatibility, and as far as i know, you only posted about it once in rainmeter forums. Then electric-tech gave you some feedback about the parameters, and told you to use syntax similar to inline options or shape meter, this is when 1.1 update came out with these changes. Plz don't hate me :c but i don't think there are a lot of skin, that are In Use, that uses the current version of the plugin, or even the first version. The reason i said this because when i (personally) found out about it, it looked really complicated, except when i needed something advanced for my visualizer then i remembered it again and started learning it. Of course i can't judge for others, but maybe similar thing happened. Here is the thing, i can't make sure that no one uses the old skins, but of course at some point they will look for more skins. If the skins developers found your plugin and realized how powerful and advanced it is, DavianArt may get flooded with skins powered by your plugin. Then the users who uses the old skins will find ones that look better than the outdated skins, and then update there skins, and the plugin shipped with them. Because the thing that frustrates most of music visualizer skin devs, is the performance and limited possibilities of AudioLevel, so they might be ready to jump and use your plugin. The reason of this mouthful speech is to think for the future, we don't wanna repeat what happened in rainmeter plugin api.😅 I mean... ~Breaking compatibility now or never.~ Because i am sure, more and more users will start adopting your plugin in there skins, when that happens, we are screwed lol. --- >Can't be. There is already another plugin with this name. What? where? i thought you the first who used this name. --- P.S I talk a bit too much when feeling sleepy, so take your time to reply. I'll continue working on the docs tomorrow.
d-uzlov commented 3 years ago

I got you, actually i wanted to do the following, OnRefreshAction=[!WriteKeyValue SectionName VarName [ChildMeasure] FilePath]. And tell the user to refresh at least once again (we won't use OnRefreshAction event of course, just an example). Then we use that VarName in Source option as an example: Source=ID [#VarName]. I mean that should work right?

Well, it should probably work. I don't think that must be a part of documentation, though. Maybe there could be an example skin that shows how to utilize LUA and section variables for some purposes, where you could use something like this. But not in the main part of the documentation: it's too specialized.


Plz don't hate me :c but i don't think there are a lot of skin, that are In Use, that uses the current version of the plugin, or even the first version.

Well, I understand that my plugins are not that popular, and it's likely due to documentation. By search on rainmeter forum I know that eclectic-tech made few skins and a guide that has AudioAnalyzer 1.1. I don't know how much people are using these, though.

I guess, it's not that big of a deal if plugin name would change as this point. I'm not sure if I'm ready to risk using "AudioAnalyzer" without suffix, though. If I just change name to something new then old skins won't get the updated version of the plugin and that's all. But if I use a name that some incompatible plugin is using, then old skins would break, and that's a much higher price. While there are most likely exactly zero skins using 1.0 version, it is still a risk. Maybe replacing "_1_1" with a short "2" would be a good enough compromise.

Can't be. There is already another plugin with this name.

What? where? i thought you the first who used this name.

I meant the 1.0 version of the plugin. Since it's incompatible, it must be treated as a separate plugin.

LI7XI commented 3 years ago

it's too specialized.

Sure, that would be in Tips and Code Snippets section.


By search on rainmeter forum I know that eclectic-tech made few skins and a guide that has AudioAnalyzer 1.1. I don't know how much people are using these, though.

About that skin, it was Downloaded 374 times, and its already been a year since it was released. Abour that guide, it's mainly for people who don't wanna touch Lua, and tbh that guide is not functional for something custom. So users who want to make there skins using that guide "may" find using Lua more intuitive than this method.

About when he mentioned your plugin in that guide, he didn't show how to use the plugin itself, actually.. i had no idea what he meant lol, because i didn't use his template (Lua goes brrrrr).

I'm not sure if I'm ready to risk using "AudioAnalyzer" without suffix, though. If I ... good enough compromise. I meant the 1.0 version of the plugin. Since it's incompatible, it must be treated as a separate plugin.

Go for it. Even if you think it's a huge risk. Why? here is the thing.

First, not a lot of users are using skins with the old plugin, so this change is for the greater good.

Second, what in the world will break compatibility with older skins (here i mean the ones with 1.0 version) except Downloading a New music visualizer skin that has a new version of the plugin. The user who will do this know what they are doing, they want to use a New visualizer, so probably the old skins will never see the light in there desktop again.

3rd, v1.1 will never get updated again, okay, how is it going to get updated in first place lol? of course by downloading a skin that has a newer version, and again, how this will happen? when the users search and download a new music visualizer that uses your plugin. The last point has one thing, there would be 2 versions of the plugin in there rainmeter plugins folder (1.1 version and the without prefix version).

But should we worry? it's not like the plugin is huge and takes a lot of space, i already checked and found the whole folder which contains 3 different versions(1.1, 1.1.5, 1.1.5.1(last one is 32bit only)) with each version has 32 and 64bit, takes only 2.1Mb .

Note that we are talking about a fraction of rainmeter community, and i'm pretty sure even this small portion will look for new skins at some point.

Just go with AudioAnalyzer without any prefix, no other plugin used/will use it except yours, why? because i'm sure.

  1. I googled but never found another "rainmeter plugin that is named AudioAnalyzer" except yours.
  2. Why would someone make this plugin and there is AudioLevel? and then, if they realized the limitations of AudioLevel, they will find out about your plugin before they even start working on a plugin with same name.
  3. If you still have concerns about the naming, i'll wish a lightning to strike me. :[
LI7XI commented 3 years ago

P.P.S. It should have probably been a separate issue, and not in this repository, because people who have the same question will never find it here. But whatever.

When we are ready to release, we can create that issue if necessary.

LI7XI commented 3 years ago

Hello, i added some warnings in skin setup page and in parent page about the letters that users can use specify names (e.g. Processes, Handlers).

Also i started adding some illustration (right now only Target rate is illustrated with images). I'm planning to add more to explain options and handler types like fft and such. Of course they are credited at the bottom of the page.

LI7XI commented 3 years ago

Section Variables docs are committed and ready for review. 🚀

d-uzlov commented 3 years ago

The Resolve Function (Function?) takes 2 arguments:

Well, it's up to rainmeter how to call these things. I don't remember what word they use exactly. But for me it pretty much looks like a function.

FirstArgument: (?, sorry i can't find an example :c )

Um, I guess you can pick any argument value from the page. What's wrong with it?

Should i say "makes the child measure return/give 'something', otherwise 'something else'?

I would say that "provides" is the best fit here. Though, child measures have nothing to do with this. I would say that section variables are independent, and child measures just use their syntax for the convenience of the user.

[!Log [&ParentMeasure:Resolve(Device List Output)]] ; Will output: …

I think it worth noting that this example is for the case when user only have 1 output audio device, and more devices will lead to more lines.

Possible values of Form factor are: RemoteNetworkDevice, Speakers, LineLevel, Headphones, Microphone, Headset, Handset, UnknownDigitalPassthrough, SPDIF, DigitalAudioDisplayDevice, "unknown".

Maybe it was not the best choice for ease of writing formatted markdown text, but <unknown> must have "less" and "more" sumbols on its sides (same goes for sample rate and channels). Also, maybe it would be better to format all the values as inline code blocks, to emphasize that these are well defined values that must be used as-is. This would also preserve <> symbols without additional hustle.

Form factor or format?

Form factor is specifically how audio device looks to user. The most reasonable use for this is to show an icon for the device depending on its form factor. Format is about channels and sampling rate.

If Proc is not specified, then the plugin will try to find a process that contains the handler specified in Handler argument.

I guess that's unnecessary since we decided that it would be the best to forbid using the same handler name in several processings, so Proc option will likely be removed both from here and from child measure.

LI7XI commented 3 years ago

Um, I guess you can pick any argument value from the page. What's wrong with it?

I mean second arg specifies what infos you want to know about the first arg, but first arg specifies what?

Though, child measures have nothing to do with this.

Typo, i was thinking about InfoRequest option when writing that.

I think it worth noting that this example is for the case when user only have 1 output audio device, and more devices will lead to more lines.

I copied it from your docs, should i remove it and let users experiment with themselves?

Maybe it was not the best choice for ease of writing formatted markdown text, but must have "less" and "more" symbols on its sides (same goes for sample rate and channels).

\<> symbols for some reason hide the word inside them in markdown, that's why i didn't use them

Also, maybe it would be better to format all the values as inline code blocks, to emphasize that these are well defined values that must be used as-is. This would also preserve <> symbols without additional hustle.

I can add code-blocks instead of \<> symbols.

P.S i realized i can escape them with a backslash \\<\>, should we go with them or with code-blocks?

Form factor is specifically how audio device looks to user. The most reasonable use for this is to show an icon for the device depending on its form factor. Format is about channels and sampling rate.

Oh, so they are different args. I thought it was a typo.

I guess that's unnecessary since we decided that it would be the best to forbid using the same handler name in several processings, so Proc option will likely be removed both from here and from child measure.

I'll remove it.

d-uzlov commented 3 years ago

I mean second arg specifies what infos you want to know about the first arg, but first arg specifies what?

I would say that the first arg specifies the type of information you want to get. [Information about] Current Device, Device List, Value [of a handler], etc.

I copied it from your docs, should i remove it and let users experiment with themselves?

No, I just mean that we should note that only one of the lines look that way. I wouldn't even say that this is confusing, it's just looks a bit incomplete to me.

P.S i realized i can escape them with a backslash \<>, should we go with them or with code-blocks?

I would say to go with the code blocks, just to show that these are exact values, like names of options or channel names.