Thread Tools Display Modes
01-07-18, 10:23 PM   #1
Krainz
A Wyrmkin Dreamwalker
Join Date: Oct 2016
Posts: 57
Queue ready sound -> play at 100% volume?

Hi, I made a custom sound for readycheck and LFG queue ready and I wanted to know if there's a way to make it play at 100% master volume instead of the current value.

The reason is: the actual sound file isn't loud enough and amplifying its dB results in a lot of noise.

Is it possible to make it play at 100% volume through code?
  Reply With Quote
01-08-18, 05:53 PM   #2
Kanegasi
A Molten Giant
 
Kanegasi's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2007
Posts: 666
EDIT: neither of these work, see this post for one that does

If you replaced the sound using the filepath trick (World of Warcraft\Sound etc):

Lua Code:
  1. local f=CreateFrame('frame')
  2. f:SetScript('OnEvent',function(self,_,handle)
  3.     if handle==self.handle then
  4.         SetCVar('Sound_MasterVolume',self.master)
  5.     end
  6. end)
  7. f:RegisterEvent('SOUNDKIT_FINISHED')
  8. hooksecurefunc('PlaySound',function(id,_,_,_,_,_,_,own)
  9.     if id==8960 and not own then
  10.         local played,handle=PlaySound(64,'Master',false)
  11.         if played and handle then
  12.             StopSound(handle) StopSound(handle-1)
  13.             played,handle=PlaySound(8960,'Master',true,true,nil,nil,nil,true)
  14.             if played and handle then
  15.                 f.handle=handle
  16.                 f.master=GetCVar('Sound_MasterVolume')
  17.                 SetCVar('Sound_MasterVolume',1)
  18.             end
  19.         end
  20.     end
  21. end)


If your sound is just in a folder (for example, Interface\AddOns\YourAddOn\sound.ogg):

Lua Code:
  1. local f=CreateFrame('frame')
  2. f:SetScript('OnEvent',function(self,_,handle)
  3.     if handle==self.handle then
  4.         SetCVar('Sound_MasterVolume',self.master)
  5.     end
  6. end)
  7. f:RegisterEvent('SOUNDKIT_FINISHED')
  8. hooksecurefunc('PlaySound',function(id)
  9.     if id==8960 then
  10.         local played,handle=PlaySound(64,'Master',false)
  11.         if played and handle then
  12.             StopSound(handle) StopSound(handle-1)
  13.             played,handle=PlaySoundFile('Interface\\path\\to\\sound.ogg','Master',true,true)
  14.             if played and handle then
  15.                 f.handle=handle
  16.                 f.master=GetCVar('Sound_MasterVolume')
  17.                 SetCVar('Sound_MasterVolume',1)
  18.             end
  19.         end
  20.     end
  21. end)


Just in case you aren't sure what to do with this, go to http://addon.bool.no, name this whatever you want at the top, copy one of these pieces of code into the big box, then download and install like any other addon.

Last edited by Kanegasi : 01-11-18 at 07:12 PM. Reason: doesn't work, new code in linked post
  Reply With Quote
01-08-18, 08:44 PM   #3
Krainz
A Wyrmkin Dreamwalker
Join Date: Oct 2016
Posts: 57
The first option doesn't work. When I use the addon (first one), the sound either doesn't play or plays at 0 volume.

The sound's directory is Sound\\Interface\\levelup2.ogg

The second option works very well when I put the file location above ^ in there.

Thank you very much!
  Reply With Quote
01-08-18, 09:03 PM   #4
Kanegasi
A Molten Giant
 
Kanegasi's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2007
Posts: 666
That's not the readycheck sound path, that's the levelup sound path, which is also the same sound as guild invites. The correct path is sound/interface/readycheck.ogg unless you want your custom sound to play whenever you level up or get a guild invite.

Since you're using the second code, you might as well just put your file in the addon folder you just installed with the code and use that path. The default ready check sound will still be replaced, since the code is looking for that id specifically, and the levelup sound will be untouched. When you move the file, make sure to quit and restart WoW.

I'm glad the code works in any case.

Last edited by Kanegasi : 01-08-18 at 09:18 PM.
  Reply With Quote
01-10-18, 12:26 PM   #5
Krainz
A Wyrmkin Dreamwalker
Join Date: Oct 2016
Posts: 57
The sound volume doesn't seem to be returning to the previous value after changing to 100% master.
  Reply With Quote
01-11-18, 07:10 PM   #6
Kanegasi
A Molten Giant
 
Kanegasi's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2007
Posts: 666
  1. My apologies, I did some testing this time.
  2. I was wrong, it really is levelup2.ogg. Damn Blizzard spaghetti code.
  3. The second code didn't work because apparently PlaySoundFile doesn't actually work exactly like PlaySound does, despite my assumption. It only has file and channel for arguments, no new fourth argument and I could've sworn it had noDupe but it doesn't. Good thing to know now lol.
  4. The first code didn't work because the UI plays sounds with no duplicates by default and apparently StopSound doesn't release that "lock" in the same frame you try to play the sound again. So, I had to use an OnUpdate script to play the sound a frame later. You won't notice the frame skip. There was also an issue with honoring no duplicates, the sound would start over if the UI or anything else using the sound wanted no duplicates and tried to play it again. While accounting for both of these issues, I went further and allowed the sound to play at 100% on any channel requested, master by default. Other code can even overlap the sound, the volume will go back down once the last duplicate is done. I think I went a bit overboard, but I'm satisfied with how it turned out.

I can now guarantee the following code works, keep your custom sound in the levelup2.ogg file path. If the sound ever changes in the future, just change the number at the very top along with finding the new file path. I doubt that would happen though.

Lua Code:
  1. local readycheck=8960 -- Sound\\Interface\\levelup2.ogg
  2. local pool,f={},CreateFrame('frame') f.handle={} f.last={}
  3. function f.pool(t,i)
  4.     if i then pool[i]:SetScript('OnUpdate',nil) pool[i].t=nil return end
  5.     for i=1,#pool do
  6.         if pool[i] and not pool[i].t then pool[i].t={i=i,t=t} return i end
  7.     end
  8.     tinsert(pool,CreateFrame('frame')) i=#pool pool[i].t={i=i,t=t} return i
  9. end
  10. f:SetScript('OnEvent',function(_,_,handle)
  11.     if f.nodupe==handle then f.nodupe=nil end
  12.     if f.handle[handle] then
  13.         if f[f.handle[handle]] and f.last[f.handle[handle]]==handle then
  14.             SetCVar(f.handle[handle],f[f.handle[handle]])
  15.             f[f.handle[handle]]=nil
  16.         end
  17.         f.handle[handle]=nil
  18.     end
  19. end)
  20. f:RegisterEvent('SOUNDKIT_FINISHED')
  21. hooksecurefunc('PlaySound',function(id,channel,nodupe,_,_,_,_,own)
  22.     if id==readycheck and not f.nodupe and not own then
  23.         local _,handle=PlaySound(64,'Master',false)
  24.         if handle then
  25.             StopSound(handle) StopSound(handle-1)
  26.             channel=(not channel and 'Master') or (strlower(channel)=='sfx' and 'SFX') or strlower(channel):gsub('^%a',strupper)
  27.             local cvar='Sound_'..channel..'Volume'
  28.             pool[f.pool({id,channel,nodupe,cvar})]:SetScript('OnUpdate',function(self)
  29.                 local _,handle=PlaySound(self.t.t[1],self.t.t[2],self.t.t[3],true,nil,nil,nil,true)
  30.                 if handle then
  31.                     if self.t.t[3]~=false then f.nodupe=handle end
  32.                     f.last[self.t.t[4]]=handle
  33.                     f.handle[handle]=self.t.t[4]
  34.                     if not f[self.t.t[4]] then
  35.                         f[self.t.t[4]]=GetCVar(self.t.t[4])
  36.                         if f[self.t.t[4]] then SetCVar(self.t.t[4],1) end
  37.                     end
  38.                 end
  39.                 f.pool('',self.t.i)
  40.             end)
  41.         end
  42.     end
  43. end)


Some tests you can run:

Code:
 -- exactly what the UI does, will play on master at 100%, using it again will do nothing while the sound is playing
/run PlaySound(8960)

 -- each line will still only play one sound, the last one in each line chooses the channel (which is weird, one would think the first one would go first)
/run PlaySound(8960,'master')PlaySound(8960,'sfx')PlaySound(8960,'dialog')
/run PlaySound(8960,'sfx')PlaySound(8960,'dialog')PlaySound(8960,'master')
/run PlaySound(8960,'dialog')PlaySound(8960,'master')PlaySound(8960,'sfx')

 -- plays two overlapping sounds at 100% on master
/run PlaySound(8960,nil,false)PlaySound(8960,nil,false)

 -- (WARNING: LOUD) will play five overlapping sounds using all five channels, all at 100%
/run PlaySound(8960,'master',false)PlaySound(8960,'ambience',false)PlaySound(8960,'dialog',false)PlaySound(8960,'music',false)PlaySound(8960,'sfx',false)

Last edited by Kanegasi : 01-11-18 at 07:15 PM.
  Reply With Quote
01-17-18, 11:10 AM   #7
Krainz
A Wyrmkin Dreamwalker
Join Date: Oct 2016
Posts: 57
Smile

Thanks Kanegasi!!
  Reply With Quote
06-25-19, 09:06 PM   #8
Krainz
A Wyrmkin Dreamwalker
Join Date: Oct 2016
Posts: 57
Sorry for necro-ing this thread, but the issue is directly related to this addon.

Apparently they've changed the filenames and sound\interface\levelup2.ogg doesn't work anymore.

Is there a way to finding out what's the new filename?

EDIT: it seems that Blizzard has completely obliterated the approach of creating a Sound\ folder and putting stuff in there to replace their sound effects.

What's a possible solution for this? Is there a way to make their readycheck sound mute and play my modified one instead?

Last edited by Krainz : 06-26-19 at 08:05 AM.
  Reply With Quote
06-11-20, 05:07 PM   #9
Kanegasi
A Molten Giant
 
Kanegasi's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2007
Posts: 666
I received a private message asking to customize the volume in my code. I also didn't notice the last post here. Here's an updated code that allows you to replace any UI sound (anything that uses PlaySound) with a custom sound OR adjust the volume of a UI sound.

Lua Code:
  1. local entries={
  2.     [8960]=1 -- ready check
  3.  -- [ID]="path\\to\\sound"
  4.  -- [ID]=volume
  5. }
  6.  
  7.  -- the table above is where you enter the sound ID you want to change,
  8.  -- with the volume you want it at OR the path to a custom sound you want.
  9.  -- for example, [8960]=0.7 will play the ready check sound at 70%.
  10.  -- a custom example of [8960]="chicken.ogg" will play the sound file at
  11.  -- World of Warcraft\_retail_\chicken.ogg instead of the default ready check.
  12.  
  13.  -- custom sounds can be placed alone anywhere in the running client's folder,
  14.  -- they do not need to be used by another addon. Examples:
  15.  -- _retail_\Sound\chicken.ogg
  16.  -- _classic_\Interface\AddOns\chicken.ogg
  17.  -- _classic_\WTF\chicken.ogg
  18.  -- _retail_\ASDFGHJKL\chicken.ogg
  19.  -- the path needed here is everything AFTER the _retail_ or _classic_ folder,
  20.  -- the sound file has to be there when WoW is started to be recognized.
  21.  
  22.  -- this code is unable to control the volume of a custom sound,
  23.  -- you have to adjust the volume of the sound file itself.
  24.  -- PlaySoundFile also does not guarantee no dupes.
  25.  
  26. local pool,f={},CreateFrame('frame') f.handles={} f.lastchan={} f.nodupeids={} f.nodupehandles={}
  27. function f.pool(t,i)
  28.     if i then pool[i]:SetScript('OnUpdate',nil) pool[i].t=nil return end
  29.     for i=1,#pool do
  30.         if pool[i] and not pool[i].t then pool[i].t={i=i,t=t} return i end
  31.     end
  32.     tinsert(pool,CreateFrame('frame')) i=#pool pool[i].t={i=i,t=t} return i
  33. end
  34. f:SetScript('OnEvent',function(_,_,handle)
  35.     if f.nodupehandles[handle] then
  36.         f.nodupeids[f.nodupehandles[handle]]=nil
  37.         f.nodupehandles[handle]=nil
  38.     end
  39.     if f.handles[handle] then
  40.         if f[f.handles[handle]] and f.lastchan[f.handles[handle]]==handle then
  41.             SetCVar(f.handles[handle],f[f.handles[handle]])
  42.             f[f.handles[handle]]=nil
  43.         end
  44.         f.handles[handle]=nil
  45.     end
  46. end)
  47. f:RegisterEvent('SOUNDKIT_FINISHED')
  48. hooksecurefunc('PlaySound',function(id,channel,nodupe,_,_,_,_,own)
  49.     if not own and not f.nodupeids[id] and entries[id] then
  50.         local _,handle=PlaySound(64,'Master',false)
  51.         if handle then
  52.             StopSound(handle) StopSound(handle-1)
  53.             channel=(not channel and 'Master') or (strlower(channel)=='sfx' and 'SFX') or strlower(channel):gsub('^%a',strupper)
  54.             local cvar='Sound_'..channel..'Volume'
  55.             pool[f.pool({id,channel,nodupe,cvar})]:SetScript('OnUpdate',function(self)
  56.                 local handle=nil
  57.                 if type(entries[self.t.t[1]])=="string" then
  58.                     _,handle=PlaySoundFile(entries[self.t.t[1]],self.t.t[2],self.t.t[3])
  59.                 else
  60.                     _,handle=PlaySound(self.t.t[1],self.t.t[2],self.t.t[3],true,nil,nil,nil,true)
  61.                 end
  62.                 if type(entries[self.t.t[1]])=="number" and handle then
  63.                     if self.t.t[3]~=false then
  64.                         f.nodupeids[self.t.t[1]]=handle
  65.                         f.nodupehandles[handle]=self.t.t[1]
  66.                     end
  67.                     f.lastchan[self.t.t[4]]=handle
  68.                     f.handles[handle]=self.t.t[4]
  69.                     if not f[self.t.t[4]] then
  70.                         f[self.t.t[4]]=GetCVar(self.t.t[4])
  71.                         if f[self.t.t[4]] then SetCVar(self.t.t[4],entries[self.t.t[1]]) end
  72.                     end
  73.                 end
  74.                 f.pool('',self.t.i)
  75.             end)
  76.         end
  77.     end
  78. end)
  Reply With Quote
03-03-21, 03:22 PM   #10
phrenetic
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Jan 2007
Posts: 5
@Kanegasi

i'm trying to set replacement for (eg. rdycheck) and to set level for the same. But seems it doesn't count the part about the volume. to make this easier, here is my config

Code:
local entries={
    [8960]="Interface\\AddOns\\[ph] SharedMedia\\Media\\Sounds\\stealth.ogg" -- ready check
    [ID]=0.5
}
  Reply With Quote

WoWInterface » AddOns, Compilations, Macros » AddOn Search/Requests » Queue ready sound -> play at 100% volume?

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off