Fork me on GitHub

使用AppleALC声卡仿冒驱动AppleHDA的正确姿势

大纲,写作中

前言

经常给网友仿冒声卡驱动, 一直都没有将过程写下来,鉴于每天会有许多人问如何仿冒声卡,就想将过程记录下来,供大家参考学习

提取codec

通过linux提取codec

制作Ubuntu Linux启动U盘:

如果你只是想通过Linux提取codec的话,可以随便下载个旧的版本即可,比如这个ubuntu 14.04.5LTS,如果想作为日后的生产力工具的话,我推荐你下载最新发布的ubuntu 17.10

制作Ubuntu Linux安装盘

  • Windows下请使用工具UltraISO,方法略
  • macOS下制作过程:

    • 插入U盘,确定设备名,方法为打开磁盘工具,选择U盘,可以看到U盘下面有两个分区:disk4s1disk4s2,那么U盘的设备名就是:disk4diskutil_disk4

    • 当然最简单的方法还是直接使用命令查看:diskutil list,输出的信息为:

      1
      2
      3
      4
      5
      6
           /dev/disk4 (internal, physical):

      #: TYPE NAME SIZE IDENTIFIER
      0: Apple_partition_scheme *2.0 GB disk4
      1: Apple_partition_map 4.1 KB disk4s1
      2: Apple_HFS 2.4 MB disk4s2

      这个disk4就是你要操作的设备名,后面我们会用到它

    • 卸载U盘,准备写入镜像,输入命令:

      1
      diskutil umountDisk disk4 # 卸载U盘
    • 使用dd命令将下载的Ubuntu Linux镜像恢复到U盘上,操作之前我有必要提醒各位小白,万一你不小心输入错了设备名,那么你连哭的机会都没有,因为dd是按扇区直接物理写入磁盘,别到时候找不到数据了再悔不当初没有认真看到这段文字

      1
      sudo dd if=/Users/sky/Downloads/ISO/ubuntu-17.10-desktop-amd64.iso of=/dev/disk4 bs=1m

      命令输入完后,请仔细认真检查下,尤其是of=/dev/disk4这里,再三确认后回车执行,输入用户密码后请耐心等待6-7分钟,写盘速度取决于你的U盘,镜像恢复的过程中不会有任何的文字输出,U盘写入成功后会显示下面类似的输出信息:

      1
      2
      3
      4
      5
      6
      7
      ~ % diskutil umountDisk disk4
      Unmount of all volumes on disk4 was successful
      ~ % sudo dd if=/Users/sky/Downloads/ISO/ubuntu-17.10-desktop-amd64.iso of=/dev/disk4 bs=1m
      Password:
      1431+1 records in
      1431+1 records out
      1501102080 bytes transferred in 906.101477 secs (1656660 bytes/sec)
    • 我的U盘竟然写了906秒(15分钟),我先找个地方哭会儿去*
      同时系统会弹出一个警告窗口,显示类似的信息:
      dd_error
      那是因为Linux的分区格式是ext,在macOS系统下无法识别才会报错,但是其实一个支持UEFI引导的Ubuntu Linux 17.10启动U盘已经制作成功了.点击Ignore忽略或者Eject退出U盘

  • 现在您可以使用这个新制作的Ubuntu Linux安装U盘引导Linux去提取codec

提取codec

开机按引导设备快捷键F12或者F8进入引导设备选单,选择Ubuntu Linux所在的USB盘回车
Boot_select
出现Ubuntu Linux的引导界面,选择Try Ubuntu without installing,该选项可以在不安装的情况下试用Ubuntu
Ubuntu_boot
回车后稍候会进入Ubuntu桌面:
ubuntu1
按组合键CTRL+ALT+t打开终端,输入以下命令:

1
2
3
4
5
6
cd ~/Desktop/ # 进入用户桌面
cp /proc/asound/card0/codec* . # 将codec开头的文件复制到当时位置
sudo cp -R /sys/firmware/acpi/tables . # 将acpi/tables目录复制到当时位置,tables目录包括了全部的DSDT和SSDT
ls -l # 列表
sudo chown -R ubuntu:ubuntu * # 将当前目录下所有文件及目录所有人修改为ubuntu
ls -l # 列表

显示输出信息如下:
ubuntu_codec_and_DSDT
将桌面上的codec开头的文件和tables目录复制到LINUX以外的支持写入的盘符下,Linux下面的工作已经完成,您可以继续试用或者重启/关机.

整理有效节点

使用到的工具:verbit.sh,下载链接
用法: verbit.sh codec#0,它会生成如下显示的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Verbs from Linux Codec Dump File: codec#0

Codec: Realtek ALC3246 Address: 0 DevID: 283902550 (0x10ec0256)

Jack Color Description Node PinDefault Original Verbs
--------------------------------------------------------------------------------------------------------
Digital Unknown Mic at Int N/A 18 0x12 0x90a60170 01271c70 01271d01 01271ea6 01271f90
Unknown Unknown Line Out at Ext N/A 19 0x13 0x40000000 01371c00 01371d00 01371e00 01371f40
Analog Unknown Speaker at Int N/A 20 0x14 0x90170140 01471c40 01471d01 01471e17 01471f90
1/8 Black Speaker at Ext Rear 24 0x18 0x411111f0 01871cf0 01871d11 01871e11 01871f41
1/8 Black Speaker at Ext Rear 25 0x19 0x411111f0 01971c10 01971d20 01971e81 01971f02
1/8 Black Speaker at Ext Rear 26 0x1a 0x411111f0 01a71cf0 01a71d11 01a71e11 01a71f41
1/8 Black Speaker at Ext Rear 27 0x1b 0x411111f0 01b71cf0 01b71d11 01b71e11 01b71f41
Analog Pink Modem Hand at Ext N/A 29 0x1d 0x40779a2d 01d71c2d 01d71d9a 01d71e77 01d71f40
1/8 Black Speaker at Ext Rear 30 0x1e 0x411111f0 01e71cf0 01e71d11 01e71e11 01e71f41
1/8 Black HP Out at Ext Front 33 0x21 0x02211030 02171c30 02171d10 02171e21 02171f02
--------------------------------------------------------------------------------------------------------


Jack Color Description Node PinDefault Modified Verbs
--------------------------------------------------------------------------------------------------------
Digital Unknown Mic at Int N/A 18 0x12 0x90a60170 01271c70 01271d00 01271ea6 01271f90
Unknown Unknown Line Out at Ext N/A 19 0x13 0x40000000 01371c00 01371d00 01371e00 01371f40
Analog Unknown Speaker at Int N/A 20 0x14 0x90170120 01471c20 01471d00 01471e17 01471f90
Analog Pink Modem Hand at Ext N/A 29 0x1d 0x40779a2d 01d71c40 01d71d90 01d71e77 01d71f40
1/8 Black HP Out at Ext Front 33 0x21 0x02211030 02171c30 02171d10 02171e21 02171f01
--------------------------------------------------------------------------------------------------------

Modified Verbs in One Line: 01271c70 01271d00 01271ea6 01271f90 01371c00 01371d00 01371e00 01371f40 01471c20 01471d00 01471e17 01471f90 01d71c40 01d71d90 01d71e77 01d71f40 02171c30 02171d10 02171e21 02171f01
--------------------------------------------------------------------------------------------------------

如果你希望将输出结果保存下来,可以将命令改为:

1
verbit.sh codec#0 > ALC256_dump.txt

这个ALC256_dump.txt就是上面显示的输出信息,你可以使用其它的文字编辑器打开它.
重要的信息不能漏掉了,后面我们在编译声卡驱动的时候会经常用到它们:

1
Codec: Realtek ALC3246   Address: 0   DevID: 283902550 (0x10ec0256)

其中的:

名称解释
Codec: Realtek ALC3246是告诉了你的声卡型号是ALC3246(ALC256)
Address: 0会告诉你生成configdata的数据的前缀是0,比如上面显示输出信息最后一行的Modified Verbs in One Line:后面所有的数据中,每组数据的第一位就是这个 0 ,如果Address: 2,那么每组数据的第一位就是 2 ,这个后面我们会用到它
DevID: 283902550 (0x10ec0256)283902550是0x10ec0256的10进制值,0x10ec 是指vendorID(芯片供应商ID),是REALTEK的设备标识,0256是指型号,去掉前面的0,您的声卡型号就是:ALC256

过去的教程会告诉你,通过运行verbit.sh整理出来的节点是:

1
2
3
18 0x12 Mic at Int
20 0x14 Speaker at Int
33 0x21 HP Out at Ext Front

至于上面输出信息里显示的0x13 0x1d都是无效的节点.而且它只有三个有效的节点,我的声卡ALC256是用于笔记本,按理说它至少还应该存在另一个Mic Ext的节点,我需要找出它来.看来使用传统的方法已经无法满足我的求知欲了.
既然使用Linux可以提取codec,那么有没有可能

通过Linux找出有效的节点

呢?
为了测试我的声卡存在第四个节点,我需要找出耳机的Mic输入节点,于是乎重新引导进入Linux,插上耳机,它弹出了这个窗口:
SelectAudioDevice
这三个选项的意思是让我选择声音设备,既然我希望找出耳机麦克风的输入,我就选择了中间带有耳麦的图标
进入Sound Settings,点击 Input,选择Headset Microphone,调节Input volume,对着耳麦说话,发现有输入电平了,再切换到内置麦克风Internal Microphone,也有输入电平,那么至少说明我的声卡功能是完整的,至少在Linux下它工作的很好.
SoundInputDeviceSelect
测试结果已经出来了,我想要知道耳麦的有效节点是什么,使用组合键CTRL+ALT+t打开终端,输入命令:dmesg看看它会有什么变化,结果我就看到了下面的文字:

1
2
3
4
5
6
7
8
[    5.040591] snd_hda_codec_realtek hdaudioC0D0: autoconfig for ALC3246: line_outs=1 (0x14/0x0/0x0/0x0/0x0) type:speaker
[ 5.040593] snd_hda_codec_realtek hdaudioC0D0: speaker_outs=0 (0x0/0x0/0x0/0x0/0x0)
[ 5.040595] snd_hda_codec_realtek hdaudioC0D0: hp_outs=1 (0x21/0x0/0x0/0x0/0x0)
[ 5.040595] snd_hda_codec_realtek hdaudioC0D0: mono: mono_out=0x0
[ 5.040596] snd_hda_codec_realtek hdaudioC0D0: inputs:
[ 5.040598] snd_hda_codec_realtek hdaudioC0D0: Headset Mic=0x19
[ 5.040599] snd_hda_codec_realtek hdaudioC0D0: Headphone Mic=0x1a
[ 5.040600] snd_hda_codec_realtek hdaudioC0D0: Internal Mic=0x12

我不想看到其它的输出信息,我只需要得到我想要的信息,于是将命令改为:

1
2
3
4
5
6
7
8
9
sky@sky-Inspiron-7560:~$ dmesg | grep snd_hda_codec_realtek
[ 5.040591] snd_hda_codec_realtek hdaudioC0D0: autoconfig for ALC3246: line_outs=1 (0x14/0x0/0x0/0x0/0x0) type:speaker
[ 5.040593] snd_hda_codec_realtek hdaudioC0D0: speaker_outs=0 (0x0/0x0/0x0/0x0/0x0)
[ 5.040595] snd_hda_codec_realtek hdaudioC0D0: hp_outs=1 (0x21/0x0/0x0/0x0/0x0)
[ 5.040595] snd_hda_codec_realtek hdaudioC0D0: mono: mono_out=0x0
[ 5.040596] snd_hda_codec_realtek hdaudioC0D0: inputs:
[ 5.040598] snd_hda_codec_realtek hdaudioC0D0: Headset Mic=0x19
[ 5.040599] snd_hda_codec_realtek hdaudioC0D0: Headphone Mic=0x1a
[ 5.040600] snd_hda_codec_realtek hdaudioC0D0: Internal Mic=0x12

得到的输出结果跟上面的相同,于是我发现了在Linux下我的声卡的有效节点分别为:

  • 0x14 Speaker out
  • 0x21 HP out
  • 0x19 Headset Mic in
  • 0x1a Headphone Mic in
  • 0x12 Internal Mic in

暂且不讨论我的声卡是几节点,我发现通过linux完全可以得出声卡的有效节点,而且这种方式好像也不需要使用什么专用的工具,只是在linux下面通过内部命令dmesg无意中就被我发现了声卡中最挠头的找有效节点的打怪秘籍,这种方法在整个Hackintosh社区里还没见有人用过.看来这跟我之前使用linux经常会通过dmesg排错的使用习惯是分不开的,这里要由衷地给自己点一个大大的

在这个特别的日子里11.11,没有陪女朋友的小伙伴们,都可以使用我刚get到的新技能愉快地打怪升级啦!

暂更于此,做个记号 2017年11月11日


继续更新

先将节点整理成一个表格,这个表格里会包括之前整理出的数据

有效节点10进制设备名称
0x1420Speaker out
0x2133HP out
0x1925Headset Mic in
0x1a26Headphone Mic in
0x1218Internal Mic in

之所以加上转换后的10进制,就是为了以后制作pathmap做准备

整理有效路径

使用codecgraph生成pathmap图
命令如下:

1
2
3
$ codecgraph codec\#0
Codec: Realtek ALC3246
Generating codec#0.svg

如果出现error: dot executable not found (did you install graphviz?)的错误提示的话,那么还需要执行下面的动作,打开终端,输入命令:

1
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" # 安装brew

安装brew的过程中会提醒你安装Xcode Command Tools,请选择yes.
安装完brew之后,继续执行:

1
brew install graphviz   # 安装codecgraph所需要的依赖程序

这个生成的codec#0.svg就是声卡的pathmap,使用Sketch.app打开它
codec
是不是看了头老大?没错,我刚开始看的时候也是一头的雾水,看多了后就会总结出经验来
还记得我们在前面整理出的有效节点吧?!
还是以我的声卡为例,上文中我已经整理出5个节点,按照顺序来:
0x14,这个是Speaker的节点,也就是喇叭,我们也俗称为外放,如果想让它正确地发声,就需要看看跟它连接的节点都有哪些,在图片里找到0x14位于图片的最下方,我把它放大下:
node_output
通过观察我们会发现,0x14与0x02连接,转换成10进制就是20->2,同样的,0x21与0x03连接,转换成10进制就是33->3,我们把它放到表格中

有效节点10进制设备名称路径
0x1420Speaker out20->2
0x2133HP out33->3
0x1925Headset Mic in
0x1a26Headphone Mic in
0x1218Internal Mic in

怎么样?也没想像的那么复杂吧?两个输出设备的节点和路径已经整理出来,下一步,我们要把输入设备和节点整理出来
node_input
再来看图片的上半部,最右侧的0x08和0x09是两个声音输入的节点,0x23和0x22是两个混音设备,最前方是设备节点,这个就是输入设备的路径.
我的声卡的0x12声音输入路径包括了3个节点;为了便于理解,被我圈起来的红线部分就是0x12(Mic in)的路径(pathmap),8->35->18就是路径,照样还是要将数据放到表格里
node12_pathmap

有效节点10进制设备名称路径
0x1420Speaker out20->2
0x2133HP out33->3
0x1925Headset Mic in
0x1a26Headphone Mic in
0x1218Internal Mic in8->35->18

还记得文章前面通过linux找出来的有效节点不?我的耳麦可是支持输入的,节点也找出来了,是0x19(Headset Mic in),我需要将路径找出来,我发现0x19同时连接了两个节点:0x23和0x22,相应地路径为:8->35->25和9->34->25,顺手也把0x1a的路径也整理出来备用,将这两组数据补充进表格里

有效节点10进制设备名称路径
0x1420Speaker out20->2
0x2133HP out33->3
0x1925Headset Mic in8->35->25 9->34->25
0x1a26Headphone Mic in8->35->26 9->34->26
0x1218Internal Mic in8->35->18

至于0x1a是否有效暂且放到一边,一个包括了有效节点/设备名称/路径的表格就整理完成了,这里需要强调的一点是:路径数值使用10进制

整理ConfigData

ConfigData的获得有两种方法:这两种方法分别为:通过codec里面的Pin Default提取以及通过PinConfigs提取,然后修正ConfigData.下面我们将分别介绍这两种提取方法

通过PinConfigs提取ConfigData

ConfigData数据位于PinConfigs.kext/Contents/Info.plist里,PinConfigs.kext作为AppleALC插件被加载.
用到的工具:Plist Editor Pro.app
还是以我的ALC256为例:打开Info.plist后,使用组合快捷键⌘+f打开搜索: ALC256 或者 283902550 ,它会直接定位到你需要查找的数据位置,再按⌘+g,将相同的字符串全部搜索完毕,直到它又跳转到第一个搜索结果的位置,结果如下图:
PlistEditorPro
ALC256的ConfigData的数据有三组,分别对应的LayoutID为:13 28 56
将这三组ConfigData复制出来:

id:13
01271C10 01271D00 01271EA6 01271F90 01471C20 01471D00 01471E17 01471F90 01971C30 01971D10 01971E8B 01971F02 02171C50 02171D10 02171E2B 02171F02 01470c02

id:28
01471C50 01471D00 01471E17 01471F90 01470c02 01A71C30 01A71D00 01A71EA0 01A71F90 02171C20 02171D10 02171E21 02171F00

id:56
01271C10 01271D00 01271EA6 01271F90 01471C20 01471D00 01471E17 01471F90 01971C30 01971D10 01971E8B 01971F02 01A71C40 01A71D10 01A71E81 01A71F02 01D71CF0 01D71D11 01D71E11 01D71F41 02171C50 02171D10 02171E2B 02171F02 01470c02 02170c02

这么看起来是杂乱无章的,我们将它格式化一下,每个节点一行,四组数据:
id:13

1
2
3
4
01271C10 01271D00 01271EA6 01271F90 
01471C20 01471D00 01471E17 01471F90
01971C30 01971D10 01971E8B 01971F02
02171C50 02171D10 02171E2B 02171F02 01470c02

id:28

1
2
3
01471C50 01471D00 01471E17 01471F90 01470c02 
01A71C30 01A71D00 01A71EA0 01A71F90
02171C20 02171D10 02171E21 02171F00

id:56

1
2
3
4
5
6
01271C10 01271D00 01271EA6 01271F90 
01471C20 01471D00 01471E17 01471F90 01470c02
01971C30 01971D10 01971E8B 01971F02
01A71C40 01A71D10 01A71E81 01A71F02
01D71CF0 01D71D11 01D71E11 01D71F41
02171C50 02171D10 02171E2B 02171F02 02170c02

从中我们可以发现:
id:13为四行四节点,节点为:0x12 0x14 0x19 0x21
id:28为三行三节点,节点为:0x14 0x1A 0x21
id:56为六行六节点,节点为:0x12 0x14 0x19 0x1A 0x1D 0x21
现在有个问题摆在你们的面前,我上面明明刚说过每个节点为四组数据,那为什么在0x14和0x21的节点后面又多出来一组数据呢?这组数据又有什么作用呢?原来秘密都藏在codec里面,它定义了某些输出设备具有EAPD,比如0x14节点的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Node 0x14 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out
Control: name="Speaker Playback Switch", index=0, device=0
ControlAmp: chs=3, dir=Out, idx=0, ofs=0
Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1
Amp-Out vals: [0x00 0x00]
Pincap 0x00010014: OUT EAPD Detect
EAPD 0x2: EAPD
Pin Default 0x90170120: [Fixed] Speaker at Int N/A
Conn = Analog, Color = Unknown
DefAssociation = 0x2, Sequence = 0x0
Misc = NO_PRESENCE
Pin-ctls: 0x40: OUT
Unsolicited: tag=00, enabled=0
Power states: D0 D1 D2 D3 EPSS
Power: setting=D0, actual=D0
Connection: 1
0x02

具有EAPD的节点需要添加参数SET_EAPD_BTLENABLE,转换成数值为0x70c,完整的数值为:Address+节点+70c+02,即:01470c02,它通过hda-verb可以执行,比如CodecCommander就是调用的hda-verb执行的命令.更多的hda-verb参数请参考我之前的文章:hda-verb参数详表
这里我教大家一个简单判断EAPD节点的方法:那就是它通常会位于Speaker OutHP Out这两个输出节点上.至于其它教程提到过的关于01470c02是组神奇的代码,可以让外放发声的说法是错误的,它可能刚好声卡的Speaker Out的输出节点是0x14而已.如果您的Speaker Out输出节点是0x16,那么就需要把它修改为01670c02,当然要遵守这个公式:Address+节点+71c+02

本节教程先更新到这里 11-13-2017 10:25PM

续更

另外一种找出EAPD节点的方法:使用工具node_dump.sh,它会显示出每个节点的信息,包括EAPD输出,详细的用法以后再补充上.

说了半天,也只说了一个01470c02是干什么用的,其它的四组数据都分别代表什么呢?这个话题如果展开讲的话,没个一两天是说不明白的.
接下来的部分就会介绍到这四组数据是怎么整理出来的.

通过codec里面的Pin Default提取并整理

将使用verbit.sh整理出来的ALC256_dump.txt重新打开:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Verbs from Linux Codec Dump File: codec#0

Codec: Realtek ALC3246 Address: 0 DevID: 283902550 (0x10ec0256)

Jack Color Description Node PinDefault Original Verbs
--------------------------------------------------------------------------------------------------------
Digital Unknown Mic at Int N/A 18 0x12 0x90a60170 01271c70 01271d01 01271ea6 01271f90
Unknown Unknown Line Out at Ext N/A 19 0x13 0x40000000 01371c00 01371d00 01371e00 01371f40
Analog Unknown Speaker at Int N/A 20 0x14 0x90170140 01471c40 01471d01 01471e17 01471f90
1/8 Black Speaker at Ext Rear 24 0x18 0x411111f0 01871cf0 01871d11 01871e11 01871f41
1/8 Black Speaker at Ext Rear 25 0x19 0x411111f0 01971c10 01971d20 01971e81 01971f02
1/8 Black Speaker at Ext Rear 26 0x1a 0x411111f0 01a71cf0 01a71d11 01a71e11 01a71f41
1/8 Black Speaker at Ext Rear 27 0x1b 0x411111f0 01b71cf0 01b71d11 01b71e11 01b71f41
Analog Pink Modem Hand at Ext N/A 29 0x1d 0x40779a2d 01d71c2d 01d71d9a 01d71e77 01d71f40
1/8 Black Speaker at Ext Rear 30 0x1e 0x411111f0 01e71cf0 01e71d11 01e71e11 01e71f41
1/8 Black HP Out at Ext Front 33 0x21 0x02211030 02171c30 02171d10 02171e21 02171f02
--------------------------------------------------------------------------------------------------------

将数据整理成如下的样式:

  • [Fixed]是内部设备
  • [Jack]是通过插孔进行连接的外部设备
  • [N/A]是其它未知设备
1
2
3
4
5
6
7
8
9
10
11
12
13
Node	PinDefault		Description 
----------------------------------------------------------
0x12 0x90a60170 [Fixed] Mic at Int
0x13 0x40000000 [N/A] Line Out at Ext N/A
0x14 0x90170140 [Fixed] Speaker at Int
0x18 0x411111f0 [N/A] Speaker at Ext Rear
0x19 0x411111f0 [N/A] Speaker at Ext Rear
0x1a 0x411111f0 [N/A] Speaker at Ext Rear
0x1b 0x411111f0 [N/A] Speaker at Ext Rear
0x1d 0x40779a2d [N/A] Modem Hand at Ext N/A
0x1e 0x411111f0 [N/A] Speaker at Ext Rear
0x21 0x02211030 [Jack] HP Out at Ext Front
----------------------------------------------------------

PinDefault进行小端转换little-endian,这里借用一张紫米教程里面的图片进行小端转换的理解:
little-endian
就是把PinDefault的数据两两对调,比如:0x12节点的[Fixed] Mic at Int原始数据为:0x90a60170,去掉前面的0x,变成90 a6 01 70,
最前面的90跑到了最后,最后的70又跑到了最前面,中间的a601再对调下,就变成了70 01 a6 90.整理后,变成如下的格式:

1
2
3
4
5
6
7
8
9
10
11
Node            c  d  e  f              Description
12 70 01 a6 90 [Fixed] Mic at Int
13 00 00 00 40 [N/A] Line Out at Ext N/A
14 40 01 17 90 [Fixed] Speaker at Int
18 f0 11 11 41 [N/A] Speaker at Ext Rear
19 f0 11 11 41 [N/A] Speaker at Ext Rear
1a f0 11 11 41 [N/A] Speaker at Ext Rear
1b f0 11 11 41 [N/A] Speaker at Ext Rear
1d 2d 9a 77 40 [N/A] Modem Hand at Ext N/A
1e f0 11 11 41 [N/A] Speaker at Ext Rear
21 30 10 21 02 [Jack] HP Out at Ext Front

下一步,我们要对数据进行修正,让它看起来更像APPLE.

修正PinDefault,并生成ConfigData

上一节我们只是把数据进一步地整理出来,并进行了格式化,我们并没有对数据进行修正.本节我们就开始进行PinDefault的修正,先上一张我整理出来的表格:
pinconfigs

  • 前面我提到过通过Linux找到的节点0x19,它在Linux下面显示的设备为Headset Mic,在上一节中我们整理出的0x19的设备为:[N/A] Speaker at Ext Rear , PinDefault值为:f0 11 11 41,通过上表我们得知,这个端口是被屏蔽掉的,就是不起作用的节点.
  • 现在我们希望它能正常工作,我的想法是把它修正为:[Jack] Mic at Ext,一个可以正常工作的外部麦克输入设备,结合上面的表格,我将f0 11 11 41修改为:70 20 a1 02.
  • 由于我的耳机插孔只有一个,也就是俗称的二合一插孔,我希望在上面的外麦克工作不正常的情况下,可以将耳麦和耳机输出定义成组合插孔(2in1),上表中Connection Type的连接类型中,正好有个B=Combination,它的意思就是:组合,我需要同时修正耳麦和耳机的数值:
    • Mic at Ext : f0 11 11 41->70 20 ab 02
    • HP Out Ext : 30 10 21 02->30 10 2b 02

屏蔽无效节点:f0 00 00 40

屏蔽掉无效的节点,避免产生杂音和底噪,更详细的描述请见其它问题

0x1d的节点为无效节点,所以必须把它屏蔽起来,为了让它更符合APPLE的规范,我们使用f0 00 00 40来屏蔽,包括其它的不用的节点.修正后的数据为:

1
2
3
4
5
6
7
8
9
10
11
Node            c  d  e  f              Description
12 70 01 a6 90 [Fixed] Mic at Int
13 f0 00 00 40 [N/A] Line Out at Ext N/A
14 40 01 17 90 [Fixed] Speaker at Int
18 f0 00 00 40 [N/A] Speaker at Ext Rear
19 70 10 ab 02 [Jack] Mic at Ext
1a f0 00 00 40 [N/A] Speaker at Ext Rear
1b f0 00 00 40 [N/A] Speaker at Ext Rear
1d f0 00 00 40 [N/A] Modem Hand at Ext N/A
1e f0 00 00 40 [N/A] Speaker at Ext Rear
21 30 10 2b 02 [Jack] HP Out at Ext Front

现在, 我们可以生成最终的ConfigData了,
ConfigData的计算公式为:

1
2
3
4
5
Final Config:
Address + Node + 71c +【c】
Address + Node + 71d +【d】
Address + Node + 71e +【e】
Address + Node + 71f +【f】

这里的c d e f就是上面整理出来的2位数值
我的ALC256的Address值为0,现在我将节点0x12ConfigData值通过上面的公式整理后得出:

1
01271c70 01271d01 01271ea6 01271f90

相应地,其它的节点整理出来的数据如下:

1
2
3
4
5
6
7
8
9
10
01271c70 01271d01 01271ea6 01271f90
01371cf0 01371d00 01371e00 01371f40
01471c40 01471d01 01471e17 01471f90 01470c02
01871cf0 01871d00 01871e00 01871f40
01971c70 01971d10 01971eab 01971f02
01a71cf0 01a71d00 01a71e00 01a71f40
01b71cf0 01b71d00 01b71e00 01b71f40
01d71cf0 01d71d00 01d71e00 01d71f40
01e71cf0 01e71d00 01e71e00 01e71f40
02171c30 02171d10 02171e2b 02171f02 02170c02

我将编辑的过程做了段视频,方便大家理解.

打开Sublime Text.app,按住鼠标中键打开块复制,将c d e f下面的数据块拷贝一份到最下面空白处,在第一列按鼠标中键一下拉到下面,输入Address0,再把上方的Node下面的数据做块复制,粘贴到0后面,再输入:71c,再将01271做块复制到后面,再分别输入d e f即可.最后在0x140x21节点后面添加两组EAPD数据.
将上面整理出来的数据去掉每行的硬回车后得到的一组数据就是最终的ConfigData
01271c70 01271d01 01271ea6 01271f90 01371cf0 01371d00 01371e00 01371f40 01471c40 01471d01 01471e17 01471f90 01470c02 01871cf0 01871d00 01871e00 01871f40 01971c70 01971d10 01971eab 01971f02 01a71cf0 01a71d00 01a71e00 01a71f40 01b71cf0 01b71d00 01b71e00 01b71f40 01d71cf0 01d71d00 01d71e00 01d71f40 01e71cf0 01e71d00 01e71e00 01e71f40 02171c30 02171d10 02171e2b 02171f02 02170c02

到这里,ConfigData的数据就算整理完了.

找出适合你的id

这一节里,我们就来一起动手找出最适合你的注入id
正确的注入id可以保证您的声卡各项功能都能正常使用,它至关重要,这里给出的方法也是为了进一步验证前面我们所做的工作.
到找注入id这一步,您至少已经有了这些数据:

  • 声卡基础资料:
名称解释
Codec: Realtek ALC3246是告诉了你的声卡型号是ALC3246(ALC256)
Address: 0会告诉你生成configdata的数据的前缀是0,比如上面显示输出信息最后一行的Modified Verbs in One Line:后面所有的数据中,每组数据的第一位就是这个 0 ,如果Address: 2,那么每组数据的第一位就是 2 ,这个后面我们会用到它
DevID: 283902550 (0x10ec0256)283902550是0x10ec0256的10进制值,0x10ec 是指vendorID(芯片供应商ID),是REALTEK的设备标识,0256是指型号,去掉前面的0,您的声卡型号就是:ALC256
  • 整理出来的有效节点及路径
有效节点10进制设备名称路径
0x1420Speaker out20->2
0x2133HP out33->3
0x1925Headset Mic in8->35->25 9->34->25
0x1a26Headphone Mic in8->35->26 9->34->26
0x1218Internal Mic in8->35->18
  • 最终的ConfigData数据:
    01271c20 01271d01 01271ea6 01271f90 01371cf0 01371d00 01371e00 01371f40 01471c40 01471d01 01471e17 01471f90 01470c02 01871cf0 01871d00 01871e00 01871f40 01971c10 01971d10 01971e8b 01971f02 01a71cf0 01a71d00 01a71e00 01a71f40 01b71cf0 01b71d00 01b71e00 01b71f40 01d71cf0 01d71d00 01d71e00 01d71f40 01e71cf0 01e71d00 01e71e00 01e71f40 02171c30 02171d10 02171e2b 02171f02 02170c02

下一步,我们就要将这些数据AppleALC相应的位置,让它发挥作用.

下载AppleALC

操作步骤:

  1. 创建AppleALC的本地仓库的克隆版本:

    • 使用git命令,更多git命令的用法请参考git使用简易指南:

      1
      2
      3
      mkdir ~/git # 在家目录下新建立`git`目录
      cd ~/git # 进入`git`目录
      git clone https://github.com/vit9696/AppleALC # 克隆AppleALC到本地
    • 或者通过浏览器下载 AppleALC最新版

  2. 打开AppleALC目录,进入Resources目录,你会发现这里面着截止到目前所支持的声卡的全部型号.我的声卡是ALC256,我就点击ALC256为便于理解,我将除了ALC256之外的其它型号的声卡目录全部删除了,它看起来如下图所示:
    ALC_Folder我们会发现该目录下包括了一个定义文件Info.plist,打开Info.plist,你会发现,它定义了一个声卡驱动所需要的数据,CodecID后面的598ALC2560x256的10进制数值,CodecName是声卡名称的描述,这里是ALC256(3246),接下来是Files,它分成两部分,一部分是Layouts,它定义声卡设备的布局,另一部分是Platforms,它定义声卡的平台注入,包括有效节点和路径的定义.
    ALC256_Info.plist

三个layout开头的文件以及三个Platforms开头的文件,Platforms为路径定义文件.其中layout13.xml.zlib layout28.xml.zlib layout56.xml.zlib就是注入的id,只是你的声卡需要注入的是哪个ID才能获得最佳效果,还需要分析其它的数据.

如何找出适合你的id

通过制作几十个声卡仿冒的驱动,我发现找出注入的id还是有些窍门的,比如说我可以通过PinConfigs.kextInfo.plist,将同一型号的声卡的ConfigData都找出来,方法:

  • 根据上面整理的声卡基础资料将Address不为0的排除出去
  • 剩下的LayoutID里,再通过ConfigData将有效节点的数据留下,无效的排除,这样剩下来的LayoutID也就没几个了
  • 最后,通过PlatformsID,找出有效节点及路径,最终确定注入的id
  • 需要注意的是,某些型号的声卡的注入id可以是唯一的,也可以是多个,这些都需要通过分析数据进行确认

这里插句题外话:之前给群友做声卡仿冒的时候,ALC269ALC887我都是直接绕路走的,或者让群友用VoodooHDA,或者直接拒绝.现在可以使用排除法,很快就能找到注入的id

更新于:11-21-2017 22:30

如何修改layoutPlatforms数据

上文中我们提到了通过PlatformsID,找出有效节点及路径,最终确定注入的id

如何确认路径是否正确,我应该怎么做呢?先打开Platforms文件,需要用到的工具:zlib转换器.app.
操作方法:

  • 打开zlib转换器.app,把需要解压缩的后缀为.zlib的文件拖进窗口里,按下CONVERT按钮,就会在当前的目录下生成去掉了.zlib后缀的可以编辑的.xml文件了.相应地,当你编辑好了的.xml文件,拖进窗口里,按下CONVERT按钮,会在当前目录下生成.zlib后缀的文件了.

使用工具PlistEdit Pro.app打开Platforms56.xml,依次打开PathMap->0->0->0,这里的NodeID就是节点id.为便于理解,我将Mic Int的路径做了说明,如下图显示:
Platforms_edit2

如何新建一个注入id

为什么要建立一个全新的layout-id呢?很多时候,我们其实仿冒声卡驱动,只是为了让自己的声卡驱动正常,而通常的做法是找出一个存在的ID,然后整理数据,修改路径和ConfigData,最后编译使用.

那如果AppleALC的维护者vit9696更新了源代码怎么办呢?你总不能再重复做一遍驱动吧?或者说你好不容易找人帮你做好了一个驱动程序,然后AppleALc就升级了,旧的驱动无法用到新的系统当中,这个时候你的选择是什么?继续找人帮你做驱动?或者自己动手仿冒?

其实最好的方法是:如果你的声卡不存在于AppleALC支持的Codecs列表中,或者其中的某个注入id并不会很好地工作,那么你就需要新建一个注入id编译使用,测试无误后,你甚至还可以将这些修改提交给vit9696,他会将这些更新合并到AppleALC的源代码中,这样以后再有更新你只需要下载个AppleALC的发行版直接使用就好了.
ALC298_ID99_ALC295_ID13

上图中,是我给小米Pro制作的全新的ALC298注入ID:99,只要是小米Pro的机型,可以直接注入id:99来驱动你的声卡.

如果你想制作属于你的专属声卡注入ID,可添加文章最后的QQ群,进入群内一起讨论.

编译AppleALC

使用xcode
通过lilu联合编译

注入id

测试

检查AppleALC是否正确加载

打开终端,输入命令:

1
kextstat | grep AppleALC

显示内容如下:

1
2
3
4
kextstat | grep AppleALC
36 0 0xffffff7f8331b000 0xb0000 0xb0000
as.vit9696.AppleALC (1.2.1)
7CDA2635-8BE4-36E1-B882-8CA3B90284F3 <35 7 5 4 3 2 1>

我们可以看到AppleALC驱动已经被正确加载,版本是1.2.1,如果没有内容输出,那么就有可能没有加载.通常这种情况是因为Lilu的版本引起的,可以尝试使用Lilu Debug版本.

检查注入id是否正确

打开终端,输入命令:

1
ioreg -l | grep layout-id

显示内容如下:

1
2
3
4
5
6
7
8
~ % ioreg -l | grep layout-id
| | | | "layout-id" = <38000000>
| | | | | "IOAudioEngineDeviceDescription" = {
"num-internal-mics"=1,
"driver digital input gain"=0,
"layout-id"=56,
"post-processing input gain"=25,
"VP-pregain"=25}

为了便于讲解,我将内容做了换行处理.
其中的"layout-id"=56就是指注入id是 56 ,而<38000000>56的16进制

检查PinConfigurations

使用IORegistryExplorer.app,找到HDEF@1F,3,右侧的PinConfigurations就是最终的四个节点的数值,同时我们发现其它的节点已经不存在了,这样的结果正是我们需要的.
ioreg_pinconfigurations

其它问题

解决耳机切换/睡眠唤醒/去除底噪等常见问题

经常会有群友在使用AppleALC声卡仿冒驱动程序驱动了声卡后,出现最多的问题就是外放正常,耳机不正常,具体表现为:耳机在插入一半的时候有声音,完全插入后却没有声音的现象;另一种最常见的现象是开机声音正常,睡眠唤醒后无声/出现杂音/有电流声(底噪)/单声道/只有伴奏音,没有人声等等的问题.

本节教程就让我们来一起解决这些常见问题,还你一个干净的,没有杂音的声卡驱动.

在我们着手解决这些问题之前,需要先说说这些问题是如何产生的:

让我们打开电脑,进入MacOS系统后,AppleALC仿冒驱动会成功加载AppleHDA以驱动你的声卡,这个时候声卡通常工作都是正常的.为了证明AppleALC加载后的有效节点的状态,我们需要使用两个工具widget_dump.shnode_dump.sh,使用方法:打开终端,输入命令:

1
widget_dump.sh

显示的输出信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
sky@skys-MacBookPro  ~  widget_dump.sh
Pin Widget Control
nid = 0x02 --> result 0x00000000
nid = 0x03 --> result 0x00000000
nid = 0x04 --> result 0x00000000
nid = 0x05 --> result 0x00000000
nid = 0x06 --> result 0x00000000
nid = 0x07 --> result 0x00000000
nid = 0x08 --> result 0x00000000
nid = 0x09 --> result 0x00000000
nid = 0x0a --> result 0x00000000
nid = 0x0b --> result 0x00000000
nid = 0x0c --> result 0x00000000
nid = 0x0d --> result 0x00000000
nid = 0x0e --> result 0x00000000
nid = 0x0f --> result 0x00000000
nid = 0x10 --> result 0x00000000
nid = 0x11 --> result 0x00000000
nid = 0x12 --> result 0x00000020 # 内置麦克风
nid = 0x13 --> result 0x00000000
nid = 0x14 --> result 0x00000040 # 喇叭
nid = 0x15 --> result 0x00000000
nid = 0x16 --> result 0x00000000
nid = 0x17 --> result 0x00000000
nid = 0x18 --> result 0x00000000
nid = 0x19 --> result 0x00000000 # 耳麦
nid = 0x1a --> result 0x00000000
nid = 0x1b --> result 0x00000000
nid = 0x1c --> result 0x00000000
nid = 0x1d --> result 0x00000000
nid = 0x1e --> result 0x00000000
nid = 0x1f --> result 0x00000000
nid = 0x20 --> result 0x00000000
nid = 0x21 --> result 0x00000000 # 耳机
nid = 0x22 --> result 0x00000000
nid = 0x23 --> result 0x00000000
nid = 0x24 --> result 0x00000000

我们可以看到,刚开机没有插入耳机的情况下,只有外放的喇叭和内置的麦克风是工作的,其它所有的节点的数据都是空白的.

当我们插入耳机后,再输入命令:

1
widget_dump.sh

显示的输出信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
sky@skys-MacBookPro  ~  widget_dump.sh
Pin Widget Control
nid = 0x02 --> result 0x00000000
nid = 0x03 --> result 0x00000000
nid = 0x04 --> result 0x00000000
nid = 0x05 --> result 0x00000000
nid = 0x06 --> result 0x00000000
nid = 0x07 --> result 0x00000000
nid = 0x08 --> result 0x00000000
nid = 0x09 --> result 0x00000000
nid = 0x0a --> result 0x00000000
nid = 0x0b --> result 0x00000000
nid = 0x0c --> result 0x00000000
nid = 0x0d --> result 0x00000000
nid = 0x0e --> result 0x00000000
nid = 0x0f --> result 0x00000000
nid = 0x10 --> result 0x00000000
nid = 0x11 --> result 0x00000000
nid = 0x12 --> result 0x00000000 # 内置麦克风
nid = 0x13 --> result 0x00000000
nid = 0x14 --> result 0x00000000 # 喇叭
nid = 0x15 --> result 0x00000000
nid = 0x16 --> result 0x00000000
nid = 0x17 --> result 0x00000000
nid = 0x18 --> result 0x00000000
nid = 0x19 --> result 0x00000020 # 耳麦
nid = 0x1a --> result 0x00000000
nid = 0x1b --> result 0x00000000
nid = 0x1c --> result 0x00000000
nid = 0x1d --> result 0x00000000
nid = 0x1e --> result 0x00000000
nid = 0x1f --> result 0x00000000
nid = 0x20 --> result 0x00000000
nid = 0x21 --> result 0x000000c0 # 耳机
nid = 0x22 --> result 0x00000000
nid = 0x23 --> result 0x00000000
nid = 0x24 --> result 0x00000000

这时我们会发现,之前工作的喇叭和内置麦克风的数据已经发生了变化

节点名称外放状态耳机状态
0x12内置麦克风(Mic Int)0x000000200x00000000
0x14喇叭(Speaker Out)0x000000400x00000000
0x19耳麦(Mic Ext/Line In)0x000000000x00000020
0x21耳机(HP Out)0x000000000x000000c0

通过上面的表格,我们可以发现内部设备和外部设备正常工作的情况下会自动切换.

widget_dump.sh是调用hda-verb这个外部命令执行的,hda-verb依赖于CodecCommander,所以请确认你已经加载了CodecCommander

CodecCommander 编解码器指挥官

CodecCommander用于更新在扬声器或耳机节点上使用给定放大器的HDA(高清晰度音频)编解码器上的EAPD(外部放大器)状态(两者,甚至在某些情况下甚至是额外的)。 在OSX中,EAPD在休眠状态下关闭,因此唤醒机器后音频仍然不起作用。

通常情况下,这个外部放大器出现在笔记本电脑和ITX板上,在使用ALC269,ALC665和类似编解码器的机器上最常见。 当机器进入睡眠状态时,功放处于关机状态,在唤醒之后,即使音频正常工作,扬声器/耳机仍然没有声音,因为功放需要发送一个编解码器命令才能启动。

最典型的两条命令是:

1
2
0x19 SET_PIN_WIDGET_CONTROL 0x24
0x21 SET_UNSOLICITED_ENABLE 0x82

其中:SET_PIN_WIDGET_CONTROL是作用于Mic Ext节点,SET_UNSOLICITED_ENABLE是作用于HP Out节点

Pin-ctls

Pin Widget Control

关于Pin Widget Control的描述请参阅英特尔HDA规范 7.3.3.13

Enable VRef

Verb IDPayload (8 Bits)Response (32 Bits)
GetF07h0Bits 31:8 are 0
Bits 7:0 are PinCntl
Set707hBits 7:0 are PinCntl0

PinCntl定义:

7654:321:0
H-Phn EnableOut EnableIn EnableRsvdVrefEn[2]VRefEn[1:0]/EPT

VRefEn 值:

VRefEn EncodingVREF Signal Level
000bHi-Z
001b50%
010bGround (0 V)
011bReserved
100b80%
101b100%
110b-111bReserved

SET_PIN_WIDGET_CONTROL:

7654 3210
ALC256
0x1970724->0010 0100->In Enable,VrefEn 80%
0x21707C0->1100 0000->Headphone Enable,Out Enable

SET_PIN_WIDGET_CONTROL命令最终格式为:

Address+NodeID+707+Pin-ctls

最终的命令为:01970724

关于这部分的讨论请参阅Any fix to the Garbled/Distorted Headphone issue?

原引:

RehabMan对于VrefEn和EPT的部分讨论内容:

我也尝试了节点0x19的0x20。 这也工作。 所以不知道在我的情况下是否需要VrefEn或EPT。 但是他们与巫毒有关,所以我使用了这个价值。我没有看过Voodoo是否明确地设置了这些值,或者是复位后的状态结果。

我认为我的设置0xC0到0x21也是没有必要的(仍在试验)。 节点0x19不在任何路径图上,所以我对于如何知道节点需要调整有些困惑。 尽管它在Linux转储中有连接到路径图上的其他节点。 进一步造成神秘,它被描述为Linux转储中的外部麦克风插孔。 为什么麦克风上的控件配置会影响耳机,这是一个谜。

还要注意,VrefEn和EPT之间有一些奇怪的重叠,这在规范中是不清楚的(它们似乎都使用相同的位)。 例如,将VRefEn设置为001b或010b(50%/地面)将设置标记为“保留”的EPT编码01b / 10b。 它确实说EPT是特定于“关联的数字Pin Widget”,所以也许这个重叠解释了VrefEn不适用于这样的小部件。 它还指出VRefEn的有效值取决于PinCaps,所以推测数字Pin小部件的PinCap不包含任何有效的VRefEn值。

如果你沿着这条路走下去,你应该计划阅读大量的东西,让整个过程神秘化。

Unsolicited Response 未经请求的响应

Unsolicited

关于Unsolicited Response的描述请参阅英特尔HDA规范 7.3.3.14

非请求响应控件确定节点是否被允许发送主动提供的响应,以及该标签将用于响应。此控制仅适用于支持主动响应的节点,如Function Group Type参数(第7.3.4.4节)和Audio Widget Capabilities参数(第7.3.4.6节)中所声明的。在获取或设置此控件之前,应该查询节点以确定它是否支持未经请求的响应。

Connection Select Control连接选择控制:

Verb IDPayload (8 Bits)Response (32 Bits)
GetF08h0Bits 31:8 are 0
EnableUnsol is bits 7:0
Set708hEnableUnsol is bits 7:00

EnableUnsol 格式:

765:0
Enable0Tag

设定值是8bits的一个数。记作a7 a6 a5 a4 a3 a2 a1 a0.
a7=1,表示enabled。
a6=0,没具体应用,不用管。
a5-a0,存放tag,需要将tag的值用6为数的二进制值表示
tag=1(十进制)=000001(二进制)
则a7 a6 a5 a4 a3 a2 a1 a0=10000001
a7 a6 a5 a4=1000(二进制)=8(十进制)
a3 a2 a1 a0=0001(二进制)=1(十进制)
则设定值=81
最后加得到的设定值加1,即82

SET_UNSOLICITED_ENABLE命令最终格式为:

Address+NodeID+708+Unsolicited

最终的命令为:

02170882

目前CodecCommander所起的作用有限,我基本上都忽略了CodecCommander的存在,因为它并不能从根本上解决这些问题.在我完善我的ALC256声卡驱动期间,我还试用过EAPDFix,最后都不得不放弃治疗.直到我遇到了ALCPlugFix,它能解决几乎所有的耳机切换问题.

ALCPlugFix能做什么?

  • 它可以解决耳机插拔状态的切换
  • 它是通过使用命令:hda-verb 0xNode SET_PIN_WIDGET_CONTROL 0xVerbs的方式进行状态切换
    • hda-verb的由来
    • hda-verb是linux下面的alsa-project的一条命令,它的作用是发送HD-audio命令

ALCPlugFix如何使用?

  • ALCPlugFix同步到本地

    1
    git clone https://github.com/daliansky/ALCPlugFix
  • 打开ALCPlugFix目录下面的main.m,将包含hda-verb语句的几行修改成如图所示
    ALCPlugFix_ALC256

  • 其中0x12Mic Int节点,0x19Mic Ext节点,之所以要这么修改,是因为我的ALC2560x19节点总是无法工作,在插入耳机的时候我希望内置的Mic Int可以工作的同时还可以使用耳机.
  • XCODE编译生成的ALCPlugFix文件复制到alc_fix目录,然后双击install双击自动安装.command,输入用户密码即可.

ALCPlugFix工具下载

刚才我前面讲了,ALCPlugFix是依赖于CodecCommander执行的,那我为什么不介绍下CodecCommander的工作原理呢,其实说白了CodecCommander里面通常执行的也是hda-verb 0x19 0x707 0x20之类的语句,只是在睡醒唤醒后CodecCommander已经无法执行hda-verb 0x19 0x707 0x20这样的语句了,而ALCPlugFix却是以守护进程的方式存在于系统中,无论什么时候它都会监听声卡的状态,该切换时它就会发出命令切换,这样就保证了声卡总是可以工作在正确的状态下.

基本上所有的耳机睡眠后没有声音的,只需要使用一条命令:hda-verb 0x19 0x707 0x20,就可以让你的耳机出声的.当然前提是你得先加载了CodecCommander这个驱动.估计我写完这段你们看完了还是一头雾水,我教大家一个简单的记法:ALCPlugFix作用于耳机,所以你需要知道自己的两个耳机节点,而0x19是耳麦的麦克风输入节点,只要找对了耳麦的节点,一条命令就可以搞定你的耳机切换.

杂音和底噪的去除

在着手解决这个问题之前,让我们先来搞清楚杂音和底噪产生的原因.

打开终端,输入命令:

1
node_dump.sh

它会输出很多的信息出来,我们只需要最后面的这组数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Configuration Default
nid = 0x02 --> result 0x00000000
nid = 0x03 --> result 0x00000000
nid = 0x04 --> result 0x00000000
nid = 0x05 --> result 0x00000000
nid = 0x06 --> result 0x00000000
nid = 0x07 --> result 0x00000000
nid = 0x08 --> result 0x00000000
nid = 0x09 --> result 0x00000000
nid = 0x0a --> result 0x00000000
nid = 0x0b --> result 0x00000000
nid = 0x0c --> result 0x00000000
nid = 0x0d --> result 0x00000000
nid = 0x0e --> result 0x00000000
nid = 0x0f --> result 0x00000000
nid = 0x10 --> result 0x00000000
nid = 0x11 --> result 0x00000000
nid = 0x12 --> result 0x90a60170 # 内置麦克风
nid = 0x13 --> result 0x400000f0
nid = 0x14 --> result 0x90170140 # 喇叭
nid = 0x15 --> result 0x00000000
nid = 0x16 --> result 0x00000000
nid = 0x17 --> result 0x00000000
nid = 0x18 --> result 0x400000f0
nid = 0x19 --> result 0x02ab1070 # 耳麦
nid = 0x1a --> result 0x400000f0
nid = 0x1b --> result 0x400000f0
nid = 0x1c --> result 0x00000000
nid = 0x1d --> result 0x400000f0
nid = 0x1e --> result 0x400000f0
nid = 0x1f --> result 0x00000000
nid = 0x20 --> result 0x00000000
nid = 0x21 --> result 0x022b1030 # 耳机
nid = 0x22 --> result 0x00000000
nid = 0x23 --> result 0x00000000
nid = 0x24 --> result 0x00000000

这些数据里:0x00000000是无效的节点,0x400000f0是被屏蔽掉的节点.其它的四个有效的节点我做了备注,方便你们看清楚.这些PinConfigurations决定了你的声卡音质.如果你的命令输出信息里面除了有效节点和0x400000f0之外的其它任何格式的数据都会产生杂音和底噪.比如0x40000000或者0x411111f0,这些无效的节点就会一直在起作用,这就好比一个流行乐队里,需要一个架子鼓,一台电钢琴,两个吉他手,再加上一个歌手,如果你生硬地再加进一把小提琴,再弄个竖琴,就会不和谐,就会产生噪音.

再让我们搬出widget_dump.sh命令:

1
widget_dump.sh

输出信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Pin Widget Control
nid = 0x02 --> result 0x00000000
nid = 0x03 --> result 0x00000000
nid = 0x04 --> result 0x00000000
nid = 0x05 --> result 0x00000000
nid = 0x06 --> result 0x00000000
nid = 0x07 --> result 0x00000000
nid = 0x08 --> result 0x00000000
nid = 0x09 --> result 0x00000000
nid = 0x0a --> result 0x00000000
nid = 0x0b --> result 0x00000000
nid = 0x0c --> result 0x00000000
nid = 0x0d --> result 0x00000000
nid = 0x0e --> result 0x00000000
nid = 0x0f --> result 0x00000000
nid = 0x10 --> result 0x00000000
nid = 0x11 --> result 0x00000000
nid = 0x12 --> result 0x00000000 # 内置麦克风
nid = 0x13 --> result 0x00000000
nid = 0x14 --> result 0x00000000 # 喇叭
nid = 0x15 --> result 0x00000000
nid = 0x16 --> result 0x00000000
nid = 0x17 --> result 0x00000000
nid = 0x18 --> result 0x00000000
nid = 0x19 --> result 0x00000020 # 耳麦
nid = 0x1a --> result 0x00000020 # 无效节点
nid = 0x1b --> result 0x00000000
nid = 0x1c --> result 0x00000000
nid = 0x1d --> result 0x00000020 # 无效节点
nid = 0x1e --> result 0x00000000
nid = 0x1f --> result 0x00000000
nid = 0x20 --> result 0x00000000
nid = 0x21 --> result 0x000000c0 # 耳机
nid = 0x22 --> result 0x00000000
nid = 0x23 --> result 0x00000000
nid = 0x24 --> result 0x00000000

我故意在四个有效的节点之外添加了两个无效的节点,为了让大家看清楚一些,这些无效的节点就会工作,它会产生底噪,尤其是戴上耳机,关闭音源,就会听到沙沙沙的声音,也有人说它是电流声,严重时还会产生杂音,包括单声道输出等等.

既然我们知道了问题是如何产生的,那么就让我们来消除这些杂音,还原干净的声音.

让我们回到整理ConfigData这一章,将有效节点之外的其它节点全部使用f0 00 00 40进行屏蔽.

声卡驱动了,音量调节的图标也显示正常,就是不发声怎么办

如果您的声卡使用了AppleALC,也注入了正确的ID后不发声怎么办呢?这个问题就出现在有效节点和路径不正确上面.
所谓条条大路通罗马,我们总不能在同一棵树上吊死吧.现在可以请出VoodooHDA[教程]万能声卡驱动程序下载链接了,说它万能是不正确的,如果它万能了估计就没AppleALC啥事儿了吧.

VoodooHDA Clover版安装教程

你需要有现成的Clover,它只会安装VoodooHDA和其他必需的组件来正常运行。

方法一:通过Clover UEFI/ESP驱动

请点击下载:VoodooHDA 2.9.0 Clover-V12.dmg
这个安装程序会自动安装到/ESP/EFI/CLOVER/kexts/以及下面的目录里10.14/10.13/10.12/10.11/10.10/10.9/10.8/10.7/10.6
安装目录取决于你安装的macOS系统决定.
这个驱动将通过Clover加载而不需要安装到/System/Library/Extensions/,同时它也不会删除系统自带的AppleHDA.kext,您甚至无需备份`/Others/AppleALC.kext`

方法二:Clover传统模式

你也可以安装VoodooHDA.kext内核扩展程序到/EFI/Clover/kexts/10.14/10.1310.12/10.11/10.10/10.9/10.8/10.7/10.6
这个驱动将通过Clover加载.

方法三: 经典方法

您也可以选择10.6到10.12的Clasic方法,这将在系统库扩展上安装VoodooHDA.kext + AppleHDADisabler.kext

这将在应用程序上安装VoodooHdaSettingsLoader.app,在Library / PreferencePanes上安装VoodooHDA.prefPane
在这两种方法中,在usr/local/bin/getdump上安装getdump。

注意:对于所有OS X系统,VoodooHDA.prefPane安装在Library / PreferancesPanes中

视频教程请点击下方

1

[Modular Image Creation

getdump用法

这里可以借助VoodooHDA自带的应用程序:getdump,使用方法:打开终端,输入命令:

1
2
3
sudo cp ~/Downloads/getdump /usr/local/bin  # 将getdump命令复制到/usr/local/bin目录下
sudo chmod +x /usr/local/bin/getdump # 为getdump添加执行权限
getdump > ~/Desktop/voodoo_dump.txt

用它可以生成一份voodoo_dump.txt的文件,里面会有两段以DUMPING Playback/Record Paths开头的文字描述,这里面即包括了有效节点,同时也包括了有效的路径
path1
path2
从上面的两张截图中,可以将有效的节点和路径整理出下面的表格:

有效节点10进制设备名称路径
0x1420Speaker out20->12->2
0x2133HP out33->13->3
0x1925Headset Mic in8->35->24 8->35->29备用
0x1218Internal Mic in9->34->18 9->34->29备用

有了这个表格,再结合configdata,找出有效的ID,编译AppleALC,注入ID并使用声卡驱动.

如果还不出声怎么办?

试试打开终端,输入这两条命令:

1
2
sudo kextunload /System/Library/Extensions/AppleHDA.kext
sudo kextload /System/Library/Extensions/AppleHDA.kext

这两条命令是重新加载AppleHDA驱动

HDA工具下载及使用

制作声卡仿冒需要用到的工具,我已经同步到仓库,您可以打包下载也可以通过git同步到本地

  • 下载链接:https://github.com/daliansky/dell7000/tree/master/hda-tools
  • 如何安装

    • hda-tools目录下的所有文件复制到/usr/local/bin下,如果/usr/local/bin目录不存在,需要新建立,命令如下:

      1
      2
      sudo mkdir /usr/local/bin   # 建立/usr/local/bin子目录
      sudo cp ~/Downloads/hda-tools/* /usr/local/bin # 将hda-tools目录下所有的应用程序复制到/usr/local/bin目录下
  • 如何使用

    • 打开终端,输入命令,直接执行.例如:
      1
      2
      3
      4
      verbit.sh codec#0 > codec_dump.txt    # 有效节点格式化
      codecgraph codec#0 # 自动生成pathmap图,文件位于codec#0相同目录下
      hda-verb 0x19 0x707 0x20 # 耳机睡眠唤醒无声修正
      widget_dump.sh # 读取SET_PIN_WIDGET_CONTROL数值

关于打赏

您的支持就是我更新的动力!
如果不希望看到博主停更的话,请点击下方的 打赏 支持一下,有钱的捧个钱场,没钱的捧个人场,谢谢大家!

QQ群列表:

688324116 一起黑苹果 2000人群
331686786 一起吃苹果 500人群
257995340 一起啃苹果 500人群
891434070 Mojave黑苹果交流群 500人群
939122730 Mojave黑苹果交流II群 500人群
891677227 黑果小兵高级群 500人群

-------------本文结束感谢您的阅读-------------
请站长喝杯咖啡吧 ´◡`
0%