1

Тема: AutoIt v3: подача звукового сигнала через системный динамик

Без гарантий. Используете на свой страх и риск.
Скрипт включает системный динамик на заданной частоте. Аналогичен скрипту представленному здесь.

Потребуется библиотека INPOUT32.DLL установленная в каталог %systemdir%.

Lang AutoIt v3
OC WinXP

;=========================================================
; Включение системного динамика на заданной частоте.
;=========================================================
; Потребуется библиотека INPOUT32.DLL установленная в 
; каталог %systemdir% (http://www.pcports.ru/files/inpout32.rar)
;
; Lang AutoIt v3
; OC WinXP
;=========================================================
 #NoTrayIcon


    Global Const $GUI_EVENT_CLOSE        = -3
    ;-------------------------------------------------
    Global Const $BS_CENTER            = 0x0300
    Global Const $BS_MULTILINE            = 0x2000
    Global Const $BS_VCENTER            = 0x0C00
    Global Const $BS_FLAT                = 0x8000
    Global Const $SS_CENTER            = 1
    Global Const $ES_CENTER            = 1
    Global Const $BS_DEFPUSHBUTTON        = 0x0001
    ;-------------------------------------------------
    Global Const $WS_BORDER            = 0x00800000
    Global Const $WS_SYSMENU            = 0x00080000
    Global Const $WS_CAPTION            = 0x00C00000
    Global Const $WS_VISIBLE            = 0x10000000
    ;-------------------------------------------------
    

;=========================================================
 Global $IODLL = DllOpen('INPOUT32.DLL')
 If $IODLL = -1 Then MsgBox(262192,'Error','Установите INPOUT32.DLL.');Exit;

 Global $iTimer = 0x0043    ;Базовый адрес системного таймера        
 Global $iTimer1 = 0x0040    ;Адрес канала 0
 Global $iTimer1 = 0x0041    ;Адрес канала 1
 Global $iTimer2 = 0x0042    ;Адрес канала 2

 Global $iSysBeep = 0x0061    ;Адрес системного динамика
 Global $a            ;Начальное состояние младшей тетрады регистра 0x61 системного динамика, когда он находится в отключенном состоянии 

 Global $isBeep = False
;---------------------------------------------------------
 Opt('GUICloseOnESC',1)
 $hGUI =    GUICreate ('System Beep',135,200,-1,-1, _
        BitOr($WS_SYSMENU,$WS_CAPTION,$WS_VISIBLE))

 $hLabel1 = GUICtrlCreateLabel ('Укажите частоту,гц',5,2,120,20, _
        BitOr($WS_BORDER,$SS_CENTER))

 $hInput1 = GUICtrlCreateInput ('1000',5,30,120,30, _
        BitOr($WS_BORDER,$ES_CENTER))


 $hCommand1 = GUICtrlCreateButton ('[beep]',5,65,120,30, _
        BitOr($BS_CENTER,$BS_DEFPUSHBUTTON))
        
 GUISetState()

    While 1
        $iMSG = GUIGetMsg()
        Select
            Case $iMSG = $GUI_EVENT_CLOSE
                ExitLoop;
            Case $iMSG = $hCommand1
                SysBeep1();
        EndSelect
    Wend
    Exit;

;[Включение/заглушка системного динамика]
;=========================================================
 Func SysBeep1()

    ;[Включить системный динамик на заданной частоте]
    ;-------------------------------------------------
    If Not $IsBeep Then

        ;[Прочитать начальное состояние системного динамика]
        ;-----------------------------------------
        $iState0 = '0x' & Hex(Inp32($iSysBeep));

        ;[Получить частоту]
        ;-----------------------------------------
        Local $hFreq = GuiCtrlRead($hInput1);
        If StringRegExp ($hFreq, '\D' , 0) Then
            MsgBox(262192,'Error','Укажите корректное значение частоты.');
            return
        EndIf
        
        $hFreq = '0x' & Hex(Int(1193180/Number($hFreq)));
        
        ;[Получить младший и старший байт значения частоты счета]
        ;-----------------------------------------
        $iHByte = '0x' & Hex(BitAnd(0x0000ff00, $hFreq));
        $iHByte = '0x' & Hex(BitShift($iHByte,8))    ;Старший байт        

        $iLByte = '0x' & Hex(BitAnd(0x000000ff,$hFreq))    ;Младший байт

        ;Команда записанная в базовый порт трехканального 
        ;таймера разрешает последовательную запись младшего и старшего байта
        ;начального значения счетчика в канал 2 таймера и циклический 
        ;счет в этом канале.
        ;-----------------------------------------
        Out32($iTimer,0x00b6);    

        ;При первом обращении к порту записывается младший 
        ;регистр начального значения счетчика, при втором - старший.
        ;-----------------------------------------
        Out32($iTimer2,$iLByte);
        Out32($iTimer2,$iHByte);

        ;Включение звука
        ;-----------------------------------------
        ;Запись битов 4-7 в регистр динамика запрещена, поэтому, вполне достаточно работать с битами 0-3
        $a = '0x' & Hex(BitAnd(0x0f,$iState0))    ;Исключить старшую тетраду
        ;-----------------------------------------
        ;1=1b-нулевой бит(слева направо), разрешает счет в канале 2 таймера
        ;2=10b-первый бит, разрешает поступление импульсов с канала 2 таймера на системный динамик
        $b = $a+1+2

        Out32($iSysBeep,$b);        

        $IsBeep = True;
        GUICtrlSetData ($hCommand1, '[mute]');

    Else
        Out32($iSysBeep,$a)    ;Заглушить системный динамик, восстановление исходного значения младшей тетрады регистра
        $IsBeep = False;
        GUICtrlSetData ($hCommand1, '[beep]');
    EndIf
 EndFunc

;[Чтение данных порта устройства]
;=========================================================
 Func Inp32($sPort)

    SetError(0);
    $result=DllCall($IODLL, _
                'short'    ,'Inp32', _
                'short'    ,$sPort);
    If Not @error Then
        return $result[0];
    Else 
        return -1;
    EndIf
 EndFunc

;[Запись данных в порт устройства]
;=========================================================
 Func Out32($sPort,$sData)

    SetError(0);
    $result=DllCall($IODLL, _
                'none'    ,'Out32', _
                'short'    ,$sPort, _
                'short', $sData);


    
    If Not @error Then
        return 1;
    Else 
        return -1;
    EndIf
 EndFunc
;=========================================================
;pltrgst