While I was blindly experimenting with the extracted data trying to figure how to make it work, Ken Shirriff made a huge post full of precious information on the chip internals. In fact it has been explored back in 80s in an electronic magazine. So now it is totally possible to emulate the thing. I think the Arduino will be a good host - readily available, easily programmable. A more hardcore option would be an ATTiny implementation in assembly, it would function just like the original - one chip and no external components besides the battery and the speaker.

The arrangement of the chunks in the song ROM is likely visually linear - basically first 64 bits of the data is bit 0 of the whole song, then next 64 bits are bit 1, and so on (there is binary decoder to the left from the mask ROM field, and its control lines seem to be parallel). So it should look more like:

1000001001111101000000100111110100000100111110111100010001000001
1101010110100100110101011010011010101011010011000011101110111110
1000000110000010100000011000001000000011000001000011010011011110
0111110011010000111111001101001011111001101001011010100101101010
1111111110111111011111111011111111111111011111101111111111110110
1111111111110111111111111111011111111111111011110111011101111111

This way it really looks like the duration is encoded in the two bottom rows (two top bits).

In order to make a software emulator with very authentic sound and limitations, we need to read out the contents of a chip, and make a parser that would yield the melody that is contained in the chip.

There is a bit older but high resolution photo of the UM66 die, so I used it to read out the mask ROM contents visually. This is the UM66T-19L variant that contains the For Alice (Für Elise) song. This video features a music card with this song, I guess that's is that encoded in the binary data below.

We know from the die photos that the LFSR is 7 bit, but the taps are unknown. There are different possibilities on that, and I can't figure out the actual one from the die photo (yet). The input frequency is presumably 32768 Hz, no intermediate dividers. There is a 9 bit divided (or that's a multiple of 9) for the clock frequency that somehow gets converted into the note durations (using another LUT), though.

One ROM on the die is 7x16 bits, that's presumably a pitch LUT for 16 pitches with 7 bits to initialize the LFSR. The weird part is that there is 3 of 16 entries are all 0. The addressing is horizontal (0..15):

0000110001000011
0010001011110000
0001100001010101
0011110000100010
0011001110110101
0010100011000011
0011110010100010

Another ROM, the largest on the die, is 16x24 bit. That's presumably the song data that is presented with 6 bits per note (4 bits for pitch, 2 for duration), 64 notes total. 16 is 1/4 of the sequence length, so the addressing is at partially horizontal (0..15 in the lowest 4 bits of the address), but the arrangement of the chunks is unknown:

1000001001111101
0000001001111101
0000010011111011
1100010001000001
1101010110100100
1101010110100110
1010101101001100
0011101110111110
1000000110000010
1000000110000010
0000001100000100
0011010011011110
0111110011010000
1111110011010010
1111100110100101
1010100101101010
1111111110111111
0111111110111111
1111111101111110
1111111111110110
1111111111110111
1111111111110111
1111111111101111
0111011101111111

Yet another ROM is 4x4 bits. That's presumably the note duration ROM, although presumably a song position is encoded as 4 bits pitch and 2 bits duration. Not sure why there is 16 bits then:

0110
1000
1010
1001

May be a very interesting read to some, the reverse engineering process of a music greeting card chip. There are numerous chips of this kind, but they're function much alike, so it is very likely they're all share a very similar design. Read the original tweets or a condensed thread.

TL;DR - it is a hardwired machine with a 64-byte ROM that uses 4 bits for pitch and 2 bits for duration. No real computations are going here, it is not an MCU of sorts, just a very simple state machine. The most interesting part is how it produces the frequencies. I was wondering on this matter in the regards of the Game & Watch, with its 32 kHz oscillator, and it seems this one uses the same trick: an RC generated 32 kHz source get divided with a 7-bit LFSR instead of an actual counter, which is also cheaper on the transistor count. Actual pitch for the 16 notes is pre-programmed with the values loaded to the LFSR, so it is not square wave, but some bit patterns unique for each note.

As it is a mask ROM hardwired non-programmable chip, we can't really reprogram one for our needs. However, we can emulate it with a modern MCU, and drive it with a custom 64-byte sequence. Like, the tiniest ATTiny10 should be able to do the trick easily (and it has 1024 bytes, enough for a dozen of the short songs).

Side note, SjAsmPlus actually has support for 8080 with Z80 syntax, it basically limits valid supported opcodes to the 8080 subset. Activated with --i8080 flag. As there isn't many (if any) good modern 8080 cross assemblers, it comes very handy.

181

(19 replies, posted in Sinclair)

A note on this issue regarding to 1tracker. Most engines will survive a quick and dirty fix. You can open a *.1te file with a text editor, find there 'out (#fe),a' line, and add a 'and 16' line just before it. It will work in most cases, although a couple of engines may break. The downside of this fix will be a bit reduced pitch and play speed.

Some engines can have pitch issue corrected, although not all of them - find a definition of 'cpuTime', and subtract 7 from the value. If there was a few 'out (#fe),a' lines, add 'and 16' to each of them, and subtract 7 for each one as well.

This is a temporary solution, as it is uncertain if/when we will be fixing the issue. At least I'll add a note for each engine that is currently not compatible with +3, I guess.

182

(19 replies, posted in Sinclair)

Wow, that's unexpected. Some of my engines guilty with the same thing, though. Squat, for one. Easy to fix, though, but it'll reduce the internal sample rate a bit.

I recall some years back there was a guy who was talking a lot about this possibility of getting four output levels on the classic 48K beeper, and proposed to use it somehow in a beeper engine. However, as they're pretty close to each other on the extreme ends, no one figured out any useful application for such a feature.

Actually, even if there was a true 2-bit DAC with proper evenly spread levels, I'm not too sure what advantage it could have over 1-bit - a two-channel engine with 'lazy' mixing perhaps, but that wouldn't give a major speed advantage, or extra opportunities for more unusual synthesis techniques. Maybe I'm wrong.

Curious little quirk, nevertheless.

184

(19 replies, posted in Sinclair)

A guy reported a very weird issue with this engine. It is completely messed up on the ZX Spectrum +3. Not too sure what causes it, but the result looks like it runs in the slow memory. Booting in 48K mode does not help, I suppose it should have a fast RAM page at 8000 in the default configuration anyways?

185

(13 replies, posted in Atari)

There is export for this SquatM engine, but it only exports an assembly source with DBs. I sure would like to eventually get to a proper support, with a built-in 6502 assembler and XEX export.

As for porting other engines, we'll see. I think it is a good to bring some more of the finest ZX developments to the Atari platform.

186

(13 replies, posted in Atari)

Thanks!

No, I barely managed to get this basic on/off stuff to work properly in time for the compo, so I didn't investigate it further than that. I guess there can be more, and in general Atari XL/XE platform is worthy enough to pay more attention in regards of the 1-bit stuff.

187

(13 replies, posted in Atari)

Thanks, guys!

Yeah, better to keep 1tracker up to date to use newer engines. Not that it changes terribly, but it does get updates and fixes time to time (now as I'm using it by myself more often).

188

(13 replies, posted in Atari)

Here it is, the source code for CA65 assembler, my song from Silly Venture 2K20+1 in 1tracker format, and SquatM engine for 1tracker that has an option to export CA65 compatible data (but Z80 version plays in the tracker).

More unnecessary details at Patreon, like (now) usual. Don't be afraid to visit it, it is not behind a paywall, I'm just running a public blog there.

189

(43 replies, posted in Atari)

Sent my GTIA entry to SV, Grey responded it is the only one so far. So if anyone up to it, would be nice to have more!

Spoiler, it is a Squat tune, so there is a 6502 port now, and you can have it. Looking at you, utz!

Can also port some other engine if someone got a tune for an engine that hasn't been ported yet, but there is too little time, so hurry up.

190

(3 replies, posted in Sinclair)

Pretty good one. It sounds kinda oldschool, not filled with fast movements or tiny details that is typical for modern compositions, so it sets up the proper classic mood, although with much improved melodic content and sound quality of (not so) modern engine(s).

191

(1 replies, posted in Sinclair)

Yes, it has been done a long while ago, can't even remember how long. A decade or longer. The thing is that it is not an improved Z80 engine, it is just a PC based rendition that uses original music data and recreates original synthesis algorithms. MATLAB powered even, if I remember correctly.

Yeah, sounds much like it.

A new 1-bit music album has been released digitally a couple weeks back (took me that long to post here). Some quite nice authentic sounding stuff from an author I've never heard of before. Made with Beepola, with some extra post-processing at places, but without going too far from the pure 1-bit aesthetics.

Original announcement post
Bandcamp page

I did implement the viznut waveforms for the VIC-20. It was full of nasty surprises for sure, given the difficulty of making well timed 6502 code (added cycles here and there depending on code/vars locations), and really lacking debug tools. Even worse, VICE has some weird audio filtering going on, and MAME does not support expanded RAM for VIC (5K default model only), so I was not able to hear the sound properly, and my test code didn't fit to run in MAME.

It worked in the end, however, it wasn't much suitable for music. The thing is that these waveforms always contains 8 zeroes and 8 ones, just arranged in different ways. So it can't do the usual 50-25-12-7 duty cycle, or arbitrary bit patterns of PET, it just adds high pitched harmonics into square wave. So a special arrangement for music is a must, that would mostly rely of square wave and emphasize some parts using waveforms.

Here is the key part of the code (waveform_table there is to attempt to arrange waveforms in order from regular bold square to the thinest one):

set_pitch_and_wave:

    pha    
    tya
    bne :+
    
    sta <PV_WAVE_PREV,x
    lda #$7e
    sta VIC20_LOW,x
    pla
    rts
:
    
    asl a
    tay
        
    lda waveform_table,y
    iny
    
    cmp PV_WAVE_PREV,x
    beq @skip_wave
    
    sta PV_WAVE_PREV,x
    sta PV_WAVE_PTN
    
    lda #$7e
    sta VIC20_LOW,x
    
    lda waveform_table,y
    
    ldy #100/5                ;delay t-states/5
:
    dey
    bne :-

    tay

@loop:

    lda <PV_WAVE_PTN        ;3
    and #$80                ;2
    ora wavecnt_table,x        ;4+
    sta VIC20_LOW,x            ;4+
    asl <PV_WAVE_PTN        ;5
    lda <PV_WAVE_PTN        ;3
    nop                        ;2
    nop                        ;2
    nop                        ;2
    dey                        ;2
    bne @loop                ;2/3=32t

@skip_wave:

    pla
    tay
    lda (PV_NOTE_TABLE),y
    sta VIC20_LOW,x
    
    rts

wavecnt_table:

    .byte $7d,$7b,$79
    
waveform_table:

    .byte %11000000,3    ;00
    .byte %10010000,6    ;14
    .byte %10100000,5    ;09
    .byte %10100000,4    ;12
    .byte %10110000,6    ;11
    .byte %10110000,5    ;07
    .byte %10000000,2    ;01
    .byte %10000000,3    ;04
    .byte %11010000,5    ;08
    .byte %10101000,6    ;13
    .byte %10010000,5    ;06
    .byte %11100000,4    ;03
    .byte %10110000,4    ;02
    .byte %11000000,5    ;10
    .byte %10000000,4    ;05
    .byte %00000000,0    ;15

In fact, I think I'll release the whole sound code sometime later. Released album code contains most of it anyways, it only missing VIC-20, C64 and NES dependent parts.

I did finish code for PET, VIC, and C64, but integration failed on the last mile - something conflicted or glitched, and my code didn't work in PET and C64 versions inside actual game by reasons unknown. As the integration was done on binary level (not source level), and I don't have a real PET or C64, and available debuggers leave a lot to be desired, and the game was already released anyways (first copies were done without sound), we're ended up with only using VIC-20 part for sound effects. David opted to do his own sound code and even a native tracker for PET instead.

As for music, initially it was supposed that I'll compose it all, to the strengths of my sound code, but as its development was lagging behind a lot, it was decided that Noelle will do SID music in goattracker, and I'll have to convert it for PET/VIC, which didn't work well, of course. So none of my music was used, and that's why I decided to release it as a standalone album.

I covered up the story in my Patreon blog, there is a few posts, you can follow it up by the 'pet robots' tag. Planning to do two more, one on the music editing process (1tracker this time) and data format (pretty compact, the songs 1000-1500 bytes large each), and another one on making of the album itself.

Long story short, I made a 8-song album for Commodore PET. It works kinda like PC Speaker music, just a single channel, but with wave shaping capabilities (different bit patterns) instead of regular square wave. No multichannel synthesis there, although it is sure possible on this beast.

https://www.youtube.com/watch?v=JEhGa5avUKM

197

(1 replies, posted in General Discussion)

Those were mostly produced by the Battle of the Bits gang, when beeper stuff was a novelty to them. I guess they're tired of it, and we're still not provided them with good enough tools to spark interest for newer engines. Like, both 1tracker or bintracker certainly isn't as easy to use as Beepola, and more recent engines don't have an XM converter either.

198

(164 replies, posted in Sinclair)

It is just matter of personal taste. There are dozens of popular trackers in the history that didn't follow the line. There are sequencers in the history that didn't display anything at all, yet was very handy to create music.

It is impossible to do with this design, anyways.

199

(164 replies, posted in Sinclair)

Thanks for report. Yeah, just noticed there is still issues with that, even though it does not do segfault to me. Damnit. Alright, more work to do!

Robin of the Wood game is from 1985, Follin started to do his stuff including Vectron the same year, so it is difficult to say, but it is sure one of the earliest. Also features kinda unusual channel mixing with a single out per loop, take a look (guess that's where ZX-3/10 and Squeeker roots are?).

200

(164 replies, posted in Sinclair)

v0.31 is out. Many fixes in the front-end and many engines. Minimal examples and docs for each and every engine. The classic two-channel engine from Robin Hood is added, in all of its original glory.