Possible to get the playedDuration from buffer/audioContext - html5-audio

If I'm using the AudioContext and AudioBuffers to play a sound as described here. Is it possible to get the playedDuration somehow? playedDuration being the duration of time that has already been played on this sample.

You can get duration from the audio metadata. Example on stackoverflow:
audioElement = new Audio('http://www.html5rocks.com/en/tutorials/audio/quick/test.mp3');
console.log(audioElement);
audioElement.addEventListener("loadedmetadata", function(_event) {
var duration = audioElement.duration;
console.log( duration );
});

Related

Empty microphone data from getUserMedia

Using the following code I get all zeroes in the audio stream from my microphone (using Chrome):
navigator.mediaDevices.getUserMedia({audio:true}).then(
function(stream) {
var audioContext = new AudioContext();
var source = audioContext.createMediaStreamSource(stream);
var node = audioContext.createScriptProcessor(8192, 1, 1);
source.connect(node);
node.connect(audioContext.destination);
node.onaudioprocess = function (e) {
console.log("Audio:", e.inputBuffer.getChannelData(0));
};
}).catch(function(error) {console.error(error);})
I created a jsfiddle here: https://jsfiddle.net/g3dck4dr/
What's wrong here?
Umm, something in your hardware config is wrong? The fiddle works fine for me (that is, it shows non-zero values). Do other web audio input tests work, like https://webaudiodemos.appspot.com/input/index.html?
Test to make sure you've selected the right input, and you don't have a hardware mute switch on.

How to show the song download represented by duration time of it

What i'm trying to do is to show the song download progress in form of song duration time. For example: 00:00, 01:05, 02:14, 03:58, .... 04:13 being 04:13 the song total duration. So far i have this code:
var soundClip:Sound;
var sTransform:SoundTransform = new SoundTransform(0.1);
function init() {
soundClip = new Sound();
soundClip.load(new URLRequest("magneto.mp3"));
//soundClip.load(new URLRequest("making.mp3"));
soundClip.addEventListener(Event.COMPLETE, soundLoaded);
soundClip.addEventListener(ProgressEvent.PROGRESS, soundLoading);
}
init();
function convertTime(millis:Number):String{
var displayMinutes:String;
var displaySeconds:String;
var Minutes:Number = (millis % (1000*60*60)/(1000*60));
var Seconds:Number = ((millis % (1000*60*60)) % (1000*60))/1000;
if(Minutes<10){
displayMinutes = "0"+Math.floor(Minutes);
}else{
displayMinutes = Math.floor(Minutes).toString();
}
if(Seconds<10){
displaySeconds = "0"+Math.floor(Seconds);
}else{
displaySeconds = Math.floor(Seconds).toString();
}
return displayMinutes + ":" + displaySeconds;
}
function soundLoaded(e:Event) {
soundClip.play(0,0,sTransform);
}
function soundLoading(e:ProgressEvent) {
trace(convertTime(soundClip.length));
}
As you can see, i'm testing it out with two songs, according to the code above the duration time of both are: 03:52 and 11:28 but according to the window these two songs last 03:52 and 05:44. Here is the code and both mp3 files.
Thank you.
EDIT:I'm analizing this page wicht play the song making.mp3, after debbuging it i realized that there is a value wicht is passed to the player, and go this way: 0, 0, 2664, 7576,...344370 these values are shown as*00:00, 01:05, 02:14, 03:58, .... 04:13* as the download progress. Knowing where this data come from would solve my problem, initially i thought it would be obtein through length propety but this only worked well for the magneto.mp3 file not for both songs.
On the whole i want to show:
00:00, 00:23, 01:23...03:57(where 03:57 is the duration time of any song) as the download progress.
Thank you for helping me. Cheers :)
Your code has no problems and your technique is correct.
You only need to fetch the total duration at the end of the download. The value of the file length changes as more data is retrieved. If your download stops before reaching the end, you will only have the length of the incomplete file. Add another handler possibly to check for errors, and if fired, let the user know that the file download is still incomplete.
Update: I figured it out. Add a call to convertTime() in the soundLoaded() method.
What is happening is that the file length is being updated in the PROGRESS event handler. But the final length is often only available in the COMPLETE event, because the PROGRESS event handler is called only when the file download is incomplete and not after it is ready.
Keep the convertTime() call in the PROGRESS event handler as you do presently.
private function soundLoaded(e:Event):void
{
soundClip.play(0, 0, sTransform);
trace(convertTime(soundClip.length));
}
This should do it.
Update 2: This is a known issue reported online at many forums. The length of any sound file sampled at less than 44 khz is reported incorrectly while the download is in progress. It's only after the download completes that the correct duration is reported. This only affects SWF files version 9 or less.
Changing the output SWF to version 10+ fixes the issue.

Audio API: Fail to resume music and also visualize it. Is there bug in html5-audio?

I have a button. Every time it is clicked, a music is played. When it's clicked the second time, the music resumes. I also want to visualize the music.
So i begin with html5 audio (complete code in http://jsfiddle.net/karenpeng/PAW7r/):
$("#1").click(function(){
audio1.src = '1.mp3';
audio1.controls = true;
audio1.autoplay = true;
audio1.loop = true;
source = context.createMediaElementSource(audio1);
source.connect(analyser);
analyser.connect(context.destination);
});
But when it's clicked more than once, it console.log error:
Uncaught Error: INVALID_STATE_ERR: DOM Exception 11
Then i change to use web audio API, and change the source to:
source = context.createBufferSource();
The error is gone.
And then, i need to visualize it.
But ironicly, it only works in html5 audio!
(complete code in http://jsfiddle.net/karenpeng/FvgQF/, it does not work in jsfiddle cuz i dont know how to write processing.js script properly, but it does run on my pc)
var audio = new Audio();
audio.src = '2.mp3';
audio.controls = true;
audio.autoplay = true;
audio.loop=true;
var context = new webkitAudioContext();
var analyser = context.createAnalyser();
var source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
var freqData = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(freqData);
//visualization using freqData
when i change the source to :
source = context.createBufferSource();
it does not show anything.
So is there way to visualize it and yet without error and enable it to resume again and again?
Actually, I believe the problem is that you're trying to create a SECOND web audio node for the same media element. (Your code, when clicked, re-sets the SRC, controls, etc., but it's not creating a new Audio().) You should either hang on to the MediaElementAudioSourceNode you created, or create new Audio elements.
E.g.:
var context = new webkitAudioContext();
var analyser = context.createAnalyser();
var source = null;
var audio0 = new Audio();
$("#0").click(function(){
audio0.src = 'http://www.bornemark.se/bb/mp3_demos/PoA_Sorlin_-_Stay_Up.mp3';
audio0.controls = true;
audio0.autoplay = true;
audio0.loop = true;
if (source==null) {
source = context.createMediaElementSource(audio0);
source.connect(analyser);
analyser.connect(context.destination);
}
});​
Hope that helps!
-Chris Wilson
From what I can tell, this is likely because the MediaElementSourceNode may only be able to take in an Audio that isn't already playing. The Audio object is declared outside of the click handler, so you're trying to analyze audio that's in the middle of playing the second time you click.
Note that the API doesn't seem to specify this, so I'm not 100% sure, but this makes intuitive sense.

Web Audio API: How to load another audio file?

I want to write a basic script for HTML5 Web Audio API, can play some audio files. But I don't know how to unload a playing audio and load another one. In my script two audio files are playing in the same time,but not what I wanted.
Here is my code:
var context,
soundSource,
soundBuffer;
// Step 1 - Initialise the Audio Context
context = new webkitAudioContext();
// Step 2: Load our Sound using XHR
function playSound(url) {
// Note: this loads asynchronously
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.responseType = "arraybuffer";
// Our asynchronous callback
request.onload = function() {
var audioData = request.response;
audioGraph(audioData);
};
request.send();
}
// This is the code we are interested in
function audioGraph(audioData) {
// create a sound source
soundSource = context.createBufferSource();
// The Audio Context handles creating source buffers from raw binary
soundBuffer = context.createBuffer(audioData, true/* make mono */);
// Add the buffered data to our object
soundSource.buffer = soundBuffer;
// Plug the cable from one thing to the other
soundSource.connect(context.destination);
// Finally
soundSource.noteOn(context.currentTime);
}
// Stop all of sounds
function stopSounds(){
// How can do this?
}
// Events for audio buttons
document.querySelector('.pre').addEventListener('click',
function () {
stopSounds();
playSound('http://thelab.thingsinjars.com/web-audio-tutorial/hello.mp3');
}
);
document.querySelector('.next').addEventListener('click',
function() {
stopSounds();
playSound('http://thelab.thingsinjars.com/web-audio-tutorial/nokia.mp3');
}
);
You should be pre-loading sounds into buffers once, at launch, and simply resetting the AudioBufferSourceNode whenever you want to play it back.
To play multiple sounds in sequence, you need to schedule them using noteOn(time), one after the other, based on buffer respective lengths.
To stop sounds, use noteOff.
Sounds like you are missing some fundamental web audio concepts. This (and more) is described in detail and shown with samples in this HTML5Rocks tutorial and the FAQ.

How to read an HTML cookie in Flash?

I'm hoping to get pointed in the right direction here. The problem I'm having is trying to figure out how to read an HTML created cookie in Flash. I have a video player that should autoplay once in a 24hour period, the next day it should autoplay again for the end-user.
This is what the script on the HTML page looks like that displays the Flash player and the cookie:
<script type="text/javascript">
var so = new SWFObject("flvplayer.swf", "mymovie", "640", "394", "8", "#90ab69");
var x = readCookie('homepageIntro') // <- The Cookie (How do I read this in Flash?)
so.addParam("quality", "high");
so.addParam("wmode", "transparent");
so.useExpressInstall('expressinstall.swf');
so.addVariable("autostart", "false");
so.addVariable("file", "video.flv");
so.addVariable("key", "");
so.addVariable("showfsbutton", "false");
so.addVariable("noControls", "false");
so.addVariable("home", "true");
so.write("flashcontent");
</script>
Not knowing how to read that var x inside of Flash, I tried to get around having to use it by using a Flash cookie, however now the video player will only ever autoplay once and never ever autoplay again(unable to clear the Flash cookie).
public function sharedObjectCheck():void
{
if (mySharedObject.data.flashCookie == "true"){
//Code to NOT autoplay video
} else if (mySharedObject.data.flashCookie == null){
mySharedObject.data.flashCookie = "true"; //if first time, set the cookie value
mySharedObject.flush(); //add the cookie
}
}
I did some searching and found this Have a HTML page play Flash movie only once (not when revisited…) but again this is just a Flash function which never allows for a restart in a certain time period.
So my question to my fellow Flash stackers is how do I read that var x(cookie) in Flash?
A direct answer to your question is to use ExternalInterface
import flash.external.*
try {
var cookie : String = ExternalInterface.call("readCookie", "homepageIntro") as String;
} catch (error : SecurityError) {
trace("SecurityError:", e.message);
} catch (error : Error) {
trace("Error:", e.message);
}
You likely also need to set allowScriptAccess to let the call run.
Using a LSO is probably your best option, or passing in the value of x as a FlashVar.
Have you tried assigning the x value to flashvars?
so.addVariable("cookie", x);
In which case , you should be able to retrieve it in Flash , by doing so in the Document Class:
var params:Object = this.loaderInfo.parameters;
var cookie:Object = params.cookie;
Do it with a flash cookie, but actually store the last time autoplayed, rather than a simple flag.