Measured on a real RV101: which channel carries your voice, which carry the room, and the claims I had to take back.
This is an English adaptation of an article I originally published in Japanese on Zenn: Rokid Glasses のマイクは 4ch で使える. The measurements and conclusions are mine; I used an AI tool to help translate and restructure the text, and I checked the numbers against the original.
Scope first
This article is about recording audio on the glasses themselves: an Android app running on the Rokid Glasses (RV101, YodaOS-Sprite / Android) and opening AudioRecord directly. It is not about the phone-side CXR-M SDK, which documents its own near-field / far-field / panoramic pickup modes. The two are easy to mix up; nothing below applies to the phone SDK.
Everything here was measured on one unit, on firmware 1.25.012. I later re-checked the structure on 1.25.015, 1.26.011, 1.27.009 and 1.28.016 (details at the end). Treat this as a measurement log of one device, not as a specification.
TL;DR
- An app on the glasses can get 4 distinct microphone channels, but only when it requests exactly 4. With
MIC, asking for 1, 2, 3, 6 or 8 channels gives you copies of a single stream (plus zero-filled channels). - What each of the 4 channels contains depends on the
AudioSource. WithUNPROCESSED: a voice-heavy stream, a copy of it, and 2 room-sound streams. WithMIC: one processed stream that keeps your voice and suppresses the room, plus 3 room-sound streams. -
VOICE_RECOGNITIONopens without error but returns all zeros on this device, no matter how many channels you request. - Opening a second
AudioRecordin the same app stops the first one (readreturns-6). - Measure your own unit before relying on any of this.
1. Requesting 4 channels
This started with a report I saw on X (paraphrased; the report counts channels from 1, while this article counts from ch0): "Rokid Glasses can record 4 channels", "channels 1 and 2 are the same data", "channels 3 and 4 are in phase", "channels 1 and 2 are DSP-processed", "maybe it's the pickup-mode switch in the translation app". That contradicted something I had written earlier in my series: that apps can use 2 microphones.
The reason for the contradiction was quick to find. My earlier claim was based on getMicrophones() returning two built-in microphones with different hardware ids, and on logs from a session opened as a single channel (equivalent to CHANNEL_IN_MONO). Every configuration I had tried was 1 or 2 channels. I had only asked for 2, so I only got 2. I never tried the configurations I hadn't asked for.
You can't express 4 or more channels cleanly with position masks (CHANNEL_IN_MONO / CHANNEL_IN_STEREO). A channel index mask lets you request the count directly:
new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setSampleRate(48000) .setChannelIndexMask((1 << 4) - 1) // request exactly 4 channels .build(); Two pitfalls:
-
AudioRecord.getMinBufferSize()does not accept an index mask. It only accepts the mono/stereo position masks and returnsERROR_BAD_VALUEfor anything else. Size the buffer yourself. My test app used half a second:ch × rate × 2 / 2bytes. - If you compute the recording size in milliseconds as
ch × rate × 2 × ms, then 48 kHz × 8 ch × 3,000 ms overflowsintand the app crashes withNegativeArraySizeException. In my first sweep, 48 kHz / 8 ch was the only configuration that crashed, for this reason. Uselong.
I tested by brute force: 4 sources × 2 sample rates × 6 channel counts (MIC / UNPROCESSED / VOICE_RECOGNITION / CAMCORDER, 16 kHz / 48 kHz, 1/2/3/4/6/8 channels). Each configuration was opened in turn, recorded for 3 seconds, and saved with the configuration in the file name. Checking whether a configuration opens is not enough: some configurations initialize successfully and then return all zeros, so I read the data and computed the RMS of every channel. The test app is called jp.example.micprobe here as an example name.
2. What the sweep showed
RMS per channel in dBFS, quiet room, 48 kHz, 4 channels requested:
| Source | 4ch | ch0 / ch1 / ch2 / ch3 |
|---|---|---|
MIC | yes | −91.4 / −74.4 / −73.2 / −75.5 |
UNPROCESSED | yes | −84.3 / −84.3 / −83.6 / −83.3 |
CAMCORDER | yes | −86.5 / −72.8 / −72.0 / −73.3 |
VOICE_RECOGNITION | opens, but | zero / zero / zero / zero |
With MIC and CAMCORDER, only ch0 is 14–17 dB lower; with UNPROCESSED all four are level. VOICE_RECOGNITION stays all-zero however many channels you request. If you record from your own app on this device, use MIC or UNPROCESSED. (The built-in features open the microphones a different way; see section 9.)
The important part: you only get 4 real channels when you request exactly 4. Counting how many distinct streams actually come back for each requested channel count (8 ch measured at 16 kHz, the rest at 48 kHz; CAMCORDER behaves like MIC):
| Requested | Non-zero channels | MIC: distinct streams | UNPROCESSED: distinct streams |
|---|---|---|---|
| 1 ch | 1 | 1 | 1 |
| 2 ch | 2 | 1 (duplicate of the same data) | 2 (separate; content not checked) |
| 3 ch | 2 | 1 (+1 zero) | 2 (+1 zero) |
| 4 ch | 4 | 4 (the only case with 4) | 3 (ch0 = copy of ch1, + 2) |
| 6 ch | 2 | 1 (+4 zero) | 2 (+4 zero) |
| 8 ch | 2 | 1 (+6 zero) | 2 (+6 zero) |
With MIC at 2 channels, ch0 == ch1 is a bit-exact match (correlation +1.0000, lag 0): the same single stream in two slots. In other words, the number of microphones returned by getMicrophones() is not a cap on the channel count. With MIC and CAMCORDER, you cannot get the room-side streams unless you request exactly 4. With UNPROCESSED, 2 channels already gives two different streams, but I did not check whether those two are voice-side or room-side.
3. Sine tones: what is ch0?
I played 500 / 1000 / 2000 / 4000 Hz tones from a PC speaker, recorded 4 channels, and measured the phase difference and amplitude ratio between channels from the FFT. (Why a PC speaker and not the glasses' own speaker: see section 10.)
Amplitude of ch0, relative to the channel that picked up each frequency best:
| Frequency | MIC ch0 | UNPROCESSED ch0 |
|---|---|---|
| 500 Hz | −98.2 dB | −7.3 dB |
| 1000 Hz | −98.1 dB | −2.4 dB |
| 2000 Hz | −28.8 dB | −6.1 dB |
| 4000 Hz | −72.1 dB | −4.2 dB |
Same microphones, same sound, same 4-channel request. Changing only the AudioSource changes ch0 by more than 90 dB at most. The MIC / CAMCORDER ch0 is a DSP-processed channel (which is also why it produces stretches of exact digital zero in a quiet room).
ch1–ch3, on the other hand, line up in phase even though the two sources were recorded separately. The phase difference of ch3, expressed as a distance:
| Frequency | MIC ch3 | UNPROCESSED ch3 |
|---|---|---|
| 2000 Hz | −42.3 mm | −42.6 mm |
| 4000 Hz | −30.5 mm | −30.6 mm |
So ch1–ch3 carry the same microphone signals under both sources; only ch0 is swapped. With UNPROCESSED, the amplitude ratio and phase of ch0 and ch1 matched to the decimal at every frequency, consistent with the bit-exact match. With UNPROCESSED, the slot that holds the processed stream under MIC holds a copy of ch1 instead. (Whether that ch1 is truly unprocessed, I did not verify; see section 5.)
4. Wearing the glasses and talking
Next I wore the glasses and recorded 4 channels for 60 seconds: silent for the first 28 seconds, talking for the last 30. No speaker playback, just my own voice.
| ch0 | ch1 | ch2 | ch3 | |
|---|---|---|---|---|
MIC silent | −104 | −77.6 | −77.3 | −77.3 |
MIC talking | −33 | −46.5 | −45.1 | −43.3 |
MIC rise | +71 dB | +31 | +32 | +34 |
UNPROC silent | −83.7 | −83.7 | −83.1 | −82.8 |
UNPROC talking | −40 | −40 | −53 | −52 |
UNPROC rise | +44 dB | +44 | +30 | +31 |
Only MIC ch0 flips position: about 27 dB below the others when I'm silent, 10–13 dB above them when I talk. Comparing the rise, the contrast between voice and room sound improves by about 40 dB.
Correlation coefficients during speech show what each slot holds:
| ch0-ch1 | ch1-ch2 | ch1-ch3 | ch2-ch3 | |
|---|---|---|---|---|
UNPROCESSED | +1.000 | +0.436 | +0.469 | +0.981 |
MIC | −0.109 | +0.990 | +0.954 | +0.979 |
Under UNPROCESSED, the voice-side pair (ch0 = ch1) correlates with the room-side channels at about 0.44. Under MIC, ch1 correlates with ch2/ch3 at 0.95–0.99. Same "4 channels", different meaning per slot depending on the AudioSource:
UNPROCESSED : ch0 = ch1 = voice-side (bit-identical copy) ch2, ch3 = room-side (2) MIC : ch0 = processed (uncorrelated with all) ch1, ch2, ch3 = room-side (3) 
Figure (labels in Japanese): the four slots ch0–ch3 for each source. UNPROCESSED: ch0 and ch1 hold the same voice-side data (ch1 is a copy of ch0), ch2 and ch3 hold room sound. MIC: ch0 holds the voice-side stream with suppression applied, ch1–ch3 hold room sound. "Voice-side" and "room-side" are my labels.
Note on the labels: "voice-side" and "room-side" are my own names. They do not describe a confirmed physical microphone layout. As the next sections explain, I could not determine the physical layout.
When I first saw this, I started writing "the hardware is 1 voice mic + 3 room mics". That goes too far. A correlation of 0.99 can come from separate physical elements or from the same element with different processing, and the number of room-side streams doesn't even agree between sources (2 under UNPROCESSED, 3 under MIC). What I can say is: under MIC, the 4 channels are one processed stream plus three mutually distinct streams.
5. Spectral ratio, and the explanation I withdrew
I computed the spectral ratio of the voice-side channel (ch0) to a room-side channel (ch2), separately for speech and silence. Values in dB:
| Band | UNPROC speech | UNPROC silence | MIC speech | MIC silence |
|---|---|---|---|---|
| 100–300 Hz | +12.8 | −0.6 | +12.0 | −24.0 |
| 600–1200 Hz | +11.9 | −0.4 | +11.9 | −20.5 |
| 2400–4800 Hz | +12.1 | −0.6 | +11.7 | −16.4 |
| 4800–9600 Hz | +11.3 | +0.3 | +11.7 | −15.9 |

Figure (labels in Japanese): bar chart of the ch0 ÷ ch2 level difference per band. During speech, both UNPROCESSED and MIC are about +12 dB across all bands. During silence, UNPROCESSED is about 0 dB and MIC is about −18 to −25 dB. The chart was recomputed from raw data and differs from the table by a few dB.
The ch0–ch2 delay during speech was also essentially zero across bands (split into three bands from 300 to 8000 Hz, all within 1 cm). Three things can be read from this: in silence, all bands are within ±1 dB (ch0 is as sensitive to the room as the room-side channels); during speech, a flat +12 dB across all bands (no frequency dependence, so neither a low-frequency-heavy bone-conduction path nor a high-frequency-heavy acoustic horn); and zero delay.
At this point I once wrote: "the +12 dB comes from physics (directional placement), so a dedicated mouth-facing microphone physically exists." I withdrew that. The same observations can be explained by beamforming output synthesized from 8 channels: a directional synthesis also boosts only the nearby voice, averages out room sound, and shows no delay if everything is time-aligned within one stream. And the guarantee that UNPROCESSED is truly unprocessed is Android's intent, not something I verified this ROM honors. So I cannot tell whether the +12 dB comes from physical placement or from synthesis.
What I can say is limited to this: what MIC adds is suppression (it drops ch0 by 16–24 dB during silence). The +12 dB voice emphasis is already present under UNPROCESSED. Combined, the per-band level difference gives about 32 dB of contrast improvement. (The "about 40 dB" in section 4 comes from the RMS rise, a different calculation.)
6. Other hypotheses I withdrew, and what survived
To estimate the physical layout, I went as far as chirps (200→8000 Hz sweeps ×3), ESS impulse responses, and direct-sound detection (first point above 35% of the peak). The values changed from measurement to measurement (ch0–ch3 went from −26.7 mm to +70.3 mm). Reverberation dominates, and a single sine or chirp can't give you the physical layout. Withdrawn.
For the same reason, I withdrew "ch2 and ch3 have different frequency responses" (the 4–8 kHz difference changed from −4.1 dB to +0.6 dB, which room position explains). The X report's "channels 1 and 3 have different acoustic characteristics / channels 3 and 4 are the same" (counted from 1) is something my measurements could neither confirm nor rule out.
The only thing that survived is ch0 == ch1. It reproduces every time at +0.00 samples, spread 0.00. It's data identity, not acoustics, so the room doesn't affect it.
7. Physical vs. synthesized can't be decided from outside
On reflection, this was never a measurement-technique problem. A physical directional microphone and linear beamforming are both linear, time-invariant, and direction-dependent. A linearity test (vary the input level and check whether the ratio stays constant) can tell you whether non-linear processing (suppression, AGC) is present, but it cannot separate "a single directional element" from "a linear synthesis".
There is weak circumstantial evidence. Beamforming usually loses directivity at low frequencies, where the wavelength is longer than the element spacing. Yet the measured boost is +12.8 dB even at 100–300 Hz and flat from 100 Hz to 9.6 kHz. That leans toward a single directional element, but adaptive beamforming can create directivity at low frequencies too, so it is not decisive. I'm closing this line of inquiry here.
8. Opening two recordings in one app: the later one wins
While trying to separate these, I opened MIC and UNPROCESSED at the same time in the same app. The result was symmetric:
Open MIC first -> MIC returns -6 on read and stops; UNPROCESSED is used Open UNPROCESSED first -> UNPROCESSED returns -6 and stops; MIC is used -6 is ERROR_DEAD_OBJECT. Both sessions report STATE_INITIALIZED, but opening the second one stops the first.
This is a different situation from another thing I checked: my recording kept running while the built-in AI assistant was active (worn, one A/B trial each way). That was coexistence across processes with a system service (uid 1000). This section is about two recordings inside your own app.
9. The official apps open 8 channels
I switched the pickup scenes in the translation feature (Hi Rokid) and looked at how the recording session was opened, via the openAudioRecord2 log line. Its mode changes per scene:
| Pickup scene | mode | channelMask | denoiseMode |
|---|---|---|---|
| Lecture / movie | 7 | 0x6000fc (8 channels) | −1 |
| Face-to-face conversation | 1 | 0x6000fc (8 channels) | −1 |
| Phone audio | 8 | 0x10 (1 channel, inputSource 500) * | −1 |
| (reference) Built-in AI | 2 | 0x6000fc (8 channels) | 2 |
* The phone-audio row was measured on firmware 1.27.009 (same in all 4 trials). On 1.25.012 it was 0x6000fc (8 channels).
For the scenes that use the microphones (lecture/movie, face-to-face) and for the built-in AI, channelMask is 0x6000fc (8 bits set), and switching scenes does not change the channel count; only mode changes. The intent is trans_ali for translation and AI_assistant for the built-in AI. Only the built-in AI uses suppression (denoiseMode 2). On 1.27.009, the phone-audio scene (translating audio playing on the phone) did not use the glasses' microphones; it opened 1 channel from an input that is not a standard AudioSource (inputSource 500).
What is observation and what is not:
- Inference: that
modecorresponds to the pickup scene. The log doesn't say whatmodemeans. - Inference: that
inputSource 500is audio coming from the phone. I did not check what500is. - I captured each scene only once; reproducibility is unconfirmed.
Capture notes: openAudioRecord2 is logged only once, when a recording session starts, so you have to reopen the translation feature (clearing the log while it's open shows nothing). Translation does not appear in dumpsys audio. A scene change made on the phone sometimes doesn't reach the glasses immediately (check the indicator at the bottom of the display).
So, when the built-in translation and AI assistant use the microphones, they handle 8 channels through their own way of opening the device. From an app, the most I could get as separate streams was 4.
This ties back to section 7: since the built-in AI uses 8 channels, it is if anything more plausible that the 4 channels an app receives are synthesized from those 8. That is exactly why "physical or synthesized" is hard to decide from outside.
10. Measurement traps
- Don't rely on synchronization. The recording start and playback start were measured 4 seconds apart. Make the analysis side search for where the tone is.
- Don't
adb pullbefore the recording finishes. You'll grab the previous file. I nearly drew a wrong conclusion this way once. - Sound played from the glasses' own speaker does not reach the recording. I assume the echo canceller (AEC) removes it, but I have no direct evidence. Using a PC speaker as the sound source turned out to be necessary, not just convenient.
11. If you're implementing this
- If you want the room-side streams reliably, request exactly 4 channels. Under
MIC/CAMCORDER, 1/2/3/6/8 channels collapse to copies of one stream. UnderUNPROCESSED, 2/3/6/8 channels give two separate streams, but I haven't checked what they contain. - The
AudioSourcechanges what each channel means. For just your own voice,MICch0 (processed). For room sound,UNPROCESSEDch2/ch3. - Open one recording at a time per app. Opening a second one stops the first.
- Above all, measure your own unit before relying on this. Source/channel assignments can change with firmware and model, and every number here comes from one device on the firmware of the time.
Firmware notes
All measurements in the body were taken on my unit on firmware 1.25.012, and results may differ in your environment.
- 1.25.015: re-ran only the sweep. The structure was unchanged: 4 distinct streams only with a 4-channel request,
ch0 == ch1,VOICE_RECOGNITIONall zero. (Absolute RMS values move with room noise, so the numbers above are from the original measurement.) - 1.26.011: checked only that
VOICE_RECOGNITIONis still all zero. - 1.27.009 and 1.28.016: the 4-channel slot layout, the number of streams per requested channel count, and the two-recordings behavior were the same. Room-dependent values such as ch0 during silence differed by several to a dozen-plus dB. Only the phone-audio row in section 9 changed, on 1.27.009, so that table shows the 1.27.009 value. On 1.28.016 I did not measure the talk/silence comparison (section 4) or how the official apps open the microphones (section 9).
About this series
This is part of my Japanese-language series on building my own apps for the Rokid Glasses (RV101): setup, a conversation-support app, input handling, and audio. The original article and the rest of the series are on Zenn: Rokid Glasses のマイクは 4ch で使える(original, Japanese). There is also a free Zenn book (Japanese) that walks through getting your own app running on the RV101 from scratch: Rokid Glasses(RV101)を買ってから、自分のアプリが動くまで.

