2010年6月16日 星期三

Testing a sprite to use as the "command line" for Adobe Alchemy

Alchemy:Documentation:Developing with Alchemy:AS3 API 提到setSprite()
可以將Sprite模擬成Command Shell,本範例測試Alchemy是否能使用C語言常用
的輸出入函數將資料導到STDIN、STDOUT、 STDERR

以下程式改自Alchemy samples其中的stringecho範例
這是C程式
#include <stdlib.h>
#include <stdio.h>
#include "AS3.h"

static AS3_Val echo(void* self, AS3_Val args)
{

char* val = NULL;
AS3_ArrayValue( args, "StrType", &val );

if(val == NULL)
{
char* nullString = "null";
//return the string "null"
return AS3_String(nullString);
}

printf("*****Test printf() OK!!!*****\n");
fprintf(stderr, "*****%s Test fprintf(stderr,...) OK!!!*****\n",val);
fprintf(stdout, "*****%s Test fprintf(stdout,...) OK!!!*****\n",val);

return AS3_String(val);
}

int main()
{

AS3_Val echoMethod = AS3_Function( NULL, echo );


AS3_Val result = AS3_Object( "echo: AS3ValType", echoMethod );


AS3_Release( echoMethod );


AS3_LibInit( result );


return 0;
}




這是as3程式
package {
import flash.display.Sprite;
import flash.text.TextField;
import flash.events.Event;
import flash.events.MouseEvent;

import cmodule.stringecho.CLibInit;

public class EchoTest extends Sprite
{
protected var alchemyLib : Object;

public function EchoTest()
{
addEventListener( Event.ADDED_TO_STAGE, addedToStageHandler );

}

protected function addedToStageHandler( event : Event ) : void
{
removeEventListener( Event.ADDED_TO_STAGE, addedToStageHandler );
var loader:CLibInit = new CLibInit;
loader.setSprite(this);
alchemyLib= loader.init();
trace(alchemyLib.echo("foo0"));
alchemyLib.echo("foo1");
throw Error(alchemyLib.echo("foo2"));
}

}
}



執行的結果如下
*****foo1 Test fprintf(stderr,...) OK!!!*****
*****foo2 Test fprintf(stderr,...) OK!!!*****


經過用力的測測測........
目前只有fprintf(stderr,...)能成功輸出
Alchemy名字取的真好
可真是"煉金術"啊
讓我可以體會自古以來西方鍊金術士鍊金過程的辛苦
發思古之幽情........

這是swf檔
[Demo]

2010年6月11日 星期五

Plasma Effect--Adobe Alchemy初體驗



本來看過Adobe Labs的Alchemy:Documentation:Getting Started"落落長"的內容有點猶豫不前,
想不到Adobe Alchemy在Ubuntu一下子就裝好了,接著搜尋到一些超炫Plasma Effect想說實驗看看

這裡有C語言實作的詳解,還有這篇Alchemy plasma experiment文章也有Alchemy實作的原始碼

以下是我修改後的C原始碼


#include <stdio.h>
#include <math.h>
#include "AS3.h"

int* palette;
int* plasma;
int* newPlasma;
int width;
int height;

AS3_Val generatePlasma(void* self, AS3_Val args)
{


AS3_ArrayValue(args, "IntType, IntType", &width, &height);

palette = malloc(256 * sizeof(int));
plasma = malloc(width * height * sizeof(int));
newPlasma = malloc(width * height * sizeof(int));

genPalette();
plasma_pattern();
return AS3_Ptr( plasma );
}


AS3_Val shiftPlasma(void* self, AS3_Val args)
{
int shift, x, y, index, paletteIndex;
AS3_ArrayValue(args, "IntType", &shift);

for(x=0; x<width; x++)
{
for(y=0; y<height; y++)
{
paletteIndex = (unsigned int)(plasma[index] + shift) % 256;
newPlasma[index] = palette[paletteIndex];
index++;
}
}

return AS3_Ptr(newPlasma);
}


void genPaletteHSV()
{
int x;
for(x=0; x<256; x++)
{
palette[x] = HSVtoRGB(x, 255, 255);
}
}

void plasma_pattern()
{
int x, y, index;
for(x=0; x<width; x++)
{
for(y=0; y<height; y++)
{
int color = (
128.0 + ( 128.0 * sin( x / 16.0 ) ) +
128.0 + ( 128.0 * sin( y / 8.0 ) ) +
128.0 + ( 128.0 * sin( ( x + y ) / 16.0 ) ) +
128.0 + ( 128.0 * sin( sqrt( x * x + y * y ) / 8.0 ) )
) / 4;
plasma[index++] = 0xff << 24 | color;
}
}
}

int main()
{
AS3_Val generatePlasmaMethod = AS3_Function( NULL, generatePlasma );
AS3_Val shiftPlasmaMethod = AS3_Function( NULL, shiftPlasma );
AS3_Val result = AS3_Object(
"generatePlasma: AS3ValType,shiftPlasma: AS3ValType",
generatePlasmaMethod, shiftPlasmaMethod
);
AS3_Release( generatePlasmaMethod );
AS3_Release( shiftPlasmaMethod );
AS3_LibInit( result );

return 0;
}




效果很炫
CPU也不怎麼操
看來書櫃裡塵封已久的C語言參考書將重見天日了

2010年3月26日 星期五

Very simple haXe coding tool



目前以文字編輯器寫haXe code好像只能做到初步語法檢查
所以我寫程式時總要在文字編輯器與haXe API Documentation之間不斷切換
這實在非常困擾我!!!
只好參考haXe Reflection API寫了個很陽春的haXe程式碼編寫工具
目前沒有語法檢查只有簡單的Code Asist功能
按'.'會跳出物件的Fields/Methods視窗
然後再用這工具編輯工具本身的程式碼

原本UI架構想採用AsWinghaxegui但嘗試haXe coding時很不順手,
後來還是改採簡簡單單的minimalcomps元件

目前的心得是haXe上手並不難
但是開發複雜一點的程式有點為難
希望我這個小工具可以幫上忙

Demo

2010年3月11日 星期四

Fast computing floating-point arrays using the Pixel Bender

前一陣子為了寫整合3D與Dynamic Sound相關套件的Flash程式,但是發覺只要加入的音頻越多的話,
常常會爆出破音甚至在IE上執行時會當掉,想說可能是Away3D吃掉太多資源所致,
也試著以Away3DLite改寫後情況也沒好到哪裡,最近剛好找到這篇文章Using Pixel Bender to calculate information
提到因為Flash是單一執行緒程式,當處理大量吃重的運算常效能不彰,
可利用Pixel Bender的多工處理的特性將某些吃重的運算挪到PBJ上面執行

於是參考這幾篇文章發表的程式碼後
Audio mixing with Pixel Bender
Using Pixel Bender with Flash Builder 4 beta as a number crunching engine

牛刀小試的改寫成了以下的程式碼

這是PBK程式碼,可多工平行運算用來加總兩個陣列的每個Item的值
<languageVersion : 1.0;>
kernel SumCalculator
<
namespace : "PixelBender";
vendor : "Charlie";
version : 1;
description : "SumCalculator";
>
{
input image1 src;
input image1 src2;

output pixel3 result;

void evaluatePixel()
{
float x = pixel1( sample(src, outCoord()) );
float y = pixel1( sample(src2, outCoord()) );

float z = x+y;

result = pixel3( z, 0.0, 0.0);
}
}


這是AS3程式碼
package
{

import com.bit101.components.*;

import flash.display.*;
import flash.events.*;
import flash.utils.*;

public class FastSumManyArray extends Sprite
{
[Embed(source="./pbks/SumCalculator.pbj", mimeType="application/octet-stream")]
private var KernelClass:Class;

const arraylength:int=5000;
private var array1:Array=new Array(arraylength);
private var array2:Array=new Array(arraylength);
private var array_result:Array=new Array();
private var text3:Text;
private var result:ByteArray;

public function FastSumManyArray()
{
stage.align="TL"
initArray(array1);
initArray(array2);
var text1:Text=new Text(this,0,0,array1.toString());
text1.height=16;
text1.width=1000;
addChild(text1);
var text2:Text=new Text(this,0,30,array2.toString());
text2.height=16;
text2.width=1000;
addChild(text2);
text3=new Text(this,0,60);
text3.height=16;
text3.width=1000;
addChild(text3);
addChild(new PushButton(this,0,100,"Start",clickHandler));
}

private function initArray(array:Array)
{
for(var i=0;i<array.length;i++)
{
array[i]=Math.random();
}
}

private function clickHandler(event:MouseEvent):void
{
initializeHandler(array1,array2);
}

protected function initializeHandler(list:Array, list2:Array):void
{
var byteArray:ByteArray = new ByteArray();
var byteArray2:ByteArray = new ByteArray();
var shader:Shader = new Shader(new KernelClass());
var shaderJob:ShaderJob;
var height:int;
var width:int;
byteArray = convertListToByteArray( list );
byteArray2 = convertListToByteArray( list2 );
width = byteArray.length >> 2;
height = 1;

shader.data.src.width = width;
shader.data.src.height = height;
shader.data.src.input = byteArray;

shader.data.src2.width = width;
shader.data.src2.height = height;
shader.data.src2.input = byteArray2;

result = new ByteArray();
result.endian = Endian.LITTLE_ENDIAN;

shaderJob = new ShaderJob(shader, result, width, height);
shaderJob.addEventListener(Event.COMPLETE, onComplete);
shaderJob.start();
}

protected function onComplete(event:Event):void
{
var length:int = result.length;
var num:Number;
var i:int;
result.position = 0;
for(i = 0; i < length; i += 4)
{
num = result.readFloat();
if(i % 3 == 0)
array_result.push(num);
}
text3.text=array_result.toString();
}



private static function convertListToByteArray(list:Array):ByteArray
{
var retVal:ByteArray = new ByteArray();
var number:Number;
var len:int = list.length;
var i:int;

retVal.endian = Endian.LITTLE_ENDIAN;

for (i; i<len; i++)
{
retVal.writeFloat( Number(list[i]) );
}

retVal.position = 0;

return retVal;
}

}
}



也可利用工具將PBJ反組譯成Assembly language,看看是否有改進的空間,再以HaXe重新組譯,
壓榨出最大的效能!!!

version : 1
name : 'SumCalculator'
meta namespace : 'PixelBender'
meta vendor : 'Charlie'
meta version : 1
meta description : 'SumCalculator'
param in f0.rg float2 _OutCoord
text0 1-channels src
text1 1-channels src2
param out f1.rgb float3 result
code :
sampleLinear f0.a, text0[f0.rg]
mov f0.b, f0.a
mov f0.a, f0.b
sampleLinear f1.a, text1[f0.rg]
mov f0.b, f1.a
mov f1.a, f0.b
mov f0.b, f0.a
add f0.b, f1.a
mov f2.r, f0.b
mov f2.g, f2.r
loadfloat f0.b, 0
mov f2.b, f0.b
loadfloat f0.b, 0
mov f2.a, f0.b
mov f1.rgb, f2.gba



這是執行結果的畫面



Demo

2010年1月29日 星期五

Away3D Tenorion



最近嘗試以Away3D改寫Tenorion程式
將程式碼剪剪貼貼一下子就完成了
有一部分的程式碼是參考flashmagazine
不過3D+Dynamic Sound運作起來似乎不怎麼流暢
或許因為倉促完成
程式碼寫得不是很有效率
找時間再改改

App
source code

2010年1月3日 星期日

A Simple Binaural Beats Generator

目前FP10可以不載入聲音檔的情況下動態產生聲音
以下是簡單的FP10's Dynamic Sound 程式碼

package
{
import flash.display.Sprite;
import flash.events.SampleDataEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
public class Main extends Sprite
{
private var sound:Sound;
private var channel:SoundChannel;
public function Main():void
{
sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, writeSampleData);
channel = sound.play();
}

private function writeSampleData(e:SampleDataEvent):void
{
for(var i:Number = 0; i<8192; i++)
{
e.data.writeFloat(Math.random()*0.5);
e.data.writeFloat(Math.random()*0.5);
}
}
}
}

















上面這個flash範例是運用雙耳波差(Binaural Beats)的原理製作的簡單程式
需戴上耳機聆聽才有效果
Carrier可設定為(100 - 800Hz)的範圍
Beats則為想誘導的腦波頻率
β波(16 - 24Hz)為意識專注,身體呈緊張狀態
α波(8 - 12Hz)為意識清醒,身體放鬆
θ波(4 - 8Hz)為意識中斷,身體深沉放鬆
δ波(1 - 4Hz)為深度熟睡,無意識狀態
請享用^ ^
A Simple Binaural Beats Generator

警告:聆聽前請將音量調小,請勿在從事需集中注意力之事務之前或當下使用

2009年8月27日 星期四

Artificial Neural Network--Random Learning Perceptron

最近開始研讀類神經網路的相關文章
打算開發類神經網路訓練來解讀股價走勢
以下程式碼改自別人的範例
是我的蹲馬步練基本功的初步成果
最基本的神經網路--感知器



import random, math
import string

from sympy import *

def hardlims(inputM,weightM,bias):
     n=(weightM*inputM)[0].evalf()-bias
     if n<0:
     a = -1
     if n>=0:
     a = 1
     return a

def sum_array(a):
     acc = 0
     for i in a:
     acc += i
     return acc

class NN:
def __init__(self):
     self.w1 = [random.random() for x in range(10)]
     self.w2 = [random.random() for x in range(10)]
     self.w3 = [random.random() for x in range(10)]
     self.bias = 0

def learn(self,input,target):
     errorAbsSum = 1
     epsilon = 1e-6

     iterations = 0
     while abs(errorAbsSum) > epsilon:
     iterations +=1
     errorAbsSum = 0
     counter = 0
     tmp1 = (sum_array(self.w1) / len(self.w1))
     tmp2 = (sum_array(self.w2) / len(self.w2))
     tmp3 = (sum_array(self.w3) / len(self.w3))
     for i,x in enumerate(input):
     activation = hardlims(Matrix(3,1,x),Matrix(1,3,[tmp1,tmp2,tmp3]),self.bias)
     error = target[i] - activation
     learningRate = random.random() / 10
     tmp1 += (error * learningRate * x[0])
     tmp2 += (error * learningRate * x[1])
     tmp3 += (error * learningRate * x[2])
     errorAbsSum += abs(error)
     print 'Learning:w1=%f w2=%f w3=%f learningRate=%f error=%f activation=%f' % ( tmp1, tmp2,tmp3,learningRate,error,activation)
     del self.w1[0], self.w2[0],self.w3[0]
     self.w1.append(tmp1)
     self.w2.append(tmp2)
     self.w3.append(tmp3)
     print 'Iterations: %d \n w1=%f w2=%f w3=%f' % (iterations, tmp1, tmp2,tmp3)


def test(self,x):
     tmp1 = (sum_array(self.w1) / len(self.w1))
     tmp2 = (sum_array(self.w2) / len(self.w2))
     tmp3 = (sum_array(self.w3) / len(self.w3))
     activation = hardlims(Matrix(3,1,x),Matrix(1,3,[tmp1,tmp2,tmp3]),self.bias)
     print 'test(%s):result=%d w1=%f w2=%f w3=%f' % (x, activation, tmp1, tmp2,tmp3)


if __name__ == '__main__':
     input =[[-1,-1,-1],[1,1,1],[1,-1,-1]]
     target = [-1,1,1]

     nn=NN();
     nn.learn(input,target)
     nn.test([1,1,1])
     nn.test([1,1,-1])
     nn.test([1,-1,1])
     nn.test([1,-1,-1])
     nn.test([-1,1,1])
     nn.test([-1,1,-1])
     nn.test([-1,-1,1])
     nn.test([-1,-1,-1])


驗收訓練成果

test([1, 1, 1]):result=1 w1=0.663924 w2=0.276574 w3=0.333518
test([1, 1, -1]):result=1 w1=0.663924 w2=0.276574 w3=0.333518
test([1, -1, 1]):result=1 w1=0.663924 w2=0.276574 w3=0.333518
test([1, -1, -1]):result=1 w1=0.663924 w2=0.276574 w3=0.333518
test([-1, 1, 1]):result=-1 w1=0.663924 w2=0.276574 w3=0.333518
test([-1, 1, -1]):result=-1 w1=0.663924 w2=0.276574 w3=0.333518
test([-1, -1, 1]):result=-1 w1=0.663924 w2=0.276574 w3=0.333518
test([-1, -1, -1]):result=-1 w1=0.663924 w2=0.276574 w3=0.333518


縮排有點亂
有誰能指點一下?