0

I'm wanting to get the amplitude of a mp3 that's playing in my SWF. The problem is, it's embedded directly on the timeline.

Is there any way I can get to the sound (via ActionScript) that's playing when it's on the timeline?

Picture of the audio stream on the timeline

Update: For more clarity, when the sound is added to the stage (literally dragged from the Library to the stage) it appears to become a property of the frame?

Picture of the Sound Frame Properties

Paul Mignard
  • 5,824
  • 6
  • 44
  • 60
  • 2
    I've worked with audio in Flash Frames a lot and have never come across any way to access that type of information for audio that is embedded on a frame. If you need to get the amplitude, I think the best way is to use the `Sound` Class. Reference: http://www.leebrimelow.com/actionscript-3-quicktip-3-sound-amplitude/ – Anil Oct 13 '14 at 20:15
  • @SlyRaskal - that's the rub, I can't use Sound - the mp3 was imported and added to the stage at design time. :( Thanks! – Paul Mignard Oct 15 '14 at 01:53
  • If it's imported then you just need to make a linkage to it as Class and then it can be used as any loaded MP3 would be. See this guide: scroll to [Playing an Internal Sound](http://www.republicofcode.com/tutorials/flash/as3sound/) – VC.One Oct 15 '14 at 08:22
  • Unless you mean your audio is inside yet another SWF that was brought into your current Flash project? If so try changing **Base Class** to being **flash.media.Sound** in the properties and follow my guide below or the link above – VC.One Oct 15 '14 at 08:32
  • No the audio is inside a single swf but there's no frame where I explicitly call sound.play(). Because it's a sound on a frame it just starts playing. The link you provided plays it as an embedded asset but the sound is actually directly on the timeline so there's no object created so to speak. The sound is literally dragged out of the library on to the stage and put on the frame it self. It's like the frame itself has a sound property... – Paul Mignard Oct 16 '14 at 14:56
  • You're right. The visual seems to be just an **animator's aid** but the sound really exists in the background and is out of access. See my other other comment below about pre-processing the audio outside of Flash before importing to library – VC.One Oct 17 '14 at 20:00

1 Answers1

3

Any imported item is accessible in the Library (ctrl+L or find under Window in top menu bar)..

In the Library just right-click the current name of your audio item (will be Type: Sound) and choose Properties. In there you should see Linkage section so tick Export For ActionScript.

In the now available Class box you can now put your own preferred instance name (no_spaces) and leave Base Class as flash.media.Sound (should be that way)

//assuming you have.. my_Audio ..as Linkage Class name
var mySound:Sound = new my_Audio();
var myChannel:SoundChannel = new SoundChannel();

myChannel = mySound.play();

addEventListener(Event.ENTER_FRAME, show_Amplitude);

function show_Amplitude(evt:Event)
{
  // where 200 is your own number for the maximum width or height of amplitude bars
  mc_ampLeft.width  = myChannel.leftPeak  * 200;
  mc_ampRight.width = myChannel.rightPeak * 200;
}


Alternative solution: Get amplitude via computeSpectrum
For whatever situations where the above solution is not applicable, then the alternative would be to just use ComputeSpectrum (which works globally on all audio since its tied to the SoundMixer not just specific sound Object). This is an example as starting point (tweak this or research a better formula)

var n_RMS   :Number = 0;
var n_FFT   :Number = 0;
var max_AMP :Number = 200; // max width or height of bar at full volume
var FFT_bytes:ByteArray = new ByteArray;

addEventListener(Event.ENTER_FRAME, compute_Amplitude);

function compute_Amplitude(evt:Event)
{
    SoundMixer.computeSpectrum( FFT_bytes, false, 0 );

    for (var i:int = 0; i < 256; i++) //GETS LEFT CHANNEL FFT
    {
        n_FFT = FFT_bytes.readFloat();
        n_RMS = 0.8 * Math.sqrt( Math.abs(n_FFT) ) / 0.434294481904;
    }
        mc_ampLeft.width = (n_RMS /2) * max_AMP; //update LEFT bar

    for (var j:int = 0; j < 256; j++) //GETS RIGHT CHANNEL FFT
    {
        n_FFT = FFT_bytes.readFloat();
        n_RMS = 0.8 * Math.sqrt( Math.abs(n_FFT) ) / 0.434294481904;
    }
        mc_ampRight.width = (n_RMS /2) * max_AMP; //update RIGHT bar
}
VC.One
  • 14,790
  • 4
  • 25
  • 57
  • Wow - thanks for the comprehensive answer! Unfortunately, it doesn't work (or maybe I'm doing something incorrectly?) Everything works IF I use sound.play() but the problem is that I'm never instantiating an object. To get the sound to play, it's being dragged from the library to the stage and the way it's manipulated is from the frame properties window (I'll update the question with screenshot of this.) Even using the SoundMixer example doesn't work with audio playing using this method (it does however work fantastically when playing a sound I've instantiated...) – Paul Mignard Oct 16 '14 at 14:59
  • I've seen the edit and get your point. The problem is Flash has 2 types of users, animators & coders. So if its on the timeline its like saying "I just need a visual of the audio for my character's lip-sync" or whatever and you never get to involve code (for audio processing/analysis they assume its something only coders would be interested in). So no luck and I'm out of ideas there (can't beat the system, lol) – VC.One Oct 17 '14 at 19:52
  • If you're using as just background audio then its worth doing the "as a Class object" version but if you needed effects like fade in/out then you'll have to pre-process before importing into Flash. You can try the free **[Audacity Audio Editor](http://audacity.sourceforge.net/download/)**. If you don't know it then Youtube has many tutorials for it – VC.One Oct 17 '14 at 19:56
  • That's cool - I really appreciate all the time that you put into this answer! Thanks for all of your help! – Paul Mignard Oct 18 '14 at 23:59