How to play several sounds one by one in flex - apache-flex

I have several sounds, how can I play them one by one. When I just use play(), the sounds play simultaneously. I also tried to handle SOUND_COMPLETE event, but it doesn't work.
sampleMP3A.play().addEventListener(
Event.SOUND_COMPLETE,
function(event:ResultEvent, o:Object):void {
sampleMP3B.play();
});
sampleMP3A plays well, but sampleMP3B doesn't play.

private var sounds:Array // it contain your sounds.
private var ind:Number = 0;
private function playSounds():void
{
var req:URLRequest = new URLRequest(sounds[ind]);
var s:Sound = new Sound(req);
var soundChannel:SoundChannel = new SoundChannel;
soundChannel = s.play();
soundChannel.addEventListener(Event.SOUND_COMPLETE,onComplete);
}
private function onComplete(event:Event):void
{
ind++;
playSounds();
}

Related

Flex: how to change the volume of an EMBEDDED sound?

Searching for how to change the volume of sounds, I always get this irritating snd=new Sound(URLRequest), followed by snd.setVolume(val). Oh, fine, but my sound is not an URLRequest, it's an embed.
I've made a lot of random attempts (1) to no avail. How am I supposed to do that instead?
(1) including casting my class to Sound, creating a Sound with the embed class as argument, creating a SoundTransform and setting it to the channel, etc.
Instantiate your embedded class like this:
[Embed(source="MySound.mp3")]
public var soundClass:Class;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
var smallSound:Sound = new soundClass() as Sound;
var trans:SoundTransform = new SoundTransform(.01);
smallSound.play(0,0,trans);
}
Update:
In case what you really wanted to know was how to change the volume if the sound was already playing:
[Embed(source="MySound.mp3")]
public var soundClass:Class;
public var smallSound : Sound;
public var vol : Number = 0.01;
public var trans : SoundTransform;
public var chan : SoundChannel = new SoundChannel();
protected function application1_creationCompleteHandler(event:FlexEvent):void {
smallSound = new soundClass() as Sound;
trans = new SoundTransform(vol);
chan = smallSound.play(0,0,trans);
}
protected function volUp_clickHandler(event:MouseEvent):void {
vol += .1;
trans = new SoundTransform(vol);
chan.soundTransform = trans;
}

AdvancedDatagrid GroupingCollection in AS3

My AIR-Application is based on Mate.
I receive Data from a SQLite and put the Date into a ArrayCollection.
In the class of my AdvancedDataGrid, i create a GroupingCollection via mxml. All works fine.
I prefer to build the GroupingCollection in Actionscript. But i can't find anything, how to code this.
In the adobe help itself, they create a GroupingCollection in mxml.
The goal is, to instanciate the gc in model of mate for another class. This will be a chart and the dataProvider must be the gc.
Another Idea is, to build the groupingCollection and put it into the model via two-way-bindung. But I'm not sure, if this will work.
Have you any hint for me?
Thank you
Frank
It works like this. What a fight.
private function onCreationComplete () :void
{
adg.dataProvider = createDataProvider();
}
private function createDataProvider () :GroupingCollection2
{
var tmp:GroupingCollection2 = new GroupingCollection2();
tmp.source = dpArrColl;
tmp.grouping = adgGrouping();
tmp.refresh(false);
return tmp;
}
private function adgGrouping () : Grouping
{
var tmp:Grouping = new Grouping();
tmp.fields = [groupingFieldArray()];
return tmp;
}
private function groupingFieldArray () :GroupingField
{
var tmp:GroupingField = new GroupingField();
tmp.name = "groupName1";
tmp.summaries = [adgSummaries()];
return tmp;
}
private function adgSummaries () : SummaryRow
{
var tmp:SummaryRow = new SummaryRow();
tmp.summaryPlacement = "group";
tmp.fields = [adgSummaryFiled1(), adgSummaryField2()];
return tmp;
}
private function adgSummaryFiled1 () :SummaryField2
{
var tmp:SummaryField2 = new SummaryField2();
tmp.dataField = "Sumfiel1";
tmp.summaryOperation = "SUM";
return tmp;
}
private function adgSummaryField2 () : SummaryField2
{
var tmp:SummaryField2 = new SummaryField2();
tmp.dataField = "Sumfield2";
tmp.summaryOperation = "COUNT";
return tmp;
}
I hope, someone will help this someday.
BR
Frank

Playing sound files one after another in flex AIR code

I have a set of sound clips to be played one after another in a sequence with couple of time interval inbetween.
In my case, its a question - followed by the set of four options.
When I write the below code, all the audop files start together at same time. How can I had time delay inbetween, so that the second clip plays only after the first one is over, and the third one starts playing, only when the second option is over.
I am with Flex AIR AS 3. See code below. Thanks in advance.
private function playCoundClips(): void
{
//set audio clips
var questionClipSource : String = "assets/quiz_voiceovers/" + questionCode + "Q.mp3";
var optionAClipSource : String = "assets/quiz_voiceovers/" + questionCode + "a.mp3";
var optionBClipSource : String = "assets/quiz_voiceovers/" + questionCode + "b.mp3";
var optionCClipSource : String = "assets/quiz_voiceovers/" + questionCode + "c.mp3";
var optionDClipSource : String = "assets/quiz_voiceovers/" + questionCode + "d.mp3";
playThisClip(questionClipSource);
playThisClip(optionAClipSource);
playThisClip(optionBClipSource);
playThisClip(optionCClipSource);
playThisClip(optionDClipSource);
}
private function playThisClip(clipPath : String) : void
{
try
{
clipPlayingNow = true;
var soundReq:URLRequest = new URLRequest(clipPath);
var sound:Sound = new Sound();
var soundControl:SoundChannel = new SoundChannel();
sound.load(soundReq);
soundControl = sound.play(0, 0);
}
catch(err: Error)
{
Alert.show(err.getStackTrace());
}
}
Thanks
Sumit
The problem is you are spawning multiple asynchronous calls. Implement a complete call back function on Sound and then call your playThisClip function inside the callback function. (You can sleep for predefined time before calling)
Time delay, is a very bad idea (in 99% of the case).
Have a look at the SOUND_COMPLETE event (see the doc)
This event is triggered when the sound stops playing.
So, it's now very easy to play sounds in sequence.
A simple example (not tested but idea is here) :
//declare somewhere a list of sounds to play
var sounds:Array=["sound_a.mp3","sound_a.mp3"];//sounds paths
//this function will play all sounds in the sounds parameter
function playSounds(sounds:Array):void{
if(!sounds || sounds.length==0){
//no more sound to play
//you could dispatch an event here
return;
}
var sound:Sound=new Sound();
sound.load(new URLRequest(sounds.pop()));
var soundChannel:SoundChannel = sound.play();
soundChannel.addEVentListener(Event.SOUND_COMPLETE,function():void{
soundChannel.removeEventListener(Event.SOUND_COMPLETE,arguments.callee);
playSounds(sounds);
});
}
This helped me
http://livedocs.adobe.com/flex/3/html/help.html?content=Working_with_Sound_09.html
One need to write code for:
sound.addEventListener(Event.ENTER_FRAME, onEnterFrame);
soundControl.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete);
private function onEnterFrame(event:Event):void
{
var estimatedLength:int =
Math.ceil(sound.length / (sound.bytesLoaded / sound.bytesTotal));
var playbackPercent:uint =
Math.round(100 * (soundControl.position / estimatedLength));
}
private function onPlaybackComplete(event:Event):void
{
Alert.show("Hello!");
}

Flash "visible" issue

I'm writing a tool in Flex that lets me design composite sprites using layered bitmaps and then "bake" them into a low overhead single bitmapData. I've discovered a strange behavior I can't explain: toggling the "visible" property of my layers works twice for each layer (i.e., I can turn it off, then on again) and then never again for that layer-- the layer stays visible from that point on.
If I override "set visible" on the layer as such:
override public function set visible(value:Boolean):void
{
if(value == false) this.alpha = 0;
else {this.alpha = 1;}
}
The problem goes away and I can toggle "visibility" as much as I want. Any ideas what might be causing this?
Edit:
Here is the code that makes the call:
private function onVisibleChange():void
{
_layer.visible = layerVisible.selected;
changed();
}
The changed() method "bakes" the bitmap:
public function getBaked():BitmapData
{
var w:int = _composite.width + (_atmosphereOuterBlur * 2);
var h:int = _composite.height + (_atmosphereOuterBlur * 2);
var bmpData:BitmapData = new BitmapData(w,h,true,0x00000000);
var matrix:Matrix = new Matrix();
var bounds:Rectangle = this.getBounds(this);
matrix.translate(w/2,h/2);
bmpData.draw(this,matrix,null,null,new Rectangle(0,0,w,h),true);
return bmpData;
}
Incidentally, while the layer is still visible, using the Flex debugger I can verify that the layer's visible value is "false".
Wait a frame between setting visible and calling changed(). Use the invalidateProperties()/commitProperties() model.
private bool _isChanged = false;
private function onVisibleChange():void
{
_layer.visible = layerVisible.selected;
_isChanged = true;
invalidateProperties();
}
protected override function commitProperties():void {
super.commitProperties();
if (_isChanged) {
_isChanged = false;
changed();
}
}

Pause and resume download in flex?

Is it possible in an air application to start a download, pause it and after that resume it?
I want to download very big files (1-3Gb) and I need to be sure if the connection is interrupted, then the next time the user tries to download the file it's start from the last position.
Any ideas and source code samples would be appreciated.
Yes, you would want to use the URLStream class (URLLoader doesn't support partial downloads) and the HTTP Range header. Note that there are some onerous security restrictions on the Range header, but it should be fine in an AIR application. Here's some untested code that should give you the general idea.
private var _us:URLStream;
private var _buf:ByteArray;
private var _offs:uint;
private var _paused:Boolean;
private var _intervalId:uint;
...
private function init():void {
_buf = new ByteArray();
_offs = 0;
var ur:URLRequest = new URLRequest( ... uri ... );
_us = new URLStream();
_paused = false;
_intervalId = setInterval(500, partialLoad);
}
...
private function partialLoad():void {
var len:uint = _us.bytesAvailable;
_us.readBytes(_buf, _offs, len);
_offs += len;
if (_paused) {
_us.close();
clearInterval(_intervalId);
}
}
...
private function pause():void {
_paused = true;
}
...
private function resume():void {
var ur:URLRequest = new URLRequest(... uri ...);
ur.requestHeaders = [new URLRequestHeader("Range", "bytes=" + _offs + "-")];
_us.load(ur);
_paused = false;
_intervalId = setInterval(500, partialLoad);
}
if you are targeting mobile devices, maybe you should take a look at this native extension: http://myappsnippet.com/download-manager-air-native-extension/ it supports simultaneous resumable downloads with multi-section chunks to download files as fast as possible.

Resources