简介

通常在VOIP通话应用场景中,两个人互相进行实时通话,会涉及到很多的技术要点(更详细内容请参考《音频开发应该知道的VOIP通话技术基础》),假设开发者已经对VOIP通话有基本的认识了,整体流程处理如图1所示:

图1

QttAudio?SDK解决了红框部分——所有声音相关的问题:

  • 采集\播放:QttAudio会控制(接管)系统的采集和播放;
  • 音频前\后处理:包括AEC、AGC、NG、混音等声音处理;
  • 音频编解码:支持opus,speex,pcm编解码。

通过接入QttAudio,开发者不再需要关心回声消除、增益、编解码等相关知识,也不需要关心具体平台的音频API调用方式。QttAudio是多平台统一接口,开发者只需通过QttAudio获得干净清晰的采集声音数据,打包发送给对方,接收解包对方发过来的声音数据,丢给QttAudio进行播放,就完成了整个通话过程。

所以,QttAudio有一个很重要的优势——不捆绑云服务,这样的好处是你可以将QttAudio深度集成进你的应用,并针对多种网络环境灵活部署。

为了解决上图红框中的技术问题,我们设计了QttAudioEngine和QttAudioStream两个类来实现:

  • QttAudioEngine

包含了QttAudio?SDK整体的初始化,音频采集\播放,音频信号处理(AEC,NS,AGC等),音频编码,以及混音等功能;

  • QttAudioStream

包含了音频解码、播放声音增益调节,播放等功能。

关于这两个类的更多使用?#24471;鰨?#35831;详细参考后面《QttAudio使用?#24471;鰲?/a>。

假设开发者想开发一个VOIP 1对1的单人语音通话应用,已经有了自己的传输方式(或包含服务器),或者至少具备基本的UDP传输知识(如果不具有传输方面的知识,开发者?#37096;?#20197;使用我们的物联网P2P传输SDK,更方便快捷稳定,请联系?#22836;Q或电话:18140105956),现在只需要QttAudio来处理所有声音相关的工作。接下来,还需要了解一些基本术语。

术语

  • AEC:Acoustic Echo Cancellation,声学回声消除,这是音视频社交中最有?#35759;?#30340;技术,没有之一。
  • AGC:?#36828;?#22686;益控制(Automatic Gain Control)使放大电路的增益?#36828;?#22320;随信号强度而调整的?#36828;?#25511;制方法。简单理解,就是将通话过程中过大的声音调小,过小的声音调大,使整个通话过程的声音平稳。
  • NS(NG):Noise Suppression(Noise Gate),降噪。常用于在音频信号处于低电平时,压制能听到而又不想要的噪声。你可以使用它来移除背景噪音、其他信号源的交扰以及低电?#38477;?#26434;音。Noise Gate 的工作原理是让临界值音量以上的信号不受阻碍地通过,同时减少低于临界值音量的信号。这样能?#34892;?#31227;除信号的?#31995;?#38899;量声部,同时让所需的音频声部通过。

理解 QttAudio

要使用QttAudio?SDK,系统采集或播放的API就不需要再使用了,因为QttAudio包含了音频的采集和播放,进而形成输入和输出两条通路的核心功能。围绕这两大核心,还有一些附加功能设置接口,比如:

针对采集/播放和编解码部分:声道数,采样率,比特?#23454;?#35774;置;

针对声音的前后处理部分:有输出、输入声音的增益(音量)调节, 降噪开关及其阈?#26723;?#33410;的设置。

整体示意如图2和表1所示。

图2

Java?API 备注
核心使用接口 QttAudioEngine 设置的onCapture()?mic采集回调 采集输出接口,QttAudioEngine开始工作后,回调函数就有数据源源不断出来
QttAudioStream?playBuffer() 播放输入接口,QttAudioStream对象开始工作后调用
编解码设置接口 QttAudioEngine setMicCodecParams() 设置采集编码参数
QttAudioStream?setCodecParams() 设置播放解码参数
声音信号处理接口 QttAudioEngine setAecLevel() 设置AEC算法等级,默认1
QttAudioEngine enableNoiseGate() 开启关闭降噪接口
QttAudioEngine setNoiseGateThres() 设置降噪阈值,可以在实时通话过程中调节
声音增益调节接口 QttAudioEngine setMicGain() 设置mic采集音量大小,可以在实时通话过程中调节
QttAudioStream?setOutputVolume() 设置stream播放音量大小,可以在实时通话过程中调节
工作状态改变接口 QttAudioEngine\QttAudioStream?start() 开启采集或播放
QttAudioEngine\QttAudioStream?stop() 关闭采集或播放
初始化\?#22836;?#25509;口 QttAudioEngine init() 初始化整个QttAudio?SDK
QttAudioEngine free() ?#22836;?#25972;个QttAudio?SDK
QttAudioEngine createStream() 初始化一个QttAudioStream对象
QttAudioStream?free() ?#22836;臦ttAudioStream对象

表1

准备工作

我们以Android平台,介绍QttAudio?SDK环境配置的工作。其他平台是C语言接口,都提供一个库文件和头文件。

?1. ?导入 SDK

图3

 

?2. ?编辑权限

图4

注:Android?6.0系统以上,需要代码动态申请红框中的权限,此处省略。

代码示例

本章节将通过实际代码片段和SingleCall工程(下载链接),介绍QttAudio的基本生命周期,掌握QttAudio?API的调用时机,以及网络收发时的线程运行模型。

?1. ?整体?#23433;?#38598;设置

?1.1? 初始化QttAudioEngine
//初始化QttAudio SDK,appkey在登录官网(链接)后台控制台可申请
QttAudioEngine.me().init(context, "your appkey");
?
1.2? 设置QttAudioEngine
  • 设置noisegate降噪开关
  • 设置mic采集编码参数
  • 设置mic采集回调函数

通过设置该回调函数,开发者可源源不断获得mic采集的,并经过aec、ns等模块处理过后干净的声音,开发者只需将该数据进行打包发送给对方即可。

//打开降噪,默认是打开的
//QttAudioEngine.me().enableNoiseGate(true);

//设置mic采集的编码参数,该参数影响mic采集回调的数据类型
QttAudioEngine.me().setMicCodecParams("opus", 1, 16000, 32000);

//设置mic的采集回调函数
QttAudioEngine.me().setMicCaptureCb(new QttCaptureCallbak() {
    @Override
    public void onCapture(byte[] buffer, int length, Object userdata) {
        //使用udp发送给对方
        udpUtil.send(buffer, length, "对方IP", destPort);
    }
}, null);
?
1.3? 开启工作,进行采集
QttAudioEngine.me().start();
?

?2. ?播放设置

?2.1?创建QttAudioStream
?2.2 设置QttAudioStream
  • 设置播放解码参数
//使用QttAudioEngine创建QttAudioStream对象
QttAudioStream stream = QttAudioEngine.me().createStream();
if (stream != null) {
    //设置stream的解码播放参数,需要与对端传过来的编码参数一致方可正确播放,否则有可能放出的是吱吱声音
stream.setCodecParams("opus", 1, 16000, 32000);
}

 

2.3 开启工作,进行播放

开发者需在另一个线程中不断进行接收对端发过来的数据并进行解包,在该QttAudioStream对象工作后,调用该QttAudioStream对象的playBuffer进行播放。

stream.start();

?3. ?参数设置

以下设置方法在engine或者stream start方法后可调用,其余设置方法均需在start方法前调用。

//将声音输出到扬声器上
QttAudioEngine.me().routeAudioTo(QttAudioOutput.SPEAKER);
//调节mic采集音量,默认为1.0f
QttAudioEngine.me().setMicGain(1.1f);

//调节降噪阈值,默认为0.05f,阈值越大过滤的噪音音量越大,太大了则会影响过?#35828;?#27491;常通话的采集声音,不太建议大于0.2f
QttAudioEngine.me().setNoiseGateThres(0.1f);

//调节stream播放音量
stream.setOutputVolume(1.1f);

?4. ?退出部分

QttAudio?API设计时,生命周期的改变方法上,init()与free()方法对应,start()与stop()方法对应。

?4.1? 停止
//停止音频播放,与stream.start()方法对应
stream.stop();
//停止音频采集,与QttAudioEngine.me().start()方法对应
QttAudioEngine.me().stop();
?
4.2? ?#22836;?/span>
//?#22836;舠tream,当不再需要该stream时,调用free()方法,与QttAudioEngine的createStream()方法对应
stream.free();

//?#22836;臩DK,在程序完全退出时或者不再需要QttAudio时调用
QttAudioEngine.me().free();

?5. ?网络收发调用模型

我们实现一个UdpUtil类,简单演示UDP裸数据包进行收发,该类的健壮性、多线程操作等方面没有完备考虑,请开发者注意。

public class UdpUtil {
    /**
     * udp接收线程的回调接口
     */
    public interface UdpRecvCallback {
        void onRecv(byte[] buffer, int offset, int length);
    }

    private static final int MTU = 1400;
    private DatagramSocket socket = null;
    private UdpRecvCallback callback = null;
    private boolean isRunning = false;

    /**
     * 设置udp接收线程的回调接口
     * @param callback
     */
    public void setRecvCallback(UdpRecvCallback callback) {
        this.callback = callback;
    }

    /**
     * udp开始工作
     * @param localPort udp监听的本地端口
     * @throws SocketException
     */
    public void start(int localPort) throws SocketException {
        stop();
        socket = new DatagramSocket(localPort);
        socket.setSoTimeout(20);
        isRunning = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                byte[] buffer = new byte[MTU];
                DatagramPacket recvPacket = new DatagramPacket(buffer, 0, MTU);
                while (isRunning) {
                    try {
                        socket.receive(recvPacket);
                        callback.onRecv(recvPacket.getData(), 0, recvPacket.getLength());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    /**
     * 发送数据给对方(IP+Port)
     * @param buffer
     * @param length
     * @param destIp
     * @param destPort
     */
    public void send(byte[] buffer, int length, String destIp, int destPort) {
        if (socket != null) {
            try {
                DatagramPacket sendPacket = new DatagramPacket(buffer, 0, length,
                        InetAddress.getByName(destIp), destPort);
                socket.send(sendPacket);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * udp停止工作
     */
    public void stop() {
        isRunning = false;
        if (socket != null) {
            socket.close();
            socket = null;
        }
    }
}

 

当接收到udp数据包后,直接调用QttAudioStream的playBuffer方法播放即可,如图6调用所示:

图6

UDP的发?#22836;?#27861;,则在QttAudioEngine的mic采集回调里就被调用了,如图7所示。

图7

QttAudio 使用?#24471;?/h3>

1. ?生命周期

图8

如图8所示,有几点需要开发者注意:

  • 生命周期对应关系

颜色一致的相互对应。比如开发者在程序启动时调用了engine的init方法,则在程序退出时需调用engine的free方法;比如调用了engine的start方法,则一定需要在某个时刻调用engine的stop方法。

  • 生命周期调用顺序

从上到下的顺序关系:总体首先需要engine?init后,方可调用engine或者stream的相关方法。结束或者需要?#22836;?#25152;有资源时,调用engine?free方法,则会将所有创建和启动的资源全部停止及?#22836;擰?/p>

平级代表相互之间没关系:比如engine和stream、以及stream对象之间,相互生命周期没有影响,各自管各自的。

2. ?采集/播放、混音

代码示例里介绍了单人1对1通话时,engine?start后可以从engine设置的回调函数得到mic采集的音频数据,发送给对方;建一个stream对象并start后,接收对方mic采集的数据,交给stream播放。

如果不调用engine start方法,除了engine采集回调没有数据,而假设stream依旧在?#20013;鴓laybuffer,这时会放出声音吗?答案是不会。

如果此时不是1对1,而是5个人在同时说话呢,还能用一个stream对象进行播放吗?答案是不能。

以上两个问题比较关键,涉及图9中要表达的几个关键知识点。当理解了图9所示的内容,则多人语音会议通话,或者手机KTV,音轨合成等应用场景都可以使用QttAudio?SDK轻松开发出来!

图9

 

  • 采集/播放完全与engine关联,或者说engine包含?#26494;?#22791;的声卡硬件驱动。
  • stream只是混音,如果engine没有start,则stream的操作或者写入操作与声卡无关。engine即使start了,?#37096;?#35774;置engine的QttLinkMode,将stream与声卡进行解耦或关联。

比如将QttLinkMode设置为SOUND_CARD_NOTHING,则stream的输入输出操作与声卡无关。

stream技术上用于多音轨、多音频文件的混音合成操作,?#35270;?#20110;多人语聊会议室,手机ktv,音频文件合成、混音等应用场景,这一切只需使用多个stream对象即可办到!1对1的单人语音通话,只是多人语音通话的一个特殊情况而言。

  • stream对象的输入自不必说,开发者需要混音什么数据就向stream输入什么数据。stream对象的输出,其?#38382;接雃ngine的mic采集回调是同样的,其内容则是其他stream对象和mic(如果有)的混音数据。如果不需要stream的输出内容,则不必设置stream的回调函数,以减少该stream混音及编码的性能消耗。

多人语音通话实现则很简单了:在一个语音?#32771;?#20869;,将mic的采集数据发送给其他人;除自?#21644;?#26377;几个人,就使用几个stream对象,并且与之对应,接收那个人发过来的mic数据,交给对应的stream播放即可。具体可参考我们demo。

3. ?采集回调注意事项

以Java?API为例,采集回调出来的数据长度是参数length,而不是buffer.length,offset偏移量是0。

QttAudioEngine.me().setMicCaptureCb(new QttCaptureCallbak() {
    @Override
    public void onCapture(byte[] buffer, int length, Object userdata) {
    }
}, null);

 

另外该回调函数体内,请将buffer[0-length]深拷贝出去使用,并且不要有阻塞或者耗时方法。

4. ?写入操作注意事项

以Java?API为例,QttAudioStream的playBuffer方法,buffer长度不可超过4096,超过会崩溃。?#27604;?#26368;好是10ms音频数据的量

5. ?AEC 等级的使用

QttAudio内置了两种AEC算法等级:1和2,默认使用的是AEC等级1。当遇到特殊设备,或者觉得等级1效果不好时,可以在QttAudio?SDK初始化后,QttAudioEngine和QttAudioStream?start()方法前进行设置。

QttAudioEngine.me().setAecLevel(2);

 

6. ?降噪参数的调节

如果开发者初始化参数时将降噪关闭,则可在实时通话时,调节降噪参数。降噪参数会影响mic采集的声音,它会过?#35828;?#22806;界环境噪音,?#27604;?#22826;大了也会过?#35828;?#20154;说话的声音。默认是0.05f,?#35805;?#19981;建议大于0.2f。如果开发者体验效果好,则不需要关心这个设置参数。

7. ?增益的调节

如果实际通话中,或者某些设备通话体验中,感觉对方说话声音太小或太大,或者对方觉得自己声音太小或太大,都可以通过QttAudio提供的API来调节采集或播放的声音增益。该音量与系统的音量无关。QttAudioEngine有设置mic的增益方法,QttAudioStream有设置输入和输出的音量方法。

API参考

1. ?Android

QttAudioEngine概览

方法 描述
me 单例模式,返回QttAudioEngine对象
init 初始化函数,整个程序期间只调用一次。会有阻塞,建议不要在主线程执行
free ?#22836;臦ttAudioEngine单例对象,在程序退出时调用该方法。与init方法相对应。
start 开启mic采集
stop 停止mic采集
setMicCodecParams 设置mic采集编码的格式
setMicCaptureCb 设置语音mic采集回调
setSilenceDetectCb mic静音检测回调
createStream 创建QttAudioStream音频流
enableNoiseGate 开启/关闭降噪功能
setNoiseGateThres 设置降噪阈值
setMicGain 设置mic增益
enableSpeaker 开启/关闭扬声器
routeAudioTo 设置音频播放路由
setAecLevel 设置AEC等级
isSpeakerOn 是否启用扬声器
startRecord 开始录音
stopRecord 停止录音
setCapturePcmBufSize 设置mic回调中返回的语音数据buffer大小
setRemoteAddr 设置远?#35828;?#22336;
muteNetSend 暂停/恢复发送
setEchoDelay 设置回声消除时延
detectEcho 如果某些机型有回声,在初始化后调用该函数一次并运行一次即可,以后无需再调用
noiseSuppressionFile PCM文件降噪处理
enableAudioCompatibilityMode 如果某些机型有回声,在初始化后调用该函数一次并运行一次即可,以后无需再调用

 

QttAudioStream概览

方法 描述
构造方法 不可调用,只能由QttAudioEngine.me().createStream()方式生成该语音流对象
free 和构造方法对应,?#22836;?#35813;语音流对象
start 启动该语音流对象,开始工作
stop 停止语音流,与start方法对应
setCodecParams 设置编解码的格式
playBuffer 播放音频buffer,听?#19981;?#32773;扬声器就会放出声音来
setOutputVolume 设置该语音流输出播放音量,影响的是扬声器或听筒的播放音量
mute 静音该语音流对象
setSilenceDetectCb 设置语音流静音检测
setCaptureCb 设置语音流的mic采集及混音回调函数
setAsFileInput 设置文件播放路径(WAV)
pauseFile 暂停文件播放
resumeFile 恢复文件播放
seekFile 快进/快退
setRtpParams 设置RTP网络收发参数,使语音流对象采用RTP方式传输音频
setAsNetInput 设置输入为网络接收
setAsNetOutput 将流输出的内容作为网络传送输出

 

QttCaptureCallbak概览

onCapture 音频流的数据采集编码回调

 

QttEventCallback概览

onEventNotify ?#24405;?#36890;知回调

 

详细描述

1.1 QttAudioEngine

/**
* 单例模式,返回QttAudioEngine对象
* @return QttAudioEngine单例对象
*/

public synchronized static QttAudioEngine me()?

/**
* 初始化函数,整个程序期间只调用一次。会有阻塞,建议不要在主线程执行
* @param context
* @param appKey
* @throws QttException 初始化失败则会抛出该异常
*/

public void init(Context context, String appKey) throws QttException

/**
* ?#22836;臦ttAudioEngine单例对象,在程序退出时调用该方法。与init方法相对应。
*/

public void free()

/**
* 启动QttAudioEngine对象,开始采集音频
* @return 0为启动成功,其他为失败
*/

public int start()

/**
* 停止音频采集,与start方法对应
*/

public void stop()

/**
* 设置mic采集编码的格式
* @param mime "pcm", "opus", "speex"三者之一
* @param channel 1,只支持单声道
* @param samplerate 采样率,8000,16000,32000,44100,48000
* @param bitrate 比特率,当mine设定为"pcm"时,该值无意义,用户传入0即可
*/

public void setMicCodecParams(String mime, int channel,? int samplerate, int bitrate)

/**
* 设置语音mic采集回调函数,通过设置该回调,开发者可以获得mic采集编码后的音频数据
* 该接口与QttAudioStream的setPayloadCallback不同之处在于,该接口只获取mic采集的声音
* @param micCallback?mic采集回调
* @param?userdata 用户传进来的对象
*/

public void setMicCaptureCb(QttCaptureCallbak micCallback, Object userdata)

/**
* 设置静音检测回调
* @param eventCallback?检测结果回调,回调返回1为开始说话,0为停止说话
* @param?userdata 用户传进来的对象
*/

public void setSilenceDetectCb(QttEventCallback eventCallback, Object userdata)

/**
* 创建QttAudioStream音频流对象
* @return QttAudioStream
*/

public QttAudioStream createStream()

/**
* 是否启用通话降噪功能
* @param on true为启用,false为不启用
*/

public void enableNoiseGate(boolean on)

/**
* 设置通话降噪的阈值,默认为0.05f
* @param val val值越大,降噪越厉害,对于正常说话声音音量要求也更大
*/

public void setNoiseGateThres(float val)

/**
* 设置mic采集的增益大小,默认为1
* @param vol 0至3的范围,当vol为1时是原声大小,为0是完全静音
*/

public void setMicGain(float vol)

/**
* 开关扬声器方法,默认为false
* @param on true: 打开扬声器; false: 关闭扬声器,使用听筒
*/

public void enableSpeaker(boolean on)

/**
* 设置音频播放路由
* @param output?HEADPHONE/SPEAKER/BLUETOOTH?听筒/扬声器/蓝牙
*/

public void routeAudioTo(QttAudioOutput output)

/**
*?设置AEC等级,默认为1
* @param level?1或者2,?#35805;?#22823;部分安卓设备1就够了;针对1效果不好的情况,使用2,2有可能会造* 成丢音等情况,以实际设备测试情况为准
*/

public void setAecLevel(int level)

/**
*?是否打开扬声器
* @return true: 扬声器为打开状态; false: 扬声器为关闭状态
*/

public boolean isSpeakerOn()

/**
*?开始录音
* @param wavFile wav文件名及路径
*/

public void startRecord(String wavFile)

/**
*?停止录音
*/

public void stopRecord()

/**
*?设置MIC回调中返回的语音数据buffer大小
* @param size?如320/640等,默认320,?#35805;?#19981;需要修改该参数
*/

public void setCapturePcmBufSize(int size)

/**
*?当调用该接口后,会直接通过内部传输协议(udp),将mic的采集数据发送给远端IP和端口
* @param?remoteIp?远端IP
* @param?remotePort 远端端口
*/

public void setRemoteAddr(String remoteIp, int remotePort)

/**
*?暂停/恢复发送
* @param?mute true暂停;false恢复
*/

public void muteNetSend(boolean mute)

/**
* 设置回声消除时延
* @param delay
*/

public synchronized void setEchoDelay(int delay)

/**
* PCM文件降噪处理接口
* @param inFile ????待处理的PCM文件路径,建议采样率不大于16000
* @param outFile ???降噪后输出的PCM文件路径
* @param samplerate 采样率
* @param mode ??????0,1,2,数字越大,降噪算法越激进
* @return 0成功, 其他失败
*/

public int noiseSuppressionFile(String inFile, String outFile, int samplerate, int mode)

/**
* 如果某些机型有回声,在初始化后调用该函数一次并运行一次即可,以后无需再调用
*/

public synchronized void detectEcho()

/**
* 如果某些特殊机型无法运行,则在init方法调用成功后,调用该函数设置为兼容模式,并传入参数true。
* 该函数?#35805;?#19981;需要调用
* @param val true为启用兼容模式;false为不启用兼容模式。
*/

public void enableAudioCompatibilityMode(boolean val)

1.2 QttAudioStream

/**
* 构造方法,调用QttAudioEngine对象的createStream( ) 创建QttAudioStream对象
* 创建QttAudioStream音频流对象
* @return QttAudioStream
*/

public QttAudioStream createStream()

/**
* ?#22836;?#35821;音流,与构造函数或者说QTTAudioEngine.me().createStream()对应
*/

public void free()

/**
* 启动QttAudioStream对象,开始工作
* @return 0为启动成功,其他为失败
*/

public int start()

/**
* 停止语音流,与start方法对应
*/

public void stop()

/**
* 设置QttAudioStream对象的编解码的格式,必须和setMicCodecParams传入参数一致,否则会导致通话不正常
* @param mime "pcm", "opus", "speex"三者之一
* @param channel 1,只支持单声道
* @param samplerate 采样率,8000,16000,32000,44100,48000
* @param bitrate 比特率,当mine设定为"pcm"时,该值无意义,用户传入0即可
*/

public void setCodecParams(String mime, int channel,? int samplerate, int bitrate)

/**
* 播放音频buf,听?#19981;?#32773;扬声器就会放出声音来
* @param buffer 音频buffer
* @param offset buffer偏移量,没有偏移量就是0
* @param length buffer长度
*/

public void playBuffer(byte[] buffer, int offset, int length)

/**
* 设置语音流输出播放音量,影响的是扬声器或听筒的播放音量
* @param vol 正常范围是0-1,1为原音量,可大于1
*/

public void setOutputVolume(float vol)

/**
* 静音该QttAudioStream对象
* @param isMute true为静音,false为不静音
*/

public void mute(boolean isMute)

/**
* 设置静音检测回调
* @param eventCallback?检测结果回调,回调返回1为开始说话,0为停止说话
* @param?userdata 用户传进来的对象
*/

public void setSilenceDetectCb(QttEventCallback eventCallback, Object userdata)

/**
* 设置语音流的mic采集及混音回调函数,通过设置该回调,开发者可以源源不断获得mic采集的混音音频数据
* 该接口与QttAudioEngine的setPayloadCallback不同之处在于,当有多个stream时,该接口获得的是其他stream播
* 放的声音与mic采集的声音的混音后的音频数据,具体数据内容可参见文档x.x节
* @param streamCaptureCB 音频采集回调接口
* @param userdata 用户传进来的对象
*/

public void setCaptureCb(QttCaptureCallbak streamCaptureCB, Object userdata)

/**
* 设置为文件播放
* @param wavFile 文件播放路径
*/

public void setAsFileInput(String wavFile, QttEventCallback onFileEOF, Object filedata)

/**
* 暂停文件播放
*/

public void pauseFile()

/**
* 恢复文件播放
*/

public void resumeFile()

/**
* 跳转到absSecs秒后开始播放
* @param absSecs 秒
*/

public void seekFile(int absSecs)

/**
* 设置RTP网络收发参数,使QttAudioStream对象采用RTP方式传输音频
* @param localRtpPort?? 本地rtp端口
* @param localRtcpPort? 本地rtcp端口
* @param remoteIP?????? 远程目的ip
* @param remoteRtpPort? 远程目的rtp端口
* @param remoteRtcpPort 远程目的rtcp端口
* @param mode?????????? 1是只接收模式,2是发送&接收模式
* @param idx??????????? 设置rtp的载荷类型,通话双方必须要一样
* @param ssrc?????????? 设置rtp的ssrc,该字?#25105;话?#29992;来区分rtp流
*/

public void setRtpParams(int localRtpPort, int localRtcpPort, String remoteIP, int remoteRtpPort, int remoteRtcpPort, int mode, int ssrc, int idx)

/**
* 以网络接收为输入
* @param localPort 本地端口
*/

public void setAsNetInput(int localPort)

/**
* 将流输出的内容作为网络传送输出,不需要就不调用
* @param destIp 远端IP
* @param destPort 远端端口
*/

public void setAsNetOutput(String destIp, int destPort)

1.3 QttCaptureCallbak


/**
* 音频采集编码的回调函数
* @param buffer ???采集编码的内容
* @param length ???buffer的长度是length,而不是buffer.length
* @param userdata ?userdata
*/

void onCapture(byte[] buffer, int length, Object userdata);

1.4 QttEventCallback


/**
* ?#24405;?#36890;知回调
* @param event 结果
* @param userdata 用户传进来的对象
*/

void onEventNotify(int event, Object userdata);

联系我们

1.? ?联系邮箱

[email protected]

2.? ??#22836;Q

3293059790

3.? ?咨询电话

028-62486620

18140105956