I am trying to set the sound volume, but the volume doesn't change no matter what volume I set.
start:
invoke mixerOpen,ADDR MixerHandle,0,0,0,0
invoke midiOutSetVolume,MixerHandle,0 ; 0 = silence ffff(65550) = max volume
invoke PlaySound,addr Sound,hInstance,SND_FILENAME or SND_SYNC
invoke ExitProcess,0
you are probably setting the level for a device other than the WAV device
i.e., there are more than one "volume" levels to set
the master level, and one for each "device"
by double-clicking on the volume control, you can see the mixer
you should be able to observe level changes as your program makes them
i think MIDI uses the SW Synth device
PlaySound uses the WAV device
also - when you run windows media player, it (for some reason) sets some of the device levels
you may have to re-set them each time you use them
I modified Greg's code. It set the speaker to 50% volume.
I have some code where I want to pump up the volume of a sound file and then return it to normal
at the program completion.
If the speaker is muted, it doesn't work.
Next project is to learn how to unmute it.
; SetSpeakerVolume.asm
;
; Original code by Greg Lyon - 2005
;
.586
.MODEL FLAT, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc
include \masm32\include\ole32.inc
include \masm32\include\msvcrt.inc
include \masm32\include\winmm.inc
include \masm32\include\advapi32.inc
include \masm32\include\dialogs.inc
include \masm32\macros\macros.asm
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
includelib \masm32\lib\ole32.lib
includelib \masm32\lib\msvcrt.lib
includelib \masm32\lib\winmm.lib
includelib \masm32\lib\advapi32.lib
EndOfString PROTO pString:PTR BYTE
IsNumericString PROTO pString:PTR BYTE
;ConvertPercent PROTO percent:DWORD
udtoa PROTO dwValue:DWORD, lpBuffer:PTR BYTE
.CONST
szTitle BYTE "Set Speaker Volume", 0
.DATA?
MyMixerLine MIXERLINE <?>
MyMixerControl MIXERCONTROL <?>
MyMixerLineControls MIXERLINECONTROLS <?>
MyMixerControlDetails MIXERCONTROLDETAILS <?>
MyMixerControlDetails_U MIXERCONTROLDETAILS_UNSIGNED <?>
.DATA
VolumePercent DWORD 25 ; <<< Set default volume percent here
hMixer DWORD 0
LineID DWORD 0
ControlID DWORD 0
BassValue DWORD 0
szCmdArgBuf BYTE 128 dup(0)
szBuf1 BYTE 64 dup(0)
szBuf2 BYTE 32 dup(0)
.CODE
start:
call main
invoke ExitProcess, eax
main PROC
invoke mixerOpen, ADDR hMixer, 0, NULL, NULL, NULL ; Open preferred Mixer Device (ID = 0)
.if eax
invoke udtoa, eax, ADDR szBuf2
invoke crt_sprintf, ADDR szBuf1, SADD("%s%s"), SADD("Error calling mixerOpen: "), ADDR szBuf2
invoke MessageBox, HWND_DESKTOP, ADDR szBuf1, ADDR szTitle, MB_ICONERROR OR MB_TASKMODAL
mov eax, -1
jmp done
.endif
mov eax, SIZEOF MIXERLINE
mov MyMixerLine.cbStruct, eax
mov eax, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS ; Set device to work with here
mov MyMixerLine.dwComponentType, eax
invoke mixerGetLineInfo, hMixer, ADDR MyMixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE
.if eax
invoke udtoa, eax, ADDR szBuf2
mov szBuf1[0], 0
invoke crt_sprintf, ADDR szBuf1, SADD("%s%s"), SADD("Error calling mixerGetLineInfo: "), ADDR szBuf2
invoke MessageBox, HWND_DESKTOP, ADDR szBuf1, ADDR szTitle, MB_ICONERROR OR MB_TASKMODAL
invoke mixerClose, hMixer
mov eax, -1
jmp done
.endif
mov eax, MyMixerLine.dwLineID
mov LineID, eax
; *** Set Volume Control ***
mov eax, SIZEOF MIXERLINECONTROLS
mov MyMixerLineControls.cbStruct, eax
mov eax, LineID
mov MyMixerLineControls.dwLineID, eax
mov MyMixerLineControls.cControls, 1
mov eax, MIXERCONTROL_CONTROLTYPE_VOLUME ; Volume control
mov MyMixerLineControls.dwControlType, eax
mov eax, OFFSET MyMixerControl
mov MyMixerLineControls.pamxctrl, eax
mov eax, SIZEOF MIXERCONTROL
mov MyMixerLineControls.cbmxctrl, eax
invoke mixerGetLineControls, hMixer, ADDR MyMixerLineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE
.if eax
invoke udtoa, eax, ADDR szBuf2
mov szBuf1[0], 0
invoke crt_sprintf, ADDR szBuf1, SADD("%s%s"), SADD("Error calling mixerGetLineControls: "), ADDR szBuf2
invoke MessageBox, HWND_DESKTOP, ADDR szBuf1, ADDR szTitle, MB_ICONERROR OR MB_TASKMODAL
invoke mixerClose, hMixer
mov eax, -1
jmp done
.endif
mov eax, MyMixerControl.dwControlID
mov ControlID, eax
mov eax, SIZEOF MIXERCONTROLDETAILS
mov MyMixerControlDetails.cbStruct, eax
mov eax, ControlID
mov MyMixerControlDetails.dwControlID, eax
mov MyMixerControlDetails.cChannels, 1
mov MyMixerControlDetails.cMultipleItems, 0
mov eax, OFFSET MyMixerControlDetails_U
mov MyMixerControlDetails.paDetails, eax
mov eax, SIZEOF MIXERCONTROLDETAILS_UNSIGNED
mov MyMixerControlDetails.cbDetails, eax
invoke mixerGetControlDetails, hMixer, ADDR MyMixerControlDetails, MIXER_GETCONTROLDETAILSF_VALUE
.if eax
invoke udtoa, eax, ADDR szBuf2
mov szBuf1[0], 0
invoke crt_sprintf, ADDR szBuf1, SADD("%s%s"), SADD("Error calling mixerGetControlDetails: "), ADDR szBuf2
invoke MessageBox, HWND_DESKTOP, ADDR szBuf1, ADDR szTitle, MB_ICONERROR OR MB_TASKMODAL
invoke mixerClose, hMixer
mov eax, -1
jmp done
.endif
mov eax, MyMixerControlDetails_U.dwValue
mov BassValue, eax
mov eax, SIZEOF MIXERCONTROLDETAILS
mov MyMixerControlDetails.cbStruct, eax
mov eax, ControlID
mov MyMixerControlDetails.dwControlID, eax
mov MyMixerControlDetails.cChannels, 1
mov MyMixerControlDetails.cMultipleItems, 0
mov eax, OFFSET MyMixerControlDetails_U
mov MyMixerControlDetails.paDetails, eax
mov eax, SIZEOF MIXERCONTROLDETAILS_UNSIGNED
mov MyMixerControlDetails.cbDetails, eax
; SET THE SPEAKER VOLUME -- Volume is from 0 -> 65535(Max Volume)
mov MyMixerControlDetails_U.dwValue,37000d
invoke mixerSetControlDetails, hMixer, ADDR MyMixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE
.if eax
invoke udtoa, eax, ADDR szBuf2
mov szBuf1[0], 0
invoke crt_sprintf, ADDR szBuf1, SADD("%s%s"), SADD("Error calling mixerSetControlDetails: "), ADDR szBuf2
invoke MessageBox, HWND_DESKTOP, ADDR szBuf1, ADDR szTitle, MB_ICONERROR OR MB_TASKMODAL
invoke mixerClose, hMixer
mov eax, -1
jmp done
.endif
invoke mixerClose, hMixer
done:
ret
main ENDP
EndOfString PROC pString:PTR BYTE
;returns address of end of string
mov eax, pString
@@:
movzx edx, BYTE PTR [eax]
.if edx
inc eax
jmp @B
.endif
ret
EndOfString ENDP
IsNumericString PROC pString:PTR BYTE
; Returns true if a string is numeric (0-9)
invoke EndOfString, pString
mov ecx, eax
mov eax, pString
@@:
movzx edx, BYTE PTR [eax]
.if (edx < 48) || (edx > 57)
jmp false
.endif
inc eax
cmp eax, ecx
jne @B
true:
mov eax, 1
jmp done
false:
xor eax, eax
done:
ret
IsNumericString ENDP
udtoa PROC udVal:DWORD, lpBuffer:PTR BYTE
; udVal is considered unsigned
invoke crt_sprintf, lpBuffer, SADD("%lu"), udVal
ret
udtoa ENDP
end start
maybe you can get some ideas from this thread...
http://www.masm32.com/board/index.php?topic=6272.0
Warning: The code I posted does not work for Windows Vista and 7. They completely rewrote the audio system in those versions of Windows, it's a whole new API and the old API is not supported.
I have code for mute and un-mute of the main volume (for Windows XP). If I remember correctly it's just a toggle, set to 0 or 1.
; Mute_Speaker.asm
; This toggles the speaker from MUTE to back on
;
.586 ; create 32 bit code
.model flat,stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\shell32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\shell32.lib
; ----------------------------------------
; The structures needed by SendInput API.
; ----------------------------------------
MOUSEINPUT STRUCT
_dx DWORD ?
_dy DWORD ?
mouseData DWORD ?
dwFlags DWORD ?
time DWORD ?
dwExtraInfo DWORD ?
MOUSEINPUT ENDS
KEYBDINPUT STRUCT
wVk WORD ?
wScan WORD ?
dwFlags DWORD ?
time DWORD ?
dwExtraInfo DWORD ?
KEYBDINPUT ENDS
HARDWAREINPUT STRUCT
uMsg DWORD ?
wParamL WORD ?
wParamH WORD ?
HARDWAREINPUT ENDS
INPUT STRUCT
_type DWORD ?
UNION
mi MOUSEINPUT <>
ki KEYBDINPUT <>
hi HARDWAREINPUT <>
ENDS
INPUT ENDS
.data
inputk INPUT <>
.code
start:
; mute or unmute sound.
invoke RtlZeroMemory,ADDR inputk,SIZEOF inputk
mov inputk._type,INPUT_KEYBOARD
mov inputk.ki.wVk,VK_VOLUME_MUTE
mov inputk.ki.wScan,0
mov inputk.ki.dwFlags,0
mov inputk.ki.time,0
mov inputk.ki.dwExtraInfo,0
invoke SendInput,1,ADDR inputk,SIZEOF inputk
invoke ExitProcess,eax
end start
Magnum, you know that code looks familiar. :bg
Yes, your work is always excellent.
In other words, acknowledge when you've simply re-arranged someone else's code, rather than written it yourself.
Tedd,
I do not mind one-iota as long as one learns from my examples. It is why I put forth the effort buddy (of course telling me I'm good at it doesn't hurt none though :bg). I think Magnum is an inspiring asm coder if he sticks to it.