Re: Looping a section of a song in StandingWave2

4 views
Skip to first unread message

Joe Berkovitz

unread,
May 20, 2010, 9:17:24 AM5/20/10
to Adrian Holovaty, standingwav...@googlegroups.com
Hi Adrian,

I'm CCing the StandingWave discussion group since it's the place to
post and answer this kind of question.

QueuePerformance is definitely the best way to go for exact looping.
As far as specifying the exact loop points in an MP3, your problem
will be that QueuePerformance wants to loop an entire list of complete
IAudioSources rather than partial sources. So the problem reduces to
how to make a source that is an excerpt of your MP3.

Here are a few ideas on that:

1. Wrap your MP3 in a SoundSource and extract a Sample for the range
to be looped, then use that Sample as the basis for looping in a
QueuePerformance.

2. Create a modified version of SoundSource that only looks at a
subrange of the underlying Sound object, applying some offset to the
passed-in starting frame and applying some maximum to the end frame.

3. Create a new IAudioFilter implementation that exposes some
arbitrary subrange of any IAudioSource as if it were the entire
source.

Hope this is helpful.

...joe


On Wed, May 19, 2010 at 6:08 PM, Adrian Holovaty <adr...@holovaty.com> wrote:
> Hi Joe,
>
> Thank you for developing and releasing StandingWave2! I've just begun
> using it for an experimental Flash sound app.
>
> I have two quick questions on how I might approach a particular
> problem using your library. I didn't notice a mailing list, so I
> apologize if it's too forward of me to e-mail you directly. If this is
> too annoying, just let me know where else to direct my question.
>
> I'd like to be able to loop a certain section of an MP3 with extreme
> accuracy (i.e., not using Flash timers). It seems like I can use
> QueuePerformance for that, but I can't figure out how to specify which
> section of the MP3 to play -- the "position" property is read-only on
> SoundSource and QueuePerformance. The docs vaguely suggest that "there
> are some exceptions" to not being able to set the position, but I
> can't figure out where to look. Is the answer to create a Filter...?
>
> Secondly (and sort of related), I'd like to be able to start playing
> an MP3 from an arbitrary position in the middle of the file, then
> start from the beginning as soon as the cursor reaches the end. What's
> the best way to do this?
>
> Again, I apologize if this e-mail is too forward -- I wasn't sure
> where else to go for help.
>
> Thank you,
> Adrian
>
> --
> Adrian Holovaty
> Chicago, IL
> http://www.holovaty.com/
>



--
... . . . j

--
You received this message because you are subscribed to the Google Groups "standingwave-discussion" group.
To post to this group, send email to standingwav...@googlegroups.com.
To unsubscribe from this group, send email to standingwave-disc...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/standingwave-discussion?hl=en.

Adrian Holovaty

unread,
May 24, 2010, 11:02:07 PM5/24/10
to standingwave-discussion
On May 20, 9:17 am, Joe Berkovitz <joseph.berkov...@gmail.com> wrote:
> 1. Wrap your MP3 in a SoundSource and extract a Sample for the range
> to be looped, then use that Sample as the basis for looping in a
> QueuePerformance.
>
> 2. Create a modified version of SoundSource that only looks at a
> subrange of the underlying Sound object, applying some offset to the
> passed-in starting frame and applying some maximum to the end frame.

Thanks very much for the helpful response, Joe. I've solved it, with
your help.

I first tried your option 1, but returning a dynamic Sample based on a
frame range was taking too much time for particularly long segments of
audio. I think this was happening because it was running
sound.extract() for the whole range of audio in advance, instead of
doing it on an as-needed basis.

I ended up implementing your option 2, subclassing SoundSource. I've
pasted my code below and grant permission to you to include it in the
StandingWave2 codebase if you feel like it. Also feel free to come up
with a better name for the class. :-)

This has been working well for me, with one exception: whenever I want
to loop a very short section of a sound, it only plays once. (To
reproduce, create a QueuePerformance with a single SoundSource or
SoundSourceSlice that's around a second or less in length. Then play
it, and it'll only play once instead of being looped infinitely.)

I think this is happening because SampleDataEvent gets fewer than 2048
samples, which causes it to assume it's reached the end of the file.
Per the SampleData Event docs (http://livedocs.adobe.com/flex/3/
langref/flash/events/SampleDataEvent.html) -- "If you provide fewer
than 2048 samples, Flash Player plays the remaining samples and then
stops the sound as if the end of a sound file was reached, generating
a SoundComplete event."

I tried modifying my SoundSourceSlice class's getSampleRange() method
to check the length of the slice and return a Sample that just
duplicates the data several times, to get past the 2048 limit, but
that messed with the position and duration and I couldn't get it to
work -- plus it feels like that fix should happen at a lower level.
Would this be considered a bug in StandingWave2, or should I be
working around it in some other way?

Adrian

-------------------------------------

package {

import flash.media.Sound;
import com.noteflight.standingwave2.elements.IAudioSource;
import com.noteflight.standingwave2.elements.Sample;
import com.noteflight.standingwave2.sources.SoundSource;

public class SoundSourceSlice extends SoundSource {
private var start_frame:Number;
private var end_frame:Number;

public function SoundSourceSlice(sound:Sound, start_frame:Number,
end_frame:Number) {
super(sound);
this._position = start_frame;
this.start_frame = start_frame;
this.end_frame = end_frame;
this.duration = (end_frame - start_frame) / 44100.0;
}
override public function resetPosition():void {
this._position = this.start_frame;
}
override public function getSampleRange(fromOffset:Number,
toOffset:Number):Sample {
return super.getSampleRange(fromOffset + this.start_frame,
toOffset + this.start_frame);
}
override public function clone():IAudioSource {
return new SoundSourceSlice(this.sound, this.start_frame,
this.end_frame);
Reply all
Reply to author
Forward
0 new messages