Skip to main content
Known Participant
July 14, 2008
Answered

how to calculate second and minisecond for audio cue point

  • July 14, 2008
  • 2 replies
  • 2298 views
I'm trying to do a sound sync for the audio and movie clip in Flash. I found a tutorial on the web and it seems to work. However, I don't know how to calculate the second and mini second from the mp3 file. The first frame has the following lines to define the time for each animation:
// Import class
import net.quip.sound.SoundSync;

// Stop main timeline
stop();

// Create an instance of SoundSync
var ss:SoundSync = new SoundSync();

ss.addCuePoint("IT", 20100);
ss.addCuePoint("admin", 20000);
ss.addCuePoint("maitenance", 19800);
ss.addCuePoint("treatment", 16479);
ss.addCuePoint("engineering", 14598);
as.addCuePoint("logo_epa_npdes", 12356);
ss.addCuePoint("construction", 8967);
ss.addCuePoint("370mgd", 7896);
ss.addCuePoint("mc_650,000",5439 );
ss.addCuePoint("130mgd", 3254);
ss.addCuePoint("1938", 2439);
ss.addCuePoint("vintage_mc", 0);

// Use instance to load external MP3
ss.loadSound("Scn04-05.mp3", true);

// Create a listener object for the
// cuePoint and onSoundComplete events
var listener:Object = new Object();
listener.cuePoint = function():Void {
play();
}
listener.onSoundComplete = function():Void {
play();
}
ss.addEventListener("cuePoint", listener);
ss.addEventListener("onSoundComplete", listener);

and the soundsync.as file as follows:
import mx.events.EventDispatcher;
import mx.utils.Delegate;
class net.quip.sound.SoundSync extends Sound {
// PROPERTIES
private var _cuePoints:Array;
private var _currentCuePoint:Number;
private var _interval:Number;
private var _intervalDuration:Number;
private var _secondOffset:Number;
// Event dispatcher
public var dispatchEvent:Function;
public var addEventListener:Function;
private var removeEventListener:Function;
// CONSTRUCTOR
public function SoundSync(target:MovieClip) {
super(target);
init();
}
// METHODS
private function init():Void {
// Initialize properties
_cuePoints = new Array();
_currentCuePoint = 0;
_intervalDuration = 200;
_secondOffset = 0;
// Initialize class instance as valid event broadcaster
EventDispatcher.initialize(this);
}
// Add Cue Point
public function addCuePoint(cuePointName:String, cuePointTime:Number):Void {
_cuePoints.push(
{
type: "cuePoint",
name: cuePointName,
time: cuePointTime,
target: this
}
);
_cuePoints.sortOn("time", Array.NUMERIC);
}
// Get Cue Point
public function getCuePoint(nameOrTime:Object):Object {
var counter:Number = 0;
while (counter < _cuePoints.length) {
if (typeof(nameOrTime) == "string") {
if (_cuePoints[counter].name == nameOrTime) {
return _cuePoints[counter];
}
} else if (typeof(nameOrTime) == "number") {
if (_cuePoints[counter].time == nameOrTime) {
return _cuePoints[counter];
}
}
counter++;
}
return null;
}
// Get Current Cue Point Index
private function getCurrentCuePointIndex(cuePoint:Object):Number {
var counter:Number = 0;
while (counter < _cuePoints.length) {
if (_cuePoints[counter].name == cuePoint.name) {
return counter;
}
counter++;
}
return null;
}
// Get Next Cue Point Index
private function getNextCuePointIndex(seconds:Number):Number {
seconds = (seconds) ? seconds : 0;
var counter:Number = 0;
while (counter < _cuePoints.length) {
if (_cuePoints[counter].time >= seconds * 1000) {
return counter;
}
counter++;
}
return null;
}
// Remove Cue Point
public function removeCuePoint(cuePoint:Object):Void {
_cuePoints.splice(getCurrentCuePointIndex(cuePoint), 1);
}
// Remove All Cue Points
public function removeAll_cuePoints():Void {
_cuePoints = new Array();
}
// Start
public function start(secondOffset:Number, loops:Number):Void {
super.start(secondOffset, loops);
dispatchEvent({type:"onStart", target:this});
// Reset current cue point
_secondOffset = secondOffset;
_currentCuePoint = getNextCuePointIndex(secondOffset);
// Poll for cue points
clearInterval(_interval);
_interval = setInterval(Delegate.create(this, pollCuePoints), _intervalDuration);
}
// Load Sound
public function loadSound(url:String, isStreaming:Boolean):Void {
super.loadSound(url, isStreaming);
clearInterval(_interval);
_interval = setInterval(Delegate.create(this, pollCuePoints), _intervalDuration);
}
// Stop
public function stop(linkageID:String):Void {
if (linkageID) {
super.stop(linkageID);
} else {
super.stop();
}
dispatchEvent({type:"onStop", target:this});
// Kill polling
clearInterval(_interval);
}
// Poll Cue Points
private function pollCuePoints():Void {
// If current position is near the current cue point's time ...
var time:Number = _cuePoints[_currentCuePoint].time;
var span:Number = (_cuePoints[_currentCuePoint + 1].time) ? _cuePoints[_currentCuePoint + 1].time : time + _intervalDuration * 2;
if (position >= time && position <= span) {
// Dispatch event
dispatchEvent(_cuePoints[_currentCuePoint]);
// Advance to next cue point ...
if (_currentCuePoint < _cuePoints.length) {
_currentCuePoint++;
} else {
_currentCuePoint = getNextCuePointIndex(_secondOffset);
}
}
}
// EVENT HANDLERS
// onSoundComplete
public function onSoundComplete():Void {
// Kill polling
clearInterval(_interval);
// Reset current cue point
_currentCuePoint = 0;
// Dispatch event
dispatchEvent({type:"onSoundComplete", target:this});
}
}

any help will be greatly appreciated.
This topic has been closed for replies.
Correct answer Newsgroup_User
wuzhishan,

> Hi Dave, your tutorial is a cute one and it is very useful.

Thanks! My daughter is the cute one. She inherited all of that from
me, so I don't have any left. ;)

> I'm sorry I didn't make my question clear.

No worries. :)

> I listen to the mp3 in Windows Media Player and try to
> get the time for the cue, I found it on the bottom of the
> player the time shows 00:26.

I'm with ya.

> How do I writer this number in the code? Is it 0026 or 26?

The code is expecting milliseconds, so 26 seconds would be written like
this:

26000

If it said 1:22 (a minute and 22 seconds), you would write it like this:

82000

... which is 60 seconds for the single minute, plus 22 from the seconds
side, then multiplied by 1,000 to get milliseconds.


David Stiller
Adobe Community Expert
Dev blog, http://www.quip.net/blog/
"Luck is the residue of good design."


2 replies

Inspiring
July 14, 2008
wuzhishan,

> I'm trying to do a sound sync for the audio and movie clip in Flash.
> I found a tutorial on the web and it seems to work. However, I
> don't know how to calculate the second and mini second from
> the mp3 file.

I wrote that article and the code, so I'll help if I can. :) But I'm
not sure I understand your question yet.

Are you asking, "How do I convert minutes and seconds into
milliseconds?" If so, here's an example. Let's say you want to add a cue
point at 4 minutes and 41 seconds. Converting the 41 seconds part is easy:
just mutiply that number by 1,000. So far, you've got 41,000 milliseconds.
Now set that number aside for just a moment and turn your attention to the
minutes.

You've got 4 minutes. There are 60 seconds in a minute, so convert to
seconds first. 4 * 60 is 240. At this point, you're back to where you were
before (a seconds value). Multiply that 240 by a thousand -- 240,000 -- and
add it to the other milliseconds value: 240,000 plus 41,000 equals 281,000
milliseconds.

So 4min 41sec is 281,000 milliseconds.

Does that help?


David Stiller
Adobe Community Expert
Dev blog, http://www.quip.net/blog/
"Luck is the residue of good design."


Newsgroup_UserCorrect answer
Inspiring
July 16, 2008
wuzhishan,

> Hi Dave, your tutorial is a cute one and it is very useful.

Thanks! My daughter is the cute one. She inherited all of that from
me, so I don't have any left. ;)

> I'm sorry I didn't make my question clear.

No worries. :)

> I listen to the mp3 in Windows Media Player and try to
> get the time for the cue, I found it on the bottom of the
> player the time shows 00:26.

I'm with ya.

> How do I writer this number in the code? Is it 0026 or 26?

The code is expecting milliseconds, so 26 seconds would be written like
this:

26000

If it said 1:22 (a minute and 22 seconds), you would write it like this:

82000

... which is 60 seconds for the single minute, plus 22 from the seconds
side, then multiplied by 1,000 to get milliseconds.


David Stiller
Adobe Community Expert
Dev blog, http://www.quip.net/blog/
"Luck is the residue of good design."


Inspiring
July 24, 2008
wuzhishan,

> I'm not a programer.

That's okay. :)

> I have very basic understanding of Actionscript. I did not
> change anything in your SoundSync.as file. I just replace
> the name of instances with mine.

In that case, I'm curious what you meant earlier when you mentioned
movie clips -- I guessing frame labels? -- but we'll find out. :) To
perform a bit of troubleshooting, let's replace a bit of code inside your
event handler function. Specifically, this means the portion of
ActionScript that "hears" the cue point event and does something about it
(handles it).

Change this part here:

// Create a listener object for the
// cuePoint and onSoundComplete events
var listener:Object = new Object();
listener.cuePoint = function():Void {
play();
}

To this:

// Create a listener object for the
// cuePoint and onSoundComplete events
var listener:Object = new Object();
listener.cuePoint = function(evt:Object):Void {
trace("cue point " + evt.time);
}

Instead of displaying frame labels on your timeline, this will send text
content to the Output panel when you test your SWF. You should see the
words "cue point" followed by a time value in milliseconds.

My goal at this point is to see if the timing of these Output panel
messages corresponds appropriately to the timing of your cue points.


David Stiller
Adobe Community Expert
Dev blog, http://www.quip.net/blog/
"Luck is the residue of good design."



wuzhishan,

> I try your code and get the following cue point:
> cue point 0
> cue point 2000
> cue point 4000
// etc.

Okay, good so far.

> They do correspond to my cue point set for the movie clips(cue point
> 64000 is missing)

Good. :) Tthat's good news. I'm not so concerned about that last
cuepoint -- the missing one -- at the moment, as it might possibly be too
close to the end of the audio file, and might have been picked up by the
"complete" event handler earleir.

> I don't have frame label in the movie. The cue point name
> "mc_community", "vintage_mc", etc. are the names of my
> movie clips. Just like the name "Benjamin Franklin" in your
> sample movie in the tutorial.

Okay.

> The differences between yours and mine is that yours are
> graphics with simple fade in and fade out movement but mine
> are movie clips containing many frames of movement.

My hunch, wuzhishan, is that your timing issue stems from the way your
movie clips are set up. I say this because you said your trace() statements
correspond to the cue points as they should. In fact, all the event handler
does is issue a play() function, which sets the timeline in motion again.
The timing involved -- between the timeline and the nested timelines of your
movie clips -- depends on the overall framerate of your movie, in addition
to the duration of your various timelines.

You don't have to use the event handler to trigger a play(). Instead,
you could use it to attach movie clips from your library, or turn on (or
off) the visibility of movie clips already on the Stage. That might improve
things for you.

Does that make sense?


David Stiller
Adobe Community Expert
Dev blog, http://www.quip.net/blog/
"Luck is the residue of good design."


Inspiring
July 14, 2008
Why do you need to compute the milli/second (I assume that is what you mean)? The cuepoints know what the time is and when they need to be called. What are you actually trying to accomplish?

In that part in your file you could change this:

listener.cuePoint = function():Void {
play();
}

to something more useful, perhaps that would help:

listener.cuePoint=function(event:Object):Void{
trace("Cuepoint "+event.name+" at: "+event.time);
play();
}