title: Actionscript sound playback accuracy in Flash 10
body: <p>We have an AS3 player that requires Flash 10 (to overcome old issues with 9 and playback offsets) to handle clipping of audio. However when I select start and end points to playback from, many times what is played back doesn't match the same clip as what is played in Audacity. Here are some details on my test mp3 (results from ffmpeg).</p>
  
  <pre><code>libavutil     49.10. 0 / 49.10. 0
  libavcodec    52. 0. 0 / 52. 0. 0
  libavformat   52.22. 1 / 52.22. 1
  libavdevice   52. 1. 0 / 52. 1. 0
  libswscale     0. 6. 1 /  0. 6. 1
  libpostproc   51. 2. 0 / 51. 2. 0
  built on Sep 24 2008 15:49:57, gcc: 4.2.4 (TDM-1 for MinGW)
  Input #0, mp3, from 'reagan_challenger.mp3':
  Duration: 00:00:14.62, start: 0.000000, bitrate: 127 kb/s
  Stream #0.0: Audio: mp3, 44100 Hz, stereo, s16, 128 kb/s
  </code></pre>
  
  <p>Original url: <a href="http://ericmalone.net/test_media/reagan_challenger.mp3" rel="nofollow noreferrer">http://ericmalone.net/test_media/reagan_challenger.mp3</a></p>
  
  <p>Clipped url: <a href="http://ericmalone.net/test_media/reagan_clipped.wav" rel="nofollow noreferrer">http://ericmalone.net/test_media/reagan_clipped.wav</a></p>
  
  <p>Clip was created on the backend using ffmpeg to get the clip from 4017ms - 7400ms:</p>
  
  <pre><code>ffmpeg -i reagan_challenger.mp3 -ss 4.017 -t 3.383 reagan_clipped.wav
  </code></pre>
  
  <p>I've also clipped the file using Audacity to the slightly less accurate positions 4.017676 seconds - 7.401333 seconds at <a href="http://ericmalone.net/test_media/reagan_challenger_from_audacity.wav" rel="nofollow noreferrer">http://ericmalone.net/test_media/reagan_challenger_from_audacity.wav</a></p>
  
  <p>Here's the clipped portion playing back via the code displayed below <a href="http://ericmalone.net/test_media/SoundExample.swf" rel="nofollow noreferrer">http://ericmalone.net/test_media/SoundExample.swf</a></p>
  
  <p>Notice that the word <em>challenger</em> completes in the flash playback, but is truncated in both the Audacity and ffmpeg based clippings.</p>
  
  <p>The method by which we stop audio playback in flash is fairly standard. I've extracted the sound bits to a test class. Here's the relevant code</p>
  
  <pre><code>package {
      import flash.display.Sprite;
      import flash.events.*;
      import flash.media.Sound;
      import flash.media.SoundChannel;
      import flash.net.URLRequest;
      import flash.text.TextField;
      import flash.utils.Timer;
  
      public class SoundExample extends Sprite {
          private var url:String = "http://www.ericmalone.net/test_media/reagan_challenger.mp3";
          private var soundFactory:Sound;
          private var song:SoundChannel;
  
          private var clipStart:int = 4017;
          private var clipEnd:int = 7400;
  
          private var timer:Timer;
          private var timerInterval:uint = 20;
  
          private var textField:TextField;
  
          public function SoundExample() {
              var request:URLRequest = new URLRequest(url);
              soundFactory = new Sound();
              soundFactory.addEventListener(Event.COMPLETE, completeHandler);
              soundFactory.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
              soundFactory.load(request);
  
              textField = new TextField();
              textField.wordWrap = true;
              textField.width = 500;
              addChild(textField);
          }
  
          private function completeHandler(event:Event):void {
              output("file completely loaded and playing");
              timer = new Timer(timerInterval);
              timer.addEventListener(TimerEvent.TIMER, onTimer);
              song = soundFactory.play(clipStart);
              timer.start();
          }
  
          private function ioErrorHandler(event:Event):void {
              output("ioErrorHandler: " + event);
          }
  
          private function onTimer(event:TimerEvent):void
          {
              //stop playback if position is greater than clip end 
              //or if there's less duration left than difference of the timer and current position
              if((song.position &gt;= clipEnd || clipEnd - song.position &lt; timerInterval))
              {
                  timer.stop();
                  song.stop();
                  output("Ending playback at " + song.position + " to be as close to " + clipEnd + " as possible");
  
              }
          }
  
          private function output(str):void
          {
              textField.text = str;
              trace(str); 
          }
      }
  }
  </code></pre>
  
  <p>So the question is, is there a better way to get more accurate playback from within flash? Does it depend on codec/sampling rate/etc?</p>