Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > ActionScript 3 > Sound.extract() для больших файлов


Автор: C4Grey 4.12.2011, 20:50
Приветствую
С постройкой графика АЧХ(Waveform, а-ля soundcloud.com) разобрался, благо примеров в интернете гуляет много. Интересует как сделать то же для больших файлов - либо с большим битрейтом, либо большой длительности. Хотелось бы строить график по ходу загрузки звука, как такое можно провернуть? Есть пару идей:
1. Отлавливать ProgressEvent, смотреть bytesLoaded, писать по порциям в ByteArray чере sound.extract(), как-то так:
Код

var vSize:int = Math.floor(FSound.length * 44.1);
FSound.extract(vData, vSize - FLoadingPosition, FLoadingPosition);
FLoadingPosition = vSize;

2. Строить график один раз, при загрузке на сервер и сохранять данные в XML или бинарник.

Идея номер 2 менее ресурсоемкая, но сильно усложняет загрузку звуков для конечного пользователя(по идее, ему нужно только вставить URL и получить код плеера) и добавляет необходимость содержать сервер с данными по трекам. С первой тоже пока проблемы - никак не удается прочитать данные верно, может чего не так делаю. В общем, подскажите, пожалуйста, может у кого есть другие идеи, или варианты дял развития этих.

P.S. Поправил код для вытягивания данных, там не байты а сэмплы(2 флоата)
P.P.S. Вытянуть данные получилось, даже график можно построить, но зажать его в нужный размер никак не получается. Проблема в том, что до загрузки звука его полную длину получить не получается, а она нужна для получения соотношения "длина звука / длина мувика с графиком" - чтобы правильно строить в ряд линии, сответсвующие значению амплитуды. Вытягиваю данные так:
Код

function OnProgres(e:ProgressEvent):void
{
    var vData:ByteArray = new ByteArray();        
    var vSize:int = Math.floor(FSound.length * 44.1);
    var vPart:int = vSize - FLoadingPosition;
    FSound.extract(vData, vPart, FLoadingPosition);
    FLoadingPosition = vSize;            
    if(vData.length > 0)
    {            
        vData.position = 0;
        FLoadedSamples.push(vData);                                
        if(FFirstLaunch)
        {                    
            FBitrate = 8 * Math.floor(FSound.bytesLoaded / FSound.length);
            FStep = 1 / (8128 * FBitrate * 2 / stage.stageWidth);
            addEventListener(Event.ENTER_FRAME, AnalyzeSample);
            FFirstLaunch = false;
        }
    }            
}


И построение графика:

Код

private function AnalyzeSample(e:Event):void
{
    var h:Number = stage.stageHeight;                
    FCurrentBuffer = FLoadedSamples[FBufferIndex];
    
    if(FCurrentBuffer.bytesAvailable)
    {        
        var vVal:Number;                
        for(var i:int = 0; i < 8128; i++)
        {
            try
            {                        
                vVal = abs(FCurrentBuffer.readFloat());
                Raster.line(FData, FDx, h/2 - vVal * h/2 / 2, FDx, h/2, 0x88FF9933);
                vVal = abs(FCurrentBuffer.readFloat());
                Raster.line(FData, FDx, h/2 + vVal * h/2 / 2, FDx, h/2, 0x88FFFF00);
                FDx += FStep;                                        
            }
            catch(E:Error){}
        }
    }
    else 
    {
        if(FBufferIndex < FLoadedSamples.length-1)
        {
            FBufferIndex++;
        }
        else
        {
            //removeEventListener(Event.ENTER_FRAME, AnalyzeSample);
        }
    }            
}


Значение FStep подобрал эксперементально, верного графика с ним не построишь.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)