2021-09-13

MTK audio note -01

adb shell cat sys/devices/virtual/misc/mtgpio/pin 查看GPIO管脚信息
adb shell cat /sys/class/misc/mtgpio/pin 查看GPIO管脚信息
adb shell cat /proc/interrupts 查看中断信息
/sys/bus/cpu/devices 查看机器cpu 信息
打印kernel函数dump GPIO值:
int mt_set_gpio_mode(unsigned long pin, unsigned long mode)
{
if (mode >= GPIO_MODE_MAX) {
GPIOERR(“Parameter mode error: %d\n”, (int)mode);
return -ERINVAL;
}

if ((pin & 0xff) == GPIO24) {
printk(“mt_set_gpio_mode::pin = %lu , mode = %lu --------”,pin, mode);
dump_stack();
}
return MT_GPIO_OPS_SET(pin, set_mode, mode);
}

修改system/core/init/device.cpp加上一段代碼以創建/dev/snd
} else if(!strncmp(uevent->subsystem, “sound”, 5)) {
base = “/dev/snd/”;
make_dir(base, 0755);

EQ英文全称Equaliser,中文也就是均衡器的意思。它的基本作用是通过对声音某一个或多个频段进行增益或衰减,从而达到调整音色的目的。
EQ通常包括以下三个参数:Frequency,频率――这是用于设定你要进行调整的频率点的参数;Gain,增益――用于调整在你设定好的F值上进行增益或衰减的参数;Quantize――用于设定你要进行增益或衰减的频段“宽度”的参数。在这里,要注意是:当你设定的Q值越小的时候,你所处理的频段就越宽,而当你设定的Q值越大的时候,你所处理的频段就越窄。

pcm.c 操作的文件是pcmC%uD%u%c
主要使用Linux提供的open/close/ioctl/mmap
主要函数pcm_open/pcm_close/pcm_is_ready/pcm_read/pcm_write

mixer.c 操作的文件是controlC%
设置mixer control
主要函数mixer_ctl_set_enum_by_string mixer_ctl_set_value
像打开audio patch、设置pga音量都是都通过Control Interface

查看系统支持多少核数
root@NOBLEX:/ # cat sys/devices/system/cpu/present

手机放音乐时连接音箱, 将音箱音量调到最大时,音乐会自动暂停
原因是:HPL上信号过大导致EINT拉高产生了耳机拨出讯号,所以音乐会自动暂停掉

耳机accdet dts配置:
&accdet {
accdet-mic-vol = <7>;
headset-mode-setting = <0x500 0x500 1 0x3F0 0x800 0x800 0x200>;
accdet-plugout-debounce = <20>;
/1:ACC mode, 2:low cost without in bias, 6:low cost with in bias/
<0x500 0x500 1 0x3F0 0x800 0x800 0x200>这几个值分别表示的是什么?
struct headset_mode_settings {
int pwm_width; /pwm frequence/
int pwm_thresh; /pwm duty/
int fall_delay; /falling stable time/
int rise_delay; /rising stable time/
int debounce0; /hook switch or double check debounce/
int debounce1; /mic bias debounce/
int debounce3; /plug out debounce/
};

adb shell echo 8 8 8 8 > /proc/sys/kernel/printk //开启 kernel log的 printk 打印
CONFIG_LOG_BUF_SHIFT=19 //将这个宏变量改为19后,可以抓取从0秒 开始记录的kernel log,默认值是17

adb shell getprop |grep number 可以查看手机 烧写的软件版本
手机连接USB,pc端输入adb devices查询设备串号,三台机器的序列号都是一样的, 需要开启下面的这个宏
CONFIG_MTK_USB_UNIQUE_SERIAL=yes

e-fuse ROM里初始都是1,当且仅能一次把1改成0。可以这么理解ROM的数据只能写一次,通常用于保护关键数据,出厂时写入一次,以后每次都是读取
e-fuse 是烧写在 机器的CPU里,这样的话 能保证 手机不被其他 用户刷机
样机如果烧录了efuse则必须烧录签名版本,如果样机未烧录efuse,烧录版本是否签名无影响

有些手机因为结构原因没有把loopback plug dongle识别成mic耳机, 会导致 “Audio Loopback Latency Test”项测试结果值小于0.6,测试不通过。

frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
Android 6.0 上修改播放音乐从听筒发出
audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
bool fromCache, audio_output_flags_t flags)
{
audio_devices_t Device;
if(strategy == STRATEGY_MEDIA)
{
Device = AUDIO_DEVICE_OUT_EARPIECE;
ALOGD("getDeviceForStrategy() from AUDIO_DEVICE_OUT_EARPIECE ");
return Device;
}

编译后清除 之前的编译环境,便于下次重新编译
git checkout – .
git clean -xdf

从提供的register来看,异常时,AUDENC_ANA_CON0 = 0x583说明input选择的是耳机的,所以导致UL无声

kernel-3.10/drivers/misc/mediatek/gpio/mt6735/mt_gpio_debug.c//打印GPIO
static ssize_t mt_gpio_dump_regs(char *buf, ssize_t bufLen)
{}

vi out/target/product/xxx6753_65u_m0/obj/KERNEL_OBJ/arch/arm64/boot/dts/cust.dtsi
//查看编译后的 i2c配置情况

checkAndSetVolume() 函数却没有执行 也不会有音量变化的

在构造AudioTrack对象的时候,传入了CallbackWrapper作为audiotrack的callback
当audiotrack需要数据的时候,就会调用此函数
void MediaPlayerService::AudioOutput::CallbackWrapper()
audiotrack启动后就会周期性的调用 回调函数从解码器获取数据

AudioTrack中构造函数的参数
bufferSizeInBytes
这个是最难理解又最重要的一个参数,它配置的是 AudioTrack 内部的音频缓冲区的大小,该缓冲区的值不能低于一帧“音频帧”(Frame)的大小

D AudioALSADeviceConfigManager: ApplyDeviceTurnonSequenceByName() DeviceName = builtin_Mic_DualMic descriptor->DeviceStatusCounte = 6
descriptor->DeviceStatusCounte = 6这里有异常 mic不能正常打开

可以把双麦克风消噪强度降低提升speech quality

连接蓝牙耳机通话时,从蓝牙耳机切换到听筒
D/BTIF_HF_SERVER(20553): disconnect_audio
D/AudioALSASpeechPhoneCallController( 289): routing(), bt_device_on = 0, sample_rate = 16000

accdet_custom.c中
16 #if defined(CONFIG_AUDIO_SUPPORT)
17 static struct headset_mode_settings cust_headset_settings = {
18 0x500, 0x200, 1, 0x3f0, 0x800, 0x800, 0x200
19 };
20 #else
21 static struct headset_mode_settings cust_headset_settings = {
22 0x500, 0x500, 1, 0x3f0, 0x800, 0x800, 0x200
23 };
24 #endif

如果将第二项 0x500改成0x200 相当于将MIC 波形改成 PWM,如果第一项和第二项 相等 ,Micbias 一直为高
最后一项 0x200 代表耳机拔出时的 debounce 时间(去抖动),将其转为十进制 除以32768 即为真正的debounce 时间
其他项目的 debounce 时间是0x20

请在accdet.c文件中配置:
#define ACCDET_DEBOUNCE3_PLUG_OUT (0x20) //为了解决拔掉耳机后误报耳机按键消息
原来是#define ACCDET_DEBOUNCE3_PLUG_OUT (0x2030) / 30 msec */

按下 耳机按键,mic脚的电压波形 将会被拉低

耳机图标有显示 说明拔出耳机时 没有产生中断。
函数accdet_setup_eint() 都没有执行,那么accdet_setup_eint内部的中断申请函数request_irq() 肯定也不会执行
这时应关注 dws中 对于GPIO2对应的 EINT:ACCDET 配置是否有异常(配成了其他的GPIO6),需要重新适配 dws
同时需在mk文件中
定义CONFIG_ACCDET_EINT=yes ,CONFIG_ACCDET_EINT_IRQ=no
在这里插入图片描述

当插入耳机按键时,首先是触发了EINT中断,然后再触发ACCDET中断,这2个中断都是PMIC函数中注册
的,属于PMIC端的中断

把耳机mic的mode改为ACC
audio_custom_exp.h 中
#define HEADSET_MIC_MODE (2)
改为
#define HEADSET_MIC_MODE (1)
在打开麦克风降噪的情况下,手机对非稳态噪音(比如使用者身边别人说话的声音)的消除增强,但是对远端的背景噪音消除能力会降低,并且会出现一定的底噪。这些都是MTK消噪算法的一些缺点,属于正常情况

播放出现卡顿时 //系统内存不足或者开启了串口log等影响了系统performance
01-01 08:03:08.428 E/AudioALSAPlaybackHandlerBase( 291): -getHardwareBufferInfo pcm_get_htimestamp fail, ret = -1, pcm_get_error = cannot start channel: Broken pipe

sound/soc/mediatek/mt_soc_audio_v3 目录下
mt_soc_pcm_routing.c AudDrv_Afe.c AudDrv_Ana.c mt_soc_pcm_fm_i2s.c mt_soc_pcm_routing.c

手机/system/etc/目录
audio_device.xml 音频通路切换
audio_effects.conf 音频效果文件
audio_policy.conf 音频配置

没带Smart PA的项目,如何在main log中查看 PA是否有open?
D/AudioALSADeviceConfigManager( 288): cltname = Ext_Speaker_Amp_Switch cltvalue = On
关闭播放时
D/AudioALSADeviceConfigManager( 288): cltname = Ext_Speaker_Amp_Switch cltvalue = Off

在mt6750平台上 调节 耳机,扬声器等音频器件的模拟增益
是AudioALSAGainController.cpp
如void AudioMTKGainController::SetSpeakerGain(int index) 函数 调节外放的模拟增益
void AudioMTKGainController::SetSpeakerGain(uint32_t index)
{
SetHeadPhoneLGain(index); //调节耳机通路上的那个gain
SetHeadPhoneRGain(index);
}

只要外部pa接在耳机声道上,调节增益时都需要调节耳机通路上的那个gain。SetSpeakerGain函数根本作用不到耳机通路,如果外部pa接在内部pa后面,才需要调用SetSpeakerGain函数

在老的 mt6735平台上调节 扬声器等音频器件的模拟增益是
AudioALSAVolumeController.cpp文件
如AudioALSAVolumeController::SetSpeakerGain

MBDRC 分频段的DRC
MTK_BESLOUDNESS_SUPPORT=yes 开启MBDRC
MBDRC(Multi-Band DRC)导致雷霆战机游戏卡顿的原因是:MBDRC运算量大,并且是track base,每个AudioTrack都要进行DRC处理。在雷霆战机游戏的过程中,最多有20多个AudioTrack同时处于active状态并进行MBDRC运算,有可能造成CPU loading过大的情况,导致卡顿

//是否插入耳机扬声器的来电铃声大小不一样
之前手机 来电响铃时 喇叭信号(没有插入耳机时)会进行DRC 处理,而插入耳机时,喇叭信号则不会进行DRC处理,所以插入耳机时 扬声器听起来音量小

D/AudioALSAHardware( 353): = SET_DUMP_AUDIO_DEBUG_INFO(1)
开启Audio pcm log时 点击“Dump Audio Debug Info”后

find * -iname “*.h” |xargs grep -inr “snd_card”
find ./ -name Android.mk -exec grep -l init {} ;
find external/ -name Android.mk -exec grep -l test_name {} ;

device/mediatek/common/audio_param Android6.0 及MT6755平台上音频参数位置

device/mediatek/k50v1_66_cxo_pre/ProjectConfig.mk
ProjectConfig.mk包含诸多版本信息,搜索BRANCH
MTK_BRANCH = alps-mp-m0.mp1 //基线地址

/kernel-3.10/drivers/misc/mediatek/i2c/mt6752/i2c.c
static S32 _i2c_deal_result(mt_i2c *i2c)
598 BUG_ON(data_size > i2c->msg_len); //BUG_ON即让 机器出现KE
上面这个 BUG_ON产生的KE,这个KE表示HW行为读出来的字节数不符合预期值

adb shell getevent -l 耳机按键上报
add device 7: /dev/input/event0
name: “ACCDET”

adb shell getevent |grep /dev/input/event1 查看音量 +/- 按键event
信息

log中看到在通话过程中进来的echo量相当大,导致经过AEC之后UL的语音信号被削得很小了,所以目前是建议您们将免提模式下面的MIC切换为负MIC进行通话。
请将Audio_Customization_Common.h中
#define USE_REFMIC_IN_LOUDSPK (1) //1表示免提打开refmic 免提通话用副麦
audio_custom_exp.h中 和AudioALSACaptureHandlerAEC.cpp中取消宏EXTCODEC_ECHO_REFERENCE_SUPPORT的定义,这样会将AEC参考信号改为MTK平台自带(而不用nxp(smartpa))
#ifndef CONFIG_BSP_AUDIO_SUPPORT
#define EXTCODEC_ECHO_REFERENCE_SUPPORT
#endif

手机灭屏后,关闭了LCD和TP,同时降低了CPU的工作频率,CPU降频后,进入低功耗工作模式,可能会改变播放线程的优先级,导致write audio data丢失,机器可能出现杂音卡顿

抓取数字寄存器reg的adb命令
adb shell cat /sys/kernel/debug/mtksocaudio > D:AFEreg.txt Digital register
抓取模拟寄存器reg的adb 命令
adb shell cat /sys/kernel/debug/mtksocanaaudio > D:PMICreg.txt Analog register

adb shell “echo Setafereg,regaddr,0x18,regvalue,0x9000100a > /sys/kernel/debug/mtksocaudio” //将bit0设为0即关闭i2s0
adb shell “echo Setafereg,regaddr,0x4c,regvalue,0x190a > /sys/kernel/debug/mtksocaudio”//将bit0设为0即关闭i2s3
adb shell “echo Setafereg,regaddr,0x4,regvalue,0x2 > /sys/kernel/debug/mtksocaudio” //soft reset lock
adb shell “echo Setafereg,regaddr,0x18,regvalue,0x9010100a > /sys/kernel/debug/mtksocaudio” //设置bit20 loopback
adb shell “echo Setafereg,regaddr,0x18,regvalue,0x9010100b > /sys/kernel/debug/mtksocaudio” //开启i2s0
adb shell “echo Setafereg,regaddr,0x4c,regvalue,0x190b > /sys/kernel/debug/mtksocaudio”//开启i2s3
adb shell “echo Setafereg,regaddr,0x4,regvalue,0x0 > /sys/kernel/debug/mtksocaudio” //normal unlock

在播放音乐过程中 反复多次插拔USB,可能会存在USB的数据流通过混用的地线串扰到音频接口上造成 播放杂音
可以使用adb命令 抓取Audio pcm log
audio_dump L版本adb命令
adb shell setprop af.track.pcm 1
adb shell setprop af.mixer.end.pcm 1
adb shell setprop af.mixer.pcm 1
adb shell setprop af.mixer.write.pcm 1
adb shell setprop streamout.pcm.dump 1
抓取reg的adb命令
adb shell cat /sys/kernel/debug/mtksocaudio > D:AFEreg
adb shell cat /sys/kernel/debug/mtksocanaaudio > D:PMICreg

当前的耳机模式下面的MIC 模拟增益值设置的是多少?我们从log中看到该值设置在172,所以看到UL的信号偏小,请帮忙将这个值设置在180然后再做相关的测试.
按照以下步驟調整 mic 音量
進入工模 (撥號畫面下輸入 ##3646633##) -> Hardware Testing -> Audio -> Headset Mode -> Type 選 Mic -> 將 Level 3 的 Value 設為 180

AudioFlinger.h中 static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3); 可以修改Standby 时间
standby是由AudioFlinger控制的,一旦满足以下条件后,没有AudioTrack处于活动状态并且已经到达了standbyTime这个时间就进入Standby模式。那么standbyTime=systemTime() + standbyDelay,也就是过了standbyDelay这段时间后,音频系统将进入待机,关闭音频设备
kDefaultStandbyTimeInNsecs 设置过短,导致播放短促音频时AudioTrack还处于活动状态,此刻已经到达了standbyTime这个时间就进入Standby模式,拨号盘会出现卡顿嘶哑的声音。

I AudioPolicyManager: loadAudioPolicyConfig() loaded /system/etc/audio_policy.conf
device/mediatek/k50v1_66_cxo_pre/audio_policy.conf
audio_policy.conf的配置根据底层Audio驱动注册信息来完成,配置好audio_policy.conf,上层便可打开audio_policy.conf中定义的虚拟设备,进而自动选择相应的音频通路。

D AudioALSAStreamManager: +routingOutputDevice(), output_devices: 0x2 => 0x20 //Device routing通路切换的关键词

从UL0到UL1会经过speech enhancement的处理
UL0是数字端能抓取的最接近mic的data,
如果UL0有问题,可能有2种情况:
1.mic hw问题导致送给PMIC的模拟信号就有问题,mic hw也有可能概率出问题;
2.PMIC的问题,这个需要通过register来检查是不是出问题时PMIC有异常;

android L DRC的开启如下:

  1. ProjectConfig.mk
    MTK_BESLOUDNESS_SUPPORT=yes //为yes表示开启了DRC

  2. alps\frameworks\av\services\audioflinger\Android.mk
    #ifeq ($(strip $(MTK_BESLOUDNESS_SUPPORT)),yes)
    LOCAL_CFLAGS += -DMTK_AUDIOMIXER_ENABLE_DRC //需要有这行
    #endif
    连接 AudioTools 工具 ,选择里面的 “DRC” 选项 ,进行读入 参数是否 有效果

  3. 在setting菜单里面的喇叭音量助推器是个动态开关,开了数据会经过DRC处理,关了DRC算法不做任何处理。

ToneGenerator: getToneForRegion, tone 0, region 2, regionTone 0 按下数字0

没有声音是因为没有audiotrack资源可用,需要apk同事帮忙check 上层是否存在没有及时release audiotrack资源的情形。
10-13 09:32:56.090 15238 15315 W AudioTrack: AUDIO_OUTPUT_FLAG_FAST denied by client
10-13 09:32:56.091 293 293 E AudioMixer: AudioMixer::getTrackName out of available tracks
10-13 09:32:56.091 293 293 E AudioFlinger: no more track names available

tar czvf mediatek.tar.gz mediatek/ 压缩下

来电铃声流程正常,log中有多个进程因为lowmemory被杀,是否是系统内存问题导致的声音卡顿.
<6>[14290.078905]<0> (0)[69:kswapd0]lowmemorykiller: Killing ‘nee.anti.stolen’ (21398), adj 18, score_adj 1000
播放音乐卡顿问题,不仅仅是cpu性能问题,还有emmc的读写瓶颈问题

在下面方法中加上打印语句,这样只要提供复现问题时的mtklog就可以打印 Audio 寄存器信息。
mt_soc_pcm_dl1_i2s0Dl1.c
static int mtk_pcm_I2S0dl1_start(struct snd_pcm_substream *substream)
{
。。。。
Ana_Log_Print(); //在return 0前加上这2行打印寄存器code.
Afe_Log_Print();

return 0;
}

MIC的BIAS电压就是为MIC内部的JFET提供合适的直接偏置电压,麦克里面有个FET管,而这个电压正是为放大管提供偏置电压的.这样的话麦克才能工作

对于短音频,由于MediaTek的HW buffer size比较大,afLatency也会比较大,在AudioTrack中计算的shared buffer size比较大,因此会发生短音频播放不出来的情况。如果要减小HW buffer size,可以降低afLatency的值,减小shared buffer size,可以播放短音频。减小HW buffer size,会增大功耗。

AudioALSAStreamOut.cpp
#ifdef MTK_DYNAMIC_CHANGE_HAL_BUFFER_SIZE
#define LOW_POWER_HAL_BUFFER_SIZE (45056)
#define LOW_LATENCY_HAL_BUFFER_SIZE (8192) Qualcomm可能 才1000左右
#endif

Android平台 统一固定采样率为 SampleRate = 44100
还是要按照MTK的设计, 不要固定采样率.
音乐采样率切换的时候只要正确配置我们PA NXP的采样率就没问题

理论上 FM外放时 采样率为 44100,AudioALSAFMController.cpp中
pAudioALSASampleRateController->setPrimaryStreamOutSampleRate(44100);
如果在device/gionee/gionee6753_66c_m0/audio_policy.conf 将sampling_rates固定为48000
则AudioALSAFMController.cpp 也应该修改pAudioALSASampleRateController->setPrimaryStreamOutSampleRate(480000)
上层与底层的采样率 要保持一致,上层会询问 kernel是否支持44100 或者48000
66 outputs {
67 primary {
68 sampling_rates 48000

增加文件 dump audio pcm
FILE *tmpFd;
tmpFd = fopen("/data/srspre.pcm", “ab+” );
if ( tmpFd < 0 ) {
ALOGE(“No dump file”);
}
else{
fwrite(mMixBuffer, mixBufferSize, 1, tmpFd);
fclose(tmpFd);
}

Mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.c
iWriteReg()中最前面加上g_pstI2Cclient->timing,表示设置I2C的速度
如果不设置,为默认值100K ,比如想将I2C的speed设置为400K,可将g_pstI2Cclient->timing设置为400K
msg.timing = I2C_MASTER_CLOCK 调整i2c传输速率,搜索关键词timing
i2c速率从 100k 提升到 400 k除了软件修改外,也需要硬件 将上拉电阻进行修改,这是因为如果硬件上不做相应适配,会导致I2C 通讯不稳定,影响到划 手势

MTK Audio PCM 工具解析步骤
1.af_mixer_pcm.pcm请使用44.1khz,双声道,32bit播放;

2.af_track_pcm_0xaac6d588.pcm请使用44.1khz,双声道,16bit播放;

3.streamout.pcm.0.AudioALSAPlaybackHandlerNormal.pcm请使用附件"PCM2WAV_Tool.rar"的工具pcm_to_wav_44.1kHz_Q9p23_stereo.exe转成wav播放;
(具体转换方法是将streamout.pcm.0.AudioALSAPlaybackHandlerNormal.pcm直接拖至工具pcm_to_wav_44.1kHz_Q9p23_stereo.exe)

4.streamout.pcm.0.AudioALSAStreamOut.pcm 请使用附件"PCM2WAV_Tool.rar"的工具pcm_to_wav_44.1kHz_32bit_stereo.exe转成wav播放.
(具体转换方法是将streamout.pcm.0.AudioALSAStreamOut.pcm直接拖至工具pcm_to_wav_44.1kHz_32bit_stereo.exe)

D SpeechDriverLAD: SetUplinkMute(), mute_on = 1, old mUplinkMuteOn = 0 在打电话的时候上行mic被静音了

一帧大小=一个采样点字节数 * 声道数

DRC:动态范围控制 (Dynamic range control) 常用于音频输出的柔和压限
DRC(dynamic range compress)动态范围压缩。其作用相当于power limiter来保护负载不被烧坏。当输出的音频信号不是很大的时候,系统会按照原来的设定输出,但是当输出的音频信号过大的时候,为了保护喇叭DRC会将输出信号的幅度进行压缩将其限制在一个范围内。因为输出的音频信号过大会引起削峰,从而引起音频失真,并且损坏喇叭,所以需要有DRC的作用来将输出限制在一定的范围内。在信号很小的时候DRC是不会起作用的,只有当输出信号的功率超过了你设定的DRC门限的时候DRC才会工作。

插入三段耳机后自动关闭micbias,Open 宏ACCDET_LOW_POWER 就可以实现.
在accdet.c文件中有定义宏
#define MICBIAS_DISALBE_TIMER (6*HZ)
修改这个值就可以修改 自动关闭micbias的时间

ACCDET_LOW_POWER
当插入三段耳机6s后自动关闭micbias,达到省电的目的
但是插入四段式 耳机后 mic将无法工作,也无法响应音量+ - 按键

耳机MIC_BIAS1配置为高 mic_bias
修改accdet.c中:
pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width));
pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VAL

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值