分类目录归档:未分类

vpncloud

https://vpncloud.ddswd.de/
https://github.com/dswd/vpncloud/

VpnCloud 是基于 UDP 的高性能点对点网状 VPN,支持强大的加密、NAT 穿越和简单的配置。 它以基于椭圆曲线密钥和 AES-256 的强大端到端加密的对等方式建立全网状自愈 VPN 网络。 VpnCloud 在主机上创建一个虚拟网络接口,并通过 UDP 将所有接收到的数据转发到目的地。 它可以在 TUN 设备(基于 IP)和 TAP 设备(基于以太网)上工作

Rust开发的

最大缺点是没有Android 客户
Tinc, Nebula, Wireguard 都有

Tinc uses UDP and TCP for connections. There is no option to only use the more efficient UDP.

Tinc requires users to create a key pair for each node and then exchange the public keys with all other nodes.

Nebula has a centralized take on security: It introduces a central authority that issues certificates for all nodes. The certificates also contain an allowed IP address, that will be enforced by other nodes. Nebula supports two symmetric ciphers (AES256 and ChaCha20) but the cipher has to be the same for the whole network.

Wireguard achieves its high throughput because it uses a kernel module to do the heavy lifting.

nebula vpn

https://github.com/slackhq/nebula
https://github.com/DefinedNet/mobile_nebula

Nebula is a scalable overlay networking tool with a focus on performance, simplicity and security. It lets you seamlessly connect computers anywhere in the world. Nebula is portable, and runs on Linux, OSX, Windows, iOS, and Android. It can be used to connect a small number of computers, but is also able to connect tens of thousands of computers.

Configure Nebula VPN on iOS/Android
https://willhbr.net/2021/06/22/configure-nebula-vpn-on-ios-android/

VPN mesh with Nebula
https://linuxblog.xyz/posts/slack-nebula/

在debian中安装 nebula-lighthouse-service 灯塔服务

UDP/noiseprotocol协议

NaiveProxy

浏览器 → NaiveProxy客户端 ⟶ GFW ⟶ 常用前端(Caddy/HAProxy等) → NaiveProxy服务端 ⟶ 互联网

使用Chrome的网络堆栈,GFW审查截获的流量行为与Chrome和标准前端(如 Caddy、HAProxy)之间的常规 HTTP/2 流量完全相同。前端还会将未经身份验证的用户和活动探测器重新路由到后端HTTP服务器,从而使得无法检测到代理的存在,比如像这样:探查⟶常用前端⟶网站页面。

https://github.com/klzgrad/naiveproxy

0. 安装Go开发环境

 下载
cd ~/
wget "https://go.dev/dl/$(curl https://go.dev/VERSION?m=text).linux-amd64.tar.gz"
解压缩
tar xvaf go1.19.3.linux-amd64.tar.gz
mv go golang
mkdir go
配置环境变量
export GOROOT=$HOME/golang
export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export PATH=$GOBIN:$GOROOT/bin:$PATH

1. 安装编译caddy

go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
~/go/bin/xcaddy build --with github.com/caddyserver/forwardproxy@caddy2=github.com/klzgrad/forwardproxy@naive
或
~/go/bin/xcaddy build --with github.com/caddyserver/forwardproxy=github.com/klzgrad/forwardproxy@naive

编译成功后,可以看到当前目录中存在一个名为caddy的文件。
https://github.com/klzgrad/naiveproxy/wiki/%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87 中介绍的方法有点过时

2. 配置caddy
创建一个 config.json

:443, softs.im
tls email@softs.im
route {
        forward_proxy {
                basic_auth username passwd
                hide_ip
                hide_via
                probe_resistance
        }
        file_server {
                root /home/softsim/www
        }
}

更好一点的配置

{
        order forward_proxy before file_server
}
:443, nr5g.softs.im {
        tls /home/softsim/ssl/softsim.cer /home/softsim/ssl/softsim.key

        forward_proxy {
                basic_auth myuser mypasswd
                hide_ip
                hide_via
                probe_resistance
        }

        root * /home/softsim/nr5g
        encode gzip
        php_fastcgi unix//run/php/php8.1-fpm.sock
        file_server
}

lte.softs.im {
        tls /home/softsim/ssl/softsim.cer /home/softsim/ssl/softsim.key
        file_server {
                root /var/lib/transmission-daemon/downloads
        }
}

注意:
(1) 用您的实际电子邮件地址替换 email@softs.im 用来接收 Let’s Encrypt 通知
或者用 文件配置 已经申请好的证书
tls /path/example.com.crt /path/example.com.key

将其格式化

caddy fmt --overwrite /etc/caddy/Caddyfile

注意:不格式化,caddy运行会报错
并且,还得用 /etc/caddy/Caddyfile 这个名字, 用别的文件名会出错

如果想建立多用户版Naive,可以将 forward_proxy 模块复制。将basic_auth中的用户密码修改成另外一个就可以了。

运行

# 以后台的方式启动 caddy
caddy start --config  /etc/caddy/Caddyfile

# 以前台的方式启动 caddy
caddy run --config  /etc/caddy/Caddyfile


caddy stop

3. 编译naiveproxy客户端

git clone --depth 1 https://github.com/klzgrad/naiveproxy.git
cd naiveproxy/src/
./get-clang.sh
./build.sh

编译出的文件为 out/Release/naive

配置naiveproxy 客户端

{
  "listen": "socks://127.0.0.1:1080",
  "proxy": "https://username:passwd@softs.im"
}

保存为np.json
运行

./naive np.json

4. 配置浏览器的 SmartProxy或者SwitchyOmega 来自动匹配要代理的网站
…..

5. 让caddy以systemd 的守护进程运行

mv  caddy  /usr/bin/
setcap cap_net_bind_service=+ep  /usr/bin/caddy

添加 /etc/systemd/system/caddy.service 文件,内容如下

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
User=www-data
Group=www-data
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

启用服务

 systemctl daemon-reload
 systemctl enable caddy
 systemctl start caddy

6. 支持一般PHP的配置

        root * /home/softsim/simpleforum
        php_fastcgi unix//run/php/php7.4-fpm.sock
        file_server

tinyfecVPN和udp2raw

https://github.com/wangyu-/tinyfecVPN

tinyfecVPN

工作在VPN方式的双边网络加速工具,可以加速全流量(TCP/UDP/ICMP)。

tinyfecVPN使用了和UDPSpeeder相同的lib,功能和UDPspeeder类似,只不过tinyfecVPN工作方式是VPN,UDPspeeder工作方式是UDP tunnel.

tinyfecVPN是无状态的点对点VPN, 收到包即连接建立成功;即使VPN断线重连,上层承载的连接不掉线。

https://github.com/wangyu-/udp2raw/blob/unified/doc/README.zh-cn.md

udp2raw tunnel,通过raw socket给UDP包加上TCP或ICMP header,进而绕过UDP屏蔽或QoS,或在UDP不稳定的环境下提升稳定性。可以有效防止在使用kcptun或者finalspeed的情况下udp端口被运营商限速。

支持心跳保活、自动重连,重连后会恢复上次连接,在底层掉线的情况下可以保持上层不掉线。同时有加密、防重放攻击、信道复用的功能。

Linux主机,有root权限或cap_net_raw capability.。可以是PC、android手机/平板、openwrt路由器、树莓派。主机上最好安装了iptables命令

最好的办法是买个能刷OpenWrt/LEDE/梅林的路由器,把udp2raw运行在路由器上。

把udp流量伪装成tcp /icmp

用raw socket给udp包加上tcp/icmp包头,可以突破udp流量限制或Udp QOS。或者在udp nat有问题的环境下,提升稳定性。 另外也支持用raw 发udp包,这样流量不会被伪装,只会被加密。
模拟TCP3次握手

模拟TCP3次握手,模拟seq ack过程。另外还模拟了一些tcp option:MSS,sackOk,TS,TS_ack,wscale,用来使流量看起来更像是由普通的linux tcp协议栈发送的。
心跳保活、自动重连,连接恢复

心跳保活、自动重连,udp2raw重连可以恢复上次的连接,重连后上层连接继续有效,底层掉线上层不掉线。有效解决上层连接断开的问题。 (功能借鉴自kcptun-raw)(就算你拔掉网线重插,或者重新拨号获得新ip,上层应用也不会断线)
================

https://github.com/wangyu-/tinyfecVPN/wiki/%E4%BD%BF%E7%94%A8%E7%BB%8F%E9%AA%8C

用udp2raw防止tinyfecVPN被限速或断流

udp2raw可以把udp流量伪装成tcp,防止udp被运营商限速或断流。即使发生断流,udp2raw可以检测到这种情况并自动帮你重连。

推荐tinyfecVPN和udp2raw一起使用。连接方式:

tinyfecVPN client—->udp2raw client—————>udp2raw server—->tinyfecVPN server
=========================

n2n和omniedge

https://github.com/ntop/n2n
https://github.com/switch-iot/hin2n/blob/dev/README_zh.md

https://github.com/omniedgeio/omniedge (类似于nebula和headscale之类的东西)

debian bookworm安装配置Kamailio

bookworm上的kamailio很新,5.6.2版本

1. 先安装MariaDB

apt install default-mysql-server

2. 切换到root用户, 执行

#  mysql -u root -p

然后在 mysql 的shell里修改 mysql数据库的root密码

ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';

因为配置Kamailio时,要用到mysql 的root用户密码

3. 安装 Kamailio

apt install kamailio kamailio-mysql-modules

4. 配置
配置文件 在 /etc/kamailio/ 目录下,有两个
一个是 /etc/kamailio/kamctlrc, 里面的配置信息,主要供 kamctl 和 kamdbctl 这两个工具命令使用

SIP_DOMAIN=
DBENGINE=MYSQL
DBRWUSER=
DBRWPW=
CHARSET="latin1"
---上面5个必须修改----
DBROUSER=
DBROPW=
DBHOST=
DBPORT=

SIP_DOMAIN可以是域名 或者 IP地址

另外一个是 /etc/kamailio/kamailio.cfg, 是供 kamailio 主程序使用的, 里面有很多 脚本

#!define WITH_MYSQL
#!define WITH_AUTH
#!define WITH_USRLOCDB

#!define DBURL "mysql://kamailio:_NEW_DBRWPW_@localhost/kamailio"

这四个选项必须修改

如果设置了SIP_DOMAIN为域名,但这个域名没有在DNS中解析, 还必须在 kamailio.cfg 设置一个选项

alias=""

5. 初始化数据库和用户

kamdbctl create

这个时候会要求输入mysql的root密码

6. 开启停止服务

systemctl start kamailio
systemctl stop kamailio
systemctl restart kamailio

7. 添加用户

kamctl add userid password
比如
kamctl add  softsimuser  softsimpassword

8. 监听 IPV6地址

listen=udp:10.0.0.10:5060

listen=[proto]:[localip]:[lport] advertise [publicip]:[pport]

如果不设置,只监听本地 ipv4地址
或者使用

auto_bind_ipv6=1

选项

9. 常用管理命令

查看用户
/usr/sbin/kamctl db show subscriber

添加用户
/usr/sbin/kamctl add  softsimuser  softsimpassword

修改用户密码
/usr/sbin/kamctl   passwd  username  passwd

显示在线用户
/usr/sbin/kamctl    online

删除用户
/usr/sbin/kamctl  rm   username


启动Kamalio
/usr/sbin/kamctl  start  

重启Kamalio
/usr/sbin/kamctl  restart 


停止Kamalio
/usr/sbin/kamctl         stop 

STREAM_VOICE_CALL

对 AudioManager.STREAM_VOICE_CALL 音频流类型进行分析

hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp
frameworks/base/media/java/android/media/AudioManager.java
frameworks/base/media/java/android/media/AudioService.java
frameworks/base/media/java/android/media/AudioSystem.java

通过音频流的类型获取对应的音频策略

AudioPolicyManagerBase.cpp:

AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(AudioSystem::stream_type stream) {
    // stream to strategy mapping
    switch (stream) {
    case AudioSystem::VOICE_CALL:
    case AudioSystem::BLUETOOTH_SCO:
        return STRATEGY_PHONE;
    ...
    }
}

可以, voice call的音频策略是 phone

通过音频策略获取到对应的输出设备

AudioPolicyManagerBase.cpp:

audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache) {
    uint32_t device = AUDIO_DEVICE_NONE;
    ... 
    switch (strategy) {
    ... 
    case STRATEGY_PHONE:
        // for phone strategy, we first consider the forced use and then the available devices by order
        // of priority
        switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) { // 判断是否有设置在通讯过程中, 强制使用某种输出设备
        case AudioSystem::FORCE_BT_SCO: // 强制使用蓝牙, 作为输出设备
            if (!isInCall() || strategy != STRATEGY_DTMF) {
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
                if (device) break;
            }
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
            if (device) break;
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
            if (device) break;
            // if SCO device is requested but no SCO device is available, fall back to default case
            // FALL THROUGH

        default:    // FORCE_NONE 没有设置通讯过程中, 强制使用某种输出设备
            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
            if (mHasA2dp && !isInCall() &&
                    (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
                    (getA2dpOutput() != 0) && !mA2dpSuspended) {
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
                if (device) break;
            }
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
            if (device) break;
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET;
            if (device) break;
            if (mPhoneState != AudioSystem::MODE_IN_CALL) {
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
                if (device) break;
            }
			// 没有设置通讯过程中, 音频的输出设备, 则默认使用听筒作为输出设备
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_EARPIECE;
            if (device) break;
            device = mDefaultOutputDevice;
            if (device == AUDIO_DEVICE_NONE) {
                ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
            }
            break;

        case AudioSystem::FORCE_SPEAKER: // 强制使用扬声器, 作为输出设备
            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
            // A2DP speaker when forcing to speaker output
            if (mHasA2dp && !isInCall() &&
                    (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
                    (getA2dpOutput() != 0) && !mA2dpSuspended) {
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
                if (device) break;
            }
            if (mPhoneState != AudioSystem::MODE_IN_CALL) {
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
                if (device) break;
            }
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER;
            if (device) break;
            device = mDefaultOutputDevice;
            if (device == AUDIO_DEVICE_NONE) {
                ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
            }
            break;
        }
    break;
	// 关于上面default位置的问题, 如果每个case选择(包括default)最终都有break语句, 则default的位置不影响执行顺序
	// 当每个case选择(包括default)不一定有break语句时, 如果输入不满足其他选择, 最终执行default. 程序会从default处从上向下执行, 直到遇到break语句停止
	// 此处的default位置并不影响执行顺序
	... // 省略
    }
    return device;
}

speech codec

G.711 (也称PCM), 用脉冲编码调制对音频采样,采样率为8k每秒。它利用一个 64Kbps 未压缩通道传输语音讯号。 起压缩率为1:2, 即把16位数据压缩成8位。
G.711 标准下主要有两种压缩算法。一种是µ-law, 北美和日本。另一种是A-law, 欧洲等其他区域

1972 年,为了将 模拟通信转向数字通信执行制定的话音编码标准

这个在通信原理的本科课程中都有介绍过。G.711采用一种称为分组丢失隐藏(PLC)的技术来减少丢包带来的实际影响。有效的信号带宽在静默期间通过语音活动检测(VAD)这一过程被减小。

延迟 0.125 ms
mos 4.1


G.729
也是ITU-T定义的音频编码算法,frame 只有10ms,G.729点到点的时延为25ms,G.729基于CELP模式,用CS-ACELP(Conjugate-Structure Algebraic Code Excited Linear Prediction)方法以8Kbps的波特率对语音进行编码。

G.729采用的是共轭结构的代数码激励线性预测算法(Conjugate Structure Algebraic Code Excited Linear Prediction,CS-ACELP),这是一种基于CELP编码模型的算法。由于G.729编码器能够实现很高的语音质量(MOS分3.9, 这个语音质量算很不错了)和很低的算法延时,被广泛地应用于数据通信的各个领域。

G.729是对8KHz采样16bit量化的线性PCM语音信号进行编码,压缩后数据速率为8Kbps,具备16:1的高压缩率。

延迟 15ms
MOS 3.9

G.729 CS-ACELP 8 3.92


G.723
G.723是ITU-T在1996年制订成型的一种多媒体语音编解码标准。G.723编码器采用LPC合成-分析法和感觉加权误差最小化原理编码。G.723标准可在6.3kbps和5.3kbps两种码率下工作。对激励信号进行量化时,高速率(6.3kbps)编码器的激励信号采用多脉冲最大似然量化(MP­-MLQ),低速率(5.3kbps)编码器的激励信号采用代数码本激励线性预测(ACELP)。其中,高码率算法(6.3kbps)具有较高的重建语音质量,而低码率算法(5.3kbps)的计算复杂度则较低。与一般的低码率语音编码算法一样,这里的G.723标准采用的线性预测的合成分析法也就是我们通常所说的Analysis-by-Synthesis。

G.723.1是一个双速率的语音编码器.
编码器首先对语音信号进行传统电话带宽的滤波(基于G.712),再对语音信号用传统8000-Hz速率进行抽样(基于G.711),并变换成16 bit线性PCM码作为该编码器的输入;
在解码器中对输出进行逆操作来重构语音信号;高速率编码器使用多脉冲最大似然量化(MP-MLQ),低速率编码器使用代数码激励线性预测(ACELP)方法,编码器和解码器都必须支持此两种速率,并能够在帧间对两种速率进行转换;
此系统同样能够对音乐和其他音频信号进行压缩和解压缩,但它对语音信号来说是最优的;采用了执行不连续传输的静音压缩,这就意味着在静音期间的比特流中加入了人为的噪声。除了预留带宽之外,这种技术使发信机的调制解调器保持连续工作,并且避免了载波信号的时通时断。

G.723.1 MP-MLQ 6.3kbps 3.9 MOS
G.723.1 ACELP 5.3kbps 3.65 MOS


G.726

Adaptive Differential Pulse Code Modulation (ADPCM),最为常用的方式是 32 kbit/s,但由于其只是 G.711速率的一半,所以可将网络的可利用空间增加了一倍。G.726具体规定了一个 64 kbpsA-law 或 µ-law PCM 信号是如何被转化为40, 32, 24或16 kbps 的 ADPCM 通道的。在这些通道中,24和16 kbps 的通道被用于数字电路倍增设备(DCME)中的语音传输,而40 kbps 通道则被用于 DCME 中的数据解调信号(尤其是4800 kbps 或更高的调制解调器)。
G.726 encoder 输入一般都是G.711 encoder的输出:64kbps A-law or u-law.其算法实质就是一个ADPCM, 自适应量化算法。


Speex 2.15 /44
Minimizes bandwidth usage by using variable bit rate. It is one of the most preferred codecs used in many VoIP apps.


SILK/ Opus


AMR


GSM


Codec2是一个开源的 语音编解码器, 最低450 bit/s
https://github.com/drowe67/codec2

Codec2的主要开发者是David Rowe ,他同时也是另一个开源语音项目Speex 的开发者。Codec2项目允许在只占用极少带宽的情况下提供通话服务,其算法是基于1980年代的论文,并避开了未过期的专利。


VoLTE使用两种语音编码标准:AMR(或AMR-NB)、AMR-WB。


VoNR使用 EVS


twinkle支持的 codec

G.711 A-law (64 kbps payload, 8 kHz sampling rate)
G.711 μ-law (64 kbps payload, 8 kHz sampling rate)
GSM (13 kbps payload, 8 kHz sampling rate)
Speex narrow band (15.2 kbps payload, 8 kHz sampling rate)
Speex wide band (28 kbps payload, 16 kHz sampling rate)
Speex ultra wide band (36 kbps payload, 32 kHz sampling rate)
iLBC (13.3 or 15.2 kbps payload, 8 kHz sampling rate)
G.726 (16, 24, 32 or 40 kbps payload, 8 kHz sampling rate)


Linphone 自己实现了一个 G.729 编解码器

Bcg729 is an open source implementation of both an encoder and decoder for the ITU G729 Annex A/B speech codec. This library was developed by Belledonne Communications, the company supporting the Linphone project. It was written from scratch and is NOT a derivative work of the ITU reference source code of any kind.

The library is written in C 99, is fully portable, and can be executed on many platforms, including ARM and x86 processors. libbcg729 supports concurrent channel encoding/decoding for multi-call applications such as conferencing.

opus
speex 32k/16k/8k
pcmu
pcma
gsm
g722
g726 40/32/24/16
aal2-g726 32/24/16


参考资料:
https://www.gl.com/voice-codecs.html

https://en.wikipedia.org/wiki/Category:Speech_codecs

Android电话API

接听电话

mTelecomManager =  getSystemService("telecom");
mTelecomManager.acceptRingingCall();  

静音

mAudioManager =  getSystemService("audio");
mAudioManager.setParameters("incall_music_mute=true");

联发科

耳机插上时
Set_SpeechCall_UL_Mute=1
未插耳机时
Set_SpeechCall_UL_Mute=1;rcv_mux=off

对应地,取消静音则是

Set_SpeechCall_UL_Mute=0
或
Set_SpeechCall_UL_Mute=0;rcv_mux=on

请求音频焦点

.requestAudioFocus()

录音

int buf_len = AudioRecord.getMinBufferSize(16000, 16, 2);
audioRecord = new AudioRecord(3, 16000, 16, 2, buf_len);  //  inputSource=3 (AUDIO_SOURCE_VOICE_DOWNLINK)
audioRecord.startRecording();
short[] buf = new short[buf_len];
audioRecord.read(buf, 0, buf_len);

音频源定义

    AUDIO_SOURCE_VOICE_UPLINK = 2,
    AUDIO_SOURCE_VOICE_DOWNLINK = 3,
    AUDIO_SOURCE_VOICE_CALL = 4,

流媒体类型定义

    AUDIO_STREAM_VOICE_CALL       = 0,
    AUDIO_STREAM_SYSTEM           = 1,
    AUDIO_STREAM_RING             = 2,
    AUDIO_STREAM_MUSIC            = 3,