topical media & game development

talk show tell print

student-mma-16-AudioBuffer.ax

student-mma-16-AudioBuffer.ax [swf] flex


  /*
  Copyright(C) 2007 Andre Michelle and Joa Ebert
  
  PopForge is an ActionScript3 code sandbox developed by Andre Michelle and Joa Ebert
  http://sandbox.popforge.de
  
  This file is part of PopforgeAS3Audio.
  
  PopforgeAS3Audio is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 3 of the License, or
  (at your option) any later version.
  
  PopforgeAS3Audio is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>
  */
  package
  {
          import de.popforge.audio.output.*;
          import mx.controls.Alert;
          import flash.media.Sound;
          import flash.media.SoundChannel;
          import flash.media.SoundTransform;
          import flash.utils.ByteArray;
          import flash.utils.Endian;
  
          
The class @ax-student-mma-16-AudioBuffer creates an endless AudioStream as long as the buffer is updated with new samples
author: Andre Michelle

  
          public class @ax-student-mma-16-AudioBuffer
          {
                  
The internal minimal sound buffer length in samples(PC)

  
                  static public const UNIT_SAMPLES_NUM: uint = 2048;
                  
                  
Stores a delegate function called, when the @ax-student-mma-16-AudioBuffer is inited.

  
                  public var onInit: Function;
                  
Stores a delegate function called, when the @ax-student-mma-16-AudioBuffer has complete its cycle.

  
                  public var onComplete: Function;
                  
Stores a delegate function called, when the @ax-student-mma-16-AudioBuffer is started.

  
                  public var onStart: Function;
                  
Stores a delegate function called, when the @ax-student-mma-16-AudioBuffer is stopped.

  
                  public var onStop: Function;
                  
                  private var multiple: uint;
                  private var channels: uint;
                  private var bits: uint;
                  private var rate: uint;
                  
                  
                  private var sound: Sound;
                  private var soundChannel: SoundChannel;
                  private var trans: SoundTransform;
                  
                  private var _numBytes: uint;
                  private var _numSamples: uint;
  
                  private var bytes: ByteArray;
                  private var samples: Array;
  
                  private var firstrun: Boolean;
                  private var playing: Boolean;
                  
                  private var isInit: Boolean;
                  
                  private var time:Number;
                  
                  
Creates an @ax-student-mma-16-AudioBuffer instance.
parameter: multiple Defines the buffer length (4times recommended)
parameter: channels Mono(1) or Stereo(2)
parameter: bits 8bit(8) or 16bit(16)
parameter: rate SamplingRate 5512Hz, 11025Hz, 22050Hz, 44100Hz

  
                  public function @ax-student-mma-16-AudioBuffer( multiple: uint, channels: uint, bits: uint, rate: uint )
                  {
                          Audio.checkAll( channels, bits, rate );
                          
                          this.multiple = multiple;
                          this.channels = channels;
                          this.bits = bits;
                          this.rate = rate;
                          
                          firstrun = true;
                          
                          init();
                  }
  
                  
Updates the @ax-student-mma-16-AudioBuffer samples for the next playback cycle Must be called after the new samples are computed

  
                  public function update(): ByteArray
                  {
                          bytes.length = 0;
                          
                          var i: int;
                          var s: Sample;
                          var l: Number;
                          var r: Number;
                          
                          switch( channels )
                          {
                                  case Audio.MONO:
  
                                          if( bits == Audio.BIT16 )
                                          {
                                                  for( i = 0 ; i < _numSamples ; i++ )
                                                  {
                                                          s = samples[i];
                                                          l = ( s.left + s.right ) / 2;
                                                          
                                                          if( l < -1 ) bytes.writeShort( -0x7fff );
                                                          else if( l > 1 ) bytes.writeShort( 0x7fff );
                                                          else bytes.writeShort( l * 0x7fff );
                                                          
                                                          s.left = s.right = 0;
                                                  }
                                          }
                                          else
                                          {
                                                  for( i = 0 ; i < _numSamples ; i++ )
                                                  {
                                                          s = samples[i];
                                                          l = ( s.left + s.right ) / 2;
                                                          
                                                          if( l < -1 ) bytes.writeByte( 0 );
                                                          else if( l > 1 ) bytes.writeByte( 0xff );
                                                          else bytes.writeByte( 0x80 + l * 0x7f );
                                                          
                                                          s.left = s.right = 0;
                                                  }
                                          }
                                          break;
                                          
                                  case Audio.STEREO:
  
                                          if( bits == Audio.BIT16 )
                                          {
                                                  for( i = 0 ; i < _numSamples ; i++ )
                                                  {
                                                          s = samples[i];
                                                          l = s.left;
                                                          r = s.right;
                                                          
                                                          if( l < -1 ) bytes.writeShort( -0x7fff );
                                                          else if( l > 1 ) bytes.writeShort( 0x7fff );
                                                          else bytes.writeShort( l * 0x7fff );
                          
                                                          if( r < -1 ) bytes.writeShort( -0x7fff );
                                                          else if( r > 1 ) bytes.writeShort( 0x7fff );
                                                          else bytes.writeShort( r * 0x7fff );
                                                          
                                                          s.left = s.right = 0;
                                                  }
                                          }
                                          else
                                          {
                                                  for( i = 0 ; i < _numSamples ; i++ )
                                                  {
                                                          s = samples[i];
                                                          l = s.left;
                                                          r = s.right;
                                                          
                                                          if( l < -1 ) bytes.writeByte( 0 );
                                                          else if( l > 1 ) bytes.writeByte( 0xff );
                                                          else bytes.writeByte( 0x80 + l * 0x7f );
                                                          if( r < -1 ) bytes.writeByte( 0 );
                                                          else if( r > 1 ) bytes.writeByte( 0xff );
                                                          else bytes.writeByte( 0x80 + r * 0x7f );
                                                          
                                                          s.left = s.right = 0;
                                                  }
                                          }
                                          break;
                          }
                          
                          SoundFactory.fromByteArray( bytes, channels, bits, rate, onNewBufferCreated );
                          
                          return bytes;
                  }
                  
                  
Starts the @ax-student-mma-16-AudioBuffer playback

  
                  public function start(): Boolean
                  {
                          if( playing ) return false;
                          
                          if( soundChannel != null )
                                  soundChannel.stop();
                          
                          if( sound != null )
                                  soundChannel = sound.play( 0, 1, trans );
                          
                          playing = true;
                          
                          if( onStart != null )
                                  onStart( this );
                          
                          return true;
                  }
                  
                  
Returns true, if the @ax-student-mma-16-AudioBuffer is playing

  
                  public function isPlaying(): Boolean
                  {
                          return playing;
                  }
  
                  
Returns number of channels.

  
                  public function getChannels(): uint
                  {
                          return channels;
                  }
  
                  
Returns number of bits.

  
                  public function getBits(): uint
                  {
                          return bits;
                  }
  
                  
Returns samplingRate in Hz

  
                  public function getRate(): uint
                  {
                          return rate;
                  }
  
                  
Returns length of the buffer (sampleNum / UNIT_SAMPLES_NUM)

  
                  public function getMultiple(): uint
                  {
                          return multiple;
                  }
  
                  
Returns samples for overriding with new amplitudes

  
                  public function getSamples(): Array
                  {
                          return samples;
                  }
  
                  
Returns number of samples

  
                  public function get numSamples(): uint        //-- read only
                  {
                          return _numSamples;
                  }
  
                  
Returns current peak(left)

  
                  public function get leftPeak(): Number
                  {
                          return soundChannel == null ? 0 : soundChannel.leftPeak;
                  }
  
                  
Returns current peak(right)

  
                  public function get rightPeak(): Number
                  {
                          return soundChannel == null ? 0 : soundChannel.rightPeak;
                  }
  
                  
Returns true, if the @ax-student-mma-16-AudioBuffer is inited

  
                  public function get isInit(): Boolean
                  {
                          return isInit;
                  }
  
                  
Returns number of milliseconds of each buffer

  
                  public function get millisEachBuffer(): Number
                  {
                          return 2048000 / rate * multiple;
                  }
                  
                  private function init(): void
                  {
                          isInit = false;
                          
                          if( multiple == 0 )
                                  throw new Error( 'Buffer must have a length greater than 0.' );
                          
                          var i: int;
                          
                          bytes = new ByteArray();
                          bytes.endian = Endian.LITTLE_ENDIAN;
                          
                          //-- compute number of bytes
                          switch( rate )
                          {
                                  case Audio.RATE44100:
                                          _numSamples = ( UNIT_SAMPLES_NUM * multiple ); break;
                                  case Audio.RATE22050:
                                          _numSamples = ( UNIT_SAMPLES_NUM * multiple ) >> 1; break;
                                  case Audio.RATE11025:
                                          _numSamples = ( UNIT_SAMPLES_NUM * multiple ) >> 2; break;
                                  case Audio.RATE5512:
                                          _numSamples = ( UNIT_SAMPLES_NUM * multiple ) >> 3; break;
                          }
                          
                          //-- compute number of bytes
                          _numBytes = _numSamples;
                          if( channels == Audio.STEREO ) _numBytes <<= 1;
                          if( bits == Audio.BIT16 ) _numBytes <<= 1;
  
                          samples = new Array();
                          for( i = 0 ; i < _numSamples ; i++ )
                                  samples.push( new Sample() );
  
                          trans = new SoundTransform();
                          
                          playing = false;
                  }
                  
                  
  
                  private function onNewBufferCreated( sound: Sound ): void
                  {
                          if( playing )
                                  this.sound = sound;
                  }
                  
                  internal function onSyncComplete(): void
                  {
                          if( soundChannel != null )
                                  soundChannel.stop();
  
                          if( sound != null )
                          {
                                  soundChannel = sound.play( 0, 1, trans );
                          }
                          
                          sound = null;
                  }
                  
                  public function changeVolume(vol:Number):void {
                          if(vol < 0 || vol > 1) return;
                          trans.volume = vol;
                          soundChannel.soundTransform = trans;
                  }
                  
          }
  }


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.