Unfortunately I don’t hear any difference. However, I’ve now ported the code to the Acorn Electron which only has an on/off state for sound (no volume control) and I can hear a recognisable tune - it has a slower 1MHz processor so needs some adjustment. Based on what I’m hearing there may still be some issues with the pattern parsing. I’ll look through a disassembly of XXL’s Atari Tritone code to see if there’s anything obviously different.
1 2024-03-16 10:19:33
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
2 2024-03-14 05:33:59
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
Do you happen to know if setting the frequency of an SN channel will reset its phase?
I may be wrong, but I believe this is only true of the LFSR (which I’m not using here). However, noise phase is reset by frequency writes, volume writes have no effect.
3 2024-03-13 06:53:00
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
Thanks - I’ll try outputting to three channels simultaneously next. I think some of the slowness is probably the values I’m using in the custom .1te engine to output the music data. I’m not sure I have the right value for CPU time.
I’ve put the code I have so far on GitHub: https://github.com/NegativeCharge/Beeb-Tritone-Player
4 2024-03-12 20:26:09
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
A quick update - I’ve now got this partially working… it’s playing back too slow, is fairly quiet and there’s a high pitched whine in the background. However, it’s making a recognisable sound now :-) Thanks utz!
The issue was that the SN volume value needs to flip between 0x0 and 0xf rather than 0xff. I added an AND 0xf before each ORA for each channel.
I now need to alter the speed and optimize the data read somehow.
5 2024-03-11 22:00:39
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
Thank you utz. Once I have something working I may take another look at the data format. Here's the revised code - I still suspect something wrong with the duty or frequency parsing
;Tritone beeper music engine
;Original Z80 code by Shiru 03'2011, released as Public Domain
;1tracker version by Shiru 03'2018
;6502 engine port by utz 03'2024
;Ported to the BBC Micro by Negative Charge 03'2024
; Constants
OSBYTE = $FFF4
OSWRCH = $FFEE
OSNEWL = $FFE7
SHEILABASE = $FE00 ; System peripherals
SYSVIA_DDRA = SHEILABASE + $43 ; Data direction register A
SYSVIA_ORAS = SHEILABASE + $4F ; Same as REGA but with no handshake I/O
SYSVIA_REGB = SHEILABASE + $40 ; Port B I/O
DISPLAY_START = $7c00
DEBUG = TRUE
ROW_DEBUG = FALSE
OP_NOP = $EA
OP_ROL_A = $2A
; Zero Page
ORG $5f
GUARD $8f
.vars_start
.loop_ptr SKIP 2
.pattern_ptr SKIP 2
.speed SKIP 2
.drum SKIP 1
.vars_end
ORG &1100
GUARD DISPLAY_START
.start
INCLUDE "lib\os.s.6502"
; Write data to sound chip then add processing delay
MACRO sound_write_slow
sta SYSVIA_ORAS ;4 Write reg/data to SN76489
lda #%00000000 ;2
sta SYSVIA_REGB ;4
nop ;2
nop ;2
nop ;2
lda #%00001000 ;2
sta SYSVIA_REGB ;4
ENDMACRO
MACRO RESET_SOUND_CHIP
; Zero volumes on all SN76489 channels, just in case anything already playing
lda #%11111111
sound_write_slow ; Channel 3 (Noise)
lda #%11011111
sound_write_slow ; Channel 2
lda #%10111111
sound_write_slow ; Channel 1
lda #%10011111
sound_write_slow ; Channel 0
ENDMACRO
.init
; Print Track Title
ldx #1
ldy #22
jsr moveTextCursor
jsr printString
equs "The Liberty Bell",0
; Print Track Artist
ldx #1
ldy #24
jsr moveTextCursor
jsr printString
equs "John Philip Sousa",0
; Set up audio
; System VIA port A to all outputs
lda #%11111111
sta SYSVIA_DDRA
sei
RESET_SOUND_CHIP
; Period to 1 on tone channel 0
lda #%10000001
sound_write_slow ; Channel 0
lda #%00000000
sound_write_slow
; System VIA Port A, place accumulator on wires, no handshake
lda #%00000000
sta SYSVIA_REGB
lda #LO(music_data)
ldx #HI(music_data)
.play
pha
txa
pha
lda #0
tax
.zero_page_reset_loop
sta vars_start,x
inx
cpx #vars_end-vars_start
bne zero_page_reset_loop
pla
sta pattern_ptr+1
pla
sta pattern_ptr+0
IF DEBUG
pha:txa:pha:tya:pha
ldx #1
ldy #1
jsr moveTextCursor
jsr printString
equs "Pattern Pointer: ",0
lda pattern_ptr+1
jsr s_print_hex
lda pattern_ptr+0
jsr s_print_hex
jsr OSNEWL
pla:tay:pla:tax:pla
ENDIF
ldy #0
lda (pattern_ptr),y
sta loop_ptr+0
iny
lda (pattern_ptr),y
sta loop_ptr+1
IF DEBUG
pha:txa:pha:tya:pha
ldx #1
ldy #2
jsr moveTextCursor
jsr printString
equs "Loop Pointer : ",0
lda loop_ptr+1
jsr s_print_hex
lda loop_ptr+0
jsr s_print_hex
jsr OSNEWL
pla:tay:pla:tax:pla
ENDIF
lda pattern_ptr+0
clc
adc #6
sta pattern_ptr+0
bcc play_loop
inc pattern_ptr+1
.play_loop
ldy #1
lda (pattern_ptr),y
bne no_loop
.return_loop
lda loop_ptr+0
sta pattern_ptr+0
lda loop_ptr+1
sta pattern_ptr+1
jmp play_loop
.no_loop
iny
lda (pattern_ptr),y
iny
sta speed+0
sta row_length_lo
lda (pattern_ptr),y
iny
sta speed+1
sta row_length_hi
IF DEBUG
pha:txa:pha:tya:pha
ldx #1
ldy #4
jsr moveTextCursor
jsr printString
equs "Speed : ",0
lda speed+1
jsr s_print_hex
lda speed+0
jsr s_print_hex
jsr OSNEWL
pla:tay:pla:tax:pla
ENDIF
jmp row
.pattern_end
cli ; Enable interrupts
RESET_SOUND_CHIP
rts
.row
ldy #0
lda (pattern_ptr),y
bne ch0
sta drum ; Silent
sta ch0_duty
sta ch0_div_lo
sta ch0_div_hi
jmp skip_ch0
.ch0
cmp #$ff
beq pattern_end
cmp #$01
beq skip_ch0 ; Same as previous ch0 entry
cmp #$80
bcc skip_drum
sta drum
iny
lda (pattern_ptr),y
.skip_drum
pha
lsr a
lsr a
lsr a
lsr a
sta ch0_duty
pla
ora #%00001111
sta ch0_div_hi
iny
lda (pattern_ptr),y
sta ch0_div_lo
.skip_ch0
iny
lda (pattern_ptr),y
bne ch1
sta ch1_duty
sta ch1_div_lo
sta ch1_div_hi
jmp skip_ch1
.ch1
cmp #$01
beq skip_ch1 ; Same as previous ch0 entry
pha
lsr a
lsr a
lsr a
lsr a
sta ch1_duty
pla
ora #%00001111
sta ch1_div_hi
iny
lda (pattern_ptr),y
sta ch1_div_lo
.skip_ch1
iny
lda (pattern_ptr),y
bne ch2
sta ch2_duty
sta ch2_div_lo
sta ch2_div_hi
jmp skip_ch2
.ch2
cmp #$01
beq skip_ch2 ; Same as previous ch0 entry
pha
lsr a
lsr a
lsr a
lsr a
sta ch2_duty
pla
ora #%00001111
sta ch2_div_hi
iny
lda (pattern_ptr),y
sta ch2_div_lo
.skip_ch2
tya
row_length_lo=*+1
ldx #0 ; reset row length counter lo byte
row_length_hi=*+1
ldy #0
IF ROW_DEBUG
jsr printRowInfo
ENDIF
clc
adc pattern_ptr+0
sta pattern_ptr+0
bcc play_note
inc pattern_ptr+1
.play_note
clc ;2 update osc
ch0_div_lo=*+1
lda #$0 ;2
ch0_acc_lo=*+1
adc #$0 ;2
sta ch0_acc_lo ;4
ch0_div_hi=*+1
lda #$0 ;2
ch0_acc_hi=*+1
adc #$0 ;2
sta ch0_acc_hi ;4
ch0_duty=*+1
cmp #$0 ;2 compare against duty threshold
sbc ch0_acc_hi ;4 A = 0 on low half-cycle, FF on hi half-cycle
ora #%10010000 ;2
sta SYSVIA_ORAS ;4
clc ;2
ch1_div_lo=*+1
lda #$0 ;2
ch1_acc_lo=*+1
adc #$0 ;2
sta ch1_acc_lo ;4
ch1_div_hi=*+1
lda #$0 ;2
ch1_acc_hi=*+1
adc #$0 ;2
sta ch1_acc_hi ;4
ch1_duty=*+1
cmp #$0 ;2
sbc ch1_acc_hi ;4
ora #%10010000 ;2
sta SYSVIA_ORAS ;4
clc ;2
ch2_div_lo=*+1
lda #$0 ;2
ch2_acc_lo=*+1
adc #$0 ;2
sta ch2_acc_lo ;4
ch2_div_hi=*+1
lda #$0 ;2
ch2_acc_hi=*+1
adc #$0 ;2
sta ch2_acc_hi ;4
ch2_duty=*+1
cmp #$0 ;2
sbc ch2_acc_hi ;4
ora #%10010000 ;2
sta SYSVIA_ORAS ;2
dex ;2 row length low byte
bne play_note ;3 -- 95 ~ 21053Hz (original is 22876Hz)
dey ; row length hi byte
bne play_note
jmp row
.s_print_hex
pha ; Save A
lsr a
lsr a
lsr a
lsr a ; Move top nybble to bottom nybble
jsr printNybble
pla
and #&0f ; Mask out original bottom nybble
.printNybble
sed
clc
adc #&90 ; Produce &90-&99 or &00-&05
adc #&40 ; Produce &30-&39 or &41-&46
cld
jmp OSWRCH ; Print it
.printRowInfo
pha:txa:pha:tya:pha
ldx #1
ldy #8
jsr moveTextCursor
jsr printString
equs "Row: ",0
lda ch0_div_hi
jsr s_print_hex
lda ch0_div_lo
jsr s_print_hex
ldx #11
ldy #8
jsr moveTextCursor
lda ch1_div_hi
jsr s_print_hex
lda ch1_div_lo
jsr s_print_hex
ldx #16
ldy #8
jsr moveTextCursor
lda ch2_div_hi
jsr s_print_hex
lda ch2_div_lo
jsr s_print_hex
pla:tay:pla:tax:pla
rts
INCLUDE "tracks\liberty_bell_tritone.6502"
.end
SAVE "MAIN",start,end,init
\ ******************************************************************
\ * Memory Info
\ ******************************************************************
PRINT "-----------------------"
PRINT " 1-BIT TRITONE PLAYER "
PRINT "-----------------------"
PRINT "CODE size = ", ~end-start
PRINT "-----------------------"
PRINT "HIGH WATERMARK = ", ~P%
PRINT "FREE = ", ~start+end
PRINT "-----------------------"
\ ******************************************************************
\ * Supporting Files
\ ******************************************************************
PUTBASIC "loader.bas","LOADER"
PUTFILE "screens\title.bin","TITLE",DISPLAY_START
PUTFILE "BOOT","!BOOT",$ffff
6 2024-03-11 21:10:32
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
For standard Tritone there only appears to be a global speed setting? - Tritone Digi has per-row.
Is the speed the value that should be plugged into the row length counter?… and if so should that be bne play_note rather than beq play_note?
I’ve tried this but still just getting a high pitched note currently.
Thanks
7 2024-03-11 14:25:15
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
One thing I spotted skimming through quickly is that you're loading a drum marker per tone channel, but there's only one global drum channel in Tritone.
Thanks - I've corrected that. I'm still getting the same high pitched output though.
8 2024-03-11 12:20:24
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
Hi utz,
I've given this a go, but I think I'm either doing something wrong iterating through the pattern data or I've messed up the play loop - all I'm getting is a high pitched squeal, and a few clicks.
I'm using Shiru's data export from 1tracker, so the format should be familiar.
I think (based on the tritone.1te) that I may be misinterpreting how the duty and frequency are being stored.
Is there anything obvious in the below code that jumps out at you as incorrect?
Thanks!
;Tritone beeper music engine
;Original Z80 code by Shiru 03'2011, released as Public Domain
;1tracker version by Shiru 03'2018
;6502 engine port by utz 03'2024
;Ported to the BBC Micro by Negative Charge 03'2024
; Constants
OSBYTE = $FFF4
OSWRCH = $FFEE
OSNEWL = $FFE7
SHEILABASE = $FE00 ; System peripherals
SYSVIA_DDRA = SHEILABASE + $43 ; Data direction register A
SYSVIA_ORAS = SHEILABASE + $4F ; Same as REGA but with no handshake I/O
SYSVIA_REGB = SHEILABASE + $40 ; Port B I/O
DISPLAY_START = $7c00
DEBUG = TRUE
OP_NOP = $EA
OP_ROL_A = $2A
; Zero Page
ORG $5f
GUARD $8f
.vars_start
.loop_ptr SKIP 2
.pattern_ptr SKIP 2
.speed SKIP 2
.ch0_drum SKIP 1
.ch1_drum SKIP 1
.ch2_drum SKIP 1
.vars_end
ORG &1100
GUARD DISPLAY_START
.start
INCLUDE "lib\os.s.6502"
; Write data to sound chip then add processing delay
MACRO sound_write_slow
sta SYSVIA_ORAS ;4 Write reg/data to SN76489
lda #%00000000 ;2
sta SYSVIA_REGB ;4
nop ;2
nop ;2
nop ;2
lda #%00001000 ;2
sta SYSVIA_REGB ;4
ENDMACRO
MACRO RESET_SOUND_CHIP
; Zero volumes on all SN76489 channels, just in case anything already playing
lda #%11111111
sound_write_slow ; Channel 3 (Noise)
lda #%11011111
sound_write_slow ; Channel 2
lda #%10111111
sound_write_slow ; Channel 1
lda #%10011111
sound_write_slow ; Channel 0
ENDMACRO
.init
\ Print Track Title
ldx #1
ldy #22
jsr moveTextCursor
jsr printString
equs "The Liberty Bell",0
\ Print Track Artist
ldx #1
ldy #24
jsr moveTextCursor
jsr printString
equs "John Philip Sousa",0
; Set up audio
; System VIA port A to all outputs
lda #%11111111
sta SYSVIA_DDRA
sei
RESET_SOUND_CHIP
; Period to 1 on tone channel 0
lda #%10000001
sound_write_slow ; Channel 0
lda #%00000000
sound_write_slow
; System VIA Port A, place accumulator on wires, no handshake
lda #%00000000
sta SYSVIA_REGB
lda #LO(music_data)
ldx #HI(music_data)
.play
pha
txa
pha
lda #0
tax
.zero_page_reset_loop
sta vars_start,x
inx
cpx #vars_end-vars_start
bne zero_page_reset_loop
pla
sta pattern_ptr+1
pla
sta pattern_ptr+0
IF DEBUG
pha:txa:pha:tya:pha
ldx #1
ldy #1
jsr moveTextCursor
jsr printString
equs "Pattern Pointer: ",0
lda pattern_ptr+1
jsr s_print_hex
lda pattern_ptr+0
jsr s_print_hex
jsr OSNEWL
pla:tay:pla:tax:pla
ENDIF
ldy #0
lda (pattern_ptr),y
sta loop_ptr+0
iny
lda (pattern_ptr),y
sta loop_ptr+1
IF DEBUG
pha:txa:pha:tya:pha
ldx #1
ldy #2
jsr moveTextCursor
jsr printString
equs "Loop Pointer : ",0
lda loop_ptr+1
jsr s_print_hex
lda loop_ptr+0
jsr s_print_hex
jsr OSNEWL
pla:tay:pla:tax:pla
ENDIF
lda pattern_ptr+0
clc
adc #6
sta pattern_ptr+0
bcc play_loop
inc pattern_ptr+1
.play_loop
ldy #1
lda (pattern_ptr),y
bne no_loop
.return_loop
lda loop_ptr+0
sta pattern_ptr+0
lda loop_ptr+1
sta pattern_ptr+1
jmp play_loop
.no_loop
iny
lda (pattern_ptr),y
iny
sta speed+0
lda (pattern_ptr),y
iny
sta speed+1
IF DEBUG
pha:txa:pha:tya:pha
ldx #1
ldy #4
jsr moveTextCursor
jsr printString
equs "Speed : ",0
lda speed+1
jsr s_print_hex
lda speed+0
jsr s_print_hex
jsr OSNEWL
pla:tay:pla:tax:pla
ENDIF
jmp row
.pattern_end
cli ; Enable interrupts
RESET_SOUND_CHIP
rts
.row
ldy #0
lda (pattern_ptr),y
bne ch0
sta ch0_drum ; Silent
sta ch0_duty
sta ch0_div_lo
sta ch0_div_hi
jmp skip_ch0
.ch0
cmp #$ff
beq pattern_end
cmp #$01
beq skip_ch0 ; Same as previous ch0 entry
cmp #$80
bcc skip_drum_0
sta ch0_drum
iny
lda (pattern_ptr),y
.skip_drum_0
pha
lsr a
lsr a
lsr a
lsr a
sta ch0_duty
pla
ora #%00001111
sta ch0_div_hi
iny
lda (pattern_ptr),y
sta ch0_div_lo
.skip_ch0
iny
lda (pattern_ptr),y
bne ch1
sta ch1_drum ; Silent
sta ch1_duty
sta ch1_div_lo
sta ch1_div_hi
jmp skip_ch1
.ch1
cmp #$01
beq skip_ch1 ; Same as previous ch0 entry
cmp #$80
bcc skip_drum_1
sta ch1_drum
iny
lda (pattern_ptr),y
.skip_drum_1
pha
lsr a
lsr a
lsr a
lsr a
sta ch1_duty
pla
ora #%00001111
sta ch1_div_hi
iny
lda (pattern_ptr),y
sta ch1_div_lo
.skip_ch1
iny
lda (pattern_ptr),y
bne ch2
sta ch2_drum ; Silent
sta ch2_duty
sta ch2_div_lo
sta ch2_div_hi
jmp skip_ch2
.ch2
cmp #$01
beq skip_ch2 ; Same as previous ch0 entry
cmp #$80
bcc skip_drum_2
sta ch2_drum
iny
lda (pattern_ptr),y
.skip_drum_2
pha
lsr a
lsr a
lsr a
lsr a
sta ch2_duty
pla
ora #%00001111
sta ch2_div_hi
iny
lda (pattern_ptr),y
sta ch2_div_lo
.skip_ch2
tya
clc
adc pattern_ptr+0
sta pattern_ptr+0
bcc play_note
inc pattern_ptr+1
.play_note
IF DEBUG
jsr printRowInfo
ENDIF
clc ;2 update osc
ch0_div_lo=*+1
lda #$0 ;2
ch0_acc_lo=*+1
adc #$0 ;2
sta ch0_acc_lo ;4
ch0_div_hi=*+1
lda #$0 ;2
ch0_acc_hi=*+1
adc #$0 ;2
sta ch0_acc_hi ;4
ch0_duty=*+1
cmp #$0 ;2 compare against duty threshold
sbc ch0_acc_hi ;4 A = 0 on low half-cycle, FF on hi half-cycle
ora #%10010000 ;2
sta SYSVIA_ORAS ;4
clc ;2
ch1_div_lo=*+1
lda #$0 ;2
ch1_acc_lo=*+1
adc #$0 ;2
sta ch1_acc_lo ;4
ch1_div_hi=*+1
lda #$0 ;2
ch1_acc_hi=*+1
adc #$0 ;2
sta ch1_acc_hi ;4
ch1_duty=*+1
cmp #$0 ;2
sbc ch1_acc_hi ;4
ora #%10010000 ;2
sta SYSVIA_ORAS ;4
clc ;2
ch2_div_lo=*+1
lda #$0 ;2
ch2_acc_lo=*+1
adc #$0 ;2
sta ch2_acc_lo ;4
ch2_div_hi=*+1
lda #$0 ;2
ch2_acc_hi=*+1
adc #$0 ;2
sta ch2_acc_hi ;4
ch2_duty=*+1
cmp #$0 ;2
sbc ch2_acc_hi ;4
ora #%10010000 ;2
sta SYSVIA_ORAS ;2
jmp row
.s_print_hex
pha ; Save A
lsr a
lsr a
lsr a
lsr a ; Move top nybble to bottom nybble
jsr printNybble
pla
and #&0f ; Mask out original bottom nybble
.printNybble
sed
clc
adc #&90 ; Produce &90-&99 or &00-&05
adc #&40 ; Produce &30-&39 or &41-&46
cld
jmp OSWRCH ; Print it
.printRowInfo
pha:txa:pha:tya:pha
ldx #1
ldy #8
jsr moveTextCursor
jsr printString
equs "Row: ",0
lda ch0_div_hi
jsr s_print_hex
lda ch0_div_lo
jsr s_print_hex
ldx #11
ldy #8
jsr moveTextCursor
lda ch1_div_hi
jsr s_print_hex
lda ch1_div_lo
jsr s_print_hex
ldx #16
ldy #8
jsr moveTextCursor
lda ch2_div_hi
jsr s_print_hex
lda ch2_div_lo
jsr s_print_hex
pla:tay:pla:tax:pla
rts
INCLUDE "tracks\liberty_bell_tritone.6502"
.end
SAVE "MAIN",start,end,init
\ ******************************************************************
\ * Memory Info
\ ******************************************************************
PRINT "-----------------------"
PRINT " 1-BIT TRITONE PLAYER "
PRINT "-----------------------"
PRINT "CODE size = ", ~end-start
PRINT "-----------------------"
PRINT "HIGH WATERMARK = ", ~P%
PRINT "FREE = ", ~start+end
PRINT "-----------------------"
\ ******************************************************************
\ * Supporting Files
\ ******************************************************************
PUTBASIC "loader.bas","LOADER"
PUTFILE "screens\title.bin","TITLE",DISPLAY_START
PUTFILE "BOOT","!BOOT",$ffff
9 2024-03-05 22:02:09
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
Thanks utz!
That’s a great starting point. I’ll try and find some time over the next few days to experiment with it. I think I can use similar code to read the data as SquatM.
In the meantime I added some of your suggestions to the BBC Micro SquatM engine here: https://github.com/NegativeCharge/BBC-M … /main.6502
I couldn’t get it to work without the volume latch, but at least the high pitched noise has gone now.
I’ll let you know how I get on, and hopefully post a sample,
10 2024-03-04 16:46:52
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
Sorry, I meant taking this even further: only ora #%10010000 at the beginning, and then just use the active latch to set the lower 4 bits, without needing to set channel and type again. Though considering how quiet the SN is at the 50% base volume we get by setting period to 1, it might be necessary to actually set multiple channels at once.
Ah, I see. Yes, you can do that, and it does work - maybe some other adjustments need to be made as although the sound is less muffled, the noise appears to become high pitched.
11 2024-03-04 11:27:08
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
Hi utz,
Ah, so we're targetting SN76489. I assumed there might be some sort of native device.
The BBC Micro uses an SN76489. The Acorn Electron has no dedicated hardware for sound - it uses a ULA. I can adapt the code for the Electron fairly easily once there's a working SN76489 version.
Would it be acceptable to leave Port B I/O in WRITE mode and only switch to READing between pattern rows? That would speed up things quite a bit.
Yes! I just tested that with the SquatM engine and it makes quite a difference. Here's a video of the playback: https://youtu.be/sqFRGEz9g_U
Also, am I correct in assuming that I could just keep pumping out DATA bytes (LATCH = 0) to set the volume of a given channel?
That's correct - it's pretty much what the SquatM engine is doing:
ora #%10010000 ; bit-7 (latch/data), bits-6/5 (channel - 0), bit 4 (type - latch volume)
sound_write_slow ; output sound bit
Thanks
12 2024-03-01 20:50:32
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
Thank you utz! I’m fairly limited on memory (32kb) without using swram banks, but I can try decompressing at runtime.
With regards to how the BBC Micro disables interrupts and emits sound, here’s a port I made of Shiru’s SquatM engine:
https://github.com/NegativeCharge/BBC-M … /main.6502
ZP can start at zero, but is $5f to $8f in the above. Code is normally compiled to $1100 to allow disk access, but can drop to $e00 depending on the file system. The code above is in BeebAsm format but should be easy enough to switch to other compilers.
Thanks!
13 2024-02-26 12:18:13
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
Eh, finally some good news. Yes, this can be done. If you can generate the bitstream from the LFSR, you can convert it to SquatM's PWM sample format, which is basically just a bitstream with run length encoding. So eg. %1111000000011000000111000011 becomes 2,4,3,6,2,7,4,0 - the final 0 is the end marker.
Thank you! I'll investigate this. For the fixed white noise there is info here I'll look into: https://www.smspower.org/Development/SN … ftRegister
For now, I've crudely mapped these to the SquatM Noise percussion, which works but doesn't give the same force that sampled drums would.
I've attached another example C64 SID conversion based on 4-Mat's Empty (512 bytes) track (Original here: https://deepsid.chordian.net/?file=/MUS … bytes.sid)
14 2024-02-25 13:20:55
Re: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
Will the converter be released? Would love to hear how "A Mind Is Born" comes out. I love that!
6502 : Look at the Peskysound engine within 1Tracker. For the PET which also runs the 6502.
Thanks - yes, I do plan on releasing the converters once I’ve finished a frontend for them. At the moment it’s a manual workflow involving up to 10 scripts.
I tried “A Mind Is Born” but it seems to heavily rely upon filters, modulation and volume changes, so isn’t a great fit. The first 30+ seconds translate to the same couple of notes playing without the filters. I need to think about how to support them.
Thanks for the suggestion on the Peskysound engine. I’ll take a look.
15 2024-02-25 09:02:26
Topic: 1-bit sound on BBC Micro / Acorn Electron (26 replies, posted in Other Platforms)
I've been experimenting with the SquatM engine on two reasonably popular 6502 8-bit systems in the UK in the 1980's. I've built a number of converters from various PSG chips that I can then transform to the .1tm format. To start with I took a simple C64 SID file (https://deepsid.chordian.net/?file=/MUS … af_Rag.sid) and transformed this into the attached .1tm file.
You can hear this playing back a BBC Micro emulator here: https://twitter.com/charge_negative/sta … 7711753485
I'm wondering if there are options to optimize this file automatically, as compiled with player is over 27kb (out of 32kb available)?
I'm also interested in whether any of the other engines have been ported to the 6502 (or variants) with source code available? My Z80 knowledge to do this myself isn't up to the task.
Finally, a long shot but does anyone have ideas on how to convert SN76489 LFSR noise to SquatM noise/percussion? (fixed rather than tuned).
Thanks,
Negative Charge