SelfStudio Keep Coding... 2020-04-28T06:44:13.333Z https://codeeagle.github.io/ Lincoln.L Hexo 关于算法 https://codeeagle.github.io/2020/04/28/About-Algorithm/ 2020-04-28T11:45:15.000Z 2020-04-28T06:44:13.333Z <![CDATA[

如果要跳槽,刷 LeetCode 是必不可少的咯?

]]>
<blockquote> <p>如果要跳槽,刷 LeetCode 是必不可少的咯?</p> </blockquote>
关于 OpenWrt 的折腾经过 https://codeeagle.github.io/2019/08/03/About-OpenWrt/ 2019-08-03T01:41:19.000Z 2020-04-28T06:44:10.271Z <![CDATA[

错入 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+ 毕竟是软路由,无线的信号也不是很好很稳定

而且,只能作为辅助热点,不能完全替代路由,可以说是个尝鲜的方案

烦恼的 R7000p

不知道什么么错觉,让我以为家里的路由器是 R7800,在后台看到是 R7000p 的那一刻,我竟然怀疑是之前返修调包了,赶紧翻出订单一看,确实是 R7000P

当时入手的时候以为只要是 NetGear 都能刷固件什么的,虽然也不是错的离谱

R7000P 就是主流的 OpenWrt/Lede 刷不了,只能刷 DDWrt 之类的

有想过还是算了吧,就刷刷 DDWrt 将就下,但是只有一个路由器,刷坏了比较麻烦

想象还是狠下心来,入手个 R7800 刚好遇上电竞节,999 入手了

R7800 的刷机配置走了大弯路

刷机很顺利,直接在网页后台上传就行了,但是刷完机,我手贱,用 树莓派3B+ 的配分直接恢复了配置,这导致了接下来的灾难

显示自己去看怎么配置 WAN,搜索有没有人共享出来 R7800 的配置,一夜郁闷的睡了

首先是一直只能利用不同网段去开配置后台,配置好后,科学上网组件运行不起来,访问不了外网。。。

开启作死模式,各种尝试修改配置

R7800 很多时候要重启才生效,配置

最糟糕的第二天,直接把 br-lan 从 静态地址 改成 pope 拨号,导致 ssh 彻底连不上了

至暗时刻,甚至想过这就是代价,认了

但是看到说有不死 uboot,可以用 tftp 刷回来

windows 下总算刷机成功,满血复活(吐槽下,windows 的命令行太难用了)

再次刷机,不恢复配置,网线直接插 WAN 口就能用了,之前到底是多蠢。。。。

所以网上也没有所谓的 R7800 的配置下载。。。。

后记

配置好科学上网后,算是成功第一步了,家里的所有设备都可几无感接入了

后面再研究下有什么新玩法

还精简了些服务,lede 自带比较多功能,有些用不上,浪费内存

]]>
<blockquote> <p>错入 NetGear R7000p,开始折腾 树莓派 3B+,最后皈依 NetGear R7800</p> </blockquote>
macOS 多账户使用 GPG 的方法 https://codeeagle.github.io/2018/09/17/GPG-with-multiple-accounts/ 2018-09-17T10:19:58.000Z 2020-04-28T02:22:03.673Z <![CDATA[

一世流流长,边个会唔用到 github, gitlab 噶

Definition

1
2
3
public enum GitAccount {
case gitLab(String), gitHub(String), bitBucket(String)
}

Intro

由于在机器上,难免会遇到这个问题,公司的GitAccount和自己的GitAccount,在SSH KeyGPG Key配置时候的各种问题。

本篇文章不讨论同域多个名账户配置(没找到好方法),即多个GitAccount共存时候SSHGPG的配置。

Tool

你可以使用 TerminalGPG,安装方法

1
brew install gpg

或者使用 GUI 工具GPG-Suite

使用此工具会异常方便,省去很多配置。。。

生成 GPG Key 的步骤在此略过

Configurations

Google 了一下,如无意外 都是

1
2
3
4
5
git config --global gpg.programe "gpg"
git config --global commit.gpgsign "true"
git config --global user.email "[email protected]"
git config --global user.name "xxx"
git config --global user.signingkey "xxxxxx"

还有什么配置 GPG-Agent 的,hin 复杂。。。。(所以我选择 GPG-Suite)

这样配置的话会导致不用账户都用该配置,会导致 commit 失败。

Solution

其实可以这样,在~/.gitconfig里面配置一个全局的账户

然后某个 Repository 你是用别的账户的,就可以独自为该 Repo 配置一下

1
2
3
4
5
git config gpg.programe "gpg"
git config commit.gpgsign "true"
git config user.email "[email protected]"
git config user.name "xxx"
git config user.signingkey "xxxxxx"

就是把 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\""

End

权当记录一下,没啥技术含量

]]>
<blockquote> <p>一世流流长,边个会唔用到 github, gitlab 噶</p> </blockquote>
构建通用的文件流提供器(Stream Provider) https://codeeagle.github.io/2018/08/01/Build-A-Generic-Streamer/ 2018-08-01T06:19:15.000Z 2020-04-28T02:22:03.672Z <![CDATA[

Code Name: APlay 02

文件流提供器协议 StreamProvider

StreamProviderCompatible.swift

Protocol 定义

我们先来定义一个名为 StreamProvider 的协议,这个协议是我们为播放器后续操作提供原始数据流制订的规范

  • 对外部隐藏读取 网络文件流本地文件流 的具体实现
  • 外部可以重写实现,方便定制
1
2
3
4
5
6
7
8
9
10
11
12
13
public protocol StreamProviderCompatible: AnyObject {
var outputPipeline: Delegated<StreamProvider.Event, Void> { get }
var position: StreamProvider.Position { get }
var contentLength: UInt { get }
var info: StreamProvider.URLInfo { get }
var bufferingProgress: Float { get }

func open(url: URL, at position: StreamProvider.Position)
func destroy()
func pause()
func resume()
init(config: ConfigurationCompatible)
}

我们可以通过 extension 为协议 StreamProvideropen(at:) 方法加上一个带有默认值 Position() 的实现

1
2
3
4
extension StreamProvider {
@inline(__always)
public func open() throws { return try open(at: Position()) }
}

下面我们来详细分析下这个协议

OutputPipeline

字面意思,输出管道,是该协议发出的事件流,是通过 Delegated 实现的,事件流的值是 Event

这些事件最终会流入 Composer 中,由 Composer 统一调度 StreamProviderAudioDecoder,最终目的是生成解码后的 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

### position
>打开流位置的记录

### contentLength
> 文件长度

### info
>有关 url 的信息,根据 url 推断出来的 `AudioFileType` 等的信息
>
>`AudioFileType` 是对 `AudioFileTypeID` 二次封装的 `RawRepresentable` 类型,避免输入是不记得类型名字的烦恼
>```swift
public enum URLInfo {
case remote(URL, AudioFileType)
case local(URL, AudioFileType)
case unknown(URL)
...
}

bufferingProgress

缓冲的进度

网络文件流 & 本地文件流

具体实现还是看代码吧,有什么疑问可以在评论区交流下 😄,Streamer.swift

下面我们来看下 网络文件流本地文件流 的实现

使用 CFReadStreamCreateWithFile 来创建 本地文件流

使用 CFReadStreamCreateForHTTPRequest 来创建 网络文件流

加入到新建的 RunloopQueue 中循环读取数据,然后派发 StreamValue

这里要加入 TagParser,分析文件流里面的 Metadata 信息,以便于计算音频长度。

有个需要注意的地方是,MP3 文件可能同时存在 ID3v1ID3v2 两个版本的信息,所以必须要检测文件最后的 128 个字节是否是 ID3v1

使用到的第三方库

RunloopQueue: A GCD-like queue powered with the magic (and ruggedness) of CFRunLoop.

在背景线程读取文件流

Delegated: 👷‍♀️ Closure-based delegation without memory leaks

消除 [weak self]

Uroboros

环形存储类,线程安全,支持同时读写。

]]>
<blockquote> <p>Code Name: APlay 02</p> </blockquote>
APlay 正式开源啦 https://codeeagle.github.io/2018/07/10/Release-APlay-Framework/ 2018-07-10T02:12:00.000Z 2020-04-28T02:22:03.674Z <![CDATA[

Version v0.0.1

APlay 正式开源啦

自从上一篇文章后,又有了许多改动,原本以为写的差不多了,但还是挺多地方需要修改的。

  • 重写了 MP3 的 metadata parser
  • 新增了 FLAC 的 metadata parser,支持 seek(需要 seektable)
  • 优化了 WAVE 的 seek 操作
  • 优化了 Packet 存储的逻辑,最大程度保证不会读取错误

后续有空的话会写下该框架的一些技术心得

有打算写个播放器 App,再看吧

Github

]]>
<blockquote> <p>Version v0.0.1</p> </blockquote>
使用 Swift 从零构建一个音乐播放器 https://codeeagle.github.io/2018/05/17/Build-A-Audio-Stream-Player/ 2018-05-17T14:56:59.000Z 2020-04-28T02:21:45.294Z <![CDATA[

Code Name: APlay 01

这是一个系列专题,我们将学习如何使用 Swift 语言从零开始一步一步构建你自己的音乐播放器。

本人水平有限,如有错漏,欢迎指导,谢谢。

系列文章列表

  • 构建通用的文件流提供器(Stream Provider)
  • 构建 ID3, Flac Metadata 解析器
  • 构建环形缓冲区(Circle Buffer)
  • 构建 iOS 系统支持音频解码器(Decoder)
  • 构建管理器(称之为 Composer),将 Streamer 和 Decoder,Circle Buffer 串联起来

前言

由于之前工作的内容是负责某小众音乐平台的 App (落网),及由此机遇开始接触到音频处理这一块,摸爬滚打了几年,算是了解了 iOS 系统下音频处理的一些大概。

一开始使用的是豆瓣开源的 DOUAudioStreamer,但是该项目缺于维护,并不能满足日益增长的实用需求。

于是乎,寻找新的替代品。考察了多个开源库,FreeStreamer 是一个相对来说功能挺完善的的第三方开源库。实现也没有很复杂的逻辑和技术,修改起来也比较简单。

FreeStreamer 的基础上,删除了部分无关的类,增加了适合项目的一些新功能。因为 FreeStreamer 是 Objective-C/C++ 实现的,对于使用 Swift 来说,不太友好。本着熟悉这个项目的目的使用 Swift 重写一遍,就有了现在的 FreePlayer

得益于重写的工作,对于 FreeStreamer 的架构设计、功能实现有了一定的了解,为实现此文的播放器打下基础。

动机

由于都是比较有年代感的项目,大牛们都是用 pthread_mutex_tpthread_cond_t 等来线程同步。如果要修改、添加功能,会很容易出错,导致死锁。

于是在一年多以前开始着手构建更现代化的音频播放器,使用 GCD 来控制线程同步。

中途放弃了好几次(对 iOS 音频处理理解不充分导致),但是保持思考着问题的话,总会在某个时间能突然灵感一现,得到启发。

背景

先看下 DOUAudioStreamerFreeStreamer 的简单分析。

DOUAudioStreamer 简要流程/核心方法

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

FreeStreamer/FreePlayer 简要流程/核心方法

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

Code Name: APlay

APlay 简要流程/核心方法

使用全新 GCD 实现流控制,简化线程同步,避免出现死锁,更低的延迟,更低的 CPU 和内存占用

FreeStreamerFreePlayer 播放器对 WAVE 格式支持不好,这也是新框架 APlay 需要解决的问题

Next

APlay 正式开源啦

学习资料

雷霄骅-视音频编解码技术零基础学习方法

Learning Core Audio A Hands-On Guide to Audio

KKBOX iOS/Mac OS X 基礎開發教材

]]>
<blockquote> <p>Code Name: APlay 01</p> <p>这是一个系列专题,我们将学习如何使用 Swift 语言从零开始一步一步构建你自己的音乐播放器。</p> </blockquote>
Re:Start https://codeeagle.github.io/2018/05/16/Re-Start/ 2018-05-16T13:08:48.000Z 2020-04-28T02:22:03.673Z <![CDATA[

0x00

前阵子刚好看到 .app 域名开放预购,顺便买了个试试,没想到成功了

想给 io 绑定域名试试,刚好前不久,Github Pages 连自定义域名都支持 Https 了

加上刚好这阵子把音乐播放器搞好了,于是重新开始写写博客吧

0x01: Learning Rust lang

Try this https://github.com/huytd/kanban-app

0x10: Publish an App

Maybe a audio player app

0x11: Blogging

What I’m doing now!

]]>
<h2><span id="0x00">0x00</span><a href="#0x00" class="header-anchor"></a></h2><p>前阵子刚好看到 <code>.app</code> 域名开放预购,顺便买了个试试,没想到成功了</p> <p>想给 <