News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Adjust volume

Started by Magnum, December 04, 2011, 12:27:55 AM

Previous topic - Next topic

Magnum

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

Have a great day,
                         Andy

dedndave

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

Magnum

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

Have a great day,
                         Andy

dedndave


GregL

#4
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.

Magnum


; 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

Have a great day,
                         Andy

Bill Cravener

Magnum, you know that code looks familiar. :bg
My MASM32 Examples.

"Prejudice does not arise from low intelligence it arises from conservative ideals to which people of low intelligence are drawn." ~ Isaidthat

Magnum

Yes, your work is always excellent.

Have a great day,
                         Andy

Tedd

In other words, acknowledge when you've simply re-arranged someone else's code, rather than written it yourself.
No snowflake in an avalanche feels responsible.

Bill Cravener

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.
My MASM32 Examples.

"Prejudice does not arise from low intelligence it arises from conservative ideals to which people of low intelligence are drawn." ~ Isaidthat