AS3 sound.extract() 用于波形

发布于 2024-11-11 06:28:14 字数 2086 浏览 4 评论 0原文

早上好!

我正在尝试为 MP3 创建可视波形。我包含的代码在成功加载 MP3 时调用。我打算从声音中提取一些重要的样本来创建波形,而不是将整个声音提取到字节数组中。即使在一台好的机器上,提取整首歌曲也会导致 Flash 冻结 3-5 秒(或更长时间!)。就我的目的而言,这是不可行的。

不幸的是,我下面得到的代码无法产生任何数字。如果我提取整首歌曲,它就会起作用,但仅提取关键点对我来说什么也没有。执行提取是否会使声音对象的其余部分对于将来的提取无效?如果是这样,是否有某种方法可以解决这个问题,在提取过程中不会长时间冻结闪存?

代码其余部分中的一些重要变量:

waveFormWidth:波形精灵的静态宽度。
waveFormHeight:波形精灵的静态高度。
歌曲:我将用来创建波形的声音对象。

    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);


        }

    }

谢谢你们的帮助!

Good morning!

I'm trying to create a visual waveform for an MP3. The code I've included is called on successful load of the MP3. I intend to extract just a few important samples from the sound to create the waveform, rather than extract the entire sound into a bytearray. Even on a good machine, extracting an entire song can cause flash to freeze up for 3-5 seconds (or longer!). For my purposes, this isn't feasible.

Unfortunately, the code I've got below is failing to produce any numbers. If I extract the entire song it functions, but extraction of just the key points is giving me nothing. Does performing an extract make the remainder of the sound object invalid for future extracts? If so, is there some way around this that won't freeze flash for an extended period of time during the extract?

Some important variables from the rest of the code:

waveFormWidth: static width of the wave form sprite.
waveFormHeight: static height of the wave form sprite.
song: sound object that I'll be using to create the wave form.

    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);


        }

    }

Thanks for your help guys!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

有深☉意 2024-11-18 06:28:14

无论如何,我只是在做完全相同的事情,并且经过一些研究后我才让它发挥作用。我似乎无法让它与 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));
}

For what it's worth, I was just working on the EXACT same thing and I just got it working after some research. I cannot seem to get it to work with WAV files, but this is compatable with MP3 files of all types. This is what I ended up with:

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));
}
无言温柔 2024-11-18 06:28:14

这是一篇旧文章,也许我没有正确理解你的问题,但是 extract 方法允许你指定样本的长度以及从哪里开始。

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

length 是要提取的样本数,startPosition 是从 byteArray 中的哪个位置开始。

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

This is an old post, and maybe I don't understand your question correctly, but the extract method allows you to specify the length of samples, and where in the start.

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

length is the number of samples to extract, and startPosition is at which position in the byteArray to start.

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

心病无药医 2024-11-18 06:28:14

使用此类:

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

我'我还将其融入到一个非常蹩脚的、半生不熟的实验中,我不久前开始制作混音器。您也可以在此处获取源代码:

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

Use this class:

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

I've also incorporated this into a really crappy, half-baked experiment I started a while back at making a sound mixer. You can get the source code for that as well here:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文