Archive for the ‘SoundManager’ Category

SoundManager Rev 2 + Loop Sequencing

I’ve updated SoundManager with a couple new features.

  • Manual and Automatic step based sequencing of loops.
  • Cross Fading between manual loop transitions.
  • Panning.
  • Global fade out, disabling and enabling

The sequencing is the really promising addition to this revision. I’m excited about this as I have a background in the Recording Engineering industry as well as doing underground dance music production. Before I get started, I must say that it’s not quite perfect yet. There is an issue with loops transitioning seamlessly depending on the processor load. It’s much much better then in AS2, but it still happens. If you’re dealing with audio/music that isn’t heavily dependent precise tempos, then you should be ok. If you are, then just be aware of this issue if your swf has a lot going on in it. I have a couple of ideas on how to fix this, but I want to make sure it’s efficient on the processor and continue doing more research on this first. I also need to get up to speed and/or get some hep with ByteArray level loading:)

Before using the sequencing feature, all loops need to be added/registered with the SoundManager:

import com.hydrotik.utils.SoundManager;

SoundManager.getInstance().addItem(new Loop1());
SoundManager.getInstance().addItem(new Loop2());
SoundManager.getInstance().addItem(new Loop3());
// etc…
 

All the above loops are registered using the library class references such as Loop1(). They can be later accessed using the string such as “Loop1″ as you will see below.

The SoundManager now has two new methods for setting up looping. The previous and still useful method is just by setting the number of loops in the play() arguments. The new methods use:

SoundManager.getInstance().startSequencer(“Loop1″);

No depending on if you add a single String for the Sound ID or an Array. Using a single String will start the sequencer in auto mode. The loop you specify in the String will continuously loop until you use the method:

SoundManager.getInstance().addSequenceItem(“Loop2″, false);

The first item is the String for the next sound. The is added to the sequence and starts as soon as the playing loop reaches the end. The second argument is a true/false for cross fading between loops.

For automatic sequencing you simple add an Array of Sound ID strings:

SoundManager.getInstance().startSequencer([“Loop1, Loop1, Loop2, Loop2, Loop3, Loop3″]);

The above will automatically play each loop in order and then stop at the end.

Here’s a diagram of the sequencing:

soundmanager_sequencing.gif

There are a number of features that I plan on adding and/or enhancing:

  • Some way to indicate cross fading in an automatic sequence
  • XML input of sequences
  • BPM output
  • Specifying of multiple phrases before the upcoming loop starts (I.e. play the loop 4 times before progressing)

I’ve omitted the source fla for the external sounds in the QueueLoader example because of the file size. Here’s the code that is on the first frame of the externalsounds.swf

import com.hydrotik.utils.SoundManager;

SoundManager.getInstance().addItem(new Loop1());
SoundManager.getInstance().addItem(new Loop2());
SoundManager.getInstance().addItem(new Loop3());
SoundManager.getInstance().addItem(new Loop4());

All of the above class references “Loop1″, etc. are located in the Library with the respective export for actionscript labels.

A number of people have been doing great work on audio processing and ByteArray streaming of PCM sound data, etc. Parsing the byte level data of loaded items is very tedious, but I plan on looking into this as a possbility for addressing the looping issue as well as other features.

I plan on including this code with a working example in the next revision of QueueLoader which I plan on posting soon. In the meantime, here’s the source:


Sound Manager Rev2 Source

Saturday, November 10th, 2007

QueueLoader AS3 rev 7 + Garbage Collection + SoundManager

Latest Version Info:
Click here for the current rev

Click here for the usage guide

Click here for the change log

Also click here for any posts related to the latest changes:
QueueLoader Updates

First things first. I’ve thrown in an additional utility that may or may not turn into it’s own project. Most likely it will as I hope to add gapless playback of loops, sound mixing, etc. But I’m already getting ahead of myself:) The reason I included my SoundManager utility is to illustrate how easy it is to use the new feature of accessing loaded swf library assets, as well as using it in a more advance management type setting. There’s a lot to cover, but first let me go over the updates I made to this revision.

  • Added a stop() method for stopping the queue. resume() is in the works.
  • Added LoaderContext for accessing the classes and references in QueueLoaded external swf.
  • Added an error dispatch for an undefined target/container.
  • Added a dispose() method for unloading loaded items from memory for Garbage Collection. More on this later.
  • More cleanup and optimization of code

The most significant changes I will go over is with the LoaderContext and dispose() method. The rest are pretty self explanatory.

dispose() + Garbage Collection
This download is a lot heavier in file size as I’ve included some large images to clearly indicate what’s happening with the Garbage Collector. I’m not going to go into too much detail on how Garbage Collection works. Essentially it is the process the Actionscript Virtual Machine uses to free up/dump unused memory. It does this intermittently and during times of low processing load, or when the memory has reached a certain level and needs to flush. To deal with this it is important to null out your variables and use removeChild to remove instances from a Display object. AS3 will retain the object in memory if there is a reference to it anywhere in the code. This can be a pain when trying to track data flow so it’s better to keep this in mind when planning your plan of attack. To learn more about Garbage Collection, check out Grant Skinner’s posts here.

I’ve included monitoring of garbage collection in the source example. System.totalMemory is the property for getting this info. But wait! There are some important things to be aware of.

  • Either there is a bug with System.totalMemory, or with the Loader.unload() method, so you will need to see changes to the GC in the browser.
  • Because of the above issue I have set the publish for local access only, so just make a note
  • System.totalMemory will give you what it says, total memory. So if you have other flash apps open in the browser you will see the memory used for those apps added to your QueueLoader Example. So be sure to close everything out.

When you dispose of a section that has used QueueLoader for loading of assets, you would use dispose() to remove the loaded assets and ready them for Garbage Collection. Lets assume we’ve set up a QueueLoader and it’s already loaded it’s assets, say for an image gallery. Here’s the block of code we would use to set up the QueueLoaded assets and the loader for GC:

_oLoader.dispose();
               
// Delete the QueueLoader containers
while(imageContainer.numChildren > 0){
        imageContainer.removeChildAt(0);
}

_oLoader = null;

You can clearly see this working in the example fla, but you get the idea. On to the next exciting feature…

Accessing externally loaded classes and library assets:
First caveat to this. Sandbox security issues come into play if you are loading things across domains. For this example we are assuming you are loading within the same domain. QueueLoader will do this, but you need to add some extra code. For more on cross scripting go here.

This feature allows you to add Library assets to an external swf, export them for actionscript as classes, and access those classes in your parent swf. This is great for loaded sounds, images, interface widgets, etc. Personally I use a separate swf for each library asset type. This also helps if you want to add a Manager class to one of your external swf files. In this example I added the SoundManager class.

You would do this by adding:

//Definition vars for accessing loaded swf libary classes in this scope
var addedDefinitions:LoaderContext = new LoaderContext();
addedDefinitions.applicationDomain = ApplicationDomain.currentDomain;

// Scope and Instantiate variables
var _oLoader:QueueLoader = new QueueLoader(false, addedDefinitions);

and then once your assets are loaded using QueueLoader you would access them using:

var Loop1Reference:Class = getDefinitionByName(“Loop1″) as Class;
var loop1:Sound = new Loop1Reference();
soundChannel = loop1.play();

I know I’m using code snippets so if it seems unclear, open up the queueloader.fla and you can see all of this in its entirety.

SoundManager
SoundManager is a class I added that may or may not be used in conjunction with QueueLoader. It’s in its infancy so this class is pretty straight forward. Basically what is happening is on the first frame of the externalsounds.swf there is code to add the library assets intro the SoundManager.

import com.hydrotik.utils.SoundManager;

SoundManager.getInstance().addItem(new Glitch1());
SoundManager.getInstance().addItem(new Glitch2());
SoundManager.getInstance().addItem(new Loop1());

Now anywhere in your application you can now play these sounds. Check out the source for more info.

My thanks to those who have commented and brought issues to my attention. Helps me to enhance this class and make it more powerful for simple as well as advanced usage. I always welcome your constructive criticism and suggestions for upcoming revisions. Please keep this in mind though. QueueLoader is a utility, and most of the control and administrative functions should be handled outside of the utility in its parent class.

If you’re using QueueLoader on a project or have used it, I’d love to hear about it!

Enjoy! :)
Donovan


A more recent version of this code has been posted! Go HERE

Monday, October 29th, 2007