IMA4 小筆記

客戶的要求如土石流一樣地來, 既然不能遷村, 就要做好防災的準備, 免得不小心就滅村了. 這次的需求是 IMA4, priority 大概第 40 順位.

這個 IMA4 是什麼東西呢? 它是 Apple Quick Time 所支援的 ADPCM 格式. 一般是 1~2 聲道, 左聲道 block 放完才放右聲道 block, 然後反覆左右, 左右 的 blocks 直到檔尾. 每個 block 由 64 個 nibble 所組成, 1 nibble 也就是 1/2 bytes or 4 bits.

為何要選 nibble 為單位呢? 據說是為了要避免 endian 的問題, 只要把 data 以 4 bits 為單位組裝起來, 就可以依據平台來解釋它是 big endian 或是  little endian. Apple 號稱這個設計有 cross-platform 的功效.

[離題一下] 話說 nibble 很像另外一個單字 nipple (奶頭), 有位前同事就把這兩者搞混了, 也誤導了我一陣子.  不過人非聖賢, 孰能無過. 身為一個工程師, 程式沒錯就很偷笑了, 偶爾打印一些 FETAL ERROR, 或是程式裡面命名一些 Globle 變數也是難免的. 反正看久就習慣了, 見怪不怪真可以說是中華文化根深蒂固的一個部分.  哈哈!

name bits structure note
preamble 16 ppppppp piiiiiii

p 代表 9 bits signed predictor,
其中後 6 bits 預設為 0

i 代表 7 bits initial step index.

block 32×8 n1n0 n3n2 …. 左聲道, nibble 0 在 nibble 1 的後面,
但是要先解, 依此類推.
block 32×8 n1n0 n3n2 …. 右聲道, 單聲道就沒有這部分,
換下一個左聲道的 block.

 欲了解 IMA4 的全貌, 最好參考 Apple 的網頁.

http://developer.apple.com/mac/library/technotes/tn/tn1081.html

 

Volatile 型別小檔案

今天有同事發信告訴大家, 他犯了一個 volatile 的錯誤, 希望大家不要重蹈覆轍. 內容大致是說, 平常大家習慣用 a = b = 10; 這樣的寫法, 但是若加上了 volatile 就不行了.

*(volatile unsigned int *) a = 

*(volatile unsigned int *) b = xxx.

為啥子呢? 因為 volatile 告訴 compiler, 這個值每次用到的時候, 都要去 a 和 b 對應的 address 裡面重新讀出來.

Compiler 如果有預見的能力, 根本不會讓它通過的. 比方說 Visual C++ 2008 Express 版, 會給這樣的訊息:

1>c:\users\cash\documents\visual studio 2008\projects\source1.cpp(6) : error C2059: 語法錯誤 : ‘volatile’

關於 volatile 的原理, 有一篇文章寫得很好, 大家可以去看看:http://blog.csdn.net/c_bg44/archive/2007/03/23/1538235.aspx

 

 

WMA 版本編號

WMA 是 Microsoft 發明的 audio compression 格式, 通常放在 ASF 的檔案格式之中. 這些都是普通常識, 到處都可以查得到.

最神奇的地方在於, WMA 有兩種編號. 官方的編號是 version 1,2,3,…乃至於現在常見的 8,9,10 等版本. 而不知道哪裡冒出來的說法, 則是把 WMA 稱為 WMA 2, WMA pro 稱為 WMA 3. 因此, 客戶常常來問我們: "WMA 3 有沒有支援?" 如果同仁或代理商跟他們說: "我們只支援到 WMA 7 喔? 不支援老舊的第三版!" 這時客戶可能也會莫名其妙地就被說服了.

要分辨檔案是 WMA 第三版, 還是 WMA pro, 其實聽多聲道的輸出就可以明白了. WMA 最多只有 2 channels, WMA pro 才有 multi-CH.

關於厚尾

過去在很多本書裡面, 都看到厚尾這個名詞. 以前, 我始終搞不清楚厚尾和 "長尾效應" 是不是同一件事?

現在我總算是比較清楚了. 厚尾 (fat tail) 是指統計上的特性. 如果一個分布的峭度 (kurtosis) 大於常態分佈 (normal distribution), 它就叫做 Leptokurtic. 這表示有比較多的機會, 這個分佈會在遠離 mean 的地方有值.

因此我們可以說厚尾 (fat tail) 可以導致明顯的長尾 (long tail), 但是 Chris Anderson 所提出的長尾效應對峭度很低的分佈仍然成立, 只要遠離 mean 的地方一直有值, 累積起來還是一個長尾.

反之, 若是峭度比常態分佈還小 (< 3, 因為常態分佈的峭度恰好是 3), 就叫做 Platykurtic, 它會有比較多的值靠近於 mean. 這是搞財務的人比較喜歡的狀況. 因為這表示他們的估計出槌的機會比較低.

另外還有機會看到一尾 (one tailed) 和兩尾 (two tailed) 的說法. 因為財務產品會估計他們的獲利的信心度. 以常態分佈為例, 在信心度 95% 的情況下, 獲利不會超過 1.96 倍的標準差, 或是低於 -1.96 倍的標準差, 此時考慮的是過高或過低兩尾的信心度.

當然, 客戶可能不介意獲利超過 1.96 倍的標準差, 畢竟多賺沒啥不好, 此時只要考慮一尾的信心度就好. 在同樣的狀況下, 賣方可以誇稱他有 97.5% 的信心度, 不會虧到 -1.96 倍標準差下.

超過幾倍標準差這個東西, 叫做 z-value, z-score, 或是 z-statistic. 統計值先減掉統計的 mean, 再除以 standard deviation 就可以得到.

z = (x – µ) / std

對了, 峭度的計算忘了講, 他是第四階的 moment.

kurtosis = summation ((xi – u)4) / (N * std4 )

excess kurtosis = kurtosis – 3 

因為 3 就是常態分佈的峭度, 以此可做為峭度高低的分野.

 

夭壽慢的 Cygwin

在軍情緊急的昨天 (2009/6/27), 本來是要幫忙解 HDMI 的 bug. 但是事件卻如雪片般地飛來~~~ 前線的 Dylan 說我 build 給他的版本有問題; Mike 多次打電話來關切; 老婆中午叫我回去教做人做事的道理, 晚上叫我教女兒英文. 另外我們的 SPDIF 規格版本太舊了, 我還得抽空上網去買新版的 SPDIF spec. 再 download 下來給 Irene 看.

然而, 真正叫人喪氣的就是: Cygwin 變得超超慢, build 一個版本似乎要好幾個小時. 我想 Dylan 應該要瘋了~~~ 為了測底消滅這個問題, 我趁 make code 的時候, 整理 Cygwin 變慢的原因如下: 

根據網路搜尋的結果, 在 Cygwin 的官網這樣解釋:

4.2.

Why is Cygwin suddenly so slow?

 

If you recently upgraded and suddenly every command takes a very long time, then something is probably attempting to access a network share. You may have the obsolete //c notation in your PATH or startup files. This now means the network share c, which will slow things down tremendously if it does not exist.

Using //c (for C:) doesn’t work anymore. (Similarly for any drive letter, e.g. //z for Z:) This “feature" has long been deprecated, and no longer works at all in the latest release. As of release 1.3.3, //c now means the network share c. For a detailed discussion of why this change was made, and how deal with it now, refer to http://sources.redhat.com/ml/cygwin/2001-09/msg00014.html.

在討論串裡面, 有類似的說明:

http://www.mail-archive.com/cygwin@cygwin.com/msg85049.html

另外一個原因好像是 Windows 2000 的 hotfix Q8114993 改了 winsock 的處理方式.

www.cygwin.com/ml/cygwin/2003-05/msg00065.html

既然我的 cygwin 本來是快的, 原因很可能出在 Windows 的 upgrade. 可惜看來看去, 網路上說的 hotfix 竟然是 2003 年的事了, 現在的這些 hotfix 並不知道要懷疑誰好? (其中 IE 8 那一包至為可疑…, 我的 notebook 灌了它之後很會當!)

再回頭看看 Cygwin 的另外一個官網 http://cygwin.com/, 裡面提到了一些實際可行的做法. 整理如下:

1. 給 Cygwin 更多的記憶體. 這個例子可以給到 1024MB, 當然, 這是指 virtual memory. 只要 Windows 的分頁記憶體比它還大就可以了.

regtool -i set /HKLM/Software/Cygnus\ Solutions/Cygwin/heap_chunk_in_mb 1024
regtool -v list /HKLM/Software/Cygnus\ Solutions/Cygwin

執行結果如下:

mounts v2\ (Cygwin)
Program Options\ (cygnus)
heap_chunk_in_mb (REG_DWORD) = 0x00000400 (1024)

2. 用 strace 跑一次 make, 從這裡可以看到很多時間花在找 path, 因此把 cygwin 的目錄往前移. 修改的地方自然是在控制台 → 系統  → 進階  → 環境變數那裡.

此外, 我也看到一個令人心痛的事實, Cygwin 花了很多時間在確認執行檔的名稱. 它先找執行檔 XXX, 再依序找 XXX.exe, XXX.lnk, 和 XXX.exe.lnk. 原來我浪費了這麼多時間在做沒意義的傻事! 

   78  373674 [main] rsdk-elf-gcc 2440 mount_info::conv_to_win32_path: src_path /rsc/ct_wu/rsdk/release/rsdk-1.4.2/cygwin/newlib/rlx-elf/lib/specs, dst g:\cygwin\rsc\ct_wu\rsdk\release\rsdk-1.4.2\cygwin\newlib\rlx-elf\lib\specs, flags 0xA, rc 0
  127  373801 [main] rsdk-elf-gcc 2440 symlink_info::check: GetFileAttributes (g:\cygwin\rsc\ct_wu\rsdk\release\rsdk-1.4.2\cygwin\newlib\rlx-elf\lib\specs) failed
   83  373884 [main] rsdk-elf-gcc 2440 geterrno_from_win_error: windows error 3 == errno 2
  116  374000 [main] rsdk-elf-gcc 2440 symlink_info::check: GetFileAttributes (g:\cygwin\rsc\ct_wu\rsdk\release\rsdk-1.4.2\cygwin\newlib\rlx-elf\lib\specs.exe) failed
   81  374081 [main] rsdk-elf-gcc 2440 geterrno_from_win_error: windows error 3 == errno 2
  117  374198 [main] rsdk-elf-gcc 2440 symlink_info::check: GetFileAttributes (g:\cygwin\rsc\ct_wu\rsdk\release\rsdk-1.4.2\cygwin\newlib\rlx-elf\lib\specs.lnk) failed
   80  374278 [main] rsdk-elf-gcc 2440 geterrno_from_win_error: windows error 3 == errno 2
  117  374395 [main] rsdk-elf-gcc 2440 symlink_info::check: GetFileAttributes (g:\cygwin\rsc\ct_wu\rsdk\release\rsdk-1.4.2\cygwin\newlib\rlx-elf\lib\specs.exe.lnk) failed
   83  374478 [main] rsdk-elf-gcc 2440 geterrno_from_win_error: windows error 3 == errno 2
   79  374557 [main] rsdk-elf-gcc 2440 symlink_info::check: 0 = symlink.check (g:\cygwin\rsc\ct_wu\rsdk\release\rsdk-1.4.2\cygwin\newlib\rlx-elf\lib\specs, 0x22C450) (0xA)
   82  374639 [main] rsdk-elf-gcc 2440 mount_info::conv_to_win32_path: conv_to_win32_path (/rsc/ct_wu/rsdk/release/rsdk-1.4.2/cygwin/newlib/rlx-elf/lib)

在 strace 裡面看到做最久的一步是 entering. 換個目錄需要很長很長的時間. 因此我想到第三步: 硬碟重組!

3. 把硬碟重新整理一下, 執行重組! 既然 Cygwin 編譯時 CPU time 是如此地少, 可見得它是 IO bound. 此時 Memory 已經給很多了, 實際上用到的記憶體 800MB 都還不到實體記憶體 1GB 的 90%, 所以可以排除 memory bound 的可能.

4. 把防毒軟體的沒用的檢查關掉一點. 把安全的檔案夾都放到 exception 裡面.

5. 把 bash.exe 的 priority 從工作管理員裡面調升到 "標準以上". 不過, 我給 Dylan 的版本就是在調升 priority 以後 make 的, 我現在不是很敢動它. 尤其是調到 "即時" 等級的話, 根本就不能 make clean  再 make all 了.

用了這幾招之後, 感覺似乎有快一點. 至少 make 一次的時間可以在 5 分鐘以內了. 不知道是不是有 bug, 哈! 其中最好的一招好像是 3: 硬碟重組. 有人知道更厲害的絕招可以教我嗎?