我对我的小组项目有几个问题。第一个问题是关于MIDI文件的播放。现在我们的程序可以播放类型0文件,准确率约为75%(如果你甚至可以测量它)。基本上,它使歌曲的“大部分”正确(或非常接近)。它显然没有播放所有声音,而且它确实播放的声音有些失真。因此,如果正确播放大部分音符,可能会导致其错过或扭曲其他音符?
第二个问题与我们的中断处理程序有关。我正在尝试调整指针,以便程序向前/向后跳过X字节,但是如果我在程序运行时尝试中断,它会停止并锁定程序。如果我逐步完成中断,它将不会停止。看起来我要么在中途还是完全没有标记(这是在早期版本上工作,但可能b / c回放功能没有正确写入)。如果我不得不猜测我会说这个问题与WITH_STATUS和WITHOUT_STATUS函数有关。是吗?
提前感谢您的帮助。
PLAY_MIDI:
addi $s5, $0, 0 # temporaries to control speed and volume
addi $t6, $0, 100
addi $t9, $0, 0
addi $sp, $sp, -4 # add a byte to the stack pointer and store the return address there
sw $ra, 0($sp)
addi $t4, $0, 3
LOOP:
lh $t0, DAT_Format
bnez $t0, NO_SUPPORTED
addi $s3, $s3, 1
addi $s1, $s1, -1
lbu $t9, 0($s3) # look for status byte
blez $s1, OFF_LOOP
bltu $t9, 0x80, LOOP
bgeu $t9, 0xa0, LOOP
WITH_STATUS:
lbu $t9, 0($s3)
lb $t6, -1($s3) #sleep time
lb $a1, 1($s3) # load note
lb $a2, 2($s3) # load volume
addi $s3, $s3, 4
addi $s1, $s1, -4
move $s2, $s1 # *** copy $s1 to $s2 for pause/play
j SLEEP
WITHOUT_STATUS:
lb $t6, -1($s3) #sleep time
lb $a1, 0($s3) # load note
lb $a2, 1($s3) # load volume
addi $s3, $s3, 3 #increase stack
addi $s1, $s1, -3
move $s2, $s1 # ** copy $s1 to $s2 for pause/play
SLEEP:
mul $t6, $t6, $t4
li $v0, 32 # sleep until the next note should be played
addu $a0, $0, $t6 # sleep for $t6 ms
syscall
and $a0, $t9,0x0F # load channel
and $t9,$t9,0x000000F0 # load Command
######################################################
## copy $s1 to $s2 for use differentiating between ##
beq $t9, 0x90, PLAY_NOTE_ON ## stop and pause ##
beq $t9, 0x80, PLAY_NOTE_OFF ## $s2 will hold last position of $s1 ##
bgeu $t9, 0xa0, LOOP ######################################################
AFTER_PLAY:
blez $s1, OFF_LOOP
lbu $t0, 0($s3)
bgeu $t0, 0x80, WITH_STATUS
j WITHOUT_STATUS
OFF_LOOP:
bne $s1, $s2, PAUSE_LOOP # get the return address from the stack and decrease the pointer
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra # jump to the address we just loaded
PLAY_NOTE_ON:
li $v0, 60 # add a byte to the stack pointer and store the return address there
syscall
j AFTER_PLAY
PLAY_NOTE_OFF:
li $v0, 61
syscall
j AFTER_PLAY
NO_SUPPORTED:
j EXIT
#### Below is part of the interrupt handler ####
SKIP_FORWARD: addi $s3, $s3, 1 # by adding to $s3 program will move pointer ahead
la $a0, skip_forward # changed from $s3 to $s1 ***
li $v0, 4
syscall
jr $ra
SKIP_BACKWARD: addi $s3, $s3, -1 # by subtracting from $s3 program will move pointer backwards
la $a0, skip_backward # changed $s3 to $s1
li $v0, 4
syscall
jr $ra