Plugin

VolumeBooster

Allows you to set the user and stream volume above the default maximum

Voice Utility
index.ts
Download

Source

src/plugins/volumeBooster/index.ts
1import { definePluginSettings } from "@api/Settings";
2import { Devs } from "@utils/constants";
3import definePlugin, { makeRange, OptionType } from "@utils/types";
4
5const settings = definePluginSettings({
6 multiplier: {
7 description: "Volume Multiplier",
8 type: OptionType.SLIDER,
9 markers: makeRange(1, 5, 0.5),
10 default: 2,
11 stickToMarkers: true,
12 }
13});
14
15interface StreamData {
16 audioContext: AudioContext,
17 audioElement: HTMLAudioElement,
18 emitter: any,
19 // added by this plugin
20 gainNode?: GainNode,
21 id: string,
22 levelNode: AudioWorkletNode,
23 sinkId: string | "default",
24 stream: MediaStream,
25 streamSourceNode?: MediaStreamAudioSourceNode,
26 videoStreamId: string,
27 _mute: boolean,
28 _speakingFlags: number,
29 _volume: number;
30}
31
32export default definePlugin({
33 name: "VolumeBooster",
34 authors: [Devs.Nuckyz, Devs.sadan],
35 description: "Allows you to set the user and stream volume above the default maximum",
36 tags: ["Voice", "Utility"],
37 settings,
38
39 patches: [
40 // Change the max volume for sliders to allow for values above 200
41 {
42 find: "#{intl::USER_VOLUME}",
43 replacement: {
44 match: /(?<=maxValue:)\i\.isPlatformEmbedded\?(\i\.\i):\i\.\i(?=,)/,
45 replace: (_, higherMaxVolume) => `${higherMaxVolume}*$self.settings.store.multiplier`
46 }
47 },
48 // Change the max volume for sliders to allow for values above 200
49 {
50 find: "currentVolume:",
51 replacement: {
52 match: /(?<=maxValue:)\i\.\i\?(\d+?):\d+?(?=,)/,
53 replace: (_, higherMaxVolume) => `${higherMaxVolume}*$self.settings.store.multiplier`
54 }
55 },
56 // Patches needed for web/vesktop
57 {
58 find: "streamSourceNode",
59 predicate: () => !IS_DISCORD_DESKTOP,
60 group: true,
61 replacement: [
62 // Remove rounding algorithm
63 {
64 match: /Math\.max.{0,30}\)\)/,
65 replace: "arguments[0]"
66 },
67 // Fix streams not playing audio until you update them
68 {
69 match: /\}return"video"/,
70 replace: "this.updateAudioElement();$&"
71 },
72 // Patch the volume
73 {
74 match: /\.volume=this\._volume\/100;/,
75 replace: ".volume=0.00;$self.patchVolume(this);"
76 }
77 ]
78 },
79 // Prevent Audio Context Settings sync from trying to sync with values above 200, changing them to 200 before we send to Discord
80 {
81 find: "AudioContextSettingsMigrated",
82 replacement: [
83 {
84 match: /(?<=isLocalMute\(\i,\i\),volume:(\i).+?\(0,\i\.\i\)\(\i,\i,\{volume:)\1(?=\}\))/,
85 replace: "$&>200?200:$&"
86 },
87 {
88 match: /(?<=Object\.entries\(\i\.localMutes\).+?volume:).+?(?=,)/,
89 replace: "$&>200?200:$&"
90 },
91 {
92 match: /(?<=Object\.entries\(\i\.localVolumes\).+?volume:).+?(?=})/,
93 replace: "$&>200?200:$&"
94 }
95 ]
96 },
97 // Prevent the MediaEngineStore from overwriting our LocalVolumes above 200 with the ones the Discord Audio Context Settings sync sends
98 {
99 find: &#039;="MediaEngineStore",&#039;,
100 replacement: [
101 {
102 match: /(\.settings\.audioContextSettings.+?)(\i\[\i\])=(\i\.volume)(.+?setLocalVolume\(\i,).+?\)/,
103 replace: (_, rest1, localVolume, syncVolume, rest2) => rest1
104 + `(${localVolume}>200?void 0:${localVolume}=${syncVolume})`
105 + rest2
106 + `${localVolume}??${syncVolume})`
107 }
108 ]
109 }
110 ],
111
112 patchVolume(data: StreamData) {
113 if (data.stream.getAudioTracks().length === 0) return;
114
115 data.streamSourceNode ??= data.audioContext.createMediaStreamSource(data.stream);
116
117 if (!data.gainNode) {
118 const gain = data.gainNode = data.audioContext.createGain();
119 data.streamSourceNode.connect(gain);
120 gain.connect(data.audioContext.destination);
121 }
122
123 // @ts-expect-error
124 if (data.sinkId != null && data.sinkId !== data.audioContext.sinkId && "setSinkId" in AudioContext.prototype) {
125 // @ts-expect-error https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/setSinkId
126 data.audioContext.setSinkId(data.sinkId === "default" ? "" : data.sinkId);
127 }
128
129 data.gainNode.gain.value = data._mute
130 ? 0
131 : data._volume / 100;
132 }
133});
134