| |
Conrad
Registered: Nov 2006 Posts: 849 |
How easy is it to calculate sine tables from the bare bones in ML?
Hi!
I'd like to have a go at coding my own routine of calculating sine/cosine tables without use of the BASIC interpreters (pi, sin(), etc) and just use pure ML instead.
Can I ask, how easy (or how SMALL) is this to do? Do I need to do additional algorithms like factorial or are there KERNAL routines for that (if any)? Multiplication code is no problem as I've seen articles on those, I'm just thinking about the rest of math involved with sine calculation.
Thanx in advance. |
|
... 22 posts hidden. Click here to view all posts.... |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
5.89 is definitely fast enough for a tinytro, but I think I'll stick to generating them with a KickAss script for normal cases.
|
| |
JackAsser
Registered: Jun 2002 Posts: 2014 |
@Cruzer: I agree and it actually SAVES memory in the end because you will not have the generator in memory, only the end result. (And buhu what I miss trig-operations and floatingpoints in ca65...) |
| |
doynax Account closed
Registered: Oct 2004 Posts: 212 |
Quote: @Cruzer: I agree and it actually SAVES memory in the end because you will not have the generator in memory, only the end result. (And buhu what I miss trig-operations and floatingpoints in ca65...)
I'd say if you're not kicking out your initialization code then a sine generator is the least of your worries (drivecode anyone?).
Personally I prefer to mirror the first 64 entries to create the rest of the table, which saves 170 bytes or so and loads a tad faster. Hey.. things like this add up, especially for game code.
Oh, and I saved another byte in the generator (down to 28) at the cost of creating a negated sine table instead, though I seriously doubt that matters for 256-byte intro use. |
| |
Monte Carlos
Registered: Jun 2004 Posts: 359 |
To avoid that the sinmax and sinmin is reached only for one byte, use a+(a-0.5)*sin(pi/180*i) instead of
a*(1+sin(pi/180*i)).
Monti Carlotti
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Quoting doynaxOh, and I saved another byte in the generator (down to 28) at the cost of creating a negated sine table instead, though I seriously doubt that matters for 256-byte intro use. Do want! :) |
| |
doynax Account closed
Registered: Oct 2004 Posts: 212 |
Quoting CruzerDo want! :) It took a bit of filesystem spelunking but here you go: http://pastebin.com/dMFP3F47
Now be sure to buy yourself something nice with that extra byte.
Sidenote: I must confess to some surprise at finding no less than three 6502 assembly dialects to choose from at pastebin. It's almost enough to get an embittered atheist into the Christmas spirit. |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1409 |
An alternate approach is to fill a table with a square wave, then filter it with a few smoothing passes to eliminate the harmonics. The following hasn't been optimised for size, but it's only 38 bytes, and only takes about 170,000 cycles to create a table of 127.5+63*cosine(i*pi/128) with an RMS error of under 1%
(warning, also trashes 52 bytes after the end of the table. Number of passes, and initial square wave phase and amplitude optimised by brute force search with a Python script. Output ranges from $40 to $bf).
ldx#127
prefill
sta cosine,x
lda#19
sta cosine+52,x
lda#250
sta cosine+128+52,x
dex
bpl prefill
ldy#30
clc
smoothloop
lda cosine,x
adc cosine,y
ror
sta cosine,x
iny
inx
bne smoothloop
dey
bne smoothloop
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Thanx, Doynax! The sine is too different to be used in my current project, and since I'm already under 256 bytes I'm good for now. But will keep it for another time. |
| |
doynax Account closed
Registered: Oct 2004 Posts: 212 |
Quoting ChristopherJamAn alternate approach is to fill a table with a square wave, then filter it with a few smoothing passes to eliminate the harmonics. The following hasn't been optimised for size, but it's only 38 bytes, and only takes about 170,000 cycles to create a table of 127.5+63*cosine(i*pi/128) with an RMS error of under 1% Well done, that is exceedingly clever. I never would have considered that approach.
Any chance of a 16-bit version or one with (closer to) full 8-bit range? |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1409 |
Thanks doynax. I was probably somewhat influenced by having spent a couple of weeks playing with Karplus–Strong string synthesis earlier this year (looking for fresh samples to try to play back on the c64 ;) - most of the sounds tended towards a sine wave eventually.
16 bit should be reasonably sane; I've just finished tuning a simulation of one that gives 16 bit results with a range from $0000 to $ffff, RMS error of around 31, or 0.04% of the full range.
It's all getting a little far from practical at this point, as it likely wouldn't save that much space over a table, which in turn you could probably LZ compress the deltas for reasonably well.
Here's the Python in any case - I leave translation to 6502 as an exercise for the reader, or my future self if I get really really bored. The N.sum(v)/256 terms could, of course, be pre-calculated.
import numpy as N
def sim(si,jo,dco,lv,hv,pw):
v=N.zeros((256,),N.int)+lv
v[dco:][:pw]*=0
v[dco:][:pw]+=hv
nv=1
i=si
j=(i+jo)&255
while 1:
nv=(v[i]+v[j])+(nv&1)
v[i]=nv/2
i=(i+1)&255
j=(j+1)&255
if(i&255==0):
j=(j-1)&255
if j==0:
break
v=(v+N.take(v,(N.arange(256)+64)%256))*256
v-=N.sum(v)/256
v=N.cumsum(v)/256
v-=N.sum(v)/256
v[0]+=0xfffe00
v=N.cumsum(v)/256
return v
v=sim(255, 31, 81, 0, 13097, 131)
|
Previous - 1 | 2 | 3 | 4 - Next |