Filling in my own Web Audio Buffer is not working - html

I'm using Web Audio for various purposes and while samples loaded via URL and oscillators are working and playing properly, building a custom source buffer is not. I have tried to load my own AudioBuffer into an AudioBufferSourceNode using the code below and through the Chrome-NetBeans debugger I can see that it's loading the buffer with data and no errors are flagged, but when start is called, no sound is ever produced. Note that I'm just filling the buffer with noise, but I plan to fill it with my own custom wave data. I realize it's likely that I'm filling the buffer with the wrong data type, but I have been unable to find any documentation or examples regarding the proper way of doing it. Any help would be appreciated.
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
var frameCount = 2000;
var sampleRate = 4000;
var myBuffer = audioContext.createBuffer(2, frameCount, sampleRate);
// FILL WITH WHITE NOISE
for (var i = 0; i < frameCount; i++) {
myBuffer[i] = Math.random() * 2 - 1;
}
sourceNode = audioContext.createBufferSource();
sourceNode.buffer = myBuffer;
sourceNode.connect(audioContext.destination);
sourceNode.start(0);

This will synth your noise inside a callback method which is called everytime you have rendered yet another BUFF_SIZE number of samples
var BUFF_SIZE = 2048; // spec allows, yet do not go below 1024
var audio_context = new AudioContext();
var gain_node = audio_context.createGain();
gain_node.connect( audio_context.destination );
var source_node = audio_context.createScriptProcessor(BUFF_SIZE, 1, 1);
source_node.onaudioprocess = (function() {
return function(event) {
var synth_buff = event.outputBuffer.getChannelData(0); // mono for now
// FILL WITH WHITE NOISE
for (var i = 0, buff_size = synth_buff.length; i < buff_size; i++) {
synth_buff[i] = Math.random() * 2 - 1;
}
};
}());
source_node.connect(gain_node);

Related

Play two videos simultaneously with sync in AS3

I am busy with a project where two videos have to play on top of each other.
Like the one in the following site, http://kindnessday.sg/home#/kindness/home
Because of the large filesize I cannot embed the videos in the swf. It will become too large. Therefore the video's must be loaded thro' webstream link. But First video plays before the second video and causing the videos unsynced.
Is there a way to play both video at the same time?
var stream = 'http://mydomain/clip1.mp4'
var stream1 = 'https://mydomain/clip2.mp4'
var http_stream:URLStream = null
var http_stream1:URLStream = null
var video:Video = new Video() // the video is used only to ensure that stream is playing
var video1:Video = new Video() // the video is used only to ensure that stream is playing
addChild(video1)
addChild(video)
var nc:NetConnection = new NetConnection()
nc.connect(null)
var ns:NetStream = new NetStream(nc)
ns.client = new Object()
ns.client.onMetaData = function(e){}
ns.play(null)
var ns1:NetStream = new NetStream(nc)
ns1.client = new Object()
ns1.client.onMetaData = function(e){}
ns1.play(null)
video.attachNetStream(ns)
video1.attachNetStream(ns1)
http_stream = new URLStream();
http_stream.addEventListener(ProgressEvent.PROGRESS, on_Progress)
http_stream.load(new URLRequest(stream))
http_stream1 = new URLStream();
//http_stream1.addEventListener(ProgressEvent.PROGRESS, on_Progress1)
http_stream1.load(new URLRequest(stream1))
function on_Progress(e:ProgressEvent):void {
var b:ByteArray = new ByteArray()
http_stream.readBytes(b, 0, http_stream.bytesAvailable)
ns.appendBytes(b)
var b1:ByteArray = new ByteArray()
http_stream1.readBytes(b1, 0, http_stream1.bytesAvailable)
ns1.appendBytes(b1)
if (ns.appendBytes(b)==ns1.appendBytes(b1)){
ns.play(stream);
ns1.play(stream1);
}
}
why not not check how much of each video has loaded and when you have enough amount (you decide) then you can run some function to play both netstreams...
var min_amount : int = 500000; //for 500 kb minimum
var check_if_ready : Boolean = true;
Also on progressEvent function of loading (URLloader or URLstream???)..
if ( check_if_ready == true )
{
if( myA_NetStream.bytesLoaded >= min_amount && myB_NetStream.bytesLoaded >= min_amount )
{
myA_NetStream.play(); myB_NetStream.play();
//reset since not needed on further progressEvents during this load
check_if_ready = false;
}
}
}
This should only play when both videos have loaded x-amount of bytes. Therefore you can be sure none starts before another)
For better synchronization control you should get into handling bytes in Flash/AS3 and using the AppendBytes method because then you can control playback on a frame-by-frame basis for both NetStreams.

Is there a way to detect audio frequency in HTML 5 web audio API?

I would like to know is there a way we can detect audio frequency from microphone in html 5 web audio. I wish to make an online guitar tuner, and I need to have the audio frequency in hertz, from the sound input. I've seen some EQ and filters effects, but I didn't see anything about frequency recognition.
EDIT:
I found this: http://www.smartjava.org/content/exploring-html5-web-audio-visualizing-sound
The 2nd point (analyser node) is really interesting. I seen his source code, but I can't figure how to connect the analyser to the microphone input.
He calls a playSound() function when the mp3 file starts to play, and there he draws his canvas. But I do not have a playSound() like function...
I wrote a web audio library which, among other things, can detect frequency from mic input. Check it out at https://github.com/rserota/wad#pitch-detection
var voice = new Wad({source : 'mic' });
var tuner = new Wad.Poly();
tuner.add(voice);
voice.play();
tuner.updatePitch() // The tuner is now calculating the pitch and note name of its input 60 times per second. These values are stored in tuner.pitch and tuner.noteName.
var logPitch = function(){
console.log(tuner.pitch, tuner.noteName)
requestAnimationFrame(logPitch)
};
logPitch();
// If you sing into your microphone, your pitch will be logged to the console in real time.
tuner.stopUpdatingPitch(); // Stop calculating the pitch if you don't need to know it anymore.
You should be able to use BiquadFilterNode.
Example code from the link:
var audioCtx = new AudioContext();
var biquadFilter = audioCtx.createBiquadFilter();
biquadfilter.getFrequencyResponse(myFrequencyArray,magResponseOutput,phaseResponseOutput);
You can use the following code to get the frequencies from the mic.
navigator.mediaDevices.getUserMedia({audio:true}).then(function(localStream){
var audioContext = new(window.AudioContext || window.webkitAudioContext)();
var input = audioContext.createMediaStreamSource(localStream);
var analyser = audioContext.createAnalyser();
var scriptProcessor = audioContext.createScriptProcessor();
// Some analyser setup
analyser.smoothingTimeConstant = 0;
analyser.fftSize = 64;
input.connect(analyser);
analyser.connect(scriptProcessor);
scriptProcessor.connect(audioContext.destination);
var getAverageVolume = function( array){
var length = array.length;
var values = 0;
var i = 0;
for (; i < length; i++) {
values += array[i];
}
return values / length;
};
var onAudio = function(){
var tempArray = new window.Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(tempArray);
var latestFrequency = (getAverageVolume(tempArray));
//use latestFrequency
};
scriptProcessor.onaudioprocess = onAudio;
})
.catch(function(){
//Handle error
});

Cocos2d-js: effect on cocos2d-js application running on browser while a move from one application to another application

i was running parkour game given on cocos2d website on my browser. everything was working fine, but when i move from my browser to sublime text and returned to my browser, the running player start to show some unexpected behaviour, the player disappeared from its position and and after few second it fall on the ground and then start running again .whenever i move from one application to another it happens.
i don't why its happening. could some one tell me how to prevent this from happen?
here is the code for animation layer:-
var AnimationLayer = cc.Layer.extend({
spriteSheet: null,
runningAction: null,
sprite: null,
space:null,
body:null,
shape:null,
ctor:function (space) {
this._super();
this.space = space;
this.init();
this._debugNode = cc.PhysicsDebugNode.create(this.space);
this._debugNode.setVisible(false);
// Parallax ratio and offset
this.addChild(this._debugNode, 10);
},
init:function () {
this._super();
// create sprite sheet
cc.spriteFrameCache.addSpriteFrames(res.runner_plist);
this.spriteSheet = cc.SpriteBatchNode.create(res.runner_png);
this.addChild(this.spriteSheet);
// init runningAction
var animFrames = [];
for (var i = 0; i < 8; i++) {
var str = "runner" + i + ".png";
var frame = cc.spriteFrameCache.getSpriteFrame(str);
animFrames.push(frame);
}
var animation = cc.Animation.create(animFrames, 0.1);
this.runningAction = cc.RepeatForever.create(cc.Animate.create(animation));
//create runner through physic engine
this.sprite = cc.PhysicsSprite.create("#runner0.png");
var contentSize = this.sprite.getContentSize();
// init body
this.body = new cp.Body(1, cp.momentForBox(1, contentSize.width, contentSize.height));
this.body.p = cc.p(g_runnerStartX, g_groundHight + contentSize.height / 2);
this.body.applyImpulse(cp.v(150, 0), cp.v(0, 0));//run speed
this.space.addBody(this.body);
//init shape
this.shape = new cp.BoxShape(this.body, contentSize.width - 14, contentSize.height);
this.space.addShape(this.shape);
this.sprite.setBody(this.body);
this.sprite.runAction(this.runningAction);
this.spriteSheet.addChild(this.sprite);
this.scheduleUpdate();
},
getEyeX:function () {
return this.sprite.getPositionX() - g_runnerStartX;
}});
and this is the code for playScene.js:-
var PlayScene = cc.Scene.extend({
space:null,
gameLayer:null,
// init space of chipmunk
initPhysics:function() {
this.space = new cp.Space();
// Gravity
this.space.gravity = cp.v(0, -350);
// set up Walls
var wallBottom = new cp.SegmentShape(this.space.staticBody,
cp.v(0, g_groundHight),// start point
cp.v(4294967295, g_groundHight),// MAX INT:4294967295
0);// thickness of wall
this.space.addStaticShape(wallBottom);
},
onEnter:function () {
this._super();
this.initPhysics();
this.gameLayer = cc.Layer.create();
//add three layer in the right order
this.gameLayer.addChild(new BackgroundLayer(), 0, TagOfLayer.background);
this.gameLayer.addChild(new AnimationLayer(this.space), 0, TagOfLayer.Animation);
this.addChild(this.gameLayer);
this.addChild(new StatusLayer(), 0, TagOfLayer.Status);
this.scheduleUpdate();
},
update:function (dt) {
// chipmunk step
this.space.step(dt);
var animationLayer = this.gameLayer.getChildByTag(TagOfLayer.Animation);
var eyeX = animationLayer.getEyeX();
this.gameLayer.setPosition(cc.p(-eyeX,0));
}
});
Ok, this may or may not solve the issue some scenarios, but after looking at it profoundly, the biggest suspect seems to be a lack of steps in the calculations of Chipmunk when the framerate drops (which appears to happen when you resize or minimize/maximize the screen).
The closest thing to a fix that I've found comes from a lead in this post in the forums, and which I've adapted it like this: where you have this.space.step(dt); in your update function, change it for the following:
var timeWindow = 1/60; //replace by your configured FPS rate if it's not 60
var steps = Math.ceil(dt / timeWindow);
var i = 0;
for (; i < steps; i++) {
this.space.step(timeWindow);
}
This should ensure that even if your application drops below 60fps the physics simulation will be updated properly, and this problem should not happen anymore.

XMP data encrypted on Canon EOD D1000

I have a question regarding encryption, once again this relates to reading serial numbers from the aux:SerialNumber namespace.
When I open my file in AS3 from photos of the Canon EOS D1000, it can't read this bit in the ByteArray var i:int = p.search('<x:xmpmeta xmlns:x="\'dobe:ns:meta/\''); because well its encrypted.
What makes this interesting is, if I open the file in Photoshop then save it and close it the XMP data is correct and my app can read it.
My question would be how would I decrypt the XMP data from within AS3? Is there a way to do it. Or another way to read it?
This is the method I use:
private function getXMP(ba:ByteArray):XML
{
var LP:ByteArray = new ByteArray();
var PACKET:ByteArray = new ByteArray();
var l:int;
ba.readBytes(LP, 2, 2);
//http://www.adobe.com/devnet/xmp.html read part 3: Storage in Files.
//that will explain the -2 -29 and other things you see here.
l = LP.readInt() - 2 -29;
ba.readBytes(PACKET, 33, l);
var p:String = trim(""+PACKET);
var i:int = p.search('<x:xmpmeta xmlns:x="adobe:ns:meta/"');
//Delete all in front of the XMP XML
p = p.substr(i);
//For some reason this left some rubbish in front, so I'll hardcode it out for now
var ar:Array = p.split('<');
var s:String = "";
var q:int;
var j:int = ar.length;
for(q=1;q<j;q++)
{
s += '<'+ar[q];
}
i = s.search('</x:xmpmeta>');
i += ('</x:xmpmeta>').length;
s = s.slice(0,i);
//Delete all behind the XMP XML
//trace(s);
return XML(s);
}

Play a random flv from a total of 5 flvs

I need your help with Actionscipt3.0. To be honest I am reall noob in flash. I am more a 3D Designer so not a lot of flash ;)
Currently I have to create a website where some videos should be played automatically.
When a User opens the URL and lands on the page, a random video of a total of 5 should be played. When the video is finished, it should chose another video of the total of 5 videos.
So an example: It should chose one video of 5 videos. Play it, then it should chose 1 video of 4 videos, then it should chose 1 video of 3 videos..and so on. And after all 5 are played, it should repeat the process.
I hope someone here can help me with that...What i have sofar is this..
var files:Array = [ "Sz01Puppet.flv", "Sz02Puppet.flv",
"Sz03Puppet.flv", "Sz04Puppet.flv", "Sz05Puppet.flv" ]; var
randomFiles:Array = [];
var i:int; for (i=0; i
randomFiles.push(files[Math.floor(Math.random() * files.length)]);
}
trace(randomFiles);
But its not working in any way..
Would be great if someone could help me out
Yup, you're nearly there.
Here's how the for loop should've been written:
var files:Array = [ "Sz01Puppet.flv", "Sz02Puppet.flv", "Sz03Puppet.flv", "Sz04Puppet.flv", "Sz05Puppet.flv" ]; var randomFiles:Array = [];
var i:int;
for(i = 0 ; i < files.length; i++) randomFiles.push(files[Math.floor(Math.random() * files.length)]);
trace(randomFiles);
Still, you're note removing items form the array, so you'll have duplicates.
Here's an an example:
var files:Array = [ "Sz01Puppet.flv", "Sz02Puppet.flv", "Sz03Puppet.flv", "Sz04Puppet.flv", "Sz05Puppet.flv" ];
var shuffledFiles:Array = shuffleArray(files);
//quick test
var testTimer:Timer = new Timer(1000);
testTimer.addEventListener(TimerEvent.TIMER,updateFile);
testTimer.start();
function updateFile(event:TimerEvent):void{
if(shuffledFiles.length == 0) shuffledFiles = shuffleArray(files);//all files played, repeat process
trace('play file',shuffledFiles[0]);
shuffledFiles.shift();
}
function shuffleArray(source:Array,clone:Boolean = true):Array {
var output:Array = [];
var input:Array = clone ? [].concat(source) : source;//clone ? preserve orignal items by making a copy for shuffling, or not
while(input.length) output.push(input.splice(int(Math.random() * input.length-1),1)[0]);
return output;
}
Goodluck
You could use the Array.sort() function to sort it randomly.
// random sort function
function shuffle(a:*, b:*):int
{
return int(Math.random() * 2) - 1;
}
var files:Array = ["Sz01Puppet.flv", "Sz02Puppet.flv", "Sz03Puppet.flv", "Sz04Puppet.flv", "Sz05Puppet.flv"];
var randomFiles:Array = files.sort(shuffle); // get a new instance of the array which is sorted
trace(randomFiles);
Here is one way to do it.