语音聊天实现(Delphi)

这个博客详细介绍了如何使用Delphi编程语言实现语音聊天功能,包括UDP数据接收、登录和退出处理、消息显示和声音播放等核心模块。同时,还涉及了音频输入输出的处理,如使用ACM控件进行音频格式转换。
摘要由CSDN通过智能技术生成


语音聊天实现
没有通过Acm控件的,比较长,有兴趣的可以看一下,还有通过UDP的聊天功能。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, NMUDP, CheckLst,winsock, ElTree,ElHeader,ShellAPI, ExtCtrls,
  ComCtrls,MMSystem,Msacm, ElXPThemedControl;

type
  TForm1 = class(TForm)
    udp_Send: TNMUDP;
    Panel1: TPanel;
    Panel2: TPanel;
    btn_Send: TButton;
    Label1: TLabel;
    edt_Words: TEdit;
    tim_Timer: TTimer;
    rih_Words: TRichEdit;
    Button1: TButton;
    Button2: TButton;
    elt_Online: TElTree;
    procedure udp_SendDataReceived(Sender: TComponent; NumberBytes: Integer;FromIP: String; Port: Integer);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure elt_OnlineHeaderColumnDraw(Sender: TCustomElHeader;Section: TElHeaderSection; R: TRect; Pressed: Boolean);
    procedure btn_SendClick(Sender: TObject);
    procedure tim_TimerTimer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    procedure WndProc(var Msg:TMessage);override;
    procedure SendWords(SendMan,ReceiveMan,Word:String;RemoteIP:String);
    Function  GetHostIP(HostName:String=''):String;
    Function  ReturnPos(buf:TMemoryStream;Len,StartPos:Integer;Separator:Char):Integer;
    procedure DisplayWords(SendMan,ReceiveMan,Word:String);
    procedure UserLogin(UserName,IP:String;RemoteIP:String='');
    procedure UserLogout(UserName,IP:String);
    function  AddNextBuffer():Integer;
    function  InitWaveInHeader():Integer;
    function  QueueNextBuffer : Integer;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

type TACMWAVEFORMAT=packed record
case Integer of
  0:(Format:twaveformatex);
  1:(Rawdata:array[0..128] of byte);
end;

const
  iBufferBlock=2040;
  oBufferLen=6;
var
  sHostIP,P_UserName,sBroadIP:String;
  nTickCount:DWord;
  NIM_Data:NOTIFYICONDATAA;
  bShowIcon,bPlayFlag:Boolean;
  iMsgCount,iBufIndex,iInputPoint,iPlayPoint:Integer;
  iHdr:Array [0..1] of WAVEHDR;
  iBuf:Array [0..1] of pChar;
  oBuf:Array [1..oBufferLen] of pChar;
  oHdr:Array [1..oBufferLen] of WAVEHDR;
  WaveFmt:TACMWAVEFORMAT;
  HOut:HWaveOut;
  HIn:HWAVEIN;

{$R *.DFM}
{$R msg.res}

 

procedure TForm1.udp_SendDataReceived(Sender: TComponent;NumberBytes: Integer; FromIP: String; Port: Integer);
var
   sUserName,sSendMan,sReceiveMan,sIP,sWord:String;
   iMsgType,iPos,i,iTmpPos:Integer;
   Node:TEltreeItem;
   mBuf:TMemoryStream;
   FindHandle, ResHandle: THandle;
   ResPtr: Pointer;
begin
   if Trim(FromIP)=sHostIP then
      Exit;

   mBuf := TMemoryStream.Create();
   mBuf.SetSize(NumberBytes);
   mBuf.Clear;
   udp_Send.ReadStream(mBuf);
   if (pchar(mBuf.Memory)^=#02) and (pchar(Longint(mBuf.Memory)+1)^=#03) then
      iMsgType := ord(pchar(Longint(mBuf.Memory)+2)^)
   else
   begin
      mBuf.Free;
      Exit;
   end;

   sUserName := '';
   case iMsgType of
      1:              //登录
      begin
        iPos := ReturnPos(mBuf,NumberBytes,4,#$1f);
        sUserName := copy(PChar(mBuf.Memory),4,iPos-4);
        sIP  := copy(PChar(mBuf.Memory),iPos+1,ReturnPos(mBuf,NumberBytes,iPos+1,#$1f)-iPos-1);
        for i:=0 to elt_Online.Items.Count-1 do
        begin
           Node := elt_Online.Items[i];
           if (strcomp(PChar(sUserName),PChar(Node.Text))=0)
              and (strcomp(PChar(sIP),PChar(Node.ColumnText[0]))=0) then
           begin
              mBuf.Free;
              Exit;
           end;
        end;
        Node := elt_Online.Items.Add(nil,sUserName);
        Node.ShowCheckBox := True;
        Node.ColumnText.Add(sIP);

        waveInStop(hIn);
        for i:=1 to 3 do
            UserLogin(p_UserName,sHostIP,sIP);
        waveInStart(hIn);
      end;
      2:              //退出
      begin
        iPos := ReturnPos(mBuf,NumberBytes,4,#$1f);
        sUserName := copy(PChar(mBuf.Memory),4,iPos-4);
        sIP  := copy(PChar(mBuf.Memory),iPos+1,ReturnPos(mBuf,NumberBytes,iPos+1,#$1f)-iPos-1);
        for i:=0 to elt_Online.Items.Count-1 do
        begin
           Node := elt_Online.Items[i];
           if (strcomp(PChar(sUserName),PChar(Node.Text))=0)
              and (strcomp(PChar(sIP),PChar(Node.ColumnText[0]))=0) then
           begin
              mBuf.Free;
              Node.Delete;
              Exit;
           end;
        end;
      end;
      3:              //收到信息
      begin
        iPos     := ReturnPos(mBuf,NumberBytes,4,#$1f);
        sSendMan := copy(PChar(mBuf.Memory),4,iPos-4);
        iTmpPos  := ReturnPos(mBuf,NumberBytes,iPos+1,#$1f);
        sReceiveMan := copy(PChar(mBuf.Memory),iPo

本程序自带反向回传语音代理服务,可以使两个不同局域网内的客户机通过国际互连网进行语音通讯,本程序使用点对点方式,不通过任何中介服务器速度快,语音延迟极小,声音清晰逼真,其效果和真实IP电话不相上下,程序界面简洁,操作简单,是在互连网上打IP电话的极好工具,唯一的要求是通话双方都要有电脑,并连入互连网。本程序能实现以下连网操作功能:1.通话双方是同一局域网内的用户2.通话双方是不同局域网内的用户,并通过各自的网关连入互连网3.通话双方一个直接连入互连网,另一个处在局域网中,并通过网关连入互连网4.通话双方直接连入互连网一般的语音聊天软件只能实现1,4两种连网功能,而本程序能完全支持所有这四种连网情况,因而能使所有用户享受到语音聊天所带来的好处,下面我们说明该软件的使用方法:------------------------------------------------------------------------1,4两种连网情况的使用方法:假设用户A的IP地址为192.168.0.4 用户B的IP地址为192.168.0.5 则用户A,B分别启动各自的mphone.exe程序,然后用户A,B分别填入对方的IP地址,比如A填192.168.0.5而B填192.168.0.4,然后A,B用户都选择P2P方式,当这两样填好后,各自按下Start键便开始通话了,在正常情况下,当对方有语音数据传过来时会看到Packets所显示的数在增加,这时你会听到对方所说的话,如果产声错误,你会看到Errors所显示的数值也在增加,另外你还能看到在Size中所显示的每个语音数据包的大小,当然你也可以在Num编辑框中输入不同数值来调节数据包的大小,数值越大,包越小,延迟也越小,默认情况下为4,就是每秒传送4个包,如果你想退出通话,可以按Stop按钮,当然直接关闭mphone程序也可以=:)-----------------------------------------------------------------------第2种连网情况下,因为不同局域网中的用户无法通过互连网直接连接,所以程序自带了反向回传代理服务器,用户A和用户B分别在各自的局域网服务器上运行mproxy.exe程序,然后A,B用户分别选择Lan模式,在各自的mphone中填入对方服务器IP地址,在各自服务器上的mproxy.exe中填入自已机器的IP地址,就可以开始通讯了,使用方法举例如下:比如用户A的局域网服务器为61.132.62.131,用户A在局域网中的地址为192.168.0.3用户B的局域网服务器为202.102.8.141,用户B在局域网中的地址为10.12.1.4则在用户A这边的设置为mphone=202.102.8.141,mproxy=192.168.0.3用户B这边的设置为mphone=61.132.62.131,mproxy=10.12.1.4-------------------------------------------------------------------------第3种连网情况下,可以这样设置,假设A是局域网用户,B直接连入互连网,设置和上面一样,则在用户A这边的设置为mphone=202.102.8.141,mproxy=192.168.0.3用户B这边的设置为mphone=61.132.62.131并且A设成Wan方式,B设成Lan方式就可以通话了======================================================================================附录:UDP端口设定: Remote LocalP2P 6660 6660 Lan 6660 6661Wan 6661 6661 proxy 6661 6660===========================================
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值