English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General

 
 
Thread Tools
Old 26 May 2011, 15:54   #1
h0ffman
Registered User
 
Join Date: Aug 2008
Location: Salisbury
Posts: 469
Maths question, divisions, remainders etc.

Hi guys

Bit of a maths question today. Funnily enough relating to scope code again. It's to do with sample rates (or periods! as they are called on the amiga) and time calculations.

This is a section of code from the original protracker scope code..

Code:
	MOVEQ.L	#0,D1
	MOVE.W	ns_period(A2),D1
	LSR.W	#1,D1
	BEQ.S	ScoNextChan
	MOVE.L	#35469,D2
	DIVU	D1,D2
	EXT.L	D2
	ADD.L	D2,D0
The above section calculates where the sample pointer needs to draw from in the next frame. The 35469 is the magic number which does this.

So, at present all the scopes I've seen or worked on simply draw the samples byte by byte to the screen and uses this calculation to simply move the pointer each frame to where the sample should be. This is not an accurate representation of the wave form, however it does suffice most requirements.

What I want to do is draw the wave at the frequency it is being played at. My idea was to simply divide the 35469 by the pixel width of the scope, then use this value to increment the sample pointer for each pixel. However, I very quickly realised that you cannot get away with this as the remainder from the division needs to be taken into consideration for each pixel iteration.

Code:
	moveq	#0,d1
	MOVE.W	#172,D1  ; period
	LSR.W	#1,D1
	MOVE.L	#35469/160,D2  ; magic number div by 160 pixels
	DIVU	D1,D2
So the result of this in D2 is $00310002, so I can assume that I can move forward two bytes to get the next pixel from the sample data, however if I just do that for all 160 pixels, it wont finish at the end because the remainder $0031 is not being taken into consideration.

So... how do you go about performing this type of calculation in 68k?

On a side note, it doesn't need to be fast, just accurate as it will all get pre-calced into look up tables anyhow.
h0ffman is offline  
Old 26 May 2011, 16:40   #2
Ed Cruse
Registered User
 
Join Date: Sep 2007
Location: Las Cruces, USA
Age: 65
Posts: 351
Quote:
Originally Posted by h0ffman View Post
Hi guys

Bit of a maths question today. Funnily enough relating to scope code again. It's to do with sample rates (or periods! as they are called on the amiga) and time calculations.

This is a section of code from the original protracker scope code..

Code:
    MOVEQ.L    #0,D1
    MOVE.W    ns_period(A2),D1
    LSR.W    #1,D1
    BEQ.S    ScoNextChan
    MOVE.L    #35469,D2
    DIVU    D1,D2
    EXT.L    D2
    ADD.L    D2,D0
The above section calculates where the sample pointer needs to draw from in the next frame. The 35469 is the magic number which does this.

So, at present all the scopes I've seen or worked on simply draw the samples byte by byte to the screen and uses this calculation to simply move the pointer each frame to where the sample should be. This is not an accurate representation of the wave form, however it does suffice most requirements.

What I want to do is draw the wave at the frequency it is being played at. My idea was to simply divide the 35469 by the pixel width of the scope, then use this value to increment the sample pointer for each pixel. However, I very quickly realised that you cannot get away with this as the remainder from the division needs to be taken into consideration for each pixel iteration.

Code:
    moveq    #0,d1
    MOVE.W    #172,D1  ; period
    LSR.W    #1,D1
    MOVE.L    #35469/160,D2  ; magic number div by 160 pixels
    DIVU    D1,D2
So the result of this in D2 is $00310002, so I can assume that I can move forward two bytes to get the next pixel from the sample data, however if I just do that for all 160 pixels, it wont finish at the end because the remainder $0031 is not being taken into consideration.

So... how do you go about performing this type of calculation in 68k?

On a side note, it doesn't need to be fast, just accurate as it will all get pre-calced into look up tables anyhow.

One possible way is to convert to double float, do the calculations, round to an integer, and then convert back to integers. It's slow but it works. You may still be off at the end, it just depends on how well the rounding averages out. I've used this method for scaling the data for plotting purposes.
Ed Cruse is offline  
Old 26 May 2011, 17:14   #3
h0ffman
Registered User
 
Join Date: Aug 2008
Location: Salisbury
Posts: 469
How do you do a double float in assembly?
h0ffman is offline  
Old 26 May 2011, 18:42   #4
dalton
tulou
dalton's Avatar
 
Join Date: Jun 2006
Location: Gothenburg / Sweden
Posts: 71
If you're on 020, you can use divu.l with 35469<<16 to get a 16.16 bit fixed point representation. That should be sufficient for 160 pixels.

If you're not on 020, perhaps Bresenham interpolation could be a solution.
dalton is offline  
Old 27 May 2011, 00:19   #5
Ed Cruse
Registered User
 
Join Date: Sep 2007
Location: Las Cruces, USA
Age: 65
Posts: 351
Quote:
Originally Posted by h0ffman View Post
How do you do a double float in assembly?

Use the Amiga math libs to do the converting and calculations. The easiest way would be to use the math libs to convert all your integers like 35469 and integers in the data registers, to single or double float. Calculate and then use the math libs to convert back to integers. It's basically a pain. It's a lot easier to do it in C.

When I was doing a lot of assembly I had macros to make it a lot easier, I also came up with my own double float constants and wrote a program that would search through my source codes and convert double float constants like 35469.0 into two dc.l. Eventually I got an assembler that new about double float constants. After 20 years of assembly programing I finally wised up and learned C, now I do assembly only when it's necessary.

I can already feel the hate from the pure assembly programers, like I used to be.
Ed Cruse is offline  
Old 27 May 2011, 15:22   #6
h0ffman
Registered User
 
Join Date: Aug 2008
Location: Salisbury
Posts: 469
Thanks for the response Ed, however, i'm more interested in how to solve this problem with assembly. I know that maths lib might be the easiest, but I'd love to know how these kind of problems are resolved when working directly with the CPU.
h0ffman is offline  
Old 27 May 2011, 16:44   #7
Ed Cruse
Registered User
 
Join Date: Sep 2007
Location: Las Cruces, USA
Age: 65
Posts: 351
Quote:
Originally Posted by h0ffman View Post
Thanks for the response Ed, however, i'm more interested in how to solve this problem with assembly. I know that maths lib might be the easiest, but I'd love to know how these kind of problems are resolved when working directly with the CPU.

I know what you mean, I've tried to complish the same thing dealing with the remainder but it's always been very difficult. Seems like there's always some odd combination of things that causes problems, so I end up using double floating point. Recently I did manage to use the remainder method and it was working, but in the normal use of what I was doing I would frequently end up with numbers after the divide that were larger then a long could handle and it messed up my whole plan. In this case speed was important and using double floating point was slow but I ended up using it anyway, I had no choice. My math isn't good enough to figure out how to use remainders reliably to do what I needed. Especially rounding.

I use WinUAE so the emulated fpu is really fast, so when I really need my float points to be fast I compile to use inline FPU code. But that also requires using at least a 68020, but you want 68000. If you could use a 68020 you can also use an assembler that knows fpu commands and use the fpu to convert, calculate, and convert back to integers. From a assembly programmers point of view the fpu is a dream to use and very fast.
Ed Cruse is offline  
Old 30 May 2011, 16:15   #8
MSL
Registered User
 
Join Date: Feb 2009
Location: Copenhagen / Denmark
Posts: 11
I'm not experienced with asm, so I might not understand your code correctly, but from what it looks like to me is, that you divide D1 with D2, where D2 is a division of 35469/160, which have a remainder.

The math can be rewritten:

A / (B / C) = (A * C) / B -> ( D1 * 160 ) / 35469

Assuming that A * C does not overflow you have removed the imprecision of one division.

Last edited by MSL; 30 May 2011 at 16:21. Reason: Spelling mistake
MSL is offline  
Old 07 June 2011, 15:35   #9
h0ffman
Registered User
 
Join Date: Aug 2008
Location: Salisbury
Posts: 469
Just thought I'd put a quick update here, managed to crack it in the end...

Code:
ScopeInitFreq	lea	FreqTable+(scopebytewd*8*2),a0
		moveq	#1,d0 		; current period

.nextperiod	move.l	#35469/(scopebytewd*8),d6  ; the magic number!
		moveq	#0,d5

		move.w	#scopebytewd*8-1,d7

		moveq	#0,d2
		moveq	#0,d3
		
.test		add.l	d6,d5				
		move.l	d5,d1
		divu	d0,d1
		move.w	d1,d2
		sub.w	d3,d1
		move.w	d1,(a0)+		; store byte move size
		move.w	d2,d3
		
		dbra	d7,.test

		add.w	#1,d0
		cmp.w	#scopemaxperiod,d0
		blo.b	.nextperiod

		RTS
Simply re-do the calculation incrementing the seed each time. Also managed to get this plugged into the scope drawing routine. You can see it re-sizing the wave depending on the frequency of the sample !
h0ffman is offline  
Old 24 June 2011, 01:03   #10
Photon
Moderator
Photon's Avatar
 
Join Date: Nov 2004
Location: Hult / Sweden
Posts: 4,591
If you're using The Player to optimize modules, there's a scope routine accurate to 1/262144th of a sample in the latest P61 playroutine by me, P6108, if you enable it it will give you pointer and length for a 50Hz frame for each playing channel. It wraps loops correctly and gives a bunch of zeroes if the channel is quiet or ending.
Photon is offline  
Old 24 June 2011, 09:40   #11
pmc
rebooting...
pmc's Avatar
 
Join Date: Apr 2007
Location: Elsewhere
Posts: 1,595
@ Photon: going slightly off topic I suppose but not too far I hope - I integrated ThePlayer into my demo shell recently but I didn't manage to get your "super optimised, all singing, all dancing" version to assemble and had to use the latest "old" release of ThePlayer instead.

With your version I got 200+ errors on assembly using Devpac3.18 - was I doing something obviously and stupidly wrong...?
pmc is offline  
Old 24 June 2011, 19:35   #12
Photon
Moderator
Photon's Avatar
 
Join Date: Nov 2004
Location: Hult / Sweden
Posts: 4,591
Differences between assemblers will give errors, basically for all sources "not made for your assembler flavor". The Player source is special in that it uses loads of conditionals and a few macros, and these features might not be supported or need to be written in another way to be used in your assembler. Same thing if someone releases a Devpac source and uses features not found in say, AsmOne or PhxAss.

The most common complaint about The Player sources is the structures macros.

Have you set ASMONE=0, to start with? This attempts to replace AsmOne macros with other flavors.

If there are remaining differences you'll have to reconcile them, or you could rip out the Scope routine+a few vars added for it at the end of the source and see if it talks to P6106.

Or check what it does and modify it to talk to Protracker, that would be ace
Photon is offline  
Old 25 June 2011, 00:58   #13
h0ffman
Registered User
 
Join Date: Aug 2008
Location: Salisbury
Posts: 469
Hey photn, thanks for the offer, however I've got my scope routine already integrated into the player. Fixed all the original bugs that came with the original source, such as sample offset, loops sample endings. I've recently done a version which draws the sample at the sample rate its playing at. Next up is it see if I can combine all four channels into one massive scope
h0ffman is offline  
Old 25 June 2011, 01:00   #14
Lonewolf10
AMOS Extensions Developer
Lonewolf10's Avatar
 
Join Date: Jun 2007
Location: near Cambridge, UK
Age: 39
Posts: 1,919
Quote:
Originally Posted by pmc View Post
With your version I got 200+ errors on assembly using Devpac3.18 - was I doing something obviously and stupidly wrong...?
I agree with Photon's reply, but just wish to check that you are not using case-sensitive mode when assembling - that gave me loads of errors when compiling with (an old version of) The Player when I first started using it.
Now I always compile assemble with case-sensitive mode off.


Regards,
Lonewolf10

Last edited by Lonewolf10; 25 June 2011 at 01:05. Reason: typo (assembling not compiling)
Lonewolf10 is offline  
Old 25 June 2011, 10:06   #15
pmc
rebooting...
pmc's Avatar
 
Join Date: Apr 2007
Location: Elsewhere
Posts: 1,595
Errrm, no - not using case sensitive and had already done all the other obvious stuff.

While Photon was around I thought I'd ask out of curiosity but now I know (rather than just suspecting...) the answer is basically to go though those errors and remedy each one I'm gonna take the approach I'd already decided on: stick with the latest un-Photon'd version of ThePlayer that works for me.
pmc is offline  
Old 25 June 2011, 22:44   #16
Photon
Moderator
Photon's Avatar
 
Join Date: Nov 2004
Location: Hult / Sweden
Posts: 4,591
pmc, I'd be interested in differences in error log between P6106 and P6108, so email me them if you want !

h0ffman, hm, read pmc's reply as one of yours, sorry for the confusion. The scope routine would then only be of abstract use for your playroutine, anyway good to hear you fixed it up! And yes, 4 fullres scopes running separately consume a not negligible amount of raster time on OCS, visualizing 4 added together to reduce the amount of plots or similar you use to visualize it is a very good idea
Photon is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
La bosse des maths 5ème dlfrsilver request.Old Rare Games 2 12 February 2013 19:23
Educational maths title, skateboard? Nipedley Looking for a game name ? 8 29 April 2011 22:56
Intel representative cant do maths alexh Retrogaming General Discussion 5 19 November 2007 00:47
Soioty & Sweep maths game ElectroBlaster HOL contributions 0 19 September 2006 02:11
Abuse AGA & Merlin's Maths icewizard2k5 request.Old Rare Games 2 21 February 2005 13:14

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 13:05.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.
Page generated in 0.08464 seconds with 15 queries