HTML5 Audio Buffer getting stuck - html5-audio

I'm using the HTML5 webkitAudioContext to get the realtime levels of a user's microphone using this following code:
var liveSource;
function getLevel(){
var context = new webkitAudioContext();
navigator.webkitGetUserMedia({audio: true}, function(stream) {
liveSource = context.createMediaStreamSource(stream);
liveSource.connect(context.destination);
var levelChecker = context.createJavaScriptNode(4096, 1 ,1);
liveSource.connect(levelChecker);
levelChecker.connect(context.destination);
levelChecker.onaudioprocess = function(e) {
var buffer = e.inputBuffer.getChannelData(0);
var maxVal = 0;
// Iterate through buffer to check if any of the |values| exceeds 1.
for (var i = 0; i < buffer.length; i++) {
if (maxVal < buffer[i]) {
maxVal = buffer[i];
}
}
if(maxVal <= 0.01){
console.log(0.0);
} else if(maxVal > 1){
console.log(1);
} else if(maxVal > 0.2){
console.log(0.2);
} else if(maxVal > 0.1){
console.log(0.1);
} else if(maxVal > 0.05){
console.log(0.05);
} else if(maxVal > 0.025){
console.log(0.025);
} else if(maxVal > 0.01){
console.log(0.01);
}
};
});
}
getLevel();
If you copy and paste this in to your console and click your fingers near your microphone (assuming you've enabled microphone input) you'll see it works for a few seconds, then suddenly stops. It doesn't report any errors. Can anybody explain why this is happening? Thanks
See http://labs.dinahmoe.com/dynamicmusicengine/ for an example where the levels are working correctly.

I had the same problem but finally got the solution! The problem is the javascript node cicle.
I suggest you to change the createJavaScriptNode() first:
var levelChecker = context.createScriptProcessor(4096, 1 ,1);
The garbage collector has a problem with "levelChecker" variable and his onaudioprocess , so you have to bind the scriptprocessor or the onaudioProcess callback to the window. Here the HOLY SOLUTION:
levelChecker.onaudioprocess = window.audioProcess = function(e) { ...
Just add window.audioProcess in that line and you will never deal with tat problem anymore.
Here you can find further info : http://lists.w3.org/Archives/Public/public-audio/2013JanMar/0304.html
Hope that works for you!

Related

Google Apps Script (seemingly) hangs (circle icon runs indefinitely) randomly in a loop

I didn't do a great job of explaining the problem. The hanging behavior seems to be related to the use of console logging (with either Logger.log or console.log statements). If I comment out the logging statements, the hanging behavior does not occur. So, if I put in a breakpoint, the looping code will stop at the breakpoint one or a few times after clicking Resume and then just hang without getting back to the breakpoint. The number of successful times hitting the breakpoint before the hanging behavior occurs seems to be random. So, it seems that the problem is related to there being console logging in the loop. If I remove the logging statements, the hanging behavior does not occur. Thanks for any suggestions, here.
I have a loop that hangs in the debugger when a breakpoint{s) are set (but seemingly not when there are no breakpoints set). I've tried putting breakpoints in at various locations and then step over the breakpointed statement and then continue execution. Sometimes (randomly) it just never returns to the breakpoint and just runs forever (until timeout). Here's my code. Can anybody see what's going on. Thanks.
function getHikesDataByMonth() {
var firstHikeMonth = events[1][0].getMonth();
var thisHikeMonth = firstHikeMonth;
//var hikesColumn = firstHikeMonth;
var hikeDate, hikeDay,hikeName, hikeLevel, hikeNameShort;
var hikeMonth, newHikeMonth;
var eventRow = 1;
var hikeRow = 0;
var participantNumber = 0;
var numParticipants;
var hikeData = [];
var hikesColumn = [];
var hikeDate, hikeName, hikeNameShort, hikeLevel;
Logger.log("events.length " + events.length)
while (eventRow < events.length) {
//if (events[eventRow][4].isBlank) { break;}
if ((!events[eventRow][4].includes("hike") && !events[eventRow][4].includes("Hike") && !events[eventRow][4].includes("HIKE")) || events[eventRow][4].includes("CANCEL")) {
eventRow += 1;
continue;
}
// found a hike
console.log("Found Hike: " + events[eventRow][4]);
hikeName = events[eventRow][4];
hikeMonth = events[eventRow][0].getMonth() - firstHikeMonth;
if (hikeMonth > thisHikeMonth - firstHikeMonth) {
newHikeMonth = true;
thisHikeMonth = hikeMonth;
} else {
newHikeMonth = false;
}
hikeLevel = getHikeLevel(hikeName);
hikeNameShort = getHikeNameShort(hikeName);
hikeDate = events[eventRow][0];
hikeDay = weekDayNames[hikeDate.getDay()];
hikeData.push(hikeDay);
hikeData.push(hikeDate.toLocaleDateString('en-US'));
hikeData.push(hikeName)
hikeData.push(hikeNameShort);
hikeData.push(hikeLevel);
hikeData.push("");
hikeData.push("");
//hikeRowArray[0] = hikeRow;
//hikeData[hikeRow] = hikeRow;
console.log("Getting Participants: " + hikeName)
while (events[eventRow][4] == hikeName){
if (events[eventRow][9] != "Paid") {
eventRow += 1;
continue;
}
hikeData.push(events[eventRow][6] + " " + events[eventRow][5]);
eventRow += 1;
participantNumber += 1;
}
numParticipants = participantNumber
for (var i = participantNumber+1; i < 30; i++){
hikeData.push("");
}
//Logger.log(hikeParticipants[participantNumber]);
hikeData.push(numParticipants < 15 ? "Yes" : "No");
hikeData.push(15 - numParticipants);
// That's all for that hike - go to next hike
participantNumber = 0;
eventRow += 1;
hikeData.push(hikeData);
hikesColumn.push(hikeData);
console.log("Going to next hike at eventRow:" + eventRow)
if (newHikeMonth) {
hikesDataByMonth.push(hikesColumn);
}
}
}

Get the first hyperlink and its text value

I hope everyone is in good health health and condition.
Recently, I have been working on Google Docs hyperlinks using app scripts and learning along the way. I was trying to get all hyperlink and edit them and for that I found an amazing code from this post. I have read the code multiple times and now I have a good understanding of how it works.
My confusion
My confusion is the recursive process happening in this code, although I am familiar with the concept of Recursive functions but when I try to modify to code to get only the first hyperlink from the document, I could not understand it how could I achieve that without breaking the recursive function.
Here is the code that I am trying ;
/**
* Get an array of all LinkUrls in the document. The function is
* recursive, and if no element is provided, it will default to
* the active document's Body element.
*
* #param {Element} element The document element to operate on.
* .
* #returns {Array} Array of objects, vis
* {element,
* startOffset,
* endOffsetInclusive,
* url}
*/
function getAllLinks(element) {
var links = [];
element = element || DocumentApp.getActiveDocument().getBody();
if (element.getType() === DocumentApp.ElementType.TEXT) {
var textObj = element.editAsText();
var text = element.getText();
var inUrl = false;
for (var ch=0; ch < text.length; ch++) {
var url = textObj.getLinkUrl(ch);
if (url != null) {
if (!inUrl) {
// We are now!
inUrl = true;
var curUrl = {};
curUrl.element = element;
curUrl.url = String( url ); // grab a copy
curUrl.startOffset = ch;
}
else {
curUrl.endOffsetInclusive = ch;
}
}
else {
if (inUrl) {
// Not any more, we're not.
inUrl = false;
links.push(curUrl); // add to links
curUrl = {};
}
}
}
if (inUrl) {
// in case the link ends on the same char that the element does
links.push(curUrl);
}
}
else {
var numChildren = element.getNumChildren();
for (var i=0; i<numChildren; i++) {
links = links.concat(getAllLinks(element.getChild(i)));
}
}
return links;
}
I tried adding
if (links.length > 0){
return links;
}
but it does not stop the function as it is recursive and it return back to its previous calls and continue running.
Here is the test document along with its script that I am working on.
https://docs.google.com/document/d/1eRvnR2NCdsO94C5nqly4nRXCttNziGhwgR99jElcJ_I/edit?usp=sharing
I hope you will understand what I am trying to convey, Thanks for giving a look at my post. Stay happy :D
I believe your goal as follows.
You want to retrieve the 1st link and the text of link from the shared Document using Google Apps Script.
You want to stop the recursive loop when the 1st element is retrieved.
Modification points:
I tried adding
if (links.length > 0){
return links;
}
but it does not stop the function as it is recursive and it return back to its previous calls and continue running.
About this, unfortunately, I couldn't understand where you put the script in your script. In this case, I think that it is required to stop the loop when links has the value. And also, it is required to also retrieve the text. So, how about modifying as follows? I modified 3 parts in your script.
Modified script:
function getAllLinks(element) {
var links = [];
element = element || DocumentApp.getActiveDocument().getBody();
if (element.getType() === DocumentApp.ElementType.TEXT) {
var textObj = element.editAsText();
var text = element.getText();
var inUrl = false;
for (var ch=0; ch < text.length; ch++) {
if (links.length > 0) break; // <--- Added
var url = textObj.getLinkUrl(ch);
if (url != null) {
if (!inUrl) {
// We are now!
inUrl = true;
var curUrl = {};
curUrl.element = element;
curUrl.url = String( url ); // grab a copy
curUrl.startOffset = ch;
}
else {
curUrl.endOffsetInclusive = ch;
}
}
else {
if (inUrl) {
// Not any more, we're not.
inUrl = false;
curUrl.text = text.slice(curUrl.startOffset, curUrl.endOffsetInclusive + 1); // <--- Added
links.push(curUrl); // add to links
curUrl = {};
}
}
}
if (inUrl) {
// in case the link ends on the same char that the element does
links.push(curUrl);
}
}
else {
var numChildren = element.getNumChildren();
for (var i=0; i<numChildren; i++) {
if (links.length > 0) { // <--- Added or if (links.length > 0) break;
return links;
}
links = links.concat(getAllLinks(element.getChild(i)));
}
}
return links;
}
In this case, I think that if (links.length > 0) {return links;} can be modified to if (links.length > 0) break;.
Note:
By the way, when Google Docs API is used, both the links and the text can be also retrieved by a simple script as follows. When you use this, please enable Google Docs API at Advanced Google services.
function myFunction() {
const doc = DocumentApp.getActiveDocument();
const res = Docs.Documents.get(doc.getId()).body.content.reduce((ar, {paragraph}) => {
if (paragraph && paragraph.elements) {
paragraph.elements.forEach(({textRun}) => {
if (textRun && textRun.textStyle && textRun.textStyle.link) {
ar.push({text: textRun.content, url: textRun.textStyle.link.url});
}
});
}
return ar;
}, []);
console.log(res) // You can retrieve 1st link and test by console.log(res[0]).
}

Validate a form with using Jquery - Problems

Sorry for my bad English.
Okay, let's go: when I try to validate my form using jQuery, it works just the else option.
I'm considering a spacing in between names, for identify the name input, for as fullname. But in doing so, nothing appears in my console.
Someone help me please.
$('form#form1').submit(function() {
var fname = $('input[name=fullname]').val()
var pho = $('input[name=phone]').val()
var mai = $('input[name=email]').val()
var amount = fname.split(' ').lenght
var splitStr = fname.split(' ')
if(amount >= 2) {
console.log('It worked!')
for(var i = 0; i < amount; i++ ) {
console.log(splitStr[1])
}
} else {
console.log("Wrong!")
return false;
}
return false;
}
It supposes to be fname.split(' ').length.
Writing fname.split(' ').lenght will result in amount == undefined and thus (undefined >= 2) will always be false.

audio won't work on safari browser

could someone please help me to find out why this won't work on safari browser? It seems to work really well in all other browsers apart from Safari. I really could not work it out.
Any help will be most appreciated.
function loadPlayer()
{
var audioPlayer = new Audio();
audioPlayer.controls="";
audioPlayer.setAttribute("data-index", -1); //set default index to -1.
audioPlayer.addEventListener('ended',nextSong,false);
audioPlayer.addEventListener('error',errorFallback,true);
document.getElementById("player").appendChild(audioPlayer);
}
function nextSong(index, e)
{
var next;
var audioPlayer = document.getElementsByTagName('audio')[0];
//check for index. If so load from index. If not, index is defined auto iterate to next value.
if (index >= 0)
{
next = index;
}
else
{
next = parseInt(audioPlayer.getAttribute("data-index"))+1;
next >= urls.length ? next = 0 : null;
}
audioPlayer.src=urls[next][0]; //load the url.
audioPlayer.setAttribute("data-index", next);
//disable the player.
var audioPlayerControls = document.getElementById("playerControls");
audioPlayer.removeEventListener('canplay',enablePlayerControls,false);
audioPlayerControls.setAttribute("disabled", true);
audioPlayer.addEventListener('canplay',enablePlayerControls,false);
audioPlayer.load();
//show the image:
var image = document.getElementById("playerList").querySelectorAll("a")[next].querySelector("img").cloneNode();
image.style.width = "30px";
if(audioPlayerControls.querySelector("img"))
{
audioPlayerControls.replaceChild(image, audioPlayerControls.querySelector("img"));
}
else
{
audioPlayerControls.insertBefore(image, audioPlayerControls.querySelector("a"));
}
}
function enablePlayerControls()
{
//File has loaded, so we can start playing the audio.
//Enable the player options.
var audioPlayer = document.getElementsByTagName('audio')[0];
audioPlayer.removeEventListener('canplay',enablePlayerControls,false);
document.getElementById("playerControls").removeAttribute("disabled");
audioPlayer.play();
}
function errorFallback() {
nextSong();
}
function playPause()
{
var audioPlayer = document.getElementsByTagName('audio')[0];
if (audioPlayer.paused)
{
audioPlayer.play();
} else
{
audioPlayer.pause();
}
}
function pickSong(e)
{
//we want the correct target. Select it via the event (e).
var target;
//pickSong does the selecting:
if (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() == "img")
{
//The event target = the img element.
target = e.target.parentElement;
}
else
{
//the event target is the a element
target = e.target;
}
var index = target.getAttribute("data-index"); //get the song index stored in the data-index attribute.
nextSong(index);
}
var urls = new Array();
urls[0] = ['http://mp3lg4.tdf-cdn.com/9079/jet_143844.mp3', 'http://radio-maghreb.net/radio/radio almazighia.png'];
urls[1] = ['http://mp3lg4.tdf-cdn.com/9077/jet_143651.mp3', "http://radio-maghreb.net/radio/alwatania.png"];
urls[2] = ['http://mp3lg4.tdf-cdn.com/9080/jet_144136.mp3', "http://radio-maghreb.net/radio/inter.jpg"];
function startAudioPlayer()
{
loadPlayer();
for (var i = 0; i < urls.length; ++i)
{
//this for loop runs through all urls and appends them to the player list. This smooths the adding off new items. You only have
//to declare them in the array, the script does the rest.
var link = document.createElement("a");
link.href = "javascript: void(0)";
link.addEventListener("click", pickSong, false);
link.setAttribute("data-index", i);
link.img = document.createElement("img");
link.img.src = urls[i][1];
link.appendChild(link.img);
document.getElementById("playerList").appendChild(link);
}
}
//Event that starts the audio player.
window.addEventListener("load", startAudioPlayer, false);
#playerControls[disabled=true] > a{
color: #c3c3c3;
}
<span id="playerControls" disabled="true">
Play
Stop
</span>
Next Track
<!-- player ends -->
<br>
<br>
<!-- img links start -->
<div id="playerList">
</div>

A* algorithm works OK, but not perfectly. What's wrong?

This is my grid of nodes:
I'm moving an object around on it using the A* pathfinding algorithm. It generally works OK, but it sometimes acts wrongly:
When moving from 3 to 1, it correctly goes via 2. When going from 1 to 3 however, it goes via 4.
When moving between 3 and 5, it goes via 4 in either direction instead of the shorter way via 6
What can be wrong? Here's my code (AS3):
public static function getPath(from:Point, to:Point, grid:NodeGrid):PointLine {
// get target node
var target:NodeGridNode = grid.getClosestNodeObj(to.x, to.y);
var backtrace:Map = new Map();
var openList:LinkedSet = new LinkedSet();
var closedList:LinkedSet = new LinkedSet();
// begin with first node
openList.add(grid.getClosestNodeObj(from.x, from.y));
// start A*
var curNode:NodeGridNode;
while (openList.size != 0) {
// pick a new current node
if (openList.size == 1) {
curNode = NodeGridNode(openList.first);
}
else {
// find cheapest node in open list
var minScore:Number = Number.MAX_VALUE;
var minNext:NodeGridNode;
openList.iterate(function(next:NodeGridNode, i:int):int {
var score:Number = curNode.distanceTo(next) + next.distanceTo(target);
if (score < minScore) {
minScore = score;
minNext = next;
return LinkedSet.BREAK;
}
return 0;
});
curNode = minNext;
}
// have not reached
if (curNode == target) break;
else {
// move to closed
openList.remove(curNode);
closedList.add(curNode);
// put connected nodes on open list
for each (var adjNode:NodeGridNode in curNode.connects) {
if (!openList.contains(adjNode) && !closedList.contains(adjNode)) {
openList.add(adjNode);
backtrace.put(adjNode, curNode);
}
}
}
}
// make path
var pathPoints:Vector.<Point> = new Vector.<Point>();
pathPoints.push(to);
while(curNode != null) {
pathPoints.unshift(curNode.location);
curNode = backtrace.read(curNode);
}
pathPoints.unshift(from);
return new PointLine(pathPoints);
}
NodeGridNode::distanceTo()
public function distanceTo(o:NodeGridNode):Number {
var dx:Number = location.x - o.location.x;
var dy:Number = location.y - o.location.y;
return Math.sqrt(dx*dx + dy*dy);
}
The problem I see here is the line
if (!openList.contains(adjNode) && !closedList.contains(adjNode))
It may be the case that an adjNode may be easier(shorter) to reach through the current node although it was reached from another node previously which means it is in the openList.
Found the bug:
openList.iterate(function(next:NodeGridNode, i:int):int {
var score:Number = curNode.distanceTo(next) + next.distanceTo(target);
if (score < minScore) {
minScore = score;
minNext = next;
return LinkedSet.BREAK;
}
return 0;
});
The return LinkedSet.BREAK (which acts like a break statement in a regular loop) should not be there. It causes the first node in the open list to be selected always, instead of the cheapest one.