hexo-start
摘要内容……
摘要内容……
经常刷 LeetCode 的读者肯定知道鼎鼎有名的 twoSum 问题,我们的旧文 Two Sum 问题的核心思想 对 twoSum 的几个变种做了解析。
但是除了 twoSum 问题,LeetCode 上面还有 3Sum,4Sum 问题,我估计以后出个 5Sum,6Sum 也不是不可能。
那么,对于这种问题有没有什么好办法用套路解决呢?本文就由浅入深,层层推进,用一个函数来解决所有 nSum 类型的问题。
[leetcode1](1. 两数之和 - 力扣(LeetCode) (leetcode-cn.com))
力扣上的 twoSum 问题,题目要求返回的是索引,这里我来编一道 twoSum 题目,不要返回索引,返回元素的值:
如果假设输入一个数组 nums 和一个目标和 target,请你返回 nums 中能够凑出 target 的两个元素的值,比如输入 nums = [5,3,1,6], target = 9,那么算法返回两个元素 [3,6]。可以假设只有且仅有一对儿元素可以凑出 target。
我们可以先对 nums 排序,然后利用前文「双指针技巧汇总」写过的左右双指针技巧,从两端相向而行就行了:
1 | vector<int> twoSum(vector<int>& nums, int target) { |
这样就可以解决这个问题,不过我们要继续魔改题目,把这个题目变得更泛化,更困难一点:
nums 中可能有多对儿元素之和都等于 target,请你的算法返回所有和为 target 的元素对儿,其中不能出现重复。
函数签名如下:
1 | vector<vector<int>> twoSumTarget(vector<int>& nums, int target); |
比如说输入为 nums = [1,3,1,2,2,3], target = 4,那么算法返回的结果就是:[[1,3],[2,2]]。
对于修改后的问题,关键难点是现在可能有多个和为 target 的数对儿,还不能重复,比如上述例子中 [1,3] 和 [3,1] 就算重复,只能算一次。
首先,基本思路肯定还是排序加双指针:
1 | vector<vector<int>> twoSumTarget(vector<int>& nums, int target { |
但是,这样实现会造成重复的结果,比如说 nums = [1,1,1,2,2,3,3], target = 4,得到的结果中 [1,3] 肯定会重复。
出问题的地方在于 sum == target 条件的 if 分支,当给 res 加入一次结果后,lo 和 hi 不应该改变 1 的同时,还应该跳过所有重复的元素:

1 | while (lo < hi) { |
这样就可以保证一个答案只被添加一次,重复的结果都会被跳过,可以得到正确的答案。不过,受这个思路的启发,其实前两个 if 分支也是可以做一点效率优化,跳过相同的元素:
1 | vector<vector<int>> twoSumTarget(vector<int>& nums, int target) { |
这样,一个通用化的 twoSum 函数就写出来了,请确保你理解了该算法的逻辑,我们后面解决 3Sum 和 4Sum 的时候会复用这个函数。
这个函数的时间复杂度非常容易看出来,双指针操作的部分虽然有那么多 while 循环,但是时间复杂度还是 O(N),而排序的时间复杂度是 O(NlogN),所以这个函数的时间复杂度是 O(NlogN)。
这是力扣第 15 题「三数之和」:

题目就是让我们找 nums 中和为 0 的三个元素,返回所有可能的三元组(triple),函数签名如下:
1 | vector<vector<int>> threeSum(vector<int>& nums); |
这样,我们再泛化一下题目,不要光和为 0 的三元组了,计算和为 target 的三元组吧,同上面的 twoSum 一样,也不允许重复的结果:
1 | vector<vector<int>> threeSum(vector<int>& nums) { |
这个问题怎么解决呢?很简单,穷举呗。现在我们想找和为 target 的三个数字,那么对于第一个数字,可能是什么?nums 中的每一个元素 nums[i] 都有可能!
那么,确定了第一个数字之后,剩下的两个数字可以是什么呢?其实就是和为 target - nums[i] 的两个数字呗,那不就是 twoSum 函数解决的问题么🤔
可以直接写代码了,需要把 twoSum 函数稍作修改即可复用:
1 | /* 从 nums[start] 开始,计算有序数组 |
需要注意的是,类似 twoSum,3Sum 的结果也可能重复,比如输入是 nums = [1,1,1,2,3], target = 6,结果就会重复。
关键点在于,不能让第一个数重复,至于后面的两个数,我们复用的 twoSum 函数会保证它们不重复。所以代码中必须用一个 while 循环来保证 3Sum 中第一个元素不重复。
至此,3Sum 问题就解决了,时间复杂度不难算,排序的复杂度为 O(NlogN),twoSumTarget 函数中的双指针操作为 O(N),threeSumTarget 函数在 for 循环中调用 twoSumTarget 所以总的时间复杂度就是 O(NlogN + N^2) = O(N^2)。
这是力扣第 18 题「四数之和」:

函数签名如下:
1 | vector<vector<int>> fourSum(vector<int>& nums, int target); |
都到这份上了,4Sum 完全就可以用相同的思路:穷举第一个数字,然后调用 3Sum 函数计算剩下三个数,最后组合出和为 target 的四元组。
1 | vector<vector<int>> fourSum(vector<int>& nums, int target) { |
这样,按照相同的套路,4Sum 问题就解决了,时间复杂度的分析和之前类似,for 循环中调用了 threeSumTarget 函数,所以总的时间复杂度就是 O(N^3)。
在 LeetCode 上,4Sum 就到头了,但是回想刚才写 3Sum 和 4Sum 的过程,实际上是遵循相同的模式的。我相信你只要稍微修改一下 4Sum 的函数就可以复用并解决 5Sum 问题,然后解决 6Sum 问题……
那么,如果我让你求 100Sum 问题,怎么办呢?其实我们可以观察上面这些解法,统一出一个 nSum 函数:
1 | /* 注意:调用这个函数之前一定要先给 nums 排序 */ |
嗯,看起来很长,实际上就是把之前的题目解法合并起来了,n == 2 时是 twoSum 的双指针解法,n > 2 时就是穷举第一个数字,然后递归调用计算 (n-1)Sum,组装答案。
需要注意的是,调用这个 nSum 函数之前一定要先给 nums 数组排序,因为 nSum 是一个递归函数,如果在 nSum 函数里调用排序函数,那么每次递归都会进行没有必要的排序,效率会非常低。
比如说现在我们写 LeetCode 上的 4Sum 问题:
1 | vector<vector<int>> fourSum(vector<int>& nums, int target) { |
再比如 LeetCode 的 3Sum 问题,找 target == 0 的三元组:
1 | vector<vector<int>> threeSum(vector<int>& nums) { |
那么,如果让你计算 100Sum 问题,直接调用这个函数就完事儿了。
gg: 跳转到文件第一行。G(Shift+g) : 跳转到文件最后一行。nG(如10G) : 跳转到第n行。:n(如:10+ 回车) : 跳转到第𝑛行。H/ M/L : 跳转到当前屏幕的最高行(High)、中间行(Middle)、最低行(Low)。0(数字零) : 跳转到当前行行首。^(Shift+6) : 跳转到当前行第一个非空字符。$(Shift+4) : 跳转到当前行行尾。Ctrl+o: 返回到跳转前的位置。%: 跳转到与之匹配的括号行https://makifx.com/boutique-software)
本人自建 音乐服(音海拾贝)| 有声书服(悦耳声阅)
通知频道:https://t.me/yinhai_notify
【悦耳声阅】有声书分享频道:https://t.me/YueErFM
DS Cloud
https://apps.apple.com/app/id6476057278
维克音乐
https://apps.apple.com/us/app/offline-music-player-wake/id6544783918?platform=iphone
LMP
https://apps.apple.com/us/app/lmp-a-better-music-player/id6451009326
音流
https://github.com/gitbobobo/StreamMusic
Cinetry
https://github.com/gstory0404/Cinetry
LMP 音乐{TF}
https://testflight.apple.com/join/H0qG853j
DS Cloud
https://apps.apple.com/app/id6476057278
维克音乐
https://apps.apple.com/us/app/offline-music-player-wake/id6544783918?platform=iphone
FeiShin
https://github.com/jeffvli/feishin
Pure Music (棉花音乐)
https://github.com/pure-music/PureMusic/releases
Cinetry
https://github.com/gstory0404/Cinetry
DS Cloud
https://apps.apple.com/app/id6476057278
维克音乐
https://apps.apple.com/us/app/offline-music-player-wake/id6544783918?platform=iphone
LMP
https://apps.apple.com/us/app/lmp-a-better-music-player/id6451009326
FeiShin
https://github.com/jeffvli/feishin
音流
https://github.com/gitbobobo/StreamMusic
Pure Music (棉花音乐)
https://github.com/pure-music/PureMusic/releases
Cinetry
https://github.com/gstory0404/Cinetry
DS One(DS Cloud)
https://play.google.com/store/apps/details?id=com.cz.player.dsone
音流
https://github.com/gitbobobo/StreamMusic
tempus
https://github.com/eddyizm/tempus
tempo
https://github.com/CappielloAntonio/tempo/releases
Cinetry
https://github.com/gstory0404/Cinetry
Symfonium
Pure Music (棉花音乐)
https://github.com/pure-music/PureMusic/releases
Musicfree(需配合插件使用)
https://github.com/CTZZG/MusicFree/releases 插件地址:
1 | https://gitee.com/Rrance/WP/raw/master/音海拾贝.js |
音流
https://github.com/gitbobobo/StreamMusic
Symfonium
Pure Music (棉花音乐)
https://github.com/pure-music/PureMusic/releases
FeiShin
https://github.com/jeffvli/feishin
Pure Music (棉花音乐)
https://github.com/pure-music/PureMusic/releases
Cinetry
https://github.com/gstory0404/Cinetry
Audiobookshelf:
https://testflight.apple.com/join/wiic7QIW
Tonspur:
https://testflight.apple.com/join/E92V6bRM
Prologue:
https://testflight.apple.com/join/zTWS6ahB
Cinetry
https://github.com/gstory0404/Cinetry
AudioBooth:
https://testflight.apple.com/join/cAG6dVeN
dscloud:
https://apps.apple.com/app/id6476057278
SoundLeaf:
https://github.com/SoundLeaf/SoundLeafApp
ShelfPlayer:
https://apps.apple.com/us/app/shelfplayer/id6475221163
audiobookshelf:
https://play.google.com/store/apps/details?id=com.audiobookshelf.app
DS One(DS Cloud)
https://play.google.com/store/apps/details?id=com.cz.player.dsone
Cinetry
https://github.com/gstory0404/Cinetry
Lissen:
https://github.com/GrakovNe/lissen-android
LitLyric:
https://github.com/shane9b3/LitLyric---Beta
Kitzi:
https://github.com/bennybar/kitzi_abs_player
Buchable:
https://github.com/Vito0912/abs_flutter
musicfree(需配合插件使用):
https://github.com/CTZZG/MusicFreeDesktop-1/releases
插件地址:
1 | https://gitee.com/Rrance/WP/raw/master/audiobookshelf.js |
Cinetry
https://github.com/gstory0404/Cinetry
Buchable:
https://github.com/Vito0912/abs_flutter
Cinetry
准备一个U盘,安装包一般大小都在12G以上,所以建议至少16G,或者直接使用移动硬盘。
插入U盘,打开Mac的磁盘工具
选择U盘-抹掉
名称:随意
格式:格式Mac OS扩展(日志式)
方案:GUID分区图

抹掉完成之后,再对U盘进行分区用于制作Mac OS安装盘,点击+号,增加新的分区
分区信息:
名称:UOS
格式:Mac OS扩展(日志式)
大小:必须大于你的安装包,我这里直接分了16G
新增分区之后,就可以准备制作Mac OS安装盘了。
下载好的Mac OS安装包默认放在应用程序中按照一下方式进行安装盘制作:
sudo”(无引号)createinstallmedia”到终端(文件位置在“安装macOS Ventura.app”-右键-显示包文件-Contents-Resources里)--volume”(无引号)--nointeraction”(无引号)以上步骤综合为这么一串代码,请根据自己系统版本和U盘名字对应修改:
1 | sudo /Applications/Install\ macOS\ Ventura.app/Contents/Resources/createinstallmedia --volume /Volumes/UOS --nointeraction |
整个制作过程如下,到最后显示出这个就表示安装盘制作完成。
1 | sudo /Applications/Install\ macOS\ Ventura.app/Contents/Resources/createinstallmedia --volume /Volumes/Install\ macOS\ Ventura --nointeraction |
到这里,如果你的引导没有屏蔽多余的启动项,在启动中已经可以看到这个安装盘了,选择既可以使用。
安装盘制作完成之后,为了可以以后将U盘作为启动盘从BIOS的启动界面启动安装盘,就需要将自己配置好的引导文件EFI文件放到EFI分区中。
使用工具挂载EFI分区,比如用OpenCore Configurator 或者Hackintool 或者 OCAuxiliaryTools都可以,挂载U盘的EFI分区之后,将自己的配置好的EFI文件放进去,就成为了自己黑苹果的专用安装盘了。
那如果需要用于不同的机器来安装黑苹果,或者调试的时候修改EFI文件,总是需要挂载EFI分区,就比较麻烦了。
我们可以在引导分区之外,新建一个公开的引导分区。
打开磁盘工具,选择U盘,点分区,选择之前制作Mac OS安装盘剩下没有使用的部分,点+号,增加新的分区。
分区信息:
名称:MAC_EFI(随意,不能有中文)
格式:MS-DOS (FAT32)
大小:1G(引导文件很小,一般大于200M即可)

这个新建的引导分区同样也可以放黑苹果的EFI引导文件,而且是无需挂载的,适合频繁修改调试引导配置和更换文件。
按照上面的方式同样新增一个分区
分区信息:
名称:WINPE(随意,同样不能有中文)
格式:MS-DOS (FAT32)
大小:大于你的PE文件
新增分区完成之后,这里就需要一个支持UEFI启动的WinPE,一般PE主流格式都是exe格式,不符合我们的需要,所以需要在Window系统下先将PE制作成iso文件。
这里推荐老毛桃PE,功能比较多,可以联网,适合大多数PE需求。
然后在Mac下,打开iso文件,将里面的文件复制到新增的WINPE分区中。
这样,一个Mac OS的安装盘和PE盘二合一的U盘就制作好了,剩下还有多余空间,可以当做正常存储U盘使用。
先将远程内网主机的共享目录挂载到 Docker 宿主机的一个本地目录上,然后再将这个本地目录作为数据卷(Volume)或绑定挂载(Bind Mount)提供给 Docker 容器使用。
1 | [ 内网共享主机 (NAS/Samba Server) ] |
因为我的内网装有qBittorrent 的docker宿主机是基于ubuntu的服务器,所以推荐使用NFS。NFS 在 Linux 环境下性能好,开销低,是首选方案。如果docker宿主机是 Windows ,或启用了NAS的 Samba服务,这种方法更合适。
威联通依次打开控制台⇨权限⇨共享目录⇨创建⇨共享文件夹

填写共享目录名称pt,记住文件夹名称,之后会用到。然后手动输入共享文件夹的路径,点击创建。

威联通依次打开控制台⇨网络和文件服务⇨Win/Mac/NFS⇨NFS服务

激活NFS v4服务和启用manage-gids,关闭写入高速缓存。
PUID=1000, PGID=1000)对挂载目录的读写权限管理,避免出现 “Permission denied” 错误。创建完的共享文件夹,会在这里显示。点击图中按钮,编辑共享文件夹权限。

依次选择⇨选择权限类别:NFS主机访问⇨勾选访问权限⇨设置访问的IP地址或域名。

主机ip:192.168.60.0/24 是 CIDR(无类别域间路由) 的表示方法,它表示了一个包含256个IP地址的网络段,范围从192.168.60.0 到 192.168.60.255。。
Squash:选择读写。需要docker宿主机能够读写共享目录。
Squash选项:选择不Squash所有用户。
/mnt/nas/downloads1 | sudo mkdir /mnt/nas/downloads |
1 | sudo mount -t nfs4 -o rw,hard,intr,timeo=300,retrans=3 192.168.50.218:/pt /mnt/nas/downloads |
参数解释:
hard:在 NFS 服务器故障时,程序会一直等待直到服务器恢复,保证数据一致性。intr:允许用户中断正在等待的 NFS 操作。timeo=300:设置超时时间为十分之300秒(即30秒)。retrans=3:设置重传次数为3次。编辑 /etc/fstab文件,sudo vim /etc/fstab。
1 | # 在 /etc/fstab 末尾添加 |
注意:_netdev 选项非常重要,它告诉系统在网络就绪后再挂载。
整体含义
将位于 IP 地址为 192.168.50.218 的服务器上的共享目录 /pt,通过网络文件系统版本 4 挂载到本地目录 /mnt/nas/downloads。
参数解释:
该配置行由 6 个字段组成,字段间用空格或制表符分隔:
192.168.50.218:/pt192.168.50.218:NFS 服务器的 IP 地址。:/pt:服务器上被共享出来的目录路径。/mnt/nas/downloadsnfs4rw,hard,intr,timeo=300,retrans=3,_netdev,autorw:以读写模式挂载(而非只读 ro)。hard:硬挂载。如果服务器无响应,客户端会持续重试。这对于保证数据一致性非常重要,但可能导致进程在访问挂载点时卡住。intr:允许中断正在等待服务器响应的 I/O 操作。当使用 hard 挂载时,如果服务器宕机,可以用这个选项来终止被挂起的进程。timeo=300:设置超时时间为 300 十分之一秒(即 30 秒)。这是客户端等待服务器响应的时间。retrans=3:在放弃并返回错误之前,进行 3 次 重传。_netdev:这是一个非常重要的选项,它告诉系统这是一个网络设备。系统会等待网络就绪后再尝试挂载,避免系统启动时因网络未准备好而挂载失败。auto:使用 mount -a 命令(通常在系统启动时执行)时会自动挂载此文件系统。0dump 备份工具使用。0 表示不需要被 dump 备份。0fsck 磁盘检查工具使用。0 表示在启动时不需要检查此文件系统(因为它是网络文件系统,不在本地磁盘上)。1 | docker run -d \ |
qbittorrent默认端口8080,可在config目录里的qbittorrent.conf配置文件修改。
®
本文将在Ubuntu22.04服务器安装OpenVpn服务端,并在配置OpenVpn客户端ovpn文件。
Easy-RSA主要用来生成CA证书,服务端证书和key,客户端证书和key。先登录Ubuntu服务器,然后用root身份执行下文的命令。
1 | sudo apt update |
执行如下命令
1 | cd /usr/share/easy-rsa |
开始制作证书
1 | # 执行完这个命令,会在/usr/share/easy-rsa下多出个pki目录 |
拷贝配置文件
1 | cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf /etc/openvpn/ |
拷贝刚才创建的CA证书,服务端证书和key(私钥),客户端证书和key,以及创建tls的key
1 | cd /etc/openvpn/ |
编辑服务端配置文件server.conf,改成如下内容,安全起见我把默认端口1194,改成了11000:
1 | # vpn服务端口 |
启动vpn服务端
1 | systemctl start openvpn@server |
如果你的Ubuntu系统是云服务器,通常管理后台可以设置防火墙,建议在Ubuntu关闭ufw:
1 | # 停止ufw |
如果你搭建的VPN服务器所在的内网还有其他云服务器,你想访问其他云服务器就应该设置ip转发。就如上文描述的,我们在VPN服务端配置文件server.conf中配置了 push "route 192.168.0.0 255.255.255.224"。
打开内核ip转发:
1 | # 编辑文件/etc/sysctl.conf |
设置防火墙(iptables )转发规则:
1 | # 设置源地址翻译SNAT:把来自10.8.100.0/24的流量在离开网络接口ens3前,修改源ip为192.168.50.14 |
重启下vpn服务端:systemctl start openvpn@server。到这里,服务端安装完成。
在openvpn官网下载客户端:这里。下载好以后点击运行,进行安装。
1 | # 准备好Ubuntu上的这4个文件 |
打开终端,复制粘贴以下脚本指令,脚本会在~/openvpn-clients/目录下,创建一个client1.ovpn客户端配置文件,内容如下:
1 | # 创建客户端的配置 |
注意替换,你的公网IP地址和修改路由转发参数
上面的 route 192.168.50.0 255.255.255.0 也是告诉服务端,客户端访问这些 192.168.50.0/255.255.255.0 地址时,才经过VPN。
保存配置文件,然后启动 openvpn gui 客户端。通常,客户端会有opvn文件导入功能,导入客户端,点连接即可。连接成功显示如下:
然后,在CMD中ping VPN服务端的地址(下面10.8.100.1是vpn分配的网关地址,vpn客户端分配到的是10.8.100.6,192.168.50.28是vpn服务器内网ip,192.168.50.4是vpn服务所在内网的另一条机器的内网ip):
至此,vpn客户端和服务端全部安装完成。
这篇文章继承自“DIY高性能音乐服务器”和“ROON+HQPlayer+NAA串流数播/网播完整教程”两篇文章,如果对于自己制作一台Core感兴趣的,可以跳转了解。经过大半年对于X86 Core的搭建,BLOG主在当前有限的环境下有了一些新的感悟。
HQPlayer embedded是HQPlayer Linxu版本的延伸,是一个完全客制化的Linux系统,里面搭载了专门制作的HQPlayer OS系统,其定制的Network Audio Adapter协议是当前世界上最强的网络音频传输协议,同时它还提供了丰富的可调节选项,是当前实际上功能最多、性能最强、音质最好的播放系统。
官方提供的NAA拓扑图
具体的请查阅官方介绍:点我
1、打开官方下载链接:点我
试用版每半小时将自动关机一次,其他功能与付费版一致
2、下载最新版本镜像并解压得到img文件
注意,当前HQPlayer embedded分为两个INTEL和AMD两个版本,各位可以根据自己的CPU自行选择,根据官方介绍,这似乎是指令集上有些不同,可能影响某些时候的运行效率。他们一般名字命名为:
INTEL:hqplayer-embedded-4.29.3-x64gen.7z
AMD:hqplayer-embedded-4.29.3-x64amd.7z
PS:国外论坛中有人提出AMD支持的指令集更完善,对音质的影响未知。intel系列CPU的玩家可以直接选择AMD版本,也没什么问题。
3、在主板上安装sata/nvme硬盘,或者插入USB设备,系统安装将完全清空整个硬盘,且不可继续做他用。根据安装方式不同,我们可以在硬盘中制作HQPlayer embedded系统,开机即可使用。也可以制作USB随身携带版本,但经过USB后,音质必然存在劣化。
4、下载镜像烧录软件
我们采用的是“balenaEtcher”进行烧录,他的优势是可以直接对硬盘和USB设备进行烧录,速度快且稳定。
官网下载:点我
5、安装balenaEtcher,并根据下方提示进行烧录镜像

(1)点击Flash from file选择下载好的HQE的img镜像

(2)选择需要写入的硬盘,注意这将完全破坏写入硬盘的所有数据。考虑到HQE本身就是个常驻运行系统,因此建议使用高性能的SSD作为启动盘为好。这里BLOG主选择的是INTEL傲腾,也是理论上同级别SSD中延迟最低、4K性能最好对硬盘,但考虑到BLOG主以前做过不同SSD测评,实在找不到什么音质规律,因此选择仅供参考。


(3)最后点击Flash!按钮,在弹出框中选择Yes,I’am sure,然后等待完成即可。
6、完成后将制作好的SSD装入音频服务器(Core)中,开机在主板设置成该硬盘启动,等待约30秒即可完成系统载入。
当前HQPlayer embedded本地播放功能难用到极点,而且本地播放到音质在没处理的情况下还不如NAA,因此这里仅推荐联网使用。很多朋友可能对网络处理没有特别多的概念,下面提供一下BLOG主当前系统部分拓扑图,各位可以参考,也可以搜索BLOG主之前写的相关文章。

安装完成HQE后,各位首先需要进入路由器界面,找到HQE服务器的内网IP地址,如下方,BLOG主自动分配的IP地址为:192.168.1.197
然后,将这个IP地址复制到浏览器中打开,即可进入HQE后台,在这里可以对HQE进行各种设置。在这个界面上,如果出现账号和密码需求,默认账号为“hqplayer”,默认密码则是“password”。如果需要修改密码则可以点到“Authentication”页面进行设置。
接下来,我们详细介绍设置页面下,各个选项的意义:
1、设置Backend(后端)

如果需要本地播放选择ALSA,如果需要通过网络进行NAA推送播放,则选择Network Audio
2、设置Output mode(音频输出模式)

Auto是根据音频本身的格式,输出PCM或者SDM。但如果希望强制音频转换成PCM或者SDM,可以选择下面两项强制输出。
3、Fixed volume(绝对音量)

该选项可以将音量锁定在某一个响度,非必要选项。如果不希望数字音量调节,可以勾选“enabled”(开启)并填入数字“0”。
4、Max volume/Min volume(最大音量/最小音量)

该选项可以自行决定音量响度的刻度尺,设定最小和最大两个数值,后面就可以在这个规定的范围内进行调节。如果打开了上面的选项,则此选项不生效。
5、Startup volume (启动音量)

本选项相当于音乐开头提供一个衰减,以降低对人耳的刺激,对音质无影响,可以不设置。
6、Adaptive volume(适应性音量)

自动平衡各音频的响度,保证每首曲子的音量基本一致,可能对音质有负面影响,建议不开启。
7、PCM gain compensation(PCM增益补偿)

播放PCM音频时,为每首曲子固定增加的音量,,可能对音质有负面影响,建议不开启。
8、Channels(声道)

选择输出声道数量,一般填写“2”,即两声道。如果是多声道音频,在硬件条件允许情况下,需要对此进行配对设置。
9、Options(其它设置)

Auto rate family:根据音频原采样率进行倍数升频,如果不选,则是根据设置的最高采样率进行升频。建议一定要开启,以保证不会出现SRC偏差。
Quick pause:快速暂停,允许在播放音频时迅速启动暂停/重新启动播放的功能。
Short buffer:短缓冲,可以有效降低播放延迟,但可能影响最终音质。除非是观看视频时出现明显音画不同步的情况,一般听音乐不选择此选项。
10、Log file(日志文件)
记录HQE系统运行时的日志文件,一般用户无需理会该选项,甚至可以选择关闭。
11、DSD sources(DSD信号源)

该部分为DSD信号源部分的设置:
Direct SDM:直接输出SDM信号,关闭升频。
Gain +6 dB:为所有DSD音频信号默认追加6dB响度。
Intergrator:低通滤波器,当前提供了5种可选,请根据听感自行选择。
SDM-SDM Conversion:DSD升频滤波设置,当前有wide和narrow两种选择。
仅供参考
Noise filter:噪声滤波器,当前有9种可选,请根据实际听感选择。
SDM-PCM Conversion:DSD升频PCM滤波选择,当前有14个可选,请根据实际听感选择。
12、PCM settings/SDM settings(PCM播放设置/SDM播放设置)

该部分设置与桌面版HQPlayer完全一致,请参考这里。
13、ALSA backend(ALSA后端设置/本地播放设置)

Device:输出设备选择
Channel offset:通道偏移,不知道有什么用,默认为0,请勿改动。
DAC bits:DAC的转换位深,根据硬件实际性能选择,如果不知道填数字“0”
Buffer time:缓冲时间,默认为100ms,可以根据硬件和体验实际进行调整。
DoP:将SDM信号打包成PCM信号输出
48k DSD:强制PCM升频DSD时采用48k整数倍升频(44.1Khz进行DSD升频为非整数倍升频,SRC可能导致失真),一般不开启,因为不推荐将PCM升频至DSD。
14、Network Audio backend(网络后端设置/NAA播放设置)

IPv6:打开对IPv6的IP地址支持,需要路由支持。
所有东西设置好!我们就可以开始听音乐了。将手机/平板连接进入与HQE同一个网络,然后下载合适的软件,选择HQE推送即可!下面推荐几个BLOG主尝试过后认为合适的方案供参考:
1、BubbleUPnP(Android)
支持连接Qobuz、TIDAL、Google Drive、Dropbox、Box、OneDrive以及本地NAS进行流媒体NAA推送播放。功能全面、响应迅速、软件免费、无广告,如果不需要ROON的数据功能,可以全面替代。
2、mconnect(Android/iOS)
持连接Qobuz、TIDAL、OneDrive以及本地NAS进行流媒体NAA推送播放。界面美观、功能全面、响应稍慢、有付费和免费版本可选择。
3、AirMusic(Android)
可以将手机/平板中所有音频信号通过UPNP协议发送,这样就可以通过整套HIFI系统看Youtube、Bilibili、抖音等视频了!注意本软件有付费和免费版,可能需要ROOT支持。
4、QQ音乐(Android/iOS)
在最新版本的QQ音乐中,HQ(含)以下音质可以直接推送到HQE中播放了!虽然并非无损格式,整体音质受损,但是瑕不掩瑜,毕竟大量无版权音乐可能只能在这里听到!顺便BS一下网易云,客户端稀烂,音质为所有播放器中垫底。
在此前已经安装好了Mac,并能正常引导但是Ubuntu的引导需要手动按F10进行选择,比较麻烦,尝试将Ubuntu的引导也加入到OC中。
参考国外大佬Ayush Sahay Chaudhary的博客[GUIDE] Opencore Dualboot/ Multiboot Guide进行的配置,该博客中有完整的win+mac+linux的安装步骤。
请确保你的OC中存在OpenShell.efi文件,没有可前往opencore官方网站进行抄作业

进入MAC,在网上下载OpenCore Configurator工具,工具版本要和OC文件版本对应。
启动到 OpenCore 并选择 OpenShell.efi
如果在OC中无法找到该选项而EFI中确实放置了OpenShell.efi,那么进入Mac中启动OpenCore Configurator。
转到工具> 挂载EFI

选择自己电脑EFI所在的硬盘并挂载

找到其中的EFI> OC> config.plist,在OpenCore Configurator中打开该文件
将其启用保存再进入OC中就可以看到OpenShell.efi

重启到 OpenCore 并选择 OpenShell.efi

你会看到这样的屏幕(这时请注意及时按一下按键)

这里的东西是,FS1, FS2,… FS7: 是所有连接到系统的驱动器的分区,你必须确定哪个是Linux 分区。
要查找分区开始输入
1 | FS1: |
然后输入
1 | dir |

继续这个操作一直到你在输入 DIR 后找到 EFI 的文件夹
输入
1 | FS2: |
然后输入
1 | dir |

再次这样输入
我在 FS7中找到了我的 总 EFI 分区:
检查你的EFI文件夹
1 | cd EFI |
如果ubuntu的文件夹是在这个分区里面

输入
1 | cd ../ |
回到你的根 EFI 分区,即 FS7
再次输入
1 | map > map-table-linux.txt |
将地址信息导出到txt文件
现在重新启动系统并从启动菜单中选择 macOS 驱动器启动到 macOS。
同样挂载EFI分区
打开 EFI分区可以看到,map-table-linux.txt

将其剪切到桌面,打开它

查到你在OpenShell中找到的驱动器号(我的是FS7),复制 PCI 行(图中选中的那一行)并将其粘贴到一个新的文本文件中,然后在 PCI 行之后添加这一行,如下所示,
1 | /\EFI\ubuntu\grubx64.efi |
注意:前面不能有空格
之后可以看到是这样子
1 | PciRoot(0x0)/Pci(0x1D,0x0)/Pci(0x0,0x0)/NVMe(0x1,20-60-A0-49-8B-44-1B-00)/HD(1,GPT,B2C56269-054C-45C4-8ACS-C321A6B52982,0x800,0xAF000)/\EFI\ubuntu\grubx64.efi |
同样打开OpenCore Configurator,进入目录EFI> OC> config.plist,将config.plist在OpenCore Configurator中打开,然后去Misc-其它设置中,选择Entries-自定义条目。

在右下角添加自定义条目
路径中添加创建好的路径,名称填写Ubuntu,风格自动,勾选启用。
效果展示

1.安装Debian:从Debian官网下载网络安装镜像,进行最小化安装。在软件选择时,只勾选“SSH server”和“Standard system utilities”。
2.更新系统:
1 | sudo apt update && sudo apt upgrade -y |
3.安装必要工具:
1 | sudo apt install -y p7zip-full squashfs-tools systemd-container |
p7zip-full用于解压7z文件,systemd-container提供了更现代的容器化管理工具(但我们仍会使用传统chroot)
1.创建工作目录:
1 | sudo mkdir -p /opt/hqplayer-chroot |
2.解压HQPlayer Embedded:
1 | sudo 7z x hqplayer-embedded-5.8.1-x64sse42.7z -o/opt/hqplayer-chroot |
这会在/opt/hqplayer-chroot下得到hqplayer-embedded-5.8.1/文件夹,里面包含bin, lib, usr等目录。这就是我们chroot的基础。
我们需要把它挂载到一个临时目录,然后复制其中的所有文件。
1 | # 创建挂载点 |
3.挂载镜像中的分区
您需要先找到镜像中的分区偏移量,然后挂载正确的分区。
第1步:查看镜像的分区信息
1 | sudo fdisk -l hqplayer-embedded-5.8.1-x64sse42.img |
fdisk 输出显示镜像中有两个分区:
分区1:Start=2048, Size=27.8M, Type=”Microsoft basic data” (这很可能是EFI系统分区)
分区2:Start=59392, Size=3G, Type=”Linux filesystem” (这是我们要的根文件系统分区)
挂载分区(分区2)
1 | # 计算分区2的偏移量 (59392 sectors * 512 bytes/sector) |
复制文件到chroot目录
1 | # 查看挂载的内容 |
4.创建必要的系统目录:
1 | sudo mkdir -p /opt/hqplayer-chroot/{proc,sys,dev,run,var/lib,etc,tmp} |
5.复制DNS解析配置:
1 | sudo cp /etc/resolv.conf /opt/hqplayer-chroot/etc/ |
6.让 chroot 环境访问主机音频设备
首先识别音频设备
1 | # 在宿主机上查看所有音频设备 |
可以看到您的音频设备配置:
card 0: AB13X USB Audio (USB DAC) - 这是您的外部USB音频设备
card 1: Ensoniq AudioPCI - 这是主板内置声卡
现在让我们确保chroot环境中的HQPlayer能够访问这些设备。
配置chroot环境访问USB DAC, 修改启动脚本确保正确映射
我们需要一个脚本来自动挂载必要的文件系统并进入chroot。
1 | sudo nano /usr/local/bin/start-hqplayer-chroot.sh |
1 | sudo nano /usr/local/bin/stop-hqplayer-chroot.sh |
设置正确的权限
1 | sudo chmod +x /usr/local/bin/start-hqplayer-chroot.sh |
重新加载并测试服务
1 | # 重新加载systemd配置 |
系统使用的是 cgroup2(统一层次结构),而不是传统的cgroup1。这可能是导致服务启动失败的原因,因为一些旧的应用或脚本可能不完全兼容cgroup2。
第1步:检查系统是否支持cgroup1
1 | # 检查是否启用了cgroup1兼容性 |
1 | sudo nano /etc/systemd/system/hqplayer-chroot.service |
使用以下配置:
1 | [Unit] |
1 | sudo systemctl start hqplayer-chroot.service |
dns或者删除符号链接并创建实际文件
1 | # 删除符号链接 |
首先查看当前大小
1 | sudo du -sh /opt/hqplayer-chroot/ --exclude=proc --exclude=sys --exclude=dev --exclude=run |
删除最大的文件(镜像文件)
1 | # 删除原始镜像文件(节省最多空间) |
删除firmware文件
1 | # 删除firmware(通常不需要) |
查看精简效果
1 | # 查看当前大小 |
验证功能正常
1 | # 重启HQPlayer服务测试 |