From db55562f6a1c30f9e1e41b40911762e745c25cfd Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 26 Nov 2022 15:53:35 +0100 Subject: [PATCH] fixed adpcm playback --- .../assignment/AugmentableAssignmentAsmGen.kt | 2 +- docs/source/todo.rst | 2 +- examples/cx16/adpcm-mono.bin | Bin 24576 -> 0 bytes examples/cx16/adpcm.p8 | 197 ------------------ examples/cx16/pcmaudio/adpcm-mono.bin | Bin 0 -> 36608 bytes examples/cx16/pcmaudio/adpcm.p8 | 187 +++++++++++++++++ examples/cx16/pcmaudio/pcm-mono.bin | Bin 0 -> 32000 bytes examples/cx16/pcmaudio/pcmplay1.asm | 149 +++++++++++++ examples/cx16/pcmaudio/pcmplay2.asm | 167 +++++++++++++++ 9 files changed, 505 insertions(+), 199 deletions(-) delete mode 100644 examples/cx16/adpcm-mono.bin delete mode 100644 examples/cx16/adpcm.p8 create mode 100644 examples/cx16/pcmaudio/adpcm-mono.bin create mode 100644 examples/cx16/pcmaudio/adpcm.p8 create mode 100644 examples/cx16/pcmaudio/pcm-mono.bin create mode 100644 examples/cx16/pcmaudio/pcmplay1.asm create mode 100644 examples/cx16/pcmaudio/pcmplay2.asm diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt index 57679696b..049e573d4 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt @@ -1873,7 +1873,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, internal fun inplaceNegate(assign: AsmAssignment) { val target = assign.target - when (assign.target.datatype) { + when (target.datatype) { DataType.BYTE -> { when (target.kind) { TargetStorageKind.VARIABLE -> { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 37cde05f5..1b3f9a55e 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,7 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- try to get the cx16 adpcm example to output audio +- fix compiler crash cx16.r0 = (-(cx16.r0 as word) as uword) - duplicate diskio for cx16 (get rid of cx16diskio, just copy diskio and tweak everything) + documentation - get f_seek_w working like in the BASIC program - this needs the changes to diskio.f_open to use suffixes ,p,m - attempt to fix the expression codegen bug with reused temp vars (github #89) diff --git a/examples/cx16/adpcm-mono.bin b/examples/cx16/adpcm-mono.bin deleted file mode 100644 index 33e5e7a009450ffef0e9222fd190581f0beeede8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24576 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 wFpMPr>4) -; ; adpcm.predict as word -; cx16.VERA_AUDIO_DATA = lsb(adpcm.predict) -; cx16.VERA_AUDIO_DATA = msb(adpcm.predict) -; nibblesptr++ -; } -; } - - -; cx16.set_rasterirq(irqhandler, 10) -; uword adpcm_size = &adpcm_data_end - &adpcm_data -; uword num_adpcm_blocks = adpcm_size / 256 -; uword nibblesptr = &adpcm_data -; -; num_adpcm_blocks = 1 -; nibblesptr = &nibbles -; -; repeat num_adpcm_blocks { -; uword @zp sample = peekw(nibblesptr) -; nibblesptr += 2 -; adpcm.init(sample, @(nibblesptr)) -; nibblesptr += 2 -; -; repeat 252 { -; ubyte @zp nibble = @(nibblesptr) -; adpcm.decode_nibble(nibble & 15) -; txt.print_w(adpcm.predict as word) -; txt.spc() -; adpcm.decode_nibble(nibble>>4) -; txt.print_w(adpcm.predict as word) -; txt.spc() -; nibblesptr++ -; } -; } - } - -; sub irqhandler() { -; cx16.vpoke(1, $fa00, 255) -; -; uword @zp sample = peekw(nibbles) -; adpcm.init(sample, nibbles[2]) -; -; ubyte @zp idx = 4 -; while idx<200 { -; ubyte @zp nibble = nibbles[idx] -; adpcm.decode_nibble(nibble & 15) -; sample = adpcm.predict -; nibble >>= 4 -; adpcm.decode_nibble(nibble) -; sample = adpcm.predict -; idx++ -; } -; -; cx16.vpoke(1, $fa00,0) -; } - -;adpcm_data: -; %asmbinary "adpcm-mono.bin" -;adpcm_data_end: - -; ubyte[256] nibbles = [216, 227, 59, 0, 32, 2, 186, 139, 24, 34, 84, 115, 19, 185, 173, 8, 0, 56, 162, -; 169, 144, 113, 55, 130, 186, 12, 33, 144, 10, 136, 10, 129, 41, 66, 210, 207, -; 9, 0, 153, 129, 185, 173, 155, 0, 37, 162, 191, 27, 36, 129, 144, 137, 82, 18, -; 87, 18, 152, 153, 136, 0, 32, 23, 0, 40, 24, 117, 19, 202, 138, 8, 176, 171, -; 24, 131, 234, 9, 32, 39, 160, 10, 153, 33, 52, 209, 137, 200, 73, 33, 233, 155, -; 136, 66, 146, 8, 152, 56, 131, 113, 23, 168, 169, 185, 9, 160, 65, 37, 49, 22, -; 64, 68, 168, 138, 153, 1, 171, 88, 35, 25, 65, 1, 176, 173, 185, 175, 168, 154, -; 153, 205, 138, 144, 152, 154, 204, 43, 53, 51, 35, 154, 184, 96, 71, 34, 152, -; 172, 138, 160, 9, 24, 16, 204, 88, 48, 54, 160, 172, 152, 65, 132, 168, 48, 4, -; 0, 190, 9, 161, 155, 218, 139, 154, 185, 207, 9, 50, 130, 184, 252, 155, 24, -; 53, 144, 172, 170, 88, 51, 1, 176, 173, 17, 40, 115, 129, 136, 200, 11, 70, -; 129, 8, 0, 0, 48, 37, 160, 42, 35, 32, 17, 18, 220, 174, 170, 143, 9, 137, 160, -; 171, 104, 4, 169, 154, 219, 142, 65, 129, 128, 168, 9, 69, 50, 130, 219, 128, -; 138, 49, 52, 146, 237, 141, 50, 21, 8, 136, 8, 153, 35, 193, 170, 2, 169, 224, -; 186, 170, 40, 253, 12, 17, 25] - -pcm_data: - %asmbinary "pcm-mono.bin" -pcm_data_end: - -} - - -adpcm { - ubyte[] t_index = [ -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8] - uword[] t_step = [ - 7, 8, 9, 10, 11, 12, 13, 14, - 16, 17, 19, 21, 23, 25, 28, 31, - 34, 37, 41, 45, 50, 55, 60, 66, - 73, 80, 88, 97, 107, 118, 130, 143, - 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, - 724, 796, 876, 963, 1060, 1166, 1282, 1411, - 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, - 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, - 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, - 32767] - - uword @zp predict - ubyte @zp index - uword @zp pstep - - sub init(uword startPredict, ubyte startIndex) { - predict = startPredict - index = startIndex - pstep = t_step[index] - } - - sub decode_nibble(ubyte nibble) { - word @zp difference = 0 - if nibble & 4 - difference += pstep - pstep >>= 1 - if nibble & 2 - difference += pstep - pstep >>= 1 - if nibble & 1 - difference += pstep - pstep >>= 1 - difference += pstep - if nibble & 8 - difference = -difference - predict += difference as uword - index += t_index[nibble] - if index & 128 - index = 0 - else if index > 88 - index = 88 - pstep = t_step[index] - } -} diff --git a/examples/cx16/pcmaudio/adpcm-mono.bin b/examples/cx16/pcmaudio/adpcm-mono.bin new file mode 100644 index 0000000000000000000000000000000000000000..ddd6028f0f67e53948a710909719bc86648e9169 GIT binary patch literal 36608 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 z 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 N*Wl|v5BPsO{{R8i6tMsR literal 0 HcmV?d00001 diff --git a/examples/cx16/pcmaudio/adpcm.p8 b/examples/cx16/pcmaudio/adpcm.p8 new file mode 100644 index 000000000..1917207d2 --- /dev/null +++ b/examples/cx16/pcmaudio/adpcm.p8 @@ -0,0 +1,187 @@ +%import textio +%import floats +%option no_sysinit +%zeropage basicsafe + +main { + + ubyte num_adpcm_blocks + ubyte adpcm_blocks_left + uword @requirezp nibblesptr + + sub start() { + uword adpcm_size = &audiodata.adpcm_data_end - &audiodata.adpcm_data + num_adpcm_blocks = (adpcm_size / 256) as ubyte ; NOTE: THE ADPCM DATA NEEDS TO BE ENCODED IN 256-byte BLOCKS ! + + txt.print_uw(adpcm_size) + txt.print(" adpcm data size = ") + txt.print_ub(num_adpcm_blocks) + txt.print(" blocks\n(b)enchmark or (p)layback? ") + + when c64.CHRIN() { + 'b' -> benchmark() + 'p' -> playback() + } + } + + sub benchmark() { + nibblesptr = &audiodata.adpcm_data + + txt.print("\ndecoding all blocks...\n") + c64.SETTIM(0,0,0) + repeat num_adpcm_blocks { + adpcm.init(peekw(nibblesptr), @(nibblesptr+2)) + nibblesptr += 4 + repeat 252 { + ubyte @zp nibble = @(nibblesptr) + adpcm.decode_nibble(nibble & 15) ; first word + adpcm.decode_nibble(nibble>>4) ; second word + nibblesptr++ + } + } + float duration_secs = (c64.RDTIM16() as float) / 60.0 + float words_per_second = 505.0 * (num_adpcm_blocks as float) / duration_secs + txt.print_uw(words_per_second as uword) + txt.print(" words/sec\n") + } + + sub playback() { + nibblesptr = &audiodata.adpcm_data + adpcm_blocks_left = num_adpcm_blocks + + cx16.VERA_AUDIO_CTRL = %10101111 ; mono 16 bit + cx16.VERA_AUDIO_RATE = 0 ; halt playback + repeat 1024 { + cx16.VERA_AUDIO_DATA = 0 + } + + sys.set_irqd() + cx16.CINV = &irq_handler + cx16.VERA_IEN = %00001000 ; enable AFLOW + sys.clear_irqd() + + cx16.VERA_AUDIO_RATE = 21 ; start playback at ~8000 hz + + float rate = (cx16.VERA_AUDIO_RATE as float) * (25e6 / 65536.0) + txt.print("\naudio via irq at ") + txt.print_uw(rate as uword) + txt.print(" hz mono\n") + + repeat { + ; audio will play via the IRQ. + } + + ; not reached: +; cx16.VERA_AUDIO_CTRL = %00100000 +; cx16.VERA_AUDIO_RATE = 0 +; txt.print("audio off.\n") + } + + sub irq_handler() { + if cx16.VERA_ISR & %00001000 { + ; AFLOW irq. + ;; cx16.vpoke(1,$fa0c, $a0) ; paint a screen color + + ; refill the fifo buffer with two decoded adpcm blocks (252 nibbles -> 1008 bytes per block) + repeat 2 { + adpcm.init(peekw(nibblesptr), @(nibblesptr+2)) + nibblesptr += 4 + repeat 252 { + ubyte @zp nibble = @(nibblesptr) + adpcm.decode_nibble(nibble & 15) ; first word + cx16.VERA_AUDIO_DATA = lsb(adpcm.predict) + cx16.VERA_AUDIO_DATA = msb(adpcm.predict) + adpcm.decode_nibble(nibble>>4) ; second word + cx16.VERA_AUDIO_DATA = lsb(adpcm.predict) + cx16.VERA_AUDIO_DATA = msb(adpcm.predict) + nibblesptr++ + } + + adpcm_blocks_left-- + if adpcm_blocks_left==0 { + ; restart adpcm data from the beginning + nibblesptr = &audiodata.adpcm_data + adpcm_blocks_left = num_adpcm_blocks + } + } + + } else { + ; TODO not AFLOW, handle other IRQ + } + + ;; cx16.vpoke(1,$fa0c, 0) ; back to other screen color + + %asm {{ + ply + plx + pla + rti + }} + } + +} + +adpcm { + + ; IMA ADPCM decoder. + ; https://wiki.multimedia.cx/index.php/IMA_ADPCM + ; https://wiki.multimedia.cx/index.php/Microsoft_IMA_ADPCM + + ubyte[] t_index = [ -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8] + uword[] t_step = [ + 7, 8, 9, 10, 11, 12, 13, 14, + 16, 17, 19, 21, 23, 25, 28, 31, + 34, 37, 41, 45, 50, 55, 60, 66, + 73, 80, 88, 97, 107, 118, 130, 143, + 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1411, + 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, + 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, + 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, + 32767] + + uword @zp predict + ubyte @zp index + uword @zp pstep + + sub init(uword startPredict, ubyte startIndex) { + predict = startPredict + index = startIndex + pstep = t_step[index] + } + + sub decode_nibble(ubyte nibble) { + ; this is the hotspot of the decoder algorithm! + cx16.r0s = 0 ; difference + if nibble & %0100 + cx16.r0s += pstep + pstep >>= 1 + if nibble & %0010 + cx16.r0s += pstep + pstep >>= 1 + if nibble & %0001 + cx16.r0s += pstep + pstep >>= 1 + cx16.r0s += pstep + if nibble & %1000 + cx16.r0s = -cx16.r0s + predict += cx16.r0s as uword + index += t_index[nibble] + if index & 128 + index = 0 + else if index > len(t_step)-1 + index = len(t_step)-1 + pstep = t_step[index] + } +} + + +audiodata { + ;; %option align_page +adpcm_data: + %asmbinary "adpcm-mono.bin" +adpcm_data_end: + +} diff --git a/examples/cx16/pcmaudio/pcm-mono.bin b/examples/cx16/pcmaudio/pcm-mono.bin new file mode 100644 index 0000000000000000000000000000000000000000..809470f7a6d747389f3efbe088fbbc7110d6c901 GIT binary patch literal 32000 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 iITfp$)>j{HeAkAQaudio_on_txt + jsr print + + ldx #pcm_data + stx pcm_ptr + sty pcm_ptr+1 + + lda #21 + sta VERA_AUDIO_RATE ; start playing + +play_loop: +_wait_for_empty_fifo: + bit VERA_AUDIO_CTRL ; fifo empty? + bvc _wait_for_empty_fifo + + ; fifo is empty, we go ahead and fill it with more sound data. + ; paint a screen color + stz VERA_CTRL + lda #$0c + sta VERA_ADDR_L + lda #$fa + sta VERA_ADDR_M + lda #$01 + sta VERA_ADDR_H + lda #$a0 + sta VERA_DATA0 + + +_copy_samples: + ; this assumes all samples are aligned to page size! + ; so we can at least copy a full page at once here. + ldy #0 +_c1 lda (pcm_ptr),y + sta VERA_AUDIO_DATA ; lsb + iny + lda (pcm_ptr),y + sta VERA_AUDIO_DATA ; msb + iny + bne _c1 + inc pcm_ptr+1 + + ; have we reached the end of the sample data? (pcm_ptr >= pcm_data_end) + ; due to page size alignment only the MSB has to be checked + lda pcm_ptr+1 + cmp #>pcm_data_end + bcc _continue + bne _end_reached +; lda pcm_ptr ; uncomment if lsb also needs to be checked +; cmp #pcm_data + sta pcm_ptr+1 + bra _continue + +stop_playback: + ; stop playback + stz VERA_AUDIO_RATE + stz VERA_AUDIO_CTRL + ldx #audio_off_txt + jsr print + rts + +audio_on_txt: .text "AUDIO ON", $0d, $00 +audio_off_txt: .text "AUDIO OFF", $0d, $00 + +print: ; -- print string pointed to by X/Y + stx r0L + sty r0H + ldy #0 +_chr: lda (r0),y + beq _done + jsr $ffd2 + iny + bne _chr +_done: rts + + .align $0100 +pcm_data: + .binary "pcm-mono.bin" +pcm_data_end: diff --git a/examples/cx16/pcmaudio/pcmplay2.asm b/examples/cx16/pcmaudio/pcmplay2.asm new file mode 100644 index 000000000..a1a448b2e --- /dev/null +++ b/examples/cx16/pcmaudio/pcmplay2.asm @@ -0,0 +1,167 @@ +; +; This program plays a short mono 16 bit PCM sample on repeat +; It uses the AFLOW IRQ that signals when the Fifo is about to drain empty. +; The flashing green bar is when the routine is busy copying sample data into the fifo. +; +; source code is for 64TASS, assemble with: 64tass pcmplay2.asm -o pcmplay2.prg +; + +.cpu 'w65c02' +.enc 'none' + +* = $0801 + ; basic launcher + .word $080b, 2022 + .text $9e, "2061", $00 + .word 0 +entrypoint: + + +CHROUT = $ffd2 +VERA_ADDR_L = $9f20 +VERA_ADDR_M = $9f21 +VERA_ADDR_H = $9f22 +VERA_DATA0 = $9f23 +VERA_CTRL = $9f25 +VERA_IEN = $9f26 +VERA_ISR = $9f27 +VERA_AUDIO_CTRL = $9f3b +VERA_AUDIO_RATE = $9f3c +VERA_AUDIO_DATA = $9f3d +IRQ_VECTOR = $0314 +r0 = $02 +r0L = $02 +r0H = $03 +r1 = $04 +r1L = $04 +r1H = $05 +pcm_ptr = $06 + + + ; stop playback and select mono 16 bit, max volume + stz VERA_AUDIO_RATE + lda #%10101111 + sta VERA_AUDIO_CTRL + + ; fill the fifo with some silence + ldy #1024/256 +_z1: ldx #0 +_z2: stz VERA_AUDIO_DATA + dex + bne _z2 + dey + bne _z1 + + ldx #audio_on_txt + jsr print + + ldx #pcm_data + stx pcm_ptr + sty pcm_ptr+1 + + ; set interrupt handler + sei + ldx #irq_handler + stx IRQ_VECTOR + sty IRQ_VECTOR+1 + lda #%00001000 ; enable the AFLOW irq + sta VERA_IEN + cli + + lda #21 + sta VERA_AUDIO_RATE ; start playback + +_wait: + wai + bra _wait + + +irq_handler: + lda VERA_ISR + and #%00001000 ; is aflow? + bne _aflow_irq + ; TODO other irq + bra _exit_irq + +_aflow_irq: + ; paint a screen color + stz VERA_CTRL + lda #$0c + sta VERA_ADDR_L + lda #$fa + sta VERA_ADDR_M + lda #$01 + sta VERA_ADDR_H + lda #$a0 + sta VERA_DATA0 + + ; refill fifo buffer (minimum 1Kb = 1/4) + ; this assumes all samples are aligned to page size! + ; so we can at least copy a full page at once here. + ldx #8 ; number of pages to copy +_copy_more_pages: + ldy #0 +_c1: lda (pcm_ptr),y + sta VERA_AUDIO_DATA ; lsb + iny + lda (pcm_ptr),y + sta VERA_AUDIO_DATA ; msb + iny + ; (in case of 16 bit stereo output, this can be unrolled by 2 bytes again). + bne _c1 + inc pcm_ptr+1 + + ; have we reached the end of the sample data? (pcm_ptr >= pcm_data_end) + ; due to page size alignment only the MSB has to be checked + lda pcm_ptr+1 + cmp #>pcm_data_end + bcc _not_at_end + bne _end_reached +; lda pcm_ptr ; uncomment if lsb also needs to be checked +; cmp #pcm_data + sta pcm_ptr+1 + bra _not_at_end + + +audio_on_txt: .text "AUDIO ON (IRQ)", $0d, $00 + +print: ; -- print string pointed to by X/Y + stx r0L + sty r0H + ldy #0 +_chr: lda (r0),y + beq _done + jsr $ffd2 + iny + bne _chr +_done: rts + + .align $0100 +pcm_data: + .binary "pcm-mono.bin" +pcm_data_end: