I made a DPCM speech synth. I never really polished the program properly, or implemented saving/loading like I wanted, but you can check it out
here.
If it would help, maybe I could post the full source code. Most of the source covers the editor and file format, the actual sound part is just an IRQ routine and a sample info table.
File format is pretty simple, each 2 bytes is either "sample speed, sample number" or "frame delay time, frame delay marker (3F)", and zero ends playback of the speech "string".
Version of the source with only the important parts:
Code:
lda #$C0 ; must to do this to use internal IRQ source
sta $4017
cli
jmp main_loop
irq:
pha
txa
pha
tya
pha
lda speech_enable
bne talk
temp_delay:
lda #%00000000
sta $4015
beq endirq
talk:
lda frame_delay
bne temp_delay
ldy #0
lda (speech_lo),y
beq stop_madness
sty $4015
tax
ora #%10000000
sta $4010
iny
lda (speech_lo),y
cmp #$3F
beq pause_madness
asl
tax
lda sample_length_index,x
sta $4013
lda sample_addr_index,x
sta $4012
lda #%00010000
sta $4015
before_end:
inc16 speech_lo
inc16 speech_lo
endirq:
pla
tay
pla
tax
pla
rti
stop_madness:
sta speech_enable
sta $4015
beq endirq
pause_madness:
stx frame_delay
lda #0
sta $4015
jmp before_end
sample_addr_index:
.word (voc00-$C000)/$40
.word (voc01-$C000)/$40
.word (voc02-$C000)/$40
.word (voc03-$C000)/$40
.word (voc04-$C000)/$40
.word (voc05-$C000)/$40
.word (voc06-$C000)/$40
sample_length_index:
.word (voc01-voc00)/16 ; a
.word (voc02-voc01)/16 ; ae
.word (voc03-voc02)/16 ; aw
.word (voc04-voc03)/16 ; ar
.word (voc05-voc04)/16 ; e
.word (voc06-voc05)/16 ; ee
.segment "SAMPLES" ; $C000 - $FFF9
voc00: .incbin "set1\a.dmc"
voc01: .incbin "set1\ae.dmc"
voc02: .incbin "set1\aw.dmc"
voc03: .incbin "set1\ar.dmc"
One thing I would have done differently, is to use bankswitching so a higher sample-rate would fit. The 'nominal' DPCM sample rate I used was $C (where $F would be the maximum), so all the samples could fit into 16kB.