Quand le palier 1 sur 7 sonne encore trop fort, le curseur n’est pas le problème. La courbe dB, si.
TL;DR
- Sur beaucoup de ROM (dont crDroid 12 / Android 16), le volume sonnerie / alarme / notif n’a que 7 paliers. Trop gros : le palier 1 est déjà trop fort.
- Les commandes ADB (
cmd media_session volume) ne servent qu’à déplacer le curseur dans la plage existante. Si tu es déjà au palier 1, elles ne changent plus rien. En prime, l’alarme a un plancher système à 1 depuis Android 13. - Le vrai levier, c’est la table de conversion index vers dB dans
/vendor/etc/audio_policy_volumes.xml. On abaisse le bas de la courbe pour que le palier minimum sonne beaucoup moins fort. - Ça se fait proprement avec un module Magisk (root requis) qui superpose une version patchée du fichier.
- Deux pièges bien réels : le Magic Mount de Magisk qui échoue en silence (contourné par un
skip_mount+ un bind-mount manuel enpost-fs-data.sh), et le cache d’audioserverqui garde l’ancienne courbe tant qu’on ne l’a pas relancé (killall audioserver) ou fait un vrai reboot à froid. - Résultat : palier 1 passé de -29,7 dB à -45 dB, soit environ 5 à 6 fois plus discret à l’oreille, sans toucher au volume max.
Télécharger le module Magisk « lowvol »
Le problème de départ
Config : crDroid 12, Android 16, root Magisk. Le souci est bête mais quotidien : les sonneries, alarmes et notifications sont trop fortes, même au minimum. Le slider de volume ne propose que 7 crans, et chaque cran fait un bond de plusieurs dB. Résultat, le palier 1 sur 7 est déjà bien trop présent, et le palier 0 coupe carrément le son (ce qui n’est pas le but, on veut « moins fort », pas « muet »).
Deux problèmes distincts se cachent là-dedans, et c’est important de ne pas les confondre :
- Réduire le volume actuel : facile, sans root, via ADB.
- Rendre le palier minimum plus faible : ça touche à la plage de contrôle elle-même, et là il faut mettre les mains dans le cambouis.
Première tentative : ADB (et pourquoi ça bloque vite)
Depuis Android 12, la vieille commande media a laissé place à cmd media_session. Les flux qui nous intéressent sont : 2 = sonnerie (RING), 4 = alarme (ALARM), 5 = notification (NOTIFICATION).
On regarde d’abord où on en est :
adb shell cmd media_session volume --stream 2 --get # sonnerie adb shell cmd media_session volume --stream 4 --get # alarme adb shell cmd media_session volume --stream 5 --get # notification
Et là, la douche froide :
[V] volume is 1 in range [0..7] # RING [V] volume is 1 in range [1..7] # ALARM (plancher à 1 !) [V] volume is 1 in range [0..7] # NOTIFICATION
Les trois flux sont déjà au palier 1, c’est-à-dire au minimum audible. L’alarme, elle, a une plage [1..7] : impossible de descendre sous 1 via ADB, c’est un plancher voulu par Google depuis Android 13 pour éviter qu’on désactive ses alarmes par erreur.
Traduction : baisser le curseur n’est plus une option. Le curseur est déjà en bas. Le problème, c’est que le palier 1 lui-même sonne trop fort. On tient là le vrai coupable : la granularité de 7 crans est trop grossière, et chaque cran représente un gros écart en dB.
Le vrai coupable : la courbe dB
Ce qui décide du volume réel d’un palier, ce n’est pas l’index UI (0 à 7), c’est une table de conversion cachée : pour chaque flux, une liste de points index -> atténuation. Cette table vit dans audio_policy_volumes.xml, et les valeurs y sont exprimées en millibels (mB), pas en décibels. Donc -2970 veut dire -29,7 dB.
On localise le fichier actif :
adb shell su -c "find /vendor /odm /system -iname 'audio_policy_volumes.xml' 2>/dev/null" # -> /vendor/etc/audio_policy_volumes.xml
On le récupère pour l’inspecter :
adb pull /vendor/etc/audio_policy_volumes.xml
Le bloc sonnerie (haut-parleur) ressemble à ça d’origine :
<volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>1,-2970</point>
<point>33,-2010</point>
<point>66,-1020</point>
<point>100,0</point>
</volume>
Le point à l’index bas est à -29,7 dB. Encore trop audible. L’idée : écraser le bas de la courbe (le palier minimum et le milieu) tout en gardant le point à 100 intact, pour ne pas amputer le volume max si un jour on en a besoin.
La solution : patcher la courbe via module Magisk
On ne touche pas /vendor en direct : c’est une partition en lecture seule protégée par dm-verity / AVB, et toute modif serait effacée au reboot. On passe donc par un module Magisk qui superpose une version patchée du fichier au démarrage.
Voici les courbes après patch (RING, ALARM et NOTIFICATION, catégorie SPEAKER) :
<volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>1,-4500</point>
<point>15,-3800</point>
<point>33,-3000</point>
<point>66,-1500</point>
<point>100,0</point>
</volume>
(Structure identique pour AUDIO_STREAM_ALARM, avec 0,-4500 comme premier point puisque l’alarme démarre à 0 dans le fichier, et pour AUDIO_STREAM_NOTIFICATION.)
Ce qui change concrètement :
| Index | Avant | Après | Gain d’atténuation |
| bas (0/1) | -29.7 dB | -45.5 dB | -15.3 dB (env. 5 à 6x plus discret) |
| 15 | (interpolé ~-24) | -38.0 dB | env. -14 dB |
| 33 | -20.1 dB | -30.0 dB | -9.9 dB |
| 66 | -10.2 dB | -15.0 dB | -4.8 dB |
| 100 (max) | 0 dB | 0 dB | inchangé |
Règle de pouce utile : chaque -10 dB correspond à peu près à diviser le volume perçu par deux. Un -15 dB en bas de courbe, c’est donc grosso modo 5 à 6 fois plus discret. Un point intermédiaire à l’index 15 a été ajouté pour lisser la transition entre le palier bas et le reste, histoire d’éviter un saut brutal.
Le tout est empaqueté dans un module minimal :
module.prop vendor/etc/audio_policy_volumes.xml (version patchée)
Avec un module.prop du genre :
id=lowvol_ringalarmnotif name=Low Volume Curves (Ring/Alarm/Notif) version=v1 versionCode=1 author=toi description=Reduit la courbe dB des flux RING/ALARM/NOTIFICATION (SPEAKER) sous crDroid.
On zippe, on installe via Magisk (Modules puis Installer depuis stockage), on reboote. En théorie, c’est fini.
En pratique, c’est là que la vraie aventure commence.
Les pièges rencontrés
Piège 1 : la commande --get ne prouve rien
Après le patch, on refait un --get et on lit toujours volume is 1 in range [0..7]. Panique. En réalité, c’est normal : cette commande n’affiche que l’index UI, jamais le gain dB réellement appliqué. Elle est donc inutile pour valider un patch de courbe. Le seul juge fiable, c’est l’oreille (et, à la marge, dumpsys audio).
Piège 2 : le Magic Mount de Magisk échoue en silence
Premier vrai mur. On vérifie le fichier réellement monté :
adb shell cat /vendor/etc/audio_policy_volumes.xml
Et on voit toujours -2970. Le module est bien listé dans /data/adb/modules/, mais son overlay ne s’applique pas. Sur certains devices / configs Android 16, le Magic Mount de Magisk peut rater un fichier de /vendor sans le moindre log clair.
La parade qui a fonctionné : abandonner le montage automatique et faire un bind-mount manuel garanti. Deux ajouts au module :
- un fichier
skip_mount(vide) qui dit à Magisk de ne pas tenter son overlay auto sur ce module, - un script
post-fs-data.shqui s’exécute très tôt au boot, avantaudioserver, et force le montage :
MODDIR=${0%/*}
mount -o bind "$MODDIR/vendor/etc/audio_policy_volumes.xml" /vendor/etc/audio_policy_volumes.xm
Structure finale du module :
module.prop skip_mount post-fs-data.sh vendor/etc/audio_policy_volumes.xml
Après reboot, on vérifie que le bind est bien actif :
adb shell su -c "mount | grep audio_policy_volumes" adb shell cat /vendor/etc/audio_policy_volumes.xml | grep -m1 "4500"
Cette fois la première commande renvoie une ligne de mount active, et la seconde affiche <point>1,-4500</point>. Le fichier vu par le système est enfin le bon.
Piège 3 : le cache d’audioserver
Le fichier est correct, mais le son peut rester identique. Raison : audioserver lit ces courbes au démarrage et les garde en cache. Si le service a démarré avant ton bind-mount (typiquement au tout premier boot après un flash, quand Magisk n’était pas encore actif), il tourne encore avec l’ancienne courbe.
Pour forcer un rechargement propre sans reboot complet :
adb shell su -c "killall audioserver"adb shell su -c "killall audioserver"
Le service redémarre tout seul et relit la config depuis /vendor. C’est le test le plus fiable pour isoler un problème de cache d’un problème de fichier. À défaut, un vrai reboot à froid (extinction complète puis rallumage, pas un simple redémarrage) fait souvent l’affaire, notamment sur certains chipsets Qualcomm où le HAL audio met les courbes en cache à un niveau bas.
Comment adapter la solution à ton appareil
La démarche est reproductible sur à peu près n’importe quelle ROM AOSP rootée. À ajuster selon ton cas :
- Trouve ton fichier. Il n’est pas toujours dans
/vendor/etc. Lance lefindsur/vendor /odm /system. Certains devices utilisent un nom spécifique au vendor (msmxxxx_audio_policy_volumes.xml) ou mettent les courbes en ligne dansaudio_policy_configuration.xml. Si tu patches le mauvais fichier, rien ne bouge. - Repère tes blocs. Cible bien la bonne
deviceCategory. Pour le haut-parleur du téléphone, c’estDEVICE_CATEGORY_SPEAKER. Pour un casque ou du Bluetooth, ce sont d’autres blocs (souvent desrefvers des courbes par défaut). - Choisis ton atténuation. Les valeurs sont en millibels : -4500 = -45 dB. Trop timide ? Descends encore, par exemple -6000 (-60 dB) pour un quasi-silence au minimum. Garde toujours
100,0intact si tu veux conserver un volume max normal. - Empaquette proprement. Pars directement sur la version robuste :
skip_mount+post-fs-data.shavec bind-mount. Ça évite de perdre une soirée sur un Magic Mount capricieux. - Valide au son, pas au
--get. Règle le palier à 1/7 dans les paramètres, déclenche un aperçu de sonnerie ou une alarme test, compare. En cas de doute,killall audioserveravant de tester. - Itère vite. Si le rendu ne te convient pas, édite le XML dans le module, rezippe, reflashe,
killall audioserver. Chaque tour prend moins de deux minutes une fois le pipeline en place.
Ce qu’il faut garder en tête
- Le patch vit par-dessus
/vendor, une partition en lecture seule. Une mise à jour de crDroid ou un flash « clean » l’annule. Il faudra réinstaller le module après chaque grosse update. - Désactiver Magisk retire aussi le patch, forcément.
- Sans root, il ne reste que les commandes ADB dans la plage 0-7 existante (donc pas grand-chose si tu es déjà au minimum) ou une app tierce type Precise Volume qui applique une atténuation logicielle. C’est une rustine correcte en attendant, mais ça ne remplace pas une vraie modif de courbe côté système.
- Le plancher à 1 sur l’alarme reste, quoi qu’il arrive, mais ce n’est plus gênant une fois la courbe abaissée : le palier 1 est maintenant très doux.
Au final, la clé de toute l’affaire tient en une phrase : sur Android, le volume ressenti d’un palier ne dépend pas du curseur mais de la table dB derrière. Une fois qu’on a compris ça, le reste n’est plus que de la plomberie Magisk.




