1.31.2009

bookmark - 野部加強英語聽力的畢生絕學

在search install vmware on ubtuntu 8.04 時,看到這一篇,覺得很有趣。
所以把他節錄下來,不知道有沒有效,但是好像有趣的樣子..
而且可以名正言順的看DVD...

from http://blog.macroviz.com
野人獻曝:野部加強英語聽力的畢生絕學

另外關於聽力訓練的部分,也一併詳述。

其實聽力訓練的目標只有一個,就是把視覺依賴轉換成聽覺依賴。過程中有三層殼,必須要層層脫去。各層脫去時間可能需要一到兩個月,全程需要半年以上,需要的是耐心,不斷練習到大腦產生化學變化為止。

1. 視覺依賴,只能靠著看中文字幕才能明白影片在演什麼。
2. 第一層,用 Power DVD 開啟中英字幕,讓自己習慣英文字幕的出現。
3. 第二層,把中文字幕關掉,只留下英文字幕,並且要用眼球去跟。
4. 第三層,把英文字幕關掉,只靠耳朵去跟影片人物的嘴型。
5. 聽覺依賴,不看影片,光聽聲音,在腦中浮現 1. 角色說話的模樣 或 2.想像一支筆在內心寫下聽到的文字。



野部在7、8 年前就針對語言學習提出第五技能–思,想像力訓練也是思的一種。許多速讀法、記憶法、大腦開發法都有提到,一定要盡力的練習。

1. 形狀練習:在內心畫出白色的線段,構成三角形,直到能夠瞬間畫出白色三角為止,可以依序練習三角,四角,五角,到圓形等等。
2. 顏色練習,用六種色彩,紅橙黃綠藍紫,依序變換三角形的顏色。
3. 變形和變色練習。
4. 寫字母練習,想像一支筆,可以寫出 26 個英文字母。
5. 寫單字練習,想像一支筆,先練習用字母寫,練習到最後,一下筆就是浮出一個單字。
6. 寫句子訓練,想像一支筆,用單字來寫句子,練習到最後,一下筆就是浮出一個句子。



另外一方面,聽覺能力也必須靠海馬迴的運作。海馬迴掌握人類短期記憶的儲存。我們聽過的人類短期記憶一個有名的理論就是魔術數字七。就是一個人可以瞬間記憶 7 個電話號碼數字,打完電話後,馬上就會忘掉了。

但是,海馬迴不是不能擴充的。要擴充,就是去用他,用越頻繁,瞬間記憶容量越多 (哈,跟USB隨身碟相反)。

練習一:新聞上講的一個短句,能否做到一字不露的用嘴巴說出呢?

練習二:新聞上講的一個短句,能否用內心產生聲音,一字不露的重新播放呢?



以上算是野部學外語的畢生絕學,道理點破不值錢,人人都知道,但是那沒有用,要達到,還是只能靠練習,就是這麼簡單。

1.20.2009

Open Source 的 GPS 軟體(因為Routing部份還沒做好,所以不敢叫 Navigation)

http://roadmap.sourceforge.net/

1.17.2009

Use GDI Draw Function in DirectDraw Surface

不論是 PRIMARY, ATTACHED, OVERLAY 還是 OFFSCREEN 的 Surface。
Create 後,都可以用 -->GetDC(&dc) 取得 Surface DC。

作一般 GDI 的 dc 操作 : copy bitmap, draw text, draw line.. etc.

DirectDraw : SurfaceHeap

以下是猜的:

DirectDraw 需要 CreateSurface( ),Surface 就是一塊memory。這塊memory 最終 可以用來指定輸出到 lcd 上。
所以可以 create 很多個 surface,然後分別指定顯示到 lcd
這個 Surface memory 是從 Display Driver 的 Heap 中 alloc 的。

這一塊 Display Driver 的記憶體一般稱為 FrameBufferHeap,或是 VideoMemoryHeap。
這塊記憶體是要和 graphic hardware 加速器合作。所以會有一些限制。
例如,要是一塊連續的記憶體,還有,要在 phyiscal memory address 的特殊位置。

但是,管理這一塊 MemoryHeap,卻是 WindowsCE OS 做的。

在 Display Driver 的生成,就要 new 一個 SurfaceHeap( ) 物件。

DisplayHeap = new SurfaceHeap(HeapSize,Start address,NULL,NULL);

在生成函式中,告知heap的 start address 和 heap size。

這塊 surfaceheap memory,會在 config.bib 中預留下來。

原來SONY有這麼多產品用 Linux

這一頁,SONY的 source code distribution service 中,列出所有使用 gpl 產品的 source code。

真不可思議,原來這麼多東西都有用到 Linux..
小從 多功能遙控器,大到 Home Server。都有用。

比較有趣的是..很多SONY相機都列在上面... H3, H10, H50...T2, T20,T300。

還有 PND.也都是 用 Linux.

1.16.2009

DirectDraw : EnumAttachedSurface

HRESULT EnumAttachedSurfaces(
LPVOID lpContext,
LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback
);

這個 function 很有趣。

在 create surface 時,可以指定 BackBufferCount,也就是說,同時有 N 個 surface attach 在這個 surface 上。

這樣 create 出來的 surface 就會有 N 個 surface attach 在後面。


所以要是有什麼動作是要對所有的 surface 一起動作的,就要一個一個的把 attached surface 叫出來,一個一個作。
這樣很麻煩,所以提供這一個 function。

EnumAttachedSurfaces 的參數有一個是 callback function,就是說,有幾個 attached surface 就會 call 這個 callback function 幾次,同時在 call 的時候,還會把那個 attached surface 的 pointer傳進去。

這樣,只要把動作寫成 callback function,再用 EnumAttachedSurface( ) apply 到所有的surface 就 OK囉。



? 很奇怪的是... 好像不會自動 call 所有的 surface,要自己手動 一直 call... sample code 是在 callback function 中又 call EnumAttachedSurface( ) ,造成 recursive,所以 call back function 要自己決定 停止 的時機 !!!!!!

DirectDraw : Overlay 的操作

先是照著開 PRIMARY 的方法 開 OVERLAY:

// create overlay
memset(&m_ddsd, 0, sizeof(m_ddsd));
m_ddsd.dwSize = sizeof(m_ddsd);
m_ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX |
DDSCAPS_VIDEOMEMORY;
m_ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_BACKBUFFERCOUNT;
m_ddsd.dwWidth = 480;
m_ddsd.dwHeight = 272;
m_ddsd.dwBackBufferCount = 1;
hr=m_pdd->CreateSurface(&m_ddsd,&m_osurf,NULL);


然後就依照慣例,Lock surface 取出 surface address 後就開始畫圖..
但是..顯示不出來..

是忘了要 Overlay SHOW 出來,要 ..

m_osurf->UpdateOverlay(NULL, m_psurf, NULL, DDOVER_SHOW,NULL);

但是...Show 出來後,整個畫面都是Overlay 的圖呀!我沒畫的部份也show出來,是黑的..

這是因為surface 是 RGB656,沒有 alpha 資料,所以不知道黑色是不是"穿透"色。

所以要設 ColorKey,告訴DirectDraw "黑色不要顯示":

DDOVERLAYFX ovfx;

memset(&ovfx,0,sizeof(ovfx));
ovfx.dwSize = sizeof(ovfx);
ovfx.dckSrcColorkey.dwColorSpaceLowValue=0; // black as the color key
ovfx.dckSrcColorkey.dwColorSpaceHighValue=0;
m_osurf->UpdateOverlay(NULL, m_psurf, NULL, DDOVER_SHOW | DDOVER_KEYSRCOVERRIDE | DDOVER_DDFX, &ovfx);
這樣就OK啦!

但是,有一天 Overlay 要顯示黑色怎麼辦?

git 開始...

慢慢來好了...

當 mercuial 使用的話..

  1. 先到 source code 的 folder 下面作: git init ,他就會建一個 git 用的 database 在這個 folder 下
  2. 用 git add . 把folder 下的 file 都加入 version control
  3. git commit 就 commit
參考資料的話:這一篇教學寫的很有趣。

1.15.2009

Create Surface with Backbuffer

如果要create一個有一個 back surface (就是兩頁)的 surface:

memset((void *)&m_ddsd, 0, sizeof(m_ddsd));
m_ddsd.dwSize = sizeof(m_ddsd);
m_ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
m_ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
m_ddsd.dwBackBufferCount = 1;

hr=m_pdd->CreateSurface(&m_ddsd, &m_psurf, NULL);
在之前的 SetCooperativeLevel( )就不可以設 NORMAL。
要設

SetCooperativeLevel(m_hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
否則會 Create Fail.

alpha blend for rgb565

ref 這一篇
把 rgb565 轉到 32 bit (但是 order 不是 RGB),然後作 32 bit 的 X alpha 運算。
這樣,就只要作一次乘法。

rgb565 轉到 32 bit 的方法也很聰明,就是把 中間的 G 移出來到 high 16 bit 中:

unsigned int x = rgb565;
x = (x | (x <<16)) & 0x07E0F81F;

算好後,轉回來的方法:

unsigned short rgb565;
rgb565 = (x | (x >> 16));

所以整個運算就是...

#define ALPHA 12 // 0~31
unsigned int bg32,color32;
unsigned short bg = getpixelvalue(x,y);

bg32 = ( bg | bg<<16 ) & 0x07E0F81F;
color32 = (color | color<<16) & 0x07E0F81F;

unsigned int result = (((color32-bg32) * ALPHA)/32 + bg32) & 0x07E0F81F;

setpixelvalue(x,y, (result | result>>16) );


結果 google 一下 0x7E0F81F,, 有一堆...

* 這一篇有更詳細的說明,assembly implement 和 benchmarking.

Fill Polygon with scan line algorithm


void FillPolygon(int *x,int *y,int cornerno,unsigned short color)
{
int max,min,j;
max=min=y[0];



//--------找出polygon 的 y line range--------
for(int i=0;i<cornerno;i++)
if(max<y[i])
max=y[i];
else if(min>y[i])
min=y[i];

//--------開始一條一條 Y line 的scan and draw --------
for(int line=min;line<=max;line++){

int sno=0;
int slist[1000]; // 所以有1000個 intersect points 的限制

//--------找出所有 polygon 與 y line 的 intersect points-----
for(j=0;j<cornerno;j++){
int np=(j+1)%cornerno;
if(y[j]==line){ // 點在 yline 上要特別處理
int pp=j-1;
if(pp<0)
pp+=cornerno;
if((y[np]>line)&&(y[pp]<line) || (y[np]<line) && (y[pp]>line) ){
slist[sno]=x[j];
sno++;
}
}else if((y[j]>line && y[np]<line) || (y[j]<line && y[np]>line)){
slist[sno]=(line-y[j])*(x[np]-x[j])/(y[np]-y[j])+x[j];
sno++;
}
}

//--------Sort intersect points--------
for(int sorti=0;sorti<sno;sorti++)
for(int n=sorti;n<sno;n++)
if(slist[sorti]>slist[n]){
int tmp=slist[sorti];
slist[sorti]=slist[n];
slist[n]=tmp;
}

//--------兩兩 intersect points 畫出一條 y line--------
if(sno>1)
for(int sect=0;sect<sno;sect+=2)
VLineWoLock(slist[sect],slist[sect+1],line,color);
}


}

是 reference google 到的一些 fill polygon 的教學網站寫的,因為那些網站好像都沒有真正copy-paste就可以用的 code。
http://alienryderflex.com/polygon_fill/



"找出 一條 y line 的所有 intersects" 這一段大概可以 optimize,就是把所有edge (corner-to-corner, 也就是'邊')的斜率先記下來,這樣每一條 y line 在計算時就不用重算 斜率。


但是要注意 round-off error (example 是先乘後除),所以可能要學 FFE?的方法,先 shift 16 bit,算出斜率。到時候乘完再 shift 回去。


還有更多optimize 的空間:利用 "相鄰scanline的inersect會相近" 這個概念,加入 "Active Edges" 的資料結構,只有在scan line 碰到 vertex (corner point)時, "Active Edges" 的內容才會改變。
這樣可以加速計算 intersects[] 的速度。

1.13.2009

取得目前display 的 X, Y 解析度:

screen_w = GetSystemMetrics(SM_CXSCREEN);
Screen_Y = GetSystemMetrics(SM_CYSCREEN);


GreateSurface(hWnd,screen_w, screen_h):
Create

1.12.2009

結果是這個 http://www.edepot.com/linee.html 的code最完整 (所有象限都支援)。
Algorithm 也不錯,一次除法,其他都是shift 和 乘。
乘的部份是 setpixel 內部,轉 x, y 到線性記憶體位址用的。
所以嚴格說起來,應該只有shift 和 +。
而且他的 benchmark source code 中,包含了所有其他 algorithm 的 ' 可用 ' 版本。

1.10.2009

這邊有快速的 LineDraw Algorithm :http://www.edepot.com/algorithm.html
上一篇的好像都有分象限。要修改。

1.09.2009

DrawLine .. 原來 Wiki 有很多資料..從 這一篇 開始.
參考資料有link到其他的資料.

1.08.2009

DirectDraw 的 Overlay Surface

翻譯一下 help 的 '''Overlay Surface Overview''':

Overlay 是一個疊在主display 畫面上的一層畫面,更動overlay 的畫面。
An overlay surface is analogous to a clear piece of plastic that you draw on and place in front of the monitor.


Overlay 這個function 需要完全由 hardware support,MS 無法提供 software emulation。

Overlay 可以用 CreateSurface( ) 來產生,在 DDSCAPS2 參數,設定 DDSCAPS_OVERLAY flag,就可以create 出一個 Overlay Surface。

因為 Overlay 只能 create 在 hardware 的 video ram 中,所以同時要將參數的 DDSCAPS_VIDEOMEMORY flag 設起來,CreateSurface( )才會成功。

用 DriectDraw 取出 video frame buffer address 直接畫圖


LPDIRECTDRAWSURFACE4 m_pSurface; // Primary Surface.
LPDIRECTDRAW4 m_pDD = NULL; // DirectDraw object
DDSURFACEDESC2 m_ddsd;



// 取得 DirectDraw4 的 interace
DirectDrawCreate(NULL, &pDD, NULL);
pDD->QueryInterface(IID_IDirectDraw4, (LPVOID *) & m_pDD);
pDD->Release();
m_pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);

// Create 一個Surface,主Surface - 一寫就直接顯示
memset(&m_ddsd, 0, sizeof(m_ddsd));
m_ddsd.dwSize = sizeof(m_ddsd);
m_ddsd.dwFlags = DDSD_CAPS;
m_ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
m_pDD->CreateSurface(&m_ddsd, &m_pSurface, NULL);

// Lock 這個 Surface,並且取得 surface ram 的 start address
m_pSurface->Lock(NULL, &m_ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);

// 將 surface ram 的 start address 傳入 自己的 pain function - 開始畫圖
Paint((unsigned short*)m_ddsd.lpSurface);

// 畫完,unlock
m_pSurface->Unlock(NULL);
在"這裡"看到的..
註解的目的

註解是用來寫目的、限制條件跟預期結果等,而不是寫出以下這些程式一行行會做些什麼(請不要拿註解再寫一次程式碼在寫的事情)。一個簡單的判斷方式是:寫在函式 “裡面” 的註解多半是不需要的 (尤其是註解寫 what? 而不是註解 why?)。在重構一書更直言回答哪裡需要重構?那就是有註解的地方:如果程式碼前方有一行註釋,就是在提醒你,可以將這段程式碼替換成一個函式,而且可以在註釋的基礎上給這個函式命名。

你要做的事情應該是讓 source code 本身容易了解,而不是透過註解。透過正確的變數命名、好的空白間隔、邏輯分離清楚的執行路徑等手法,我們很少需要在函式裡面註明這些程式在做什麼,我自己的經驗除非是有參考外部的程式碼或複雜演算法,我會多註明參考來源(網址)。否則沒有必要的註解對我來說就像噪音一樣,妨礙閱讀。

最佳的註解就是程式碼。所以要寫出別人看得懂的code,比較重要 -- 但這往往是不容易的,也無法列出規定,所以,有些人就只好從coding style 中規定一堆...
結果,規定的都是一些不著邊際的rule..
hDC = GetDC(hWnd) : 取得目前這個 application 的輸出裝置 handle。
hBMP = CreateDIBSection( ... &bufferaddress) : create 一塊區域,用來畫圖用。
SelectObject(hDC,hBMP) : 告訴OS,用這個 BMP 作為輸出的內容。

之後,就可以用 CreateDIBSection( ) 中,以argument 傳回的 &bufferaddress 作為 framebuffer 起始位址,開始塗寫...