AS3 Sound Visualizer app or code


#1

I have been editing on a sound wave recently and found it interesting to see the visualization of the sounds that are part of the waveform. We have all made mp3 players that showed the waveform live like so:

I would like to be able to show the spectral display as the sound is playing and have it move in the background. This is from Adobe Audition and it does not support follow the cursor. The cursor moves from left side of the screen to the right side of the screen.

I want the cursor to stay locked in the center of the screen and the spectral display (red background) to move from right to left as the sound is played back.

Before I reinvent the wheel is there an app that does this (free - this is for a single video)? If not is there an AS3 library or project that already does this? In the past you could throw a mouse at your office and hit a guy who wrote a sound visualizer.

If nothing is out there anyone want to help code this?


#2

I’m not sure I understand the effect you want to achieve

is it something like that ?

see Andre Michelle’s Sound Spectrum
sources are available: http://lab.andre-michelle.com./swf/f9/soundspectrum/SoundSpectrum.zip


#3

There are two things I’m trying to do: Display the sound wave spectrum in real time and have it scroll by (so I have to read ahead a bit).

Here is an example. The sound is playing back but I am manually using the scroll bar to keep the cursor in the same place (not doing a very good job of it).

The top half of the screen is the form of the sound wave in time (green). The bottom half is the spectral frequency display (red). I am interested in reading a sound wave and displaying that area in real time.

How I understand spectral frequency area is that the bright red shows the concentration of the sound wave. The top on the vertical scale is the high frequency and the bottom is the low frequency. The faster the frequency of the sound wave the higher the pitch. The slower the sound wave frequency the lower the pitch.

I know you know this but for someone else sound is simply the vibration of pressure through a medium such as air or water.

Thanks for the link. I’ll take a look.


#4

OK I’ve kind of got something working. :slight_smile:
The code gave me a starting point but most of the work is done by compute spectrum. Here is what I’ve got so far:

It’s pretty rough. Notes below code.

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
					   xmlns:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx"
					   applicationComplete="windowedapplication1_applicationCompleteHandler(event)"
					   resize="component_resizeHandler(event)"
					   keyUp="windowedapplication1_keyUpHandler(event)"
					   showStatusBar="false"
					   frameRate="90"
					   height="500" width="800">
	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
			import mx.events.ResizeEvent;
			import mx.utils.ColorUtil;
			
			private var sound: Sound;
			private var soundChannel: SoundChannel;
			private var bytes: ByteArray;
			
			private var peaks: BitmapData;
			private var displace: Matrix;
			private var rect: Rectangle;
			public var soundArray:Array = [];
			public var peakBitmap:Bitmap;
			public var isPlaying:Boolean;
			
			protected function windowedapplication1_applicationCompleteHandler(event:FlexEvent):void
			{
				sound = new Sound();
				sound.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
				sound.load( new URLRequest( 'song1.mp3' ) );
				soundChannel = sound.play(0, 100);
				isPlaying = true;
				
				bytes = new ByteArray();
				
				peaks = new BitmapData( stage.stageWidth, stage.stageHeight, false, 0xFFFFFFFF);
				
				rect = new Rectangle(0, 0, width, height);
				peaks.fillRect(rect, 0x0);
				
				displace = new Matrix();
				//displace.tx = 2;
				//displace.ty = -1;
				
				rect = new Rectangle( 0, 0, 1, 0 );
				peakBitmap = new Bitmap( peaks ) ;
				
				component.addChild( peakBitmap );
				
				stage.addEventListener( Event.ENTER_FRAME, onEnterFrame );
				stage.addEventListener( KeyboardEvent.KEY_UP, windowedapplication1_keyUpHandler);
			}
			
		private function onEnterFrame(event:Event):void {
			var value:Number;
			var values:Array = [];
			var xPosition:int;
			var yPosition:int;
			var color:uint;
			var centerX:int;
			var maxDisplayWidth:int= 100;
			
			if (peaks.height!=height || peaks.width!=width) {
				rect = new Rectangle(0, 0, width, height);
				peaks.fillRect(rect, 0x0);
			}
			
			SoundMixer.computeSpectrum(bytes, true, 0);
			
			// get current sound values
			for (var i:int; i < 256 ; i++ ) {
				value = bytes.readFloat();
				
				if (value>1) {
					// value is supposed to be -1 to 1 and it's showing 1.28...??
				}
				values.push(value);
			}
			
			centerX = width/2;
			
			//peaks.lock();
			
			xPosition = centerX;
			
			peaks.scroll(-1,0);
			
			// draw sound sample - vertical position
			for (var j:int; j < 256; j++) {
				value = values[j];
				yPosition = height+-j;
				
				if (value==0) {
					color = 0;
				}
				else {
					color = ColorUtil.adjustBrightness2(0xFF0000, value*100);
				}
				
				peaks.setPixel(xPosition, yPosition, color);
			}
			
		}
			
			private function onIOError( event: IOErrorEvent ): void
			{
			}
			
			protected function component_resizeHandler(event:ResizeEvent):void
			{
				rect = new Rectangle(0, 0, width, height);
				if (peaks) {
					peaks.fillRect(rect, 0x0);
				}
			}
			
			protected function windowedapplication1_keyUpHandler(event:KeyboardEvent):void
			{
				if (event.keyCode==Keyboard.SPACE) {
					
					if (!isPlaying) {
						sound.play(0);
						isPlaying = true;
						trace("play");
					}
					else {
						soundChannel.stop();
						isPlaying = false;
						trace("stop");
					}
				}
			}
			
		]]>
	</fx:Script>
	
	<mx:UIComponent id="component" 
					width="100%" 
					height="100%" 
					resize="component_resizeHandler(event)"/>
</s:WindowedApplication>

Notes:

  • It doesn’t show the nice gradient from red to white. It appears to be mostly all red or white.
  • It only shows left channel
  • It does not fill the height of the view
  • It app is resized it breaks
  • It is scrolling the pixels off the screen. What concerns is there on long duration sounds?
  • The sound values are sometimes above 1.0 when the values from computeSpectrum should be between -1.0 to 1.0??? Consistent values around 1.28…
  • There’s no zoom support or increase of levels

Edit:
If I change the stretch factor to 2 (computeSpectrum) and increase the frame rate I can get a larger view with more updates but at a lower quality (gif is really compressed).