[前言]
曾遇到过这种场景,手上却只有一个手机和一台蓝牙音箱,但是没有话筒。
这时候脑子里冒出来的第一个念头多半是:要是手机能变成一个话筒就好了。
OpenMic 就是为这个念头写的。它不是让你的手机去“连”音箱(手机本来就能连蓝牙音箱放歌),而是反过来了——把手机当成话筒,把麦克风收到的人声,实时推给蓝牙音箱放出来。说直白点,它把一个普通的蓝牙音箱,变成了一套“手机版无线扩音系统”。而这一切,只靠一个开源的小 App 就能做到。
开源地址:
- GitHub:https://github.com/LogicLiu1024/OpenMic
- Gitee(国内镜像):https://gitee.com/logicliu/open-mic
它能干什么?
核心就一件事:实时音频回环(Audio Loop)。手机开麦克风收音,经过一小段处理,马上播到蓝牙音箱里。链路很短,但想做到“实时、不卡、不啸叫、不炸音”,能抠的细节其实不少。
功能做得很克制,每一条都冲着“好用”去:
- 一键开关:一个开关,开了就“收音 → 处理 → 播放”,关了即停。
- 音量增益:一个滑杆,把拾音音量放大 0~2 倍。人声小就推大点,嫌吵就拉回来。
- 噪声门(自动静音):环境安静时就输出静音,不会让音箱一直“沙沙沙”地放底噪。
- 限幅(防破音):增益拉太猛容易溢出、破音,它把幅度钳制在 80% 上限,让声音不至于“炸”。
- 常驻通知:开启后就变成前台服务,切后台、锁屏都不中断,通知栏还带一个“停止”按钮。
- 蓝牙状态一目了然:音箱连没连上、有没有在跑,界面直接用一个红/黄/绿的状态告诉你。
如何做到“边录边放”
很多人第一反应是“这不就是录音加播放吗”。其实真正难的,是边录边放、几乎零延迟,这比把一整个文件录完再播要难不少。OpenMic 的主循环在 AudioLoopEngine 里,跑在一条 IO 协程上,核心其实就三行:
// 每次循环:读一小段 → 处理 → 推给蓝牙音箱
val bytesRead = audioRecord?.read(buffer, 0, buffer.size) ?: 0
if (bytesRead > 0) {
val processed = processAudio(buffer, bytesRead)
audioTrack?.write(processed, 0, processed.size)
}
采样率与缓冲:不同机型对采样率、缓冲的支持差异很大。它按 44100 / 48000 / 16000 依次尝试初始化,哪个能初始化成功就用哪个,并把录音、播放的缓冲区取较大的那个,尽量降低卡顿和兼容性问题。这套“探测式初始化”,本质上就是为了多兼容一台设备。
字节与短整型:录音出来是 PCM16 字节流、小端序。处理前要用 ByteBuffer 按小端序解成 ShortArray(一个采样点一个 short),处理完再打包回去。所以你会在代码里反复看到 LITTLE_ENDIAN——这不是啰嗦,是在跟底层对齐。
增益、噪声门、啸叫
几个词看着吓人,其实都不难懂,我用更日常的说法拆开讲:
- 增益(gain):把每个采样值乘上一个 0~2 的系数,相当于给声音“拧大音量旋钮”。
- 限幅(hard clip):增益一旦超过某个点,采样值就会溢出、破音。它在溢出前把幅度“削平”到 80%,让声音不至于刺耳。
- 噪声门(noise gate):先算这一小段音频的能量(RMS),太低就判定“环境安静”,整段直接输出静音。效果就是没人说话时,音箱不“空响”。
- 啸叫(feedback):这是麦克风靠近音箱时最经典的物理问题——麦收音 → 音箱放大 → 又钻进麦克风 → 再放大,循环起来就是那声刺耳的“喂——”。OpenMic 没法物理地消除它,但它很诚实:界面里直接提示“别把手机正对音箱、保持距离”,把最容易踩的坑先明明白白告诉你。
如何切到后台还能一直工作
Android 对后台是出了名地“严格”,App 一退后台,普通代码很容易被系统掐断。OpenMic 靠前台服务(Foreground Service)常驻:启动时调 startForegroundService,带一条有“停止”按钮的常驻通知,并在 Manifest 里声明 FOREGROUND_SERVICE_MICROPHONE 服务类型(Android 14+ 的新要求)。系统一看“这是个一直在用麦克风的 App”,就不会随便杀它。
UI 和服务之间用绑定(Bound Service)通信——主界面只管开关、调增益,真正干活的其实是服务里的音频引擎。顺带一提,权限这条“隐形门槛”也值得注意:Android 13+ 要单独申请通知权限(POST_NOTIFICATIONS),Android 14+ 前台服务还要声明服务类型。这些细节直接决定 App 能不能“跑起来”,做 Android 的同学应该都懂。
相关链接
- GitHub:https://github.com/LogicLiu1024/OpenMic
- Gitee(国内镜像):https://gitee.com/logicliu/open-mic
- 许可证:本项目基于 MIT License 开源
版权声明:本文遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
