Play oscillator in left/right channel with Web Audio Api, Ionic and Crosswalk - api

I want to play an oscillator in left, right or both channel and to achieve this i use the StereoPannerNode from the Web Audio Api.
When i run "ionic serve" on Chrome everything works fine, but when i test the code on Android (i installed the crosswalk plugin) the sound comes from both channels (lower in the channel i don't want the sound to play).
I also tried Merger and Splitter nodes with the same results: works on Chrome, doesn't work on Android.
I tried to use Asus ZenFone with Android 4.4.2 and Huawei p8 with Android 6.0.
This is how i create my audio context and the panner node.
var contextClass = (window.AudioContext);
var audioCtx = new contextClass();
var panNode = audioCtx.createStereoPanner();
I don't know how to fix this, any idea?

On Android 6.0, the following script works. It makes use of the Web Audio API. I have not yet tested it on iOS, but I have a good feeling it will work there (please comment if it does not).
You need an "omg.mp3" file in your root directory to test with. You also should build using Cordova and not worry about the CORS or Same-domain error you might get in your browser
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>StereoPannerNode example</title>
<link rel="stylesheet" href="">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<h1>StereoPannerNode example</h1>
<audio controls>
<source src="omg.mp3" type="audio/mp3">
<p>Browser too old to support HTML5 audio? How depressing!</p>
</audio>
<h2>Set stereo panning</h2>
<input class="panning-control" type="range" min="-1" max="1" step="0.1" value="0">
<span class="panning-value">0</span>
</body>
<script>
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var myAudio = document.querySelector('audio');
var panControl = document.querySelector('.panning-control');
var panValue = document.querySelector('.panning-value');
// Create a MediaElementAudioSourceNode
// Feed the HTMLMediaElement into it
var source = audioCtx.createMediaElementSource(myAudio);
// Create a stereo panner
var panNode = audioCtx.createStereoPanner();
// Event handler function to increase panning to the right and left
// when the slider is moved
panControl.oninput = function() {
panNode.pan.value = panControl.value;
panValue.innerHTML = panControl.value;
}
// connect the AudioBufferSourceNode to the gainNode
// and the gainNode to the destination, so we can play the
// music and adjust the panning using the controls
source.connect(panNode);
panNode.connect(audioCtx.destination);
</script>
</html>

Related

Browser keeps on accessing the camera with red dot even after stopping the stream aafter establishing the peer connection using webRTC

let localStream;
let peerConnection;
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
}).then(function(stream) {
createPeerConnection();
localStream = stream;
peerConnection.addStream(localStream);
});
so when stopping the stream it stops the video
localStream.getTracks().forEach(track => track.stop());
But the browser tab says that it is accessing the camera or microphone with a red dot besides it. I just do not want to reload the page in order to stop that.
Note: this happens when after establishing a peer connection using webRTC and after disconnecting the peers the camera light stays on.
Is there any way to do that. Thanks for your help in advance.
you can use boolean value or condition in which tab access camera after track.stop() you can set the value to false then the camera will not be acessed anymore. (p.s you can try that if its works)
<!DOCTYPE html>
<html>
<head>
<title>Web Client</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id="callerIDContainer">
<button onclick="call_user();">Call User</button>
</div>
<div class="video-container">
<video autoplay muted class="local-video" id="local-video"></video>
</div>
<div>
<button onclick="hangup();">Hangup</button>
</div>
</body>
<script >
var localStream;
var accessRequired=true
function call_user() //your function
{
if(accessRequired)
{
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
}).then(function(stream) {
localStream = stream;
const localVideo = document.getElementById("local-video");
if (localVideo) {
localVideo.srcObject = localStream;
}
});
}
}
function hangup(){
localStream.getTracks().forEach(track => track.stop()).then(()=>{accessRequired=false});
}
</script>
</html>
try this call user then hangup it is working
The sample code in your question looks like it uses gUM() to create an audio-only stream ({video: false, audio:true}).
It would be strange if using .stop() on all the tracks on your audio-only stream also stopped the video track on some other stream. If you want to turn off your camera's on-the-air light you'll need to stop the video track you used in peerConnection.addTrack(videoTrack). You probably also need to tear down the call using peerConnection.close().
I had same issue with webRTC and React. I have stopped tracks of remote stream but I forgot to stop local stream :
window.localStream.getTracks().forEach((track) => {
track.stop();
});

Peerjs is not retrieved in vue js

I am trying to use peerjs in vue app. So I added the cdn script in vue index.html file's header like this.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta data-n-head="true" name="viewport" content="width=device-width, initial-scale=1.0">
<title>peer</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/peerjs/0.3.9/peer.min.js"></script>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
Now in a components' mounted hook, I am doing this to just console the id
var peer1 = new Peer();
peer1.on('open', function(id) {
console.log('My peer1 ID is: ' + id);
});
Nothing happens.
I then created a simple html file and run that html file I was able to see the id.
Next I tired to see XHR tab, I see when running a plain html file, two ajax calls is sent and in the result an ID is returned. But in vue, there is nothing like this. All I get a socket that returns this values
{websocket: true, origins: ["*:*"], cookie_needed: false, entropy: 1058218289}
cookie_needed
:
false
entropy
:
1058218289
origins
:
[":"]
websocket
:
true
One more thing, peers js documentations says to use api key, but if I use api key nothing happens in vue or html. Without the key, in html file I get the id.
Anyone knows please help me. Thank you.

Any possibility for live-videostreaming within a-frame?

I want to create a site with a 360 video thats streamed from my computers 360 cam (ricoh theta s) and uses the possibilites of a-frame. I did not have any luck with embedding youtube livestreaming within a-frame though. I would have a webserver and the stream would not be really public so maybe there is some solution that involves selfhosting? Does anybody have any experience with achieving sth like this? i cant find anything related so far and this plays a crucial role in my robotproject...
EDIT 1:
I might specify even more after some research:
it would be perfect if a-videosphere and a-video would support sth like hls or mpeg-dash - streams. since that would need some kind of player for chrome and android stuff i think the easiest route would be to support a motionjpg-support because they are very easy to create. flashstreams can be good too but i dont think there is a future for that.
is there anything like that in the planning by someone because i am quite sure that nothing like that exists yet... i took 2-3 days of researching and find nothing about that topic... just a getUserMedia for webcam example showed up but its not good for my purpose.
another approach i could live with would be a routine that just autoreloads pictures in a-sky (if possible without flickering). i tried to integrate javascripts that are supposed to do that within normal divs and so but nothing worked...
or did somewhere someone get a stream of any kind running in a-videosphere and if so how?
EDIT 2:
i got it working... somehow... not really but looks promising...
the stream is provided by "yawcam" which uploads a new picture every second to my ftp. if i now click on the red sphere the script starts via addEventListener 'click' and the content of a-sky gets updated... is there any way to make a loop out of that script so one doesnt have to click anymore and it just update itself every second?
<head>
<meta charset="utf-8">
<title>joeinterface</title>
<meta name="description" content="360 Video — A-Frame">
<script src="https://aframe.io/releases/0.3.2/aframe.min.js"></script>
</head>
<body>
<script>
AFRAME.registerComponent('set-sky', {
schema: {default:''},
init() {
const sky = document.querySelector('a-sky');
this.el.addEventListener('click', () => {
sky.setAttribute( 'src', this.data + "?" + Math.random());
});
}
});
</script>
<a-scene>
<a-camera position="0 0 0">
<a-cursor color="#4CC3D9" fuse="true" timeout="10"></a-cursor>
</a-camera>
<a-sphere color="#F44336" radius="8" position="-8 2 -8" set-sky="image1.jpg"></a-sphere>
<a-sky></a-sky>
</a-scene>
</body>
so here is the solution for the proposed "kind-of" solution...
the picture "out" is updated via "yawcam" on my server every second and updated in the a-sky tag - even without flickering... so no sound but at least kind of a live-video-feed in a-sky.
<head>
<meta charset="utf-8">
<title>joeinterface</title>
<meta name="description" content="360 Video � A-Frame">
<script src="https://aframe.io/releases/0.3.2/aframe.min.js"></script>
</head>
<body>
<script>
AFRAME.registerComponent('set-sky', {
schema: {default:''},
init: function() {
this.timeout = setInterval(this.updateSky.bind(this), 100);
this.sky = this.el;
},
remove: function() {
clearInterval(this.timeout);
this.el.removeObject3D(this.object3D);
},
updateSky: function() {
this.sky.setAttribute( 'src', this.data + "?" + Math.random());
}
});
</script>
<a-scene>
<a-camera position="0 0 0">
<a-cursor color="#4CC3D9 " fuse="true" timeout="10"></a-cursor>
</a-camera>
<a-sphere color="#F44336 " radius="2" position="-8 2 -8"></a-sphere>
<a-sky set-sky="out"></a-sky>
</a-scene>
</body>

Is there a way to call a function before the dependencies are loaded in Sencha Touch application

Sencha Touch application has requires:[] option to specify the list of controllers and models and stores etc that are loaded that we need for the application to work but is there a way to execute something that we need even before the loading of the dependencies. FOr e.g. I need the Browsers Language even before the loading of all dependencies. So is it possible to do?
Keep in mind: Sencha Touch is nothing but JavaScript.
You can add some script in your index.html in front of the script tag that loads the sencha microloader.
<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
<meta charset="UTF-8">
<title>FNL</title>
<style type="text/css">
<!-- sencha stuff -->
</style>
<script id="myScript" type="text/javascript" src="myScript.js"></script>
<!-- The line below must be kept intact for Sencha Command to build your application -->
<script id="microloader" type="text/javascript" src=".sencha/app/microloader/development.js"></script>
</head>
<body>
<div id="appLoadingIndicator">
<div></div>
<div></div>
<div></div>
</div>
</body>
</html>
I added some lines to the ST Microloader:
this.css = processAssets(manifest.css, 'css');
// Load language strings
var xhr = new XMLHttpRequest();
xhr.open('GET', 'api/Settings', false);
xhr.send(null);
var settings = eval("(" + xhr.responseText + ")");
Lang = settings.Translations[0];
Options = settings.Options[0];
// End Load Language Strings
this.js = processAssets(manifest.js, 'js');
In ExtJS i accomplished this by loading a Dependency class first
Ext.require([
'MyApp.Dependencies',
..
]);
so the Dependecies class is loaded before all controllers which looks like this
Dependencies.js:
Ext.define('MyApp.Dependencies', {
singleton: true,
init: function() {
// load translation data
}
});
MyApp.Dependecies.init();
and for completition my init function looks something like this:
inti: function(){
function loadScriptSync(url) {
var xhrObj = new XMLHttpRequest();
// open and send a synchronous request
xhrObj.open('GET', url, false);
xhrObj.send('');
// add the returned content to a newly created script tag
var se = document.createElement('script');
se.type = "text/javascript";
se.text = xhrObj.responseText;
document.getElementsByTagName('head')[0].appendChild(se);
}
var language = this.getLanguage();
loadScriptSync("resources/locale/locale." + language + ".js");
}

Google transliterate API problem in Firefox

I am trying to use Google Transliterate API helloWorld in Firefox 4.0.1 and WindowsXP
I am using node.js 0.4.7 to serve the page
When I load the page through node.js, i get the following error: "attempt to run compile-and-go script on a cleared scope"
The page is rendered successfully if I double-click it and open in Firefox from disk, or if I open it in IE8, Opera or Chrome
Any idea why this happens and what is the way around it? Here is the code:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript" src="https://www.google.com/jsapi?api-key-here">
</script>
<script type="text/javascript">
// Load the Google Transliterate API
google.load("elements", "1", {
packages: "transliteration"
});
function onLoad() {
var options = {
sourceLanguage:
google.elements.transliteration.LanguageCode.ENGLISH,
destinationLanguage:
[google.elements.transliteration.LanguageCode.URDU],
shortcutKey: 'ctrl+g',
transliterationEnabled: true
};
// Create an instance on TransliterationControl with the required
// options.
var control =
new google.elements.transliteration.TransliterationControl(options);
// Enable transliteration in the textbox with id
// 'transliterateTextarea'.
control.makeTransliteratable(['transliterateTextarea']);
}
google.setOnLoadCallback(onLoad);
</script>
</head>
<body>
Type in Urdu (Press Ctrl+g to toggle between English and Urdu)<br>
<textarea id="transliterateTextarea" style="width:600px;height:200px"></textarea>
</body>
</html>