Does setValueAtTime has a specific duration? - web-audio-api

In the docs says:
The setValueAtTime() method of the AudioParam interface schedules an instant change to the AudioParam value at a precise time, as measured against AudioContext.currentTime. The new value is given in the value parameter.
From what one can think it makes an instant change but when a run this code
...
biquadNode.gain.setValueAtTime(12, this._AudioContext.currentTime);
console.log("biquadNode.gain " + biquadNode.gain.value);
console.log("biquadNode.frequency " + biquadNode.frequency.value);
setTimeout(() => {
console.log("biquadNode.gain " + biquadNode.gain.value);
console.log("biquadNode.frequency " + biquadNode.frequency.value);
}, 100);
...
It outputs:
0
12
I am not sure why...

It's instant, right, yet asynchronous (and is assumed to be a non-blocking op), as it's executed in a separate thread - note the word schedules in the description. That's why you won't see the change immediately.
Note that another method of updating value, via direct assignment to the corresponding property...
biquadNode.gain.value = 12;
... isn't synchronous either - and is basically equivalent to setValueAtTime(newValue, currentTime), as explained in this issue.

Related

Is there an Operation to block onComplete?

I am trying to learn reactive programming, so forgive me if I ask a silly question. I'm also open to advice on changing my design.
I am working in scala-swing to display the results of a simulator. With one setting, a chart is displayed as a histogram; with the other setting the chart is displayed as the cumulative sum. (I'm probably using the wrong word; in the first setting you might have bin1=2, bin2=5, bin3=3; in the second setting the first height is 2, the second is 2 + 5, the third is 2 + 5 + 3, etc.). The simulator can be slow, so I originally used a Future to compute it, and the set the data into the chart. I decided to try a reactive approach, so my requirements are: 1. I don't want to recreate the data when I change the display mode, and 2. I want to set the Observable once for the chart and have the chart listen to the same Observable permanently.
I got this to work when I started the chain with a PublishSubject and the Future set the data into the start of the chain. When the display mode changed, I created a new PublishSubject().map(newRenderingLogic).subscribe(theChartsObservable). I am now trying to do what looks like the "right way," but it's not working correctly. I've tried to simplify what I have done:
val textObservable: Subject[String] = PublishSubject()
textObservable.subscribe(text => {
println(s"Text: ${text}")
})
var textSubscription: Option[Subscription] = None
val start = Observable.from(Future {
"Base text"
}).cache
var i = 0
val button = new Button() {
text = "Click"
reactions += {
case event => {
i += 1
if (textSubscription.isDefined) {
textSubscription.get.unsubscribe()
}
textSubscription = Some(start.map(((j: Int) => { (base: String) => s"${base} ${j}" })(i)).subscribe(textObservable))
}
}
}
On start, an Observable is created and logic to print some text is added to it. Then, an Observable with the generated data is created and a cache is added so that the result is replayed if the next subscription comes in after its results are generated. Then, a button is created. Then on button clicks a middle observable is chained with unique logic (it's a function that creates a function to append the value of i into the string, run with the current value of i; I tried to make something that couldn't just be reused) that is supposed to change with each click. Then the first Observable is subscribed to it so that the results of the whole chain end up being printed.
In theory, the cache operation takes care of not regenerating the data, and this works once, but onComplete is called on textObservable and then it can't be used again. It works if I subscribe it like this:
textSubscription = Some(start.map(((j: Int) => { (base: String) => s"${base} ${j}" })(i)).subscribe(text => textObservable.onNext(text)))
because the call to onComplete is intercepted, but this looks wrong and I wanted to know if there was a more typical way to do this, or architect it. It makes me think that I don't understand how this is supposed to be done if there isn't an out-of-the-box operation to do this.
Thank you.
I'm not 100% sure if I got the essence of your question right, but: if you have an Observable that may complete and you want to turn it into an Observable that never completes, you can just concatenate it with Observable.never.
For example:
// will complete after emitting those three elements:
val completes = Observable.from(List(1, 2, 3))
// will emit those three elements, but will never complete:
val wontComplete = completes ++ Observable.never

WebUI.getText() returns empty String

I want to get the text of my TestObject, I use WebUI.getText(). My code works fine for one of my pages but fails for another page. I can't figure out why it fails, everything is literally the same and it should not fail. This is what I am doing:
#Keyword
public boolean verifyIPAddr(Socket socket){
//create test object for the ip header
TestObject ipHeader = new TestObject().addProperty("id", ConditionType.EQUALS, 'ipaddr-in-header')
WebUI.waitForElementPresent(ipHeader, 20, FailureHandling.OPTIONAL)
//get text (IP) from ipHeader
String ipHeaderStr = WebUI.getText(ipHeader)
KeywordUtil.logInfo("ipHeaderStr: " + ipHeaderStr.toString())
//split the ipHeaderStr so that "IP: " portion can be removed and only "0.0.0.0" portion is left
String[] ipHeaderStrArr = ipHeaderStr.split(' ')
//store the ip in a variable
String guiIPAddress = ipHeaderStrArr[1]
//get the socket side ip
String cassetteIP = socket.getInetAddress().getHostAddress()
KeywordUtil.logInfo(" address:" + cassetteIP)
//validate that both are the same
if(cassetteIP.equals(guiIPAddress)){
KeywordUtil.logger.logPassed(guiIPAddress + " IP from GUI matches: " + cassetteIP + " from socket")
return true;
}
else{
KeywordUtil.logger.logFailed(guiIPAddress + " IP from GUI does not match: " + cassetteIP + " IP from socket")
return false
}
}
]2
I am 100% it has something to do with WebUI.getText() but it's confusing me because it works for one page but fails for the other.
The following is the HTML for the working page:
The following is the HTML for the page that is not working:
Update:
I just noticed that the one that was failing, fails sometimes and sometimes it passes, I still want to know how I can guarantee the behavior to stay stable.
There are a couple of things you can try:
You can add a delay before getting the text of the element:
WebUI.delay(30)
You can prolong the wait
WebUI.waitForElementPresent(ipHeader, 60, FailureHandling.OPTIONAL)
The reason is, Katalon (Selenium) code often depends on elements outside of its sphere of influence, like load times, network traffic, computer hardware, competing race-conditions, etc.
So, even with same code, sometimes the wait times will differ and that's why it is better to use flexible waits (like waitForElement*() methods).

RxJS interleaving merged observables (priority queue?)

UPDATE
I think I've figured out the solution. I explain it in this video. Basically, use timeoutWith, and some tricks with zip (within zip).
https://youtu.be/0A7C1oJSJDk
If I have a single observable like this:
A-1-2--B-3-4-5-C--D--6-7-E
I want to put the "numbers" as lower priority; it should wait until the "letters" is filled up (a group of 2 for example) OR a timeout is reached, and then it can emit. Maybe the following illustration (of the desired result) can help:
A------B-1-----C--D-2----E-3-4-5-6-7
I've been experimenting with some ideas... one of them: first step is to split that stream (groupBy), one containing letters, and the other containing numbers..., then "something in the middle" happen..., and finally those two (sub)streams get merged.
It's that "something in the middle" what I'm trying to figure out.
How to achieve it? Is that even possible with RxJS (ver 5.5.6)? If not, what's the closest one? I mean, what I want to avoid is having the "numbers" flooding the stream, and not giving enough chance for the "letters" to be processed in timely manner.
Probably this video I made of my efforts so far can clarify as well:
Original problem statement: https://www.youtube.com/watch?v=mEmU4JK5Tic
So far: https://www.youtube.com/watch?v=HWDI9wpVxJk&feature=youtu.be
The problem with my solution so far (delaying each emission in "numbers" substream using .delay) is suboptimal, because it keeps clocking at slow pace (10 seconds) even after the "characters" (sub)stream has ended (not completed -- no clear boundary here -- just not getting more value for indeterminate amount of time). What I really need is, to have the "numbers" substream raise its pace (to 2 seconds) once that happen.
Unfortunately I don't know RxJs5 that much and use xstream myself (authored by one of the contributor to RxJS5) which is a little bit simpler in terms of the number of operators.
With this I crafted the following example:
(Note: the operators are pretty much the same as in Rx5, the main difference is with flatten wich is more or less like switch but seems to handle synchronous streams differently).
const xs = require("xstream").default;
const input$ = xs.of("A",1,2,"B",3,4,5,"C","D",6,7,"E");
const initialState = { $: xs.never(), count: 0, buffer: [] };
const state$ = input$
.fold((state, value) => {
const t = typeof value;
if (t === "string") {
return {
...state,
$: xs.of(value),
count: state.count + 1
};
}
if (state.count >= 2) {
const l = state.buffer.length;
return {
...state,
$: l > 0 ? xs.of(state.buffer[0]) : xs.of(value) ,
count: 0,
buffer: state.buffer.slice(1).concat(value)
};
}
return {
...state,
$: xs.never(),
buffer: state.buffer.concat(value),
};
}, initialState);
xs
.merge(
state$
.map(s => s.$),
state$
.last()
.map(s => xs.of.apply(xs, s.buffer))
)
.flatten()
.subscribe({
next: console.log
});
Which gives me the result you are looking for.
It works by folding the stream on itself, looking at the type of values and emitting a new stream depending on it. When you need to wait because not enough letters were dispatched I emit an emptystream (emits no value, no errors, no complete) as a "placeholder".
You could instead of emitting this empty stream emit something like
xs.empty().endsWith(xs.periodic(timeout)).last().mapTo(value):
// stream that will emit a value only after a specified timeout.
// Because the streams are **not** flattened concurrently you can
// use this as a "pending" stream that may or may not be eventually
// consumed
where value is the last received number in order to implement timeout related conditions however you would then need to introduce some kind of reflexivity with either a Subject in Rx or xs.imitate with xstream because you would need to notify your state that your "pending" stream has been consumed wich makes the communication bi-directionnal whereas streams / observables are unidirectionnal.
The key here the use of timeoutWith, to switch to the more aggresive "pacer", when the "events" kicks in. In this case the "event" is "idle detected in the higher-priority stream".
The video: https://youtu.be/0A7C1oJSJDk

FakeItEasy ReturnsLazily with out parameter

I'm new to using FakeItEasy and rather stuck at my first attempt. The interface i want to fake has a method like this:
byte[] ReadFileChunk(string path,int offset,int count,out long size);
I would like to see how the arguments are passed on, so I'm using ReturnsLazily. Here is my attempt:
long resSize;
A.CallTo(() => dataAttributesController
.ReadFileChunk(A<string>.Ignored, A<int>.Ignored, A<int>.Ignored, out resSize))
.ReturnsLazily((string path, int offset, int count) =>
{
return Encoding.UTF8.GetBytes("You requested: " + path + "(" + offset + "," + count + ")");
})
.AssignsOutAndRefParameters(123);
This compiles, but when ran it generates this exception:
The faked method has the signature (System.String, System.Int32, System.Int32, System.Int64&), but returns lazily was used with (System.String, System.Int32, System.Int32).
Which is correct, but i can't figure out how to add the out parameter. If I change the ReturnLazily part to this:
.ReturnsLazily((string path, int offset, int count, out long size) =>
{
size = 0;
return Encoding.UTF8.GetBytes("You requested: " + path + "(" + offset + "," + count + ")");
})
it will not compile, and I don't understand the errors:
error CS1593: Delegate 'System.Func<FakeItEasy.Core.IFakeObjectCall,byte[]>' does not take 4 arguments
error CS1661: Cannot convert lambda expression to delegate type 'System.Func<string,int,int,long,byte[]>' because the parameter types do not match the delegate parameter types
error CS1677: Parameter 4 should not be declared with the 'out' keyword
For a novice like me, this reads like it doesn't like 4 parameters nor understands what to do with 'out'. Can someone please explain me how I should be reading these errors? A working example would be very welcome as well :-)
Thanks a lot!
--- EDIT ---
This seems to work:
A.CallTo(() => dataAttributesController
.ReadFileChunk(A<string>.Ignored, A<int>.Ignored, A<int>.Ignored, out resSize))
.ReturnsLazily(x =>
Encoding.UTF8.GetBytes("You requested: " + x.Arguments.Get<string>(0) + "(" + x.Arguments.Get<int>(1) + "," + x.Arguments.Get<int>(2) + ")"))
.AssignsOutAndRefParameters((long)123);
A bit less readable then I was hoping for, is this anywhere near the intended use of ReturnsLazily?
Is that interface under your control?
byte[] ReadFileChunk(string path, int offset, int count, out long size);
if so: Isn't out long size just the same as the size of the returning byte[]?
In that case I would just remove the size parameter from the interface method and use the "nice-to-read" ReturnsLazily method as you intended first.
Update: the issue I mention below was fixed in FakeItEasy release 1.15, so update to the latest version and you shouldn't have to worry about the out/ref specifiers on the methods when using ReturnsLazily.
Sorry for the delay. I'm glad you found a solution that at least functions for you.
I agree that the syntax you landed on isn't the most readable, but it does appear to be the correct one. The "convenience" versions of ReturnsLazily won't work with out/ref parameters because the lambda can't take the out/ref modifiers.
It doesn't help you today, but I've created FakeItEasy issue 168 to deal with the problem. If you have additional opinions, please drop by and comment or something.

Where can I find the emit() function implementation used in MongoDB's map/reduce?

I am trying to develop a deeper understanding of map/reduce in MongoDB.
I figure the best way to accomplish this is to look at emit's actual implementation. Where can I find it?
Even better would just be a simple implementation of emit(). In the MongoDB documentation, they show a way to troubleshoot emit() by writing your own, but the basic implementation they give is really too basic.
I'd like to understand how the grouping is taking place.
I think the definition you are looking for is located here:
https://github.com/mongodb/mongo/blob/master/src/mongo/db/commands/mr.cpp#L886
There is quite a lot of context needed though to fully understand what is going on. I confess, I do not.
1.Mongo's required JS version is no longer in O.Powell's url, which is dead. I cannot find it.
2.The below code seems to be the snippet of most interest. This cpp function, switchMode, computes the emit function to use. It is currently at;
https://github.com/mongodb/mongo/blob/master/src/mongo/db/commands/mr.cpp#L815
3.I was trying to see if emit has a default to include the _id key, which seems to occur via _mrMap, not shown here. Elsewhere it is initialized to {}, the empty map.
void State::switchMode(bool jsMode) {
_jsMode = jsMode;
if (jsMode) {
// emit function that stays in JS
_scope->setFunction("emit",
"function(key, value) {"
" if (typeof(key) === 'object') {"
" _bailFromJS(key, value);"
" return;"
" }"
" ++_emitCt;"
" var map = _mrMap;"
" var list = map[key];"
" if (!list) {"
" ++_keyCt;"
" list = [];"
" map[key] = list;"
" }"
" else"
" ++_dupCt;"
" list.push(value);"
"}");
_scope->injectNative("_bailFromJS", _bailFromJS, this);
}
else {
// emit now populates C++ map
_scope->injectNative( "emit" , fast_emit, this );
}
}