2017-05-16 1 views
1

어셈블리에서 "simon"게임을하고 있습니다. 버튼이 켜질 때마다 경고음이 들리게해야합니다. 경고음도 서로 달라야합니다. 감사합니다.조립품 8086 - DOSBOX - 삐 소리를내는 방법?

+1

[DOSBox의 Sound Blaster 장치에서 .wav 파일 재생하기] (http://stackoverflow.com/questions/41359112/playing-wav-files-on-dosboxs-sound-blaster- 장치) –

+1

상담해 주겠습니까? 도스 인터럽트 참조? – Michael

답변

6

speaker을 사용하면 디자인을 단순하게 유지할 수 있습니다.
스피커를 사용하면 서로 다른 주파수, 즉 it can actually be used to reproduce digital audio에있는 구형파를 재생할 수 있지만 더 복잡합니다.

스피커는 전자석 일 뿐이며 전류가 흐르면 뒤로 당겨 지지만 그렇지 않은 경우에는 기본 위치로 유지됩니다.
스피커를 앞뒤로 움직이면 음파를 생성 할 수 있습니다.

스피커는 수동 또는 동일한 포트를 인 포트에 61H 2.
비트 0 스피커 소스 제어 (0 = 서, 1 = PIT)과 비트 1을 PIT의 채널을 이용하여 이동 될 수

PIT (스피커가 아닌 경우 "위치")를 사용할 때 "스피커 사용 가능"비트.

가 PIT는 포트 40H-43H를 통해 제어된다 Speaker schematic

, 우리는 모드 3 (구형파 발생기)를 사용할 때마다 설정 :

여기 수동 구동 부분 누락 (이 page)에서 개략적있어 디바이더의 양쪽 바이트
PIT는 발진기가 약 1.193180MHz에서 작동하며, 분배기는 구형파의주기를 제어하는 ​​데 사용됩니다.
내부를 다루지 않고 : PIT 오실레이터의 각 틱에서로드 된 분배기가 감소합니다. 구형파의주기는 PIT가 디바이더를 0으로 감소시키는 데 필요한 시간과 같습니다.

소리를 생성하는 것은 원하는 구분선을 사용하고 스피커를 활성화하는 것만으로 PIT를 프로그래밍하는 것입니다.
나중에 어느정도 비활성화해야합니다.
쉬운 방법은 초당 18.2 회라는 int 1ch을 사용하는 것입니다.

사운드를 처음 재생할 때 변수를 저장하면 int 1ch의 틱마다 감소시키고 카운트가 0이되면 스피커를 비활성화하여 신호음의 지속 시간을 제어 할 수 있습니다.

int 1ch를 사용하려면 설정 기능 (beep_setup)과 teardown 기능 (beep_teardown)이 필요합니다. 원래 코드의 결함을 고정 Sep Roland

BITS 16 

ORG 100h 

__start__: 

;Setup 
call beep_setup 

;Sample beep of ~2sec 
mov ax, 2000 
mov bx, 36 
call beep_play 

;Wait for input 
xor ax, ax 
int 16h 

;Tear down 
call beep_teardown 

mov ax, 4c00h 
int 21h 

;------------------------------------------------- 

; 
;Setup the beep ISR 
; 

beep_setup: 
    push es 
    push ax 

    xor ax, ax 
    mov es, ax 

    ;Save the original ISR 
    mov ax, WORD [es: TIMER_INT * 4] 
    mov WORD [cs:original_timer_isr], ax 
    mov ax, WORD [es: TIMER_INT * 4 + 2] 
    mov WORD [cs:original_timer_isr + 2], ax 

    ;Setup the new ISR 

    cli 
    mov ax, beep_isr 
    mov WORD [es: TIMER_INT * 4], ax 
    mov ax, cs 
    mov WORD [es: TIMER_INT * 4 + 2], ax 
    sti 

    pop ax 
    pop es 
    ret 


; 
;Tear down the beep ISR 
; 

beep_teardown: 
    push es 
    push ax 

    call beep_stop 

    xor ax, ax 
    mov es, ax 

    ;Restore the old ISR 

    cli 
    mov ax, WORD [cs:original_timer_isr] 
    mov WORD [es: TIMER_INT * 4], ax 
    mov ax, WORD [cs:original_timer_isr + 2] 
    mov WORD [es: TIMER_INT * 4 + 2], ax 
    sti 

    pop ax 
    pop es 
    ret 

; 
;Beep ISR 
; 
beep_isr: 
    cmp BYTE [cs:sound_playing], 0 
    je _bi_end 

    cmp WORD [cs:sound_counter], 0 
    je _bi_stop 

    dec WORD [cs:sound_counter] 

jmp _bi_end 

_bi_stop: 
    call beep_stop 

_bi_end: 
    ;Chain 
    jmp FAR [cs:original_timer_isr] 

; 
;Stop beep 
; 
beep_stop: 
    push ax 

    ;Stop the sound 

    in al, 61h 
    and al, 0fch ;Clear bit 0 (PIT to speaker) and bit 1 (Speaker enable) 
    out 61h, al 

    ;Disable countdown 

    mov BYTE [cs:sound_playing], 0 

    pop ax 
    ret 

; 
;Beep 
; 
;AX = 1193180/frequency 
;BX = duration in 18.2th of sec 
beep_play: 
    push ax 
    push dx 

    mov dx, ax 

    mov al, 0b6h 
    out 43h, al 

    mov ax, dx 
    out 42h, al 
    mov al, ah 
    out 42h, al 


    ;Set the countdown 
    mov WORD [cs:sound_counter], bx 

    ;Start the sound 

    in al, 61h 
    or al, 3h ;Set bit 0 (PIT to speaker) and bit 1 (Speaker enable) 
    out 61h, al 


    ;Start the countdown 

    mov BYTE [cs:sound_playing], 1 

    pop dx 
    pop ax 
    ret 

;Keep these in the code segment 
sound_playing  db 0 
sound_counter  dw 0 
original_timer_isr  dd 0 

TIMER_INT  EQU  1ch 

특별 감사!

삐 소리를 내기 위해 beep_play을 사용할 수 있습니다. 사용되는 단위는 위에서 설명한 하드웨어 구성의 "자연스러운"단위입니다.
주파수와 지속 시간이 고정되어 있으면이 장치가 무료로 코드를 단순화합니다.

주어진 시간이 지나면 경고음이 멈추며, beep_stop을 사용하여 강제로 멈출 수 있습니다.

한 번에 여러 사운드 재생 (PWM 기술을 사용하지 않고도 여러 사운드를 믹싱 할 수 없음).
다른 경고음이 재생되는 동안 beep_play으로 전화하면 현재 경고음을 중지하고 새 경고음을 시작하는 효과가 있습니다.

+0

훌륭한 대답입니다. +1하지만 * beep_isr * 인터럽트 서비스 루틴은 중요한 문제가 있습니다! 'AX' 레지스터를 사용할 수없고 그것을 보존 할 수 없습니다. 'cmp WORD [cs : sound_counter], 0''je _bi_stop'' dec WORD [cs : sound_counter]'라고 쓰면 간단합니다. 'AX'를 전혀 사용할 필요가 없습니다. –

+0

대단히 감사합니다 @SepRoland! 크레딧으로 답변을 업데이트하고 있습니다 :) –

관련 문제