2008年1月15日星期二

webbrowser_external

using System.Windows.Forms;
using System.Security.Permissions;

[PermissionSet(SecurityAction.Demand, Name="FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]

public class Form1 : Form
{
private WebBrowser webBrowser1 = new WebBrowser();
private Button button1 = new Button();

[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}

public Form1()
{
button1.Text = "call script code from client code";
button1.Dock = DockStyle.Top;
button1.Click += new EventHandler(button1_Click);
webBrowser1.Dock = DockStyle.Fill;
Controls.Add(webBrowser1);
Controls.Add(button1);
Load += new EventHandler(Form1_Load);
}

private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.AllowWebBrowserDrop = false;
webBrowser1.IsWebBrowserContextMenuEnabled = false;
webBrowser1.WebBrowserShortcutsEnabled = false;
webBrowser1.ObjectForScripting = this;
// Uncomment the following line when you are finished debugging.
//webBrowser1.ScriptErrorsSuppressed = true;

webBrowser1.DocumentText =
"<html><head><script>" +
"function test(message) { alert(message); }" +
"</script></head><body><button " +
"onclick=\"window.external.Test('called from script code')\">" +
"call client code from script code</button>" +
"</body></html>";
}

public void Test(String message)
{
MessageBox.Show(message, "client code");
}

private void button1_Click(object sender, EventArgs e)
{
webBrowser1.Document.InvokeScript("test",
new String[] { "called from client code" });
}

}

2008年1月3日星期四

让你的.NET程序脱离Framework跑起来

摘自:
Mono虽好,可是他毕竟不是Microsoft .NET Framework,至少它的WinForms是采用了java里swing同样的方法,所以无论用户的主题多么漂亮,WinForm都是传统的Windows界面,作为桌面应用时就显得格格不入。

安装

但.NET核心文件并不多(相对而言,相比mono你会发现他很庞大)

我给出我的报告文件,看这个要比看那2mb的log轻松得多。

///////////////////////

files:

c:\windows\system32\mscoree.dll

c:\windows\system32\mscorier.dll

c:\windows\system32\mscories.dll

c:\windows\system32\dfshim.dll

c:\windows\system32\netfxperf.dll

这几个文件一定要放在system32下面

C:\windows\system32\mui\0409\mscoreer.dll

C:\windows\system32\mui\0409\mscorees.dll

我猜想mui下面其他版本的也是必须的

C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089

c:\windows\assembly\gac_32\[others]

需要其他的组件也要添加,比如System.Windows.Forms

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorjit.dll

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\[others]

这个文件夹下面只需要mscorjit.dll mscorwks.dll两个文件就可以使console运作正常,其他的我还没试过

c:\windows\winsxs\Manifests\...

c:\windows\winsxs\policies\...

c:\windows\winsxs\...

winsxs下有很多重要的组件,版本也很繁杂。确保一个都不能少。这些文件支撑着mscorwks.dll,没有他,mscorwks也无法加载。

////////////////////////////

REG:

HKEY_CLASSES_ROOT\TypeLib\{BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}

HKEY_CLASSES_ROOT\TypeLib\{BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}\2.0 = REG_SZ, "mscorlib.dll"

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\InstallRoot = "REG_SZ,C:\WINDOWS\Microsoft.NET\Framework\"

  只要设置了安装位置,jit自己能找到相应的framework

  有了这些文件,你就能运行.net 2.0的程序了。当然这是最小要求。

  我提供这些文件清单不是想让你把他们弄到你客户的电脑里去,而是希望有人能做出像thinstall那样的虚拟环境供程序运行,那么提供thinstall那样的功能也就不是什么难事了。

.NET Framework时,他对你系统的改动还真不少,光是一个记录文件就有2mb。(在一个不带.net framework的winxp sp2虚拟机上安装.net framework 2.0得到)

让 .Net 程序 脱离 .net framework框架 运行(源代码实现说明)

前面介绍了 “让 .Net 程序 脱离 .net framework框架 运行的方法”,
该方法主要是利用了Fetion的框架来实现的,
今天我们要介绍的是不使用Fetion的框架,自己来实现Fetion框架的相关功能,
并给出相关实现代码。

关于Fetion框架它主要是有两个文件,FetionVM.exe和FetionVM.rsm。其中对于第二个文件,我们在介绍 native compile 保护的dotNet本地程序还原成dotNet IL程序集 时已经给出了其实现的源代码。

今回就给出 FetionVM.exe 功能实现的,近似代码。

首先使用 remote的试用版 创建一个demo 程序,然后对这个demo程序进行分析,分析发现它的 loader 实际使用是通过调用 rsdeploy.dll 导出的三个函数完成初始化工作,并把控制权转交到dotNet程序集。

这三个函数的原型定义:
typedef BOOL (WINAPI* pInitialize)(HMODULE h, LPCSTR szModule, LPCSTR szMainExe);
typedef BOOL (WINAPI* pReloc)(HMODULE hModule, PIMAGE_NT_HEADERS pNtHeader);
typedef BOOL (WINAPI* pResolveImportDLL)(HMODULE);

有朋友对此多有不满,删除完整实现代码,只对实现代码进行说明

首先是Load要运行的dotNet程序文件,得到HMODULE 句柄,在三个函数中都要用到了。
然后调用 Initialize函数,szModule 是 dotNet程序的文件名,szMainExe 当前执行文件的文件名。
再调用 Reloc 处理重定位表。pNtHeader 也是 dotNet程序在内存中加载后的 NtHeader。
然后 调用ResolveImport,处理导入的dll。
最后将jmp到 dotNet程序的入口,转移控制权。


另外我还发现了另外一种使用实现方法,就是上次提到的那个 dotNet加密壳的 vm unpacker,它也使用了remotesoft 的虚拟框架,但是它没有使用rsdeploy导出的那三个函数。

昨天上 ReTeam 的论坛看到这个 unpacker 更新了。下载回来研究了一下,对于其初始化 DotNetVM 的部分还没有细看,主要看了一下它对框架 hook 的变化,发现其在Jit层中的 Hook 位置移动了。好像是Hook了 emitter对象的一个成员函数,emitter对象是被 complie调用的,位置应该算比较深了,方法体重构方式没有变化。目前的加密壳核心似乎都无法逃过其Hook的拦截。
它拦截的位置比较深,DNGuard HVM标准版对其也没有检测,不过对于DNGuard HVM标准加密的程序集,其脱壳功能仍然无害。试用版的就不能幸免了。

目前对其使用 dotnetvm 的方法比较感兴趣了,简单的看了一下,它只是load了rsdeploy.dll。没有调用rsdeploy导出的三个函数。看起来好像是直接调用了mscorwks中的函数,有可能它自己实现了这三个函数的功能。
感兴趣的朋友可以一起来分析一下,有什么收获再跟大家分享。

引用:

2008年1月2日星期三

.NET资源列表

迅雷博客上的一些视频教程:
http://xiazhi33.blog.xunlei.com

MicroSoft The .Net Show
http://msdn.microsoft.com/theshow/default.aspx
相当不错的~

C#高级编程(第3版)在线看
http://www.51shuji.com/article/10/16176/index.html

关于API的
http://www.webtropy.com/articles/Win32-API-DllImport-art9.asp

2007年12月24日星期一

混音

Symbian 6.1上实现的混音是个比较麻烦的问题,因为程序只能同时播放一个音乐,实现混音就需要程序自己来实现。下面是我从newlc上找到的一个关于PCM脉冲编码的音频信号的混音实现,其中包含了一个关键的混音算法!

Hi !!!!

I am not sure weather I have fully understood your question or not, I persume that you are asking
"How can we mix two or more audio stream", If this is the question then I am explaning below the
mixing of the two audio stream (You Can Mix More Audio Stream),

Step 1,

Get the Raw data of the two files, (Example, of the sample 8bit and 8Kh, means one sample is of
8bit)


Step 2

Let the two audio signal be A and B respectively, the range is between 0 and 255. Where A and B are the
Sample Values (Each raw data) And store the resultant into the Y

If Both the samples Values are possitve

Y = A + B - A * B / 255

Where Y is the resultant signal which contains both signal A and B, merging two audio streams into single
stream by this method solves the problem of overflow and information loss to an extent.


If the range of 8-bit sampling is between -127 to 128

If both A and B are negative Y = A +B - (A * B / (-127))
Else Y = A + B - A * B / 128


Similarly for the nbit (ex 16bit data)

For n-bit sampling audio signal


If both A and B are negative Y = A + B - (A * B / (-(2 pow(n-1) -1)))
Else Y = A + B - (A * B / (2 pow(n-1))


Step 3.

Add the Header to the Resultant (mixed) data and play back.

If some thing is unclear and ambigious let me know.

Regards
Ranjeet Gupta.

还有简单C程序示意代码,但是其中包含了核心算法:
#include
#include
#include
#include

int main(int argc,char *argv[]) {
char mixname[255];
FILE *pcm1, *pcm2, *mix;
char sample1, sample2;
int value;

pcm1 = fopen(argv[1],"r");
pcm2 = fopen(argv[2],"r");

strcpy (mixname, argv[1]);
strcat (mixname, "_temp.wav");
mix = fopen(mixname, "w");

while(!feof(pcm1)) {

sample1 = fgetc(pcm1);
sample2 = fgetc(pcm2);

if ((sample1 < 0) && (sample2 < 0)) {
value = sample1 + sample2 - (sample1 * sample2 / -(pow(2,16-1)-1));
}else{
value = sample1 + sample2 - (sample1 * sample2 / (pow(2,16-1)-1));
}

fputc(value, mix);
}


fclose(pcm1);
fclose(pcm2);
fclose(mix);

return 0;
}

另外,如果只是在Symbian上实现混音,在Nokia 的官方网站上,也有一个SoundMixer的examples
http://www.forum.nokia.com/info/sw.nokia.com/id/70a2bde5-9b14-41b3-89ae-198b0d8d380d/SoundMixer_Example_v1_0.zip.html

2007年12月23日星期日

多路数字语音合成

摘要数字音频混音是嵌入式多媒体设备不可缺少的功能,本文介绍数字混音的基本原理,并提供了几种实际应用方法,并进行了实际的测试,取得了良好的效果。 ---- 关键词 多路语音合成,混音,衰减因子。 1.引言 ---- 随着嵌入式处理器的处理能力不断加强,网络技术的不断进展,嵌入式多媒体通讯已经迅速普及,其应用产品前途很越来越广泛,如IP电话,音频会议产品,多媒体教学产品。这些产品的一个基本功能就……
【文章正文】

摘要 数字音频混音是嵌入式多媒体设备不可缺少的功能,本文介绍数字混音的基本原理,并提供了几种实际应用方法,并进行了实际的测试,取得了良好的效果。
---- 关键词 多路语音合成,混音,衰减因子。
1.引言
---- 随着嵌入式处理器的处理能力不断加强,网络技术的不断进展,嵌入式多媒体通讯已经迅速普及,其应用产品前途很越来越广泛,如IP电话,音频会议产品,多媒体教学产品。这些产品的一个基本功能就是语音采集(数字化),语音传输和实时播放。但由于成本和设计资源的限制,一个终端一般只可能有一路(立体声)输出能力,这在一对一通话是不会产生任何问题。但在多个终端同时通话时(如音频会议),如果接收到的数字语音信号不经特殊处理,就很难模拟出多个与会者在一个会议室进行对话的情形。这就要求终端有能力将收到到多路数字语音合成(混合)成一路输出。因此必须采取多路音频流混合方案。
2.设计思想:
2.1 混音的合理性和必要性:
---- 传输话音这种连续的、时间要求严格的流与传输别的数据不同。这涉及声波转换为数字信号,数字信号恢复为声波。虽然AD/DA由硬件完成,但录音和播放由用户设置。特别需要注意的是,不象典型的视频流在空间/时间域占有唯一的位置,在同一时间和位置的图象元素叠加是无任何意义的,但人耳可以感知在同一空间/ 时间播放多个音频流。这就是混音的合理性和必要性。混音就是用一个输出设备播放多个音频流。
2.2 混音方案的理论依据:
---- 在时域上语音是短时平稳信号,对语音信号进行处理的一个基本概念就是对语音样本以缓冲区为单位处理,即对输入的语音样本分帧。为了满足合理的延时要求,语音帧的长度一般是选10~20ms。
---- 当多个音频源在一个房间播放时,人耳听到的声波是各个声源声波的线性叠加,这正是模拟混音的基础。该事实表明数字话音的混音也应线性相加。假设有n路输入音频流进行混音,Xi(t)是t时刻的第i路输入语音的采样值,则t时刻的混音值为:
---- m(t)=ΣXi(t),i=0,1,…,n-1
---- 数字音频的重要参数是采样率和采样位数,其中各路输入音频流的采样率相同是混音的前提。
3. 混音的实际算法:
考虑到数字音频的采样位数,其每点的的采用的最大最小值是被限定的,如8位采样,则采样值的范围是-127~+127。因此在混音计算时,m(t)=ΣXi (t)必须考虑其溢出的情况。简单的处理溢出的方法是m(t)=(ΣXi(t))/n, 其中n表示参与混音的路数,这样即可以保证每个采样点都不会溢出。
但这种算法的缺点也很明显,即每路音频的音量都被缩小了n倍,没有使每路的音频在不溢出的情况下达到最大的输出(与混音前的每路音频尽量接近)。要达到这种效果,就需要使用另外一种比较复杂的算法: 使用衰减因子f, m(t)=Σ(Xi(t)*f)。其中 (1/n)<= f <= 1, n为混音的路数。
如上面所说,一个语音帧是一个处理单元。初始化时令f=1,每次开始处理一个新的语音帧时,任何一个合成值m(t)超过了范围,将m(t)箝位,并且求得对应的新的f,在时序上位于此点之后的样本都采用新的f。可以看出这样一来,f有越来越小的趋势。为了避免语音不必要的被衰减,因此需要有让f变大的地方,这发生在每个新的语音帧开始处理的入口。新的语音帧样本仍然需要衰减的可能性是很大的,所以f不能每次都又从1开始,而是应该在某种程度上继承过去的值。即在每个新的样本缓冲区的入口处,只要f不等于1,就将其调整为比f稍大一些的值,让它成为新的衰减因子。若样本的确不需要衰减,经过若干帧后f会慢慢变回1。
流程图如下,每次处理语音帧样本长度在10~20ms内选取, 以16位采样为例, f可取1/16, 2/16,… 15/16,1 。 也可以根据不同的应用取不同的取值范围,和不同的 #1, #2 算法。


4.注意事项:
考虑到不同的处理器的处理能力,以及产品对时延的不同要求,我们可以合理的采用上述两种方法。值得注意的是,每点的采样值都是有符号数,不能用简单的无符号数进行处理和运算。
同时,随着需要混合的语音信号路数的增加,在用户不采取任何附加的预防措施的情况下,一些并不需要的信号(例如回声和噪音)就会累积起来并终将导致让人无法接受的质量劣化。这样,每个终端还可以进行输入音频的有声/无声检测,对无有效信号的音道直接丢弃。
5.结束语
---- 在笔者开发音频会议终端(采用ARM7处理器)上,对上述两种方法都进行了测试。结果证明两种方法都能取的比较满意的效果。

2007年12月21日星期五

c#调节音量

多媒体的应用,往往离不开音频文件,DELPHI偏偏不带音量控制的控件,虽然可以安装第三方的音量控制控件,不过对于我们这些编程的超级菜鸟来说,自己动手才是丰脑之道,这里,我利用API函数就实现了WAVE文件的总音量控制及左右声道音量分别控制。

为了调用Windows函数,先在Uses中加上MMSystem,Delphi提供了调用WaveOutSetVolume 函数的Pascal语言的接口,不信看看MMSystem.pas文件*&^@*<。

我编了演示程序,界面如下:
加入三个TrackBar,分别命名为TB_vol,TB_l,TB_r,将Max值设为255(即8位二进制数的最大值),Frequency的值设为10。

先看看总音量控制的实现:


procedure TForm1.TB_volChange(Sender: TObject);

var
pos,vol:longint;

begin
pos:=TB_vol.Position;

vol:=(pos shl 8)or(pos shl 24);

waveoutsetvolume(0,vol);

end;


首先我们得到TrackBar的位置,用这个值来记录音量的大小,第二句转换Windows函数中对应的正确形式,末一句设置音量。

WaveOutSetVolume函数有两个参数:

第一个参数为波形文件输出设备的标识符,这里的标识符为0。

第二个参数为音量的大小,他是一个32位的整数,低16位表示左声道的音量,高16位表示右声道的音量。

由于TrackBar只用8位二进制数表示音量,因而先把得到的8位音量值pos左移8位,变成左声道16为中的高8位,然后将pos右移24位,变成右声道16为中的高8位,将两个值进行or运算赋给vol,将vol加给WaveOutSetVolume函数的第二个参数,这样就可以实现同时改变两个声道的音量了。

理解上述方法后,分别控制左右声道就不难了,看看左声道的实现:


procedure TForm1.TB_lChange(Sender: TObject);

var
pos,vol:longint;

begin
pos:=TB_l.Position;

waveoutgetvolume(0,@vol);

vol:=vol and $ffff0000 or (pos shl 8);

waveoutsetvolume(0,vol);

end;


由于只修改左声道的值,为了保存右声道的音量,即保存得到音量值pos的高16位,我们将vol和$ffff0000(16进制数)进行or运算,这样,vol的低16位被清零,高16位保持不变,再将低16位左移8位表示新的左声道的音量。

右声道同理实现


procedure TForm1.TB_rChange(Sender: TObject);

var
pos,vol:longint;

begin
pos:=TB_r.Position;

waveoutgetvolume(0,@vol);

vol:=vol and $0000ffff or (pos shl 24);

waveoutsetvolume(0,vol);

end;


同时,我们为了程序一运行滑块就能到当前的音量(完善完善嘛),需要在Form的Create事件中加入以下语句:



procedure TForm1.FormCreate(Sender: TObject);

var
vol:longint;

begin
waveoutgetvolume(0,@vol);

TB_l.Position :=hi(vol); {设置左声道音量}

TB_r.Position :=hi(vol shr 16); {设置右声道音量}

end;