AS3 sound.extract () для формы волны - PullRequest
5 голосов
/ 29 мая 2011

Доброе утро!

Я пытаюсь создать визуальную форму волны для MP3. Код, который я включил, вызывается при успешной загрузке MP3. Я намерен извлечь лишь несколько важных сэмплов из звука, чтобы создать форму волны, а не извлекать весь звук в байтовый массив. Даже на хорошей машине извлечение всей песни может привести к зависанию вспышки на 3-5 секунд (или дольше!). Для моих целей это невозможно.

К сожалению, код, который я получил ниже, не может произвести никаких чисел. Если я извлекаю всю песню, она функционирует, но извлечение только ключевых моментов мне ничего не дает. Делает ли выполнение извлечения остаток звукового объекта недействительным для будущих извлечений? Если это так, есть ли способ избежать этого, который не остановит вспышку в течение длительного периода времени во время извлечения?

Некоторые важные переменные из остального кода:

waveFormWidth: статическая ширина спрайта формы волны.
waveFormHeight: статическая высота спрайта формы волны.
song: звуковой объект, который я буду использовать для создания формы волны.

    public function mapWaveForm(e:Event = null):void
    {

        // Clear the wave form sprite
        waveForm.graphics.clear();
        waveForm.graphics.lineStyle(0, 0x000000, 1);

        // Storage for the wave form bit data
        var byteOutput:ByteArray;
        var leftPeakSize:Number;
        var rightPeakSize:Number;
        var songTotalSamples:int;
        var thisSample:int;

        byteOutput = new ByteArray();

        // How many samples?
        songTotalSamples = (song.length * 44.1);

        // Loop for the wave form width
        for (var peakCount:int = 0; (peakCount < waveFormWidth); peakCount++)
        {

            // Get info at each peak.
            thisSample = Math.floor(songTotalSamples * (peakCount / waveFormWidth));
            song.extract(byteOutput, 1, thisSample);
            byteOutput.position = 0;
            trace(thisSample, byteOutput.readFloat());

            leftPeakSize = byteOutput.readFloat() / 1.27;
            rightPeakSize = byteOutput.readFloat() / 1.27;

            // Turn those peaks into something usable.
            leftPeakSize = leftPeakSize * (waveFormHeight * .5);
            rightPeakSize = rightPeakSize * (waveFormHeight * .5);

            // Make the left channel line
            waveForm.graphics.moveTo(peakCount, (waveFormHeight * .5));
            waveForm.graphics.lineTo(peakCount, (waveFormHeight * .5) - leftPeakSize);

            // Make the right channel line
            waveForm.graphics.moveTo(peakCount, (waveFormHeight * .5));
            waveForm.graphics.lineTo(peakCount, (waveFormHeight * .5) + rightPeakSize);


        }

    }

Спасибо за вашу помощь, ребята!

Ответы [ 3 ]

2 голосов
/ 25 июня 2012

Что бы это ни стоило, я просто работал над ТОЧНОЙ вещью, и я только получил ее после некоторых исследований.Я не могу заставить его работать с файлами WAV, но это совместимо с файлами MP3 всех типов.Вот чем я закончил:

var IMAGE_SIZE:int = new int(600); // Final width of image
var IMAGE_DEPTH:int = new int(5); // How many passes per pixel of image
var RESOLUTION:int = new int(IMAGE_SIZE * IMAGE_DEPTH);
var DRAW_AMPLITUDE:int = new int(150); // pixel height of max volume line

var waveForm:Shape = new Shape();

var mp3File:Sound = new Sound();
mp3File.load(new URLRequest("audio.mp3"));
mp3File.addEventListener(Event.COMPLETE, parseSound);

function parseSound(e:Event):void {
    var soundBytes:ByteArray = new ByteArray();
    for (var i:int=0; i<RESOLUTION; i++) {
        mp3File.extract(soundBytes, 1, Math.floor((mp3File.length*44.1)*(i/RESOLUTION)));
        soundBytes.position = 0;
        while (soundBytes.bytesAvailable > 0) {
            var tmpNum:Number = new Number();
            tmpNum += soundBytes.readFloat();
        }
        drawWave(i, tmpNum);
        soundBytes.clear();
    }
    this.addChild(waveForm);
    trace("--DONE--");
}

function drawWave(i:Number, amp:Number):void {
    var pixX:Number = new Number(Math.floor(i/IMAGE_DEPTH));
    var pixY:Number = new Number((amp*DRAW_AMPLITUDE)/2);
    waveForm.graphics.lineStyle(1, 0x0, (1.2/IMAGE_DEPTH));
    waveForm.graphics.moveTo(pixX, ((DRAW_AMPLITUDE/2)-pixY));
    waveForm.graphics.lineTo(pixX, ((DRAW_AMPLITUDE/2)+pixY));
}
1 голос
/ 13 апреля 2012

Это старый пост, и, возможно, я не правильно понимаю ваш вопрос, но метод извлечения позволяет вам указать длину семплов и место в начале.

"public function extract(target:ByteArray, length:Number, startPosition:Number = -1):Number"

длина - это количество выборок для извлечения, а startPosition - это то, с какой позиции в byteArray начинать.

См. http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#extract%28%29

0 голосов
/ 29 мая 2011

Используйте этот класс:

http://www.bytearray.org/?p=329

Я также включил это в действительно дурацкий, недоделанный эксперимент, который я начал некоторое время назад при создании звукового микшера. Вы также можете получить исходный код для этого здесь:

http://code.google.com/p/ascensionsystems/downloads/list

...