对讲开发关键技术总结

1,对讲部署环境

对讲分为前端(设备端)和后端(PC端)。

前后端要根据制定的数据通信协议,执行各种功能,包括:

1)      设备端发起呼叫

2)      PC端接听呼叫或拒接呼叫

3)      设备端挂断

4)      PC端挂断

5)      语音数据的获取、收发、播放

1.1设备端

l  设备端有按钮可以发起对讲呼叫。对讲中按按钮,则可以结束对讲。

l  设备端有麦克风和喇叭,分别用于拾取语音和播放语音。

l  设备端有控制板,将麦克风拾取的语音发送给PC端,同时接收PC端发来的语音进行播放。

l  语音数据采用定长包传输,如500或1000个字节为一个包。

l  对讲对语音的质量要求不高,麦克风可以采用16K采样率、单声道、8位数据存储。

1.2 PC端

l  PC端为一个运行于windows系统的程序

l  PC端监听设备呼叫,可以接听或拒接。对讲中,可以主动结束对讲。

l  PC端有麦克风和喇叭,分别用于拾取语音和播放语音。

l  PC端将麦克风拾取的语音发送给设备端,同时接收设备端发来的语音进行播放。

l  语音采样采用16K采样率、单声道、8位数据存储。

2,PC端关键技术

PC端程序开发的关键技术如下:

1)      麦克风语音数据流的读取和发送

2)      设备端语音数据流的接收和播放

3)      windows消息传递

 

以下分别说明。

2.1 麦克风语音数据流的读取和发送

采用TSoundCaptureStream拾取PC麦克风数据

在CaptureFilledBuffer中,发送PC端语音到设备

  FCapture: TSoundCaptureStream;

  FCapture.Stop;
  FCapture.BufferLength := VP_DATA_SIZE;

  FCapture.OnFilledBuffer := CaptureFilledBuffer;
  FCapture.CaptureFormat := 16;       //16K SamplesPerSec, 8 BitsPerSample, 1 Channels

2.2 设备端语音数据流的接收和播放

 

1)      采用directSound播放接收到的语音数据流。

2)      采用TWaveStream作为设备语音播放缓冲区。

      FormVoice:= TFormVoice.Create(nil);
      MemoryStream := TMemoryStream.Create;
      MemoryStream.SetSize(VP_DATA_SIZE);

      FWaveStreamIn := TWaveStream.Create(MemoryStream);

      FWaveStreamIn.SetPCMFormat(16000,8,1);
      FWaveStreamIn.Size := VP_DATA_SIZE;
      FWaveStreamIn.Open(True);

      Audio := TAudioStream.Create(FormVoice.DXSound.DSound);

      Audio.WaveStream := FWaveStreamIn;
    Audio.Looped := True;
      Audio.AutoUpdate := True;
      Audio.BufferLength := VP_DATA_SIZE;

注意:以上Audio.Looped := True;这一句是关键。如果流式播放不设置Loop属性为True,则PC端播放的语音会出现连续性的噪音。

参见:(19条消息) DirectSound开发指南_newrtc的博客-CSDN博客

 

3)      接收到设备发来的语音包时,将数据写入缓冲区,并播放。

      FWaveStreamIn.Position := 0;
      FWaveStreamIn.Writebuffer(vBuff[8], VP_DATA_SIZE);

      Audio.Play;

 

2.3 windows消息传递

PC端程序有时免不了要进行postMessage操作,但如果对讲功能是封装在DLL中的话,消息传递的Handle需要自己创建。

1) 在工程文件中调用CreateHandle

library YYY;

uses
  SysUtils,
  Classes,
  Forms,
  。。。

exports
  XXX  ;

begin
    Application.Initialize;

    if Application.Handle = 0 then
    begin
        Application.CreateHandle;
    end;

    Application.Run;
end.

2)  在单元类中创建消息队列、发送和接收消息

var
  DllWndHandle: HWND = 0;

constructor TOutIntf.Create(CameraIP:PChar);
begin
  DllWndHandle := AllocateHWnd(DllWndProc);    
end;

destructor TOutIntf.destroy;
begin
 
  if DllWndHandle <> 0 then
  begin
    DeallocateHWnd(DllWndHandle);
    DllWndHandle := 0;
  end;

  inherited;
end;

//发送消息给DLL自己
PostMessage(DllWndHandle,  WM_USER, 0, 0);

//处理消息
procedure TOutIntf.DllWndProc(var Message: TMessage);
begin
  if (Message.Msg = WM_USER) then begin

    //do something

  end else
    Message.Result := DefWindowProc(DllWndHandle, Message.Msg, Message.WParam, Message.LParam);
end;

需要注意的是,上述第一步如果不做的话,编译并无错误,但是程序运行将异常。

posted @ 2022-07-08 17:23  jack0424  阅读(185)  评论(0编辑  收藏  举报