]]>如果要跳槽,刷 LeetCode 是必不可少的咯?
错入 NetGear R7000p,开始折腾 树莓派 3B+,最后皈依 NetGear R7800
为什么要折腾 OpenWrt 呢,这个问题,应该是日益增长的设备对科学上网的渴望所导致的
一开始就只有电脑和手机有需求,但是开了个 100GB/mo 的套餐,这样花起来就不太值得了,每月都剩下 90% 的流量
还有有时候想让 PS4,NS 等也可以翻墙,都要去装个客户端就太麻烦了
所以思考着,透明网关之类的解决方案
之前工作中接触到和硬件相关的东西,一时兴起买了个 树莓派3B+,最初打算是用来控制开关什么的,后来热情淡了就不了了之了
电脑端一直用着 ClashX,感觉挺好,希望用它来做一个透明网关
在树莓派装好 Ubuntu 装好 Clash 之后,剩下的网关配置等的阻碍了我的脚步,无奈之下只好又尘封它了
直到上周,忘记什么原因,一下子就陷入到 OpenWrt/Lede 中,寻思着拿 树莓派3B+ 试试
下载的版本刷到树莓派上,不是 彩屏,就是 Luci 服务跑不起来
还是要自己编译才行
在 macOS 上编译了一下,各种问题,还是要按照推荐,用 Ubuntu 来 build
在安装了个虚拟机,成功编译出 树莓派3B+ 的固件,之后就是刷机什么的
刷好 Lede 固件后,基本是开机就用,插上网线就行了
缺点还是有的,树莓派3B+ 毕竟是软路由,无线的信号也不是很好很稳定
而且,只能作为辅助热点,不能完全替代路由,可以说是个尝鲜的方案
不知道什么么错觉,让我以为家里的路由器是 R7800,在后台看到是 R7000p 的那一刻,我竟然怀疑是之前返修调包了,赶紧翻出订单一看,确实是 R7000P
当时入手的时候以为只要是 NetGear 都能刷固件什么的,虽然也不是错的离谱
R7000P 就是主流的 OpenWrt/Lede 刷不了,只能刷 DDWrt 之类的
有想过还是算了吧,就刷刷 DDWrt 将就下,但是只有一个路由器,刷坏了比较麻烦
想象还是狠下心来,入手个 R7800 刚好遇上电竞节,999 入手了
刷机很顺利,直接在网页后台上传就行了,但是刷完机,我手贱,用 树莓派3B+ 的配分直接恢复了配置,这导致了接下来的灾难
显示自己去看怎么配置 WAN,搜索有没有人共享出来 R7800 的配置,一夜郁闷的睡了
首先是一直只能利用不同网段去开配置后台,配置好后,科学上网组件运行不起来,访问不了外网。。。
开启作死模式,各种尝试修改配置
R7800 很多时候要重启才生效,配置
最糟糕的第二天,直接把 br-lan 从 静态地址 改成 pope 拨号,导致 ssh 彻底连不上了
至暗时刻,甚至想过这就是代价,认了
但是看到说有不死 uboot,可以用 tftp 刷回来
在 windows 下总算刷机成功,满血复活(吐槽下,windows 的命令行太难用了)
再次刷机,不恢复配置,网线直接插 WAN 口就能用了,之前到底是多蠢。。。。
所以网上也没有所谓的 R7800 的配置下载。。。。
配置好科学上网后,算是成功第一步了,家里的所有设备都可几无感接入了
后面再研究下有什么新玩法
还精简了些服务,lede 自带比较多功能,有些用不上,浪费内存
]]>一世流流长,边个会唔用到 github, gitlab 噶
1 | public enum GitAccount { |
由于在机器上,难免会遇到这个问题,公司的GitAccount和自己的GitAccount,在SSH Key与GPG Key配置时候的各种问题。
本篇文章不讨论同域多个名账户配置(没找到好方法),即多个GitAccount共存时候SSH和GPG的配置。
你可以使用 Terminal 的 GPG,安装方法
1 | brew install gpg |
或者使用 GUI 工具GPG-Suite
使用此工具会异常方便,省去很多配置。。。
生成 GPG Key 的步骤在此略过
Google 了一下,如无意外 都是
1 | git config --global gpg.programe "gpg" |
还有什么配置 GPG-Agent 的,hin 复杂。。。。(所以我选择 GPG-Suite)
这样配置的话会导致不用账户都用该配置,会导致 commit 失败。
其实可以这样,在~/.gitconfig里面配置一个全局的账户
然后某个 Repository 你是用别的账户的,就可以独自为该 Repo 配置一下
1 | git config gpg.programe "gpg" |
就是把 Global 去掉。。。。。(哈哈哈,就是这么简单明了)
我们可以把这个整理成一个 alias,放在~/.zshrc里面,下次就直接输入就好了
1 | alias configgitrepo="git config user.signingkey \"xxxxx\" && git config user.email \"[email protected]\" && git config user.name \"xxx\" && git config gpg.programe \"gpg\" && git config commit.gpgsign \"true\"" |
权当记录一下,没啥技术含量
]]>Code Name: APlay 02
我们先来定义一个名为 StreamProvider 的协议,这个协议是我们为播放器后续操作提供原始数据流制订的规范
1 | public protocol StreamProviderCompatible: AnyObject { |
我们可以通过 extension 为协议 StreamProvider 的 open(at:) 方法加上一个带有默认值 Position() 的实现
1 | extension StreamProvider { |
下面我们来详细分析下这个协议
字面意思,输出管道,是该协议发出的事件流,是通过
Delegated实现的,事件流的值是Event这些事件最终会流入
Composer中,由Composer统一调度StreamProvider和AudioDecoder,最终目的是生成解码后的 PCM 数据,存储到环形缓冲区Uroboros中
1
2 > public enum Event {
>
case readyForReadycase hasBytesAvailable(UnsafePointer<UInt8>, UInt32, Bool)case endEncounteredcase errorOccurred(APlay.Error)case metadata([MetadataParser.Item])case metadataSize(UInt32)case flac(FlacMetadata)case unknown(Error)}
1 |
|
缓冲的进度
具体实现还是看代码吧,有什么疑问可以在评论区交流下 😄,Streamer.swift
下面我们来看下 网络文件流 和 本地文件流 的实现
使用 CFReadStreamCreateWithFile 来创建 本地文件流
使用 CFReadStreamCreateForHTTPRequest 来创建 网络文件流
加入到新建的 RunloopQueue 中循环读取数据,然后派发 StreamValue
这里要加入 TagParser,分析文件流里面的 Metadata 信息,以便于计算音频长度。
有个需要注意的地方是,MP3 文件可能同时存在 ID3v1 和 ID3v2 两个版本的信息,所以必须要检测文件最后的 128 个字节是否是 ID3v1。
RunloopQueue: A GCD-like queue powered with the magic (and ruggedness) of CFRunLoop.
在背景线程读取文件流
Delegated: 👷♀️ Closure-based delegation without memory leaks
消除 [weak self]
]]>环形存储类,线程安全,支持同时读写。
Version v0.0.1
自从上一篇文章后,又有了许多改动,原本以为写的差不多了,但还是挺多地方需要修改的。
后续有空的话会写下该框架的一些技术心得
有打算写个播放器 App,再看吧
]]>Code Name: APlay 01
这是一个系列专题,我们将学习如何使用 Swift 语言从零开始一步一步构建你自己的音乐播放器。
本人水平有限,如有错漏,欢迎指导,谢谢。
由于之前工作的内容是负责某小众音乐平台的 App (落网),及由此机遇开始接触到音频处理这一块,摸爬滚打了几年,算是了解了 iOS 系统下音频处理的一些大概。
一开始使用的是豆瓣开源的 DOUAudioStreamer,但是该项目缺于维护,并不能满足日益增长的实用需求。
于是乎,寻找新的替代品。考察了多个开源库,FreeStreamer 是一个相对来说功能挺完善的的第三方开源库。实现也没有很复杂的逻辑和技术,修改起来也比较简单。
在 FreeStreamer 的基础上,删除了部分无关的类,增加了适合项目的一些新功能。因为 FreeStreamer 是 Objective-C/C++ 实现的,对于使用 Swift 来说,不太友好。本着熟悉这个项目的目的使用 Swift 重写一遍,就有了现在的 FreePlayer。
得益于重写的工作,对于 FreeStreamer 的架构设计、功能实现有了一定的了解,为实现此文的播放器打下基础。
由于都是比较有年代感的项目,大牛们都是用 pthread_mutex_t、pthread_cond_t 等来线程同步。如果要修改、添加功能,会很容易出错,导致死锁。
于是在一年多以前开始着手构建更现代化的音频播放器,使用 GCD 来控制线程同步。
中途放弃了好几次(对 iOS 音频处理理解不充分导致),但是保持思考着问题的话,总会在某个时间能突然灵感一现,得到启发。
先看下 DOUAudioStreamer 和 FreeStreamer 的简单分析。

批量解码,导致 CPU 瞬时峰值比较高

每次解码单个 packet,CPU 平稳。但是歌曲切换时候,会有残留 buffer 等,延迟大。不支持 Wave 格式播放

使用全新 GCD 实现流控制,简化线程同步,避免出现死锁,更低的延迟,更低的 CPU 和内存占用
FreeStreamer,FreePlayer 播放器对 WAVE 格式支持不好,这也是新框架 APlay 需要解决的问题
前阵子刚好看到 .app 域名开放预购,顺便买了个试试,没想到成功了
想给 io 绑定域名试试,刚好前不久,Github Pages 连自定义域名都支持 Https 了
加上刚好这阵子把音乐播放器搞好了,于是重新开始写写博客吧
Try this https://github.com/huytd/kanban-app
Maybe a audio player app
What I’m doing now!
]]>