audio - 汇编播放音频文件 TASM 16 位

标签 audio assembly x86 dos tasm

您好,我正在为学校项目编写游戏,但播放音频文件时遇到问题。
我能够播放该文件,但问题是程序卡住并停止响应用户

音乐文件代码

proc read Near ; Read next sample
    push bx
    push cx
    push dx
    mov ah, 3Fh
    mov bx, [filehandle]
    mov cx, 1
    lea dx, [Buffer]
    int 21h
    jc errorcode
    mov al, [Buffer]
    xor ah, ah
    mov bx, 54
    mul bx
    ; mov ax, dx ; Result is in DX because we need to div by 65536 which is all of AX
    shr ax, 8
    pop dx
    pop cx
    pop bx
    ret
endp
proc br Near; Print line break
    push dx
    push ax
    mov dl, 10
    mov ah, 2
    int 21h
    mov dl, 13
    mov ah, 2
    int 21h
    pop ax
    pop dx
    ret
endp
proc PlayMusic Near
    mov ah, 3Dh
    xor al, al
    lea dx, [filename]
    int 21h
    mov [filehandle], ax
    call br
    mov al, 90h
    out 43h, al
in al, 61h
    or al, 3
    out 61h, al
    cli
    mov ax, 0
totalloop:
    call read ; Read file
    out 42h, al ; Send data
    mov bx, ax
    mov cx, [delay]
portloop:
    loop portloop
    mov ax, bx
    out 42h, ax ; Send data
    mov cx, [delay]
rloop:
    loop rloop
    call read
    jmp totalloop
    ret
errorcode:
    ; Close
    sti
    mov al, 86h
    out 43h, al
    mov ah, 3Eh
    mov bx, [filehandle]
    int 21h
    pop dx
    pop cx
    pop bx
    ret
endp PlayMusic

在我调用这个过程之后,我调用 int 16h 从用户那里读取一个 key ,但是音乐文件阻止了 IO
有人知道我需要做什么吗?
顺便说一句对不起我的英语不好
而且我在组装方面有点新,所以我不太好

最佳答案

您要做的是“并行化”您的游戏代码(不使用线程)。关于如何执行此操作的选项很少:

  • 交错代码

    这是最简单的实现方式。所以你的游戏架构应该是这样的:
    loop:handle input
         handle game logic
         render frame
         play sound (20-40ms)
         jmp loop
    

    这种架构将允许游戏“并行”运行其所有任务。如果您的任务较慢,您可以多交错音乐
    loop:handle input
         play sound (~10ms)
         handle game logic
         play sound (~10ms)
         render frame
         play sound (~10ms)
         jmp loop
    

    如果任何任务真的很慢,那么您需要直接将声音交织到其中,否则您会听到断断续续的声音。这是一个例子(没有声音):
  • What is the best way to move an object on the screen?

  • 这是声音(但不是游戏):
  • No Signal demo

  • 你需要让你的键盘测试非阻塞。取自我的无信号演示,它是这样完成的:
        mov ah,1    ; non blocking key test
        int 16h
        jz keyr0
        sub ax,ax   ; blocking key test
        int 16h
        ; here handle the key press...
    keyr0:          ; here continues your code
    
  • 使用 PIT 作为发生器播放声音

    我没有用这个,但是 IIRC 可配置为使用扬声器播放恒定频率。因此,无需设置扬声器开/关,您只需设置其每帧的频率左右...这将在后台播放,在此期间 中央处理器 可以做其他事情...
  • 使用 PIT 作为计时器在后台播放声音

    为了更好地计时并在后台播放与您的游戏代码平行的声音,您可以将播放的声音移动到 PIT ISR完全可以在 1193180.0/16bit_divider Hz 操作所以设置目标声音采样频率。设置 ISR 为它并在其中获取/播放单个位......

    如果您使用 PWM和采样频率的倍数,您可以将 Speaker 变成 数模转换器 玩偶 PCM *.wav文件。

    在这种情况下,您根本没有在游戏循环中交错的声音代码。

  • 不要忘记在退出 之前将 PIT 频率设置回 18.2 Hz因为 MS-DOS 游戏用它来计时。许多游戏可以通过更改 来加速坑单独频率。此外,当您更改 PIT 频率和 ISR 时,最好从新 ISR 中调用具有 18.2Hz 频率的原始 ISR。

    有关 PC MS-DOS 和游戏的更多信息,请参阅:
  • PCGPE 1.0
  • WPCGPE 1.0这应该是 *.hlp格式(你需要 Windows6.1-KB917607 Win7+ 的补丁,因为他们不再支持它)

  • 这是我所知道的从组装开始的最佳选择:
  • Assembler a ZX Spectrum 1
  • Assembler a ZX Spectrum 2

  • 但它是捷克语的 Z80 CPU 而且我不知道任何翻译....

    关于audio - 汇编播放音频文件 TASM 16 位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48507031/

    相关文章:

    linux - FreeBSD 系统上简单汇编程序的虚假结果

    macos - 0xbffff8a8 : aam $-0x8 error when saving the base pointer

    x86 - .section .text 和 .text with gas 的区别

    gcc - 为什么 `mov %eax, %eax; nop` 比 `nop` 快?

    linux - 多级页表概念

    android - 如何确定 Android MediaFormat.KEY_SAMPLE_RATE 的值

    objective-c - 如何将音频数据存储到文档目录中?

    assembly - "load"和 "store"是什么意思?

    actionscript-3 - 当外部文件中的数字更改时播放声音

    google-chrome - 音频下载链接在 Firefox 中有效,但在 Chrome 中流式传输