Точность воспроизведения звука в ActionScript во Flash 10 - PullRequest
1 голос
/ 31 марта 2009

У нас есть проигрыватель AS3, которому требуется Flash 10 (для преодоления старых проблем с 9 и смещениями воспроизведения) для обработки отсечения звука. Однако, когда я выбираю начальную и конечную точки для воспроизведения, часто воспроизводимое изображение не совпадает с клипом, который воспроизводится в Audacity. Вот некоторые подробности о моем тестовом mp3 (результаты ffmpeg).

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

Оригинальный URL: http://ericmalone.net/test_media/reagan_challenger.mp3

Отсеченный URL: http://ericmalone.net/test_media/reagan_clipped.wav

Клип был создан на сервере с помощью ffmpeg, чтобы получить клип от 4017 мс - 7400 мс:

ffmpeg -i reagan_challenger.mp3 -ss 4.017 -t 3.383 reagan_clipped.wav

Я также обрезал файл, используя Audacity, в несколько менее точные позиции 4,017676 секунд - 7,401333 секунд при http://ericmalone.net/test_media/reagan_challenger_from_audacity.wav

Вот отсеченная часть, воспроизводимая с помощью кода, показанного ниже http://ericmalone.net/test_media/SoundExample.swf

Обратите внимание, что слово претендент завершается при воспроизведении во флэш-памяти, но усекается как в вырезках на основе Audacity, так и ffmpeg.

Метод, с помощью которого мы прекращаем воспроизведение звука во флэш-памяти, является довольно стандартным. Я извлек звуковые биты в тестовый класс. Вот соответствующий код

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 >= clipEnd || clipEnd - song.position < 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); 
        }
    }
}

Итак, вопрос в том, есть ли лучший способ получить более точное воспроизведение изнутри вспышки? Зависит ли это от кодека / частоты дискретизации / и т. Д.

1 Ответ

2 голосов
/ 31 марта 2009

Непосредственно относительно правильной кодировки mp3, но может помочь ...

Вы должны знать, что класс Timer имеет определенный запас точности.

Тест в вашем примере звучал хорошо для меня (без щелчка в середине), и я приблизился на 0,2% к желаемому результату, что вполне приемлемо для ИМО.

Относительно кода есть деталь, которую я хотел бы рассмотреть, учитывая следующее условие из вашего примера:

clipEnd - song.position < timerInterval

Представьте себе следующий сценарий:

  • Таймер работает с интервалом 20 мс, от 0 до 7400
  • Ближайший к последнему тику приземляется на 7381, продвигаясь на 1ms
  • Звук останавливается на 99,74%

Если бы условие не отменило его, я думаю, оно остановилось бы на 7401 (100,01%)

Может быть, вы должны попробовать что-то вроде (остерегайтесь, слепой код):

if(song.position >= clipEnd || (clipEnd - song.position < (song.position + timerInterval) - clipEnd))
{
    // Stop Timer
} 

Задержка будет зависеть от кода, который вы выполняете, компьютера и т. Д., Но я предлагаю сыграть с разными значениями интервалов, чтобы приблизиться к наилучшей «ровности».

Кроме того, убедитесь, что у вас нет других методов для отсрочки выполнения события таймера. Для этого вам, вероятно, следует изолировать эту часть таймера, чтобы сравнить ее (также удалив звук).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...