Jump to content
IGNORED

SV2k17 256 Bytes of Blues


ivop

Recommended Posts

Thanks! :) I have been interested in generative music for years, but never got to actually programming it, until now. First time compo entry, too, so I'm very satisfied I came in second.

 

There are not that many comments in the source, but if you want, I can explain some more. Core idea is using the three least significant bits of every byte of a page in ROM as an index in a pentatonic scale table. It proves what I was taught when I was eight, that you can play pretty much any note of the pentatonic scale on top of a chord pattern in the same scale, especially if you don't play the notes too long.

Edited by ivop
  • Like 8
Link to comment
Share on other sites

OH NOES - you even had 10 bytes free. And there are 14 more bytes to free with minor changes. I absolutely love this one.

If only you had put in some PM VU meter/rainbow/flash instead of the blue graphics 0 screen this would have won the compo easily!

In my entry I play the scroll text instead of the OS, looks like you did the better choice :-)

  • Like 3
Link to comment
Share on other sites

OH NOES - you even had 10 bytes free.

 

Yeah, I wasn't sure if I needed to include a run address.

 

And there are 14 more bytes to free with minor changes. I absolutely love this one.

 

I'd be interested in seeing how that's done! Proves it definitely helps to have another pair of fresh eyes :)

 

If only you had put in some PM VU meter/rainbow/flash instead of the blue graphics 0 screen this would have won the compo easily!

 

I actually never considered adding something graphical. Total tunnel vision on audio :) Even with 4 bytes to spare, I could at least have added a store to some color register.

 

In my entry I play the scroll text instead of the OS, looks like you did the better choice :-)

At one point, I did have it play page zero, so effectively it was playing itself :) But I didn't like the tune, so I switched back to an OS page.

  • Like 2
Link to comment
Share on other sites

Thanks! :) I have been interested in generative music for years, but never got to actually programming it, until now. First time compo entry, too, so I'm very satisfied I came in second.

 

There are not that many comments in the source, but if you want, I can explain some more. Core idea is using the three least significant bits of every byte of a page in ROM as an index in a pentatonic scale table. It proves what I was taught when I was eight, that you can play pretty much any note of the pentatonic scale on top of a chord pattern in the same scale, especially if you don't play the notes too long.

 

Nice work and the idea behind it.

 

What you say reminds me of when I was a kid and I was taught about various alternatives to the major/minor like pentatonic, wholetone etc. The teachers used to say: "well, these are easy to learn but extremely hard to master". And the bad results of practical exams usually proved they were right later on ;)

Edited by makary
  • Like 1
Link to comment
Share on other sites

A couple of months ago a few friends and I were discussing how 256b when spelled with a 'b' is really 256 bits, so here's one in 256 bits ;)

It's my interpretation of a famous piece by John Cage! All three movements are included in the zip file.

Must be run with 48+kB and Basic disabled in order to have the screen memory start at $bc40

mus32.zip

Edited by ivop
  • Like 10
Link to comment
Share on other sites

I'd be interested in seeing how that's done! Proves it definitely helps to have another pair of fresh eyes :)

 

Absolutely true. And sometimes even the own eye are better after a break. When I released SillyThings in 2010 I had spent 1 month getting the speed of the plot routine so good, it runs at 50 Hz in 90% of the cases. Two weeks after the party I looked at the code and saw I could easily make it 100% and still have time left per frame with just 3 lines of source changed....

 

Here is the source of the shortened 232 bytes version. I'd love to see a "final" with some visuals packed in there.

MUS256-jac.zip

 

Here are the differences:

 

Move code a little further down the zero page, so parts of the data move below $100. This way, "LDA zp,x" ca be used instead of "LDA abs,x".

Save the initial skipping by adding a useless additional loop.

post-17404-0-84143300-1513512027_thumb.png

Replace check for bit 0 using AND by LSR. Use BIT abs (.$2c) trick to fall-through the else part.

post-17404-0-67162900-1513512035_thumb.png

Trash RTCLOCK+2 using LSR instead of LDA/CMP. Reorder last branch, so it fits into the -128 bytes range.

post-17404-0-53879700-1513512046_thumb.png

  • Like 5
Link to comment
Share on other sites

Replace check for bit 0 using AND by LSR. Use BIT abs (.$2c) trick to fall-through the else part.

 

Trash RTCLOCK+2 using LSR instead of LDA/CMP. Reorder last branch, so it fits into the -128 bytes range.

 

Thanks! Have to remember this type of tricks for next time :) Very nice!!

 

One could save additional space by changing from 12 bar blues to for example an 8 bar chord progression (Canon in D :)), which saves 12 more bytes (4 bytes bass, 8 bytes chords) or an even shorter progression. BTW all this source code is public domain. Use it whenever you need a small music routine.

 

Link to comment
Share on other sites

Haven't analysed your code deeply, but couldn't the tables interdigitate to save some bytes without loosing anything?

hatclsf dta $00, $00, $00, $00, $00, $00
hatclsc dta $00, $00, $00, $00, $84, $88

...

crd1pat
    dta  81, 121,  91,  81
    dta 121, 121,  91,  91
    dta 121, 121, 121, 121
crd2pat
    dta  53,  81,  60,  53
    dta  81,  81,  60,  60
    dta  81,  81,  81,  81
pentatonic
    dta 121, 108, 96, 81, 72
    dta 60, 53, 47

will be e.g.:

hatclsf dta $00, $00 
hatclsc dta $00, $00, $00, $00, $84, $88

...

crd2pat
    dta  53,  81,  60,  53
    dta  81,  81,  60,  60
    dta  81,  81,  81
crd1pat
    dta  81, 121,  91,  81
    dta 121, 121,  91,  91
    dta 121, 121, 121

pentatonic
    dta 121, 108, 96, 81, 72
    dta 60, 53, 47

then...

  • Like 2
Link to comment
Share on other sites

The crd2pat, crd1pat, pentatonic overlap can indeed be eliminated! Saves 2 bytes. Sadly, with the audf/audc tables this won't work as there's a strict requirement for them to be 6 bytes apart.

    lda drumpat,x
    sta drumf
    clc
    adc #6
    sta drumc

But, down to 230 bytes :)

 

Edit: because this is always run right after it loops after waiting for the next frame with lsr:rcc 20, carry will always be set, so it can be changed to adc #5 without clc. Another byte saved! (229)

 

Edit2: attached zip

mus256-229bytes.zip

Edited by ivop
  • Like 4
Link to comment
Share on other sites

Sadly, with the audf/audc tables this won't work as there's a strict requirement for them to be 6 bytes apart.

 

Ok, I see.

 

But what about:

    lda drumpat,x
    sta drumf
    sbc #6              ; subs 6, carry is always set after looping
    sta drumc
...

snarec  dta $84, $86, $88, $8a, $ac, $ae
snaref  dta $00, $00, $00, $00, $a0, $80

hatclsc dta $00, $00, $00, $00, $84, $88
hatclsf dta $00, $00, $00, $00

kickc   dta $00, $00, $a8, $aa, $ac, $8e
kickf   dta $00, $00, $ff, $f0, $e0, $40

?

  • Like 1
Link to comment
Share on other sites

Hi!

 

The crd2pat, crd1pat, pentatonic overlap can indeed be eliminated! Saves 2 bytes. Sadly, with the audf/audc tables this won't work as there's a strict requirement for them to be 6 bytes apart.

    lda drumpat,x
    sta drumf
    clc
    adc #6
    sta drumc

 

You can rearrange them and save 4 bytes, see attached.

 

    lda drumpat,x
    sta drumc
    adc #(drums.hatclsf-drums.hatclsc-1)  ; adds 6 because carry is always set after looping
    sta drumf
....

 

drumpat .local
    dta <drums.hatclsc,  <drums.hatclsc, <drums.hatclsc, <drums.snarec
    dta <drums.hatclsc,  <drums.hatclsc, <drums.hatclsc, <drums.kickc
    dta <drums.hatclsc,  <drums.kickc,   <drums.hatclsc, <drums.snarec
    dta <drums.kickc,    <drums.hatclsc, <drums.hatclsc, <drums.kickc
    .endl
    m_assert_same_page drumpat

drums   .local
hatclsc dta $00, $00, $00, $00, $84, $88
kickc   dta $00, $00, $a8, $aa, $ac, $8e
snarec  dta $84, $86, $88, $8a, $ac, $ae

hatclsf = *-4   
        dta $00, $00
kickf   dta $00, $00, $ff, $f0, $e0, $40
snaref  dta $00, $00, $00, $00, $a0, $80
Note that when control value is $00, the frequency value can be anything.

 

Also, with current code, <drums.hatclsc is exactly 0, so there are a lot of zeroes in the "drumpat" table...

mus256.asm

  • Like 5
Link to comment
Share on other sites

Hi!

 

But, down to 230 bytes :)

More optimizations, down to 216 bytes:

 

- Use "EOR" to change chord notes instead of comparison/branch. Basically, do

hiero = *+1
    lda #$0
    sta $d204
chiero = *+1
    eor #$00        ; Interchange note for next in chord
    sta hiero
- Don't read "lda crdc,y" twice for chord and notes, read once and use for both.

- Exchange X and Y in inner loops, so more table reads can be zeropage.

 

Enjoy!

mus256.asm

  • Like 4
Link to comment
Share on other sites

That's an acceptable change IMHO. Still sounds good and almost the same. Here's 196 :) Changes the bass instrument slightly (sixth value played is now $c0 instead of $c2).

 

Another possibility is merging pentatonic and chord, but that would change the lead melody, because the order of pentatonic would be different. Would save another 3 bytes.

 

Edit: on the other hand, perhaps some people are already hearing something different than I do and the sv2k17 attendants did, because of a different ROM. The page that's played was selected for its melody from the 800XL stock ROM.

mus256.asm

mus256.xex

Edited by ivop
  • Like 2
Link to comment
Share on other sites

So do I :)

 

211 bytes.

 

205 bytes

 

 

Haven't access to an assembler now, you could try this:

Merge bassc and crdc table, save 4 bytes
-----

...

  lda bassc,x
  bne orbass
  lda #2
orbass				
  ora #$C0 		 
  sta $d203

...

  lda crdc,x
  ora #$A0
  bcs nocrd 

...

bassc   .local
crdc    .local
    dta $00, $05, $08, $0a, $0c, $0e
    .endl
    m_assert_same_page bassc

Link to comment
Share on other sites

Oh - too late... :)

 

Edit: Another idea:

 

"Compress" the "bluespat"-table, two bits per entry:

 

bluespat .local
dta %10000110
dta %00000101
dta %00000000
.endl

 

"Decompression" code may be shorter than the 7 saved bytes...

(not 9 because of smaller drumpat = *-1 overlap)

 

(Same "compression" could maybe applied to drumpat table)

Edited by Irgendwer
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...