This content has been marked as final. Show 10 replies
one of the nice things about flash is, it's extensible. if you find the sound class fails to meet your needs, extend it to a class that includes the things you want.
Extensibility is great. I extend classes all the time. However, SoundChannel, (the class you would generally extend in this case, so you can access its sound property), is marked FINAL. This means you *can't* extend it. This is why I wrote:
" I wouldn't mind nearly so much, if it weren't for the fact that some one for some impenetrably idiotic reason, chose to make SoundChannel FINAL." I needed to vent.
That's also why I need a workaround. I can fix some ills by extending Sound, (which isn't FINAL), but this doesn't help address the fact that you're usually manipulating SoundChannel instances, not Sound objects.
I don't like my current workaround, since it doesn't elegantly handle situations where you have multiple instances of the same sound, and some are set to loop while some aren't.
Currently, I'm using the array index of a sound that's playing to look up a matching SoundChannel, and vice versa. This is proving to break down quickly when you have multiple SoundChannel instances playing, and you're not sure which one you should be manipulating.
If you're building a game, for example, it doesn't take long before you have a lot of sounds running around...
If inheritance is a no go why not composition, or decoration?
i wouldn't extend the soundchannel class. i'd extend the sound class and add a class property for the soundchannel because that seems to be irking you. for example:
I have basically ended up using a composition object based on the Sound class - extending Sound and adding array members to it where I can stash SoundChannel objects - a slightly more evolved approach of what kglad was getting at above, (after all, you have to track multiple channels, and also keep track of which sounds are looping, and how many iterations they've run through).
This way I can iterate through all the soundChannel instances bound to a sound, and I can also keep track of how many times looped soundChannel instances have repeated. This works, but it involves a good deal of brute force, which "feels" wrong to me. It also forces me to make assumptions about how things should behave - for example, if I get a call to fade a sound out - do I only manipulate the last instance of it, or every instance, or do I build in yet another property and lable instances?...
Imagine how much simpler handling audio would be, if, for example, you could dynamically bind ID's and event handlers to SoundChannel instances...
At any rate, I have a workable solution now that's much neater than external arrays - even if it has more lines of code, and more properties to keep track of than I would have liked. Thanks for your help.
why not have one sound instance for each sound like i did in my above code? then each sound has a reference to, for example, its own soundchannel.
the only master class you might need would be one that would contain a reference to all the sound instances created.
yeah, I believe you should pursue kglad's suggestion, in that each sound object has it's own SoundChannel member, as a Sound Has-A SoundChannel, right?
You can customize events, to pass SoundChannel properties, and implement this within your custom Sound class. Check it: http://www.gskinner.com/blog/archives/2007/07/building_a_stat_1.html
I might think of setting up your structure as such.
Sound Control Class responsible for instancing IveySound instances. IveySound instances have SoundChannel members, and dispatch customEvents on certain events such as 'LOOP_RESTARTED', 'SOUND_ENDED, etc'. But I would make the IveySound instance responsible for tracking it's number of loops, and disposal.
The customEvents pass the IveySound instance name, and any other pertinent info.
Sound Control Class listens for these events, as well as user-interaction events, so that when your user scores a point, the Sound Control class can instance an IveySound('score.mp3', 1), which has a loop property of 1 so it only plays once, then disposes itself. Whereas when the user enters level 2, the Sound Control Class can instance an IveySound('level2.mp3', 0, 'levelLoop'), which loops infinitely until the Sound Control Class tells all IveySound instances with levelLoop members to stop. etc
I think you're not understanding what I'm talking about, and it's important to clarify in case someone else reads this and is lead astray.
Binding individual soundChannel instances to sound objects is a very, very bad idea. In a game, for example, you almost never end up playing only one instance of a sound at a time. Loading multiple sound instances into memory would be a huge waste, and it takes time. How would you handle this? What if you loaded five instances of a sound effect into memory, and you needed to play a sixth while the five your created were all playing? You'd have to load a new instance of the sound, and then by the time you accessed your hard drive, everything would be out of synch.
You need to be able to dynamically create instances of sounds as you play them. That's why you can't have a 1to1 relationship between sounds and soundChannels.
And what's with the link to Mr. Skinner's article on creating eventDispatcher objects from inside static classes? That's nice. I do, coincidentally, use exactly that mechanism where appropriate. However, it has nothing to do with this situation.
I've never done what you're doing with streaming multiple sound objects simultaneously, so don't know the performance limitations that would encounter.
But in my case I am using a class which extends Sound, and has SoundChannel as a class member. I also have a static event object which broadcasts info about that sound object, so I know it's position, id, and other info.
soundChannel instances are already bound to an individual Sound. there's nothing you can do about that.
your issue was accessing the soundChannel instance via its Sound instance. and i gave you a solution allowing your access the soundChannel instance via a sound instance.
if you want to reuse the same sound instance then remove the URLRequest and play() method from the constructor. otherwise, just kill the sound instance when it's no longer needed.