私の質問は、以下のこの質問の続きのようなものですが、新しい質問を始めるのが最善だと思いました.
この as3 コードをピクセル ベンダー コードに変換するのに役立ちます
そのため、mp3 から pcm データを抽出し、複数のズーム レベルで波形を描画する波形描画の実装がフラッシュにありました。数分以上のトラックを処理し始めるまでは問題なく動作しますが、受け入れられないほど遅すぎます. だから私はより速い解決策を求めています。
計算がとても速いと聞いたので、最初はピクセルベンダーを試してみようと思いました。これは事実ですが、上記のリンクに示されているように、for ループがないため、このテクノロジは不適切な候補になります。
だから今、私は代替手段として最善の道と財布を考えています.
波形計算コードを c で記述し、alchemy を使用すると、認識可能な速度とパフォーマンスの向上が得られますか? その基本的にはまだ as3 が正しく動作していますか?
ある種のサーバー側スクリプトを使用したほうがよいでしょうか? pcm データを bytearray として php スクリプトに渡し、スクリプトがプロット データを返すようにすることはできますか?
他に検討できるテクニックがあれば教えてください。
編集:>>
私がas3でやろうとしていることは
mp3s オーディオ データをバイト配列に抽出する 最大ズーム レベルでプロットする仮想ピクセル数を決定する (たとえば、800 ピクセル = 2 倍ズームでのトラックの 10 秒)
したがって、サンプル数 = 33315840 で、仮想ピクセルの最大数 = 1600 (ビューポートの幅が 800 ピクセルであるためスクロールが必要) の場合、チャンク サイズ = 33315840/1600 = 20822 となります。
したがって、hte bytearray の 20822 サンプルごとに最大値を見つけ、その値をプロット値として使用します
編集2
@backtodos
私はあなたが作ったポイントについて考えました、そしてそれはこの最大のビジネス全体よりも賢明に思えます.
あなたが話していたことを表していると思う次のコードを完成させました。問題の 1 つは、解像度を 800 を超える値に変更すると、線が非常に高くなり、線が非常に短くなり、非常に奇妙に見えることです。800 では非常に素晴らしい波形です。
解像度が 1600 を超えると、四角形を描画しようとすると、パラメーターが無効であるというエラーがスローされます。
ズーム戦略について少し混乱していると思います。「ズームインすると、解像度が重複して波形が再描画されます」と言います。私はあなたが何を意味するのかよくわかりません。一度に 800 ピクセルしか描画できないことはわかっています。2 倍のズームを行ったとします。これは、サンプル ソースからの読み取り量を 2 倍にし、1600 個のプロット ポイントを持っていますが、スクロール位置に基づいて一度に 800 個しか描画しないことを意味しますか?
private function calculatePlottingData():void
{
this._container=new UIComponent()
drawon=new MovieClip()
_container.addChild(drawon)
addChild(_container)
var spriteSize:Number;
spriteSize=800; // my resolution
//ba is a bytearray filled with my extracted audio data
//blocksize helps me determine where in the bytearray
//to read a sample value from for plotting
blocksize=Math.floor(ba.length / spriteSize);
var tstart:Number=getTimer()
var l:Number
var r:Number
var la:Number
var ra:Number
var readpoint:int=0;
var val:Number;
for (var i:int=0; i < spriteSize; i++)
{
readpoint=i * blocksize
ba.position=readpoint;
//read teh left and right sample
la=ba.readFloat();
ra=ba.readFloat();
val=(la + ra) / 2;
plottingvalues[i]=val
drawon.graphics.beginFill(0xff0000)
}
var tend:Number=getTimer() - tstart;
trace("time taken=" + tend / 1000)
draw()
}
private function draw():void
{
var val:Number
for (var i:int=0; i < _viewportwidth; i++)
{
drawon.graphics.beginFill(0xffffff)
val=plottingvalues[i];
drawon.graphics.drawRect(i, 50, 1, val * 50)
}
}
編集 3 > 800 個のプロット ポイントしか得られないことに基づいてコードを改善しました。このコードは、私の目的には十分速いようです。解像度に固執するという@backtodosの提案を使用して、多くの処理を節約します。
package drawing
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.media.Sound;
import flash.utils.ByteArray;
import flash.utils.getTimer;
import mx.core.Application;
public class WaveformView extends MovieClip
{
private var _sound:Sound
private var _resolution:Number
private var _quality:int=1;
private var _buffersize:int;
private var _ba:ByteArray=new ByteArray()
private var _step:Number
private var _zoomby:int=1;
private var _zoomfactor:int=2;
private var _blocksize:int;
private var _scrollbar:Bitmap
private var _scrollthumb:MovieClip
private var _relativeThumbPosition:Number=0
private var _sliderRange:int
private var _sliderCenterMinLeft:int
private var _sliderCenterMax_Right:int;
public var _slider_rel_pos:Number=0;
private var _sliderCenter:Number=0;
public function WaveformView(snd:Sound, res:Number=800, quality:int=2, buffersize:int=2048)
{
super();
this._sound=snd;
this._resolution=res;
this._quality=quality; // not implemented yet
this._buffersize=buffersize;
initScrollBar();
getPCM()
drawwaveform()
}
private function initScrollBar():void
{
var sbbmd:BitmapData=new BitmapData(_resolution, 20, false, 0xcccccc)
_scrollbar=new Bitmap(sbbmd)
_scrollbar.y=120
addChild(_scrollbar)
sbbmd=new BitmapData(_resolution, 16, false, 0xeeeeee)
_scrollthumb=new MovieClip()
_scrollthumb.graphics.beginFill(0xff0000)
_scrollthumb.graphics.drawRect(0, 0, _resolution, 10)
_scrollthumb.graphics.endFill()
_scrollthumb.y=125
addChild(_scrollthumb)
_scrollthumb.buttonMode=true
_scrollthumb.addEventListener(MouseEvent.MOUSE_DOWN, beginthumbdrag)
}
private function beginthumbdrag(e:MouseEvent):void
{
_scrollthumb.startDrag(false, new Rectangle(_scrollbar.x, _scrollbar.y + 5, _scrollbar.width - (_scrollthumb.width), 0))
_scrollthumb.addEventListener(MouseEvent.MOUSE_MOVE, shuttleMoving, false, 0, true);
_scrollthumb.addEventListener(MouseEvent.MOUSE_UP, endthumbdrag, false, 0, true);
}
private function endthumbdrag(e:MouseEvent):void
{
_scrollthumb.stopDrag();
e.updateAfterEvent();
_scrollthumb.removeEventListener(MouseEvent.MOUSE_MOVE, shuttleMoving);
}
private function shuttleMoving(e:MouseEvent):void
{
calculateShuttleRelativePosition();
drawwaveform()
e.updateAfterEvent()
}
private function calculateShuttleRelativePosition():void
{
var _x:Number=_scrollthumb.x
_sliderCenter=_x + (_scrollthumb.width / 2)
_sliderRange=_scrollbar.width - _scrollthumb.width;
_slider_rel_pos=(_sliderCenter - _sliderCenterMinLeft) / _sliderRange
}
public function getPCM():void
{
var len:int=_sound.length * 44.1
_sound.extract(_ba, len)
this._blocksize=_ba.length / (_resolution * _zoomby)
shaveblocksize()
}
public function zoomin():void
{
if (this._zoomby < 16)
{
this._zoomby*=2
resizeThumb()
drawwaveform()
}
}
public function zoomout():void
{
if (_zoomby >= 2)
{
this._zoomby/=2
resizeThumb()
drawwaveform()
}
}
private function resizeThumb():void
{
_scrollthumb.width=_scrollbar.width / _zoomby
if (_scrollthumb.width == _resolution)
{
_slider_rel_pos=0
}
_sliderCenterMinLeft=_scrollthumb.width / 2;
_sliderCenterMax_Right=_scrollbar.width - (_scrollthumb.width / 2);
_sliderRange=_scrollbar.width - _scrollthumb.width;
_sliderRange=_scrollbar.width - _scrollthumb.width;
_scrollthumb.x=(_slider_rel_pos * _sliderRange)
}
public function drawwaveform():void
{
var starttime:Number=getTimer()
var readposition:int
var l:Number
var r:Number
var p:Number
this._blocksize=_ba.length / (_resolution * _zoomby)
shaveblocksize()
this.graphics.clear()
this.graphics.beginFill(0xc5c5c5, 0.5)
this.graphics.drawRect(0, 50, _resolution, 1)
var max:int=_ba.length - (_blocksize * _resolution)
var pos:int=Formulas.interpolate(_slider_rel_pos, 0, max)
_ba.position=pos
for (var i:int=0; i < _resolution; i++)
{
l=Math.abs(_ba.readFloat());
r=Math.abs(_ba.readFloat());
l*=50
r*=50
p=(l + r)/2
try
{
this.graphics.drawRect(i, 50, 1, p)
this.graphics.drawRect(i, 50, 1, -p)
}
catch (e:Error)
{
}
_ba.position+=_blocksize
}
}
private function shaveblocksize():void
{
do
{
_blocksize--
} while (_blocksize % 4);
}
}
}
解決法 backtodos の助けに感謝します。これには非常に多くの最適化が必要ですが、誰かにとっては良い出発点です。
package drawing
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.media.Sound;
import flash.utils.ByteArray;
import flash.utils.getTimer;
public class WaveformView extends MovieClip
{
private var _sound:Sound
private var _resolution:Number
private var _quality:int=1;
private var _buffersize:int;
private var _ba:ByteArray=new ByteArray()
private var _zoomby:int=1;
private var _zoomXFactor:int=2;
private var _maximumSecondsPerViewPort:int=10;
;
private var _blocksize:int;
private var _scrollbar:Bitmap
private var _scrollthumb:MovieClip
private var _relativeThumbPosition:Number=0
private var _sliderRange:int
private var _sliderCenterMinLeft:int
private var _sliderCenterMax_Right:int;
public var _slider_rel_pos:Number=0;
private var _sliderCenter:Number=0;
private var _resolutions:Array
private var _zoomsInSecondsArray:Array=new Array();
private var _numberOfZoomLevels:int;
public function WaveformView(snd:Sound, res:Number=800, quality:int=2, buffersize:int=2048, height:int=100)
{
super();
this._sound=snd;
this._resolution=res;
this._quality=quality; // not implemented yet
this._buffersize=buffersize;
// addChild(viewportBitmap)
_resolutions=new Array()
initScrollBar();
getPCM()
calculateZoomLevelData()
drawwaveform()
}
public function calculateZoomLevelData():void
{
_zoomsInSecondsArray=[]
var amt:int=Math.round(_sound.length / 1000);
_zoomsInSecondsArray.push(amt);
while (amt >= _maximumSecondsPerViewPort)
{
amt=amt / _zoomXFactor;
if (amt >= _maximumSecondsPerViewPort)
{
_zoomsInSecondsArray.push(amt);
}
}
_numberOfZoomLevels=_zoomsInSecondsArray.length;
var checkSize:int=_resolution;
var r:ResolutionCache
r=new ResolutionCache(checkSize)
_resolutions.push(r)
for (var c:int=1; c < _numberOfZoomLevels + 1; c++)
{
checkSize=checkSize * _zoomXFactor;
r=new ResolutionCache(checkSize)
_resolutions.push(r)
}
_resolutions.pop()
}
private function initScrollBar():void
{
var sbbmd:BitmapData=new BitmapData(_resolution, 20, false, 0xcccccc)
_scrollbar=new Bitmap(sbbmd)
_scrollbar.y=120
addChild(_scrollbar)
sbbmd=new BitmapData(_resolution, 16, false, 0xeeeeee)
_scrollthumb=new MovieClip()
_scrollthumb.graphics.beginFill(0xff0000)
_scrollthumb.graphics.drawRect(0, 0, _resolution, 10)
_scrollthumb.graphics.endFill()
_scrollthumb.y=125
addChild(_scrollthumb)
_scrollthumb.buttonMode=true
_scrollthumb.addEventListener(MouseEvent.MOUSE_DOWN, beginthumbdrag)
}
private function beginthumbdrag(e:MouseEvent):void
{
_scrollthumb.startDrag(false, new Rectangle(_scrollbar.x, _scrollbar.y + 5, _scrollbar.width - (_scrollthumb.width), 0))
_scrollthumb.addEventListener(MouseEvent.MOUSE_MOVE, shuttleMoving, false, 0, true);
_scrollthumb.addEventListener(MouseEvent.MOUSE_UP, endthumbdrag, false, 0, true);
}
private function endthumbdrag(e:MouseEvent):void
{
_scrollthumb.stopDrag();
e.updateAfterEvent();
_scrollthumb.removeEventListener(MouseEvent.MOUSE_MOVE, shuttleMoving);
}
private function shuttleMoving(e:MouseEvent):void
{
calculateShuttleRelativePosition();
drawwaveform()
//e.updateAfterEvent()
}
private function calculateShuttleRelativePosition():void
{
var _x:Number=_scrollthumb.x
_sliderCenter=_x + (_scrollthumb.width / 2)
_sliderRange=_scrollbar.width - _scrollthumb.width;
_slider_rel_pos=(_sliderCenter - _sliderCenterMinLeft) / _sliderRange
}
public function getPCM():void
{
var len:int=_sound.length * 44.1
_sound.extract(_ba, len)
this._blocksize=_ba.length / (_resolution * _zoomby)
shaveblocksize()
}
public function zoomin():void
{
if (this._zoomby < 16)
{
this._zoomby*=2
resizeThumb()
drawwaveform()
}
}
public function zoomout():void
{
if (_zoomby >= 2)
{
this._zoomby/=2
resizeThumb()
drawwaveform()
}
}
private function resizeThumb():void
{
_scrollthumb.width=_scrollbar.width / _zoomby
if (_scrollthumb.width == _resolution)
{
_slider_rel_pos=0
}
_sliderCenterMinLeft=_scrollthumb.width / 2;
_sliderCenterMax_Right=_scrollbar.width - (_scrollthumb.width / 2);
_sliderRange=_scrollbar.width - _scrollthumb.width;
_sliderRange=_scrollbar.width - _scrollthumb.width;
_scrollthumb.x=(_slider_rel_pos * _sliderRange)
}
private function getResolutionCache(vww:int):ResolutionCache
{
var r:ResolutionCache
for (var i:int=0; i < _resolutions.length; ++i)
{
if (_resolutions[i].name == vww)
{
r=_resolutions[i];
break;
}
}
return r;
}
public function drawwaveform():void
{
var starttime:Number=getTimer()
var readposition:int
var viewPortWidth:int=_resolution;
var virtualWindowWidth:int=_resolution * _zoomby;
var l:Number
var r:Number
var p:Number
var rc:ResolutionCache=getResolutionCache(virtualWindowWidth)
this._blocksize=_ba.length / virtualWindowWidth
shaveblocksize()
this.graphics.clear()
this.graphics.beginFill(0xc5c5c5, 0.5)
this.graphics.drawRect(0, 50, _resolution, 1)
var pixel:int=(_slider_rel_pos * (virtualWindowWidth - viewPortWidth - 1));
var readpoint:int=pixel * _blocksize;
var rect:Rectangle
_ba.position=readpoint;
this.graphics.clear()
this.graphics.beginFill(0xffffff)
for (var i:int=0; i < _resolution; i++)
{
if (rc.points[pixel] == -1)
{
_ba.position=pixel * _blocksize
l=_ba.readFloat() * 100;
r=_ba.readFloat() * 100;
p=(l + r) / 2
rc.addPoint(pixel, i, height / 2, p)
rect=rc.points[pixel]
//this.graphics.drawRect(rect.x,rect.y,rect.width,rect.height)
this.graphics.drawRect(i, 50, 1, p)
this.graphics.drawRect(i, 50, 1, -p)
}
else
{
//viewportBitmapdata.fillRect(rc.points[pixel], 0xffffff)
rect=rc.points[pixel]
this.graphics.drawRect(i, 50, 1, rect.height)
this.graphics.drawRect(i, 50, 1, -rect.height)
//this.graphics.drawRect(i,height/2,rect.width,rect.height)
}
pixel++
}
}
private function shaveblocksize():void
{
do
{
_blocksize--
} while (_blocksize % 4);
}
}
}