A.D.A. Amiga Demoscene Archive

  Welcome guest! Please register a new account or log in

  

  

  

log in with SceneID

  

Demos Amiga Demoscene Archive Forum / Coding / Coding a protracker scope

 

Author Message
h0ffman
Member
#1 - Posted: 4 Jan 2011 11:45
Reply Quote
Hi Guys

I am nearing the end of development of my music disk. Fingers crossed I can get it finished ready for a Datastorm release :)

Anyway, for a really nice finishing touch to music disk, I want to draw a scope of the music that is playing. My aim is to get it running the full width of the screen with all 4 channels mixed. I'd also like to be able to fill the scope. The best example I think is in protracker 3.62. Thats a really nice scope.

Was wondering if anyone had any pointers on how to write one and also how to fill it.

Cheers

Ian
yoki
Member
#2 - Posted: 5 Jan 2011 09:38
Reply Quote
Hey Ian!
Great to hear that you are coming to datastorm!!
Mail me @ Markus at ikachan.com and i'll help you out with the scopez :)

// yoki/up rough
h0ffman
Member
#3 - Posted: 5 Jan 2011 11:20
Reply Quote
Oh no, I'm not going to datastorm sadly! It's at exactly the same time as my wifes birthday :( :( :(

I know a few people who are going who should be able to release it for me. Will email you anyhow :)
skp
Member
#4 - Posted: 5 Jan 2011 12:32 - Edited
Reply Quote
Hey Hoffman,

The hard part of oscilloscope is not the rendering but getting the correct playing sample + offset + window size, so mostly it will depend on your replayer and what you can extract from it. (And supposing you want an amiga sample oscilloscope, not a freq analyzer ;-) )

For the rendering you can use the good old trick of the eor filler for a fast vertical filling: first render your sample data plotting only the start y / stop y of each column, then parse the window in top/bottom order using the eor instruction to make the fill (same thing as a blitter filler, but in a vertical mode). The code look something like :


.loopX moveq #0,d0 ; use -1 to start with a direct filling
.loopY move.l (a0),d1 ; get the current 32 pixels
eor.l d1,d0 ; enable/disable new column filling
move.l d0,(a0) ; set the filled 32 pixels
lea mod(a0),a0 ; next line
dbf d7,.loopY ; loop for each line
lea -mod*height+4(a0),a0 ; Go back in the first line but start at pixel 32
dbf d6,.loopX ; Loop for each column


(This is a simple, non checked asm example, you can optimize it but mostly on Amiga you will be limited by the chip memory speed)

Anyway, IIRC there is an example of a sound oscilloscope in one of the tracker replayer (don't remember if it's from a pt replay or from an old theplayer).

But well, the theplayer 610.8 do not have it... Probably if you use TP, Photon or Noname can help here...And it seems that Photon add a direct way to get sample data inside TP610.8, so getting oscilloscope from this one is probably not too hard...

Hope that can help !
h0ffman
Member
#5 - Posted: 5 Jan 2011 16:59
Reply Quote
Wow, cheers for that skp, will give it a whirl.

I managed to rip the old scopes from the ProTracker 2 source code and plug them into my replay code. Got two bugs at the moment. First is the 9 command doesn't seem to play the scope at the right point and the E commands seem to disable the scope. The E command bug I think is just because I haven't captured the new note trigger point correctly. The 9 command is a little more taxing.

This fill technique may well be worth a shot, although i'm intending this music disk to run on an A600. Depending on power consumption, I may have to disable them for the 68000.
skp
Member
#6 - Posted: 5 Jan 2011 21:09
Reply Quote
I can't really help for the protracker command problem, but I can give some ideas for speeding up the rendering:

* Do the plotting and the filling at the same time using the CPU (and clear using the blitter).
* Unroll the loop for drawing more than 32pixs/step (current is 32x1, do 64x4 or whatever is the best)
* If you save the min/max Y for each 32pixs you can avoid drawing useless top/bottom part
* Draw only one point per column, and use screen modulo for a symmetric bottom part
* And you can play on the height of your oscilloscope ;-)
h0ffman
Member
#7 - Posted: 6 Jan 2011 14:48
Reply Quote
Cheers for the tips skp. I've managed to write a pretty quick fill routine using movem commands.. looks something like..

TestFill	move.l	TextBplPtr,a0
lea (scopepos*scopeplanewidth)+4(a0),a0

move.l a0,a2 ; backup plane ptr

moveq #1,d5 ; now fill top half
.loop2 move.w d5,a5
moveq #scopesize-1,d6
moveq #0,d0
moveq #0,d1
moveq #0,d2
moveq #0,d3
.loop1 move.w d6,a6 ; backup loop count 2
movem.l (a0)+,d4/d5/d6/d7
eor.l d4,d0
eor.l d5,d1
eor.l d6,d2
eor.l d7,d3
movem.l d3/d2/d1/d0,-(a0)
lea scopeplanewidth(a0),a0
move.w a6,d6
dbra d6,.loop1
lea 16(a2),a0
move.w a5,d5
dbra d5,.loop2
dalton
Member
#8 - Posted: 7 Jan 2011 07:44
Reply Quote
If you're doing this on a plain 68k/ocs-machine, it might be worth a shot doing the vertical eor fill using the blitter. The blitter has built-in support for horizontal eor fill of course, but it's not that difficult to make it perform the vertical dito. You have to set it to use bitplane row 0 as source A and dest, and row 1 as source B. Then set the minterms so that D=A eor B. Modulos and sizes are set just like in a normal copy operation.
skp
Member
#9 - Posted: 7 Jan 2011 19:10
Reply Quote
Oh yes, like Dalton said, do not hesitate to use the blitter to boost the filling speed ! (And like he said, it's not really complicated to do it from the blitter), and IIRC use A,C,D instead of A,B,D it's a little faster. (But probably other can confirm or not that point)

Just take care, D must point on the line n+1 with one source, the other source must point on line n.

About your code, also do more loop unrolling, on 68000 every instruction count ;-)

Instead of working on one line, do it for several line at the same time -> a branch take a lot of cycles on 68000, you must avoid it !
Also instead of lea n(a0),a0, put n in a reg and do a "add.l ax,a0". (And take care that lea 16(a2),a0 will always give the same result to a0, and not the next columns)
And probably it's a little better to use a cmp.l ax,ay, bne.b .loop, instead of 2xmove + dbra (precompute the end address before the loop).

Ok now you get everything to get a smooth oscillo effects ;-)
skp
Member
#10 - Posted: 8 Jan 2011 00:11
Reply Quote
After checking the blitter timing, on A500/600 definitively use the blitter for the filling, it will go a lot faster than the 68k ! And I think that for a standard A1200 this is also the good way to do, especially if there is no fast mem. In my memory the blitter was a lot slower than that, but probably it was the >030+fast mem that were really fast ;-)
h0ffman
Member
#11 - Posted: 10 Jan 2011 10:30
Reply Quote
Cheers SKP / Dalton, I now have a phat scope running nice and quick on an A600 :)
Vektor
Member
#12 - Posted: 23 Jan 2011 16:55
Reply Quote
This is how I coded the scope plotter about 20 years ago. The comment in the source states it plot 1600 pixels per frame on a std A500


POINT_ROUTINE:
move.L screen(pc),a0
add.L 00(a5),a0 ;pos in screen (offset)
move.L 04(a5),a1 ;pointer to sample
lea.L Volume_mulu_table(pc),a3
moveq #0,d2
move.B n_volume(a6),d2
moveq #9,d0
lsl.W d0,d2
add.L d2,a3

moveq #44,d7
pointloop:
move.B (a1)+,d0
add.W d0,d0
move.W (a3,d0.W),d0
moveq #7,d1
bset d1,(a0,d0.W)

move.B (a1)+,d1
add.W d1,d1
move.W (a3,d1.W),d1
moveq #6,d0
bset d0,(a0,d1.W)

move.B (a1)+,d0
add.W d0,d0
move.W (a3,d0.W),d0
moveq #5,d1
bset d1,(a0,d0.W)

move.B (a1)+,d1
add.W d1,d1
move.W (a3,d1.W),d1
moveq #4,d0
bset d0,(a0,d1.W)

move.B (a1)+,d0
add.W d0,d0
move.W (a3,d0.W),d0
moveq #3,d1
bset d1,(a0,d0.W)

move.B (a1)+,d1
add.W d1,d1
move.W (a3,d1.W),d1
moveq #2,d0
bset d0,(a0,d1.W)

move.B (a1)+,d0
add.W d0,d0
move.W (a3,d0.W),d0
moveq #1,d1
bset d1,(a0,d0.W)

move.B (a1)+,d1
add.W d1,d1
move.W (a3,d1.W),d1
moveq #0,d0
bset d0,(a0,d1.W)

addq.l #1,a0 ;next 8 pixels
dbf d7,pointloop
rts
Lonewolf10
Member
#13 - Posted: 3 Feb 2011 20:22
Reply Quote
Cool, I might borrow that code for use in my current demo, or for atleast examination and education purposes ;)

I noticed you ended the loop with a dbf instruction. I normally use DBRA. What is the difference and is there a list of ALL condition codes somewhere? I have a list of some, but it doesn't include the "f" one.


Regards,
Lonewolf10
kasbah
Member
#14 - Posted: 3 Feb 2011 20:58
Reply Quote
DBF is a byword for DBRA, it is the same instruction. (F stands for false in that case.)
You can find a complete reference of the condition codes in the Motorola Programmers Reference Manual in section 3-19 conditional tests.
Lonewolf10
Member
#15 - Posted: 4 Feb 2011 23:29
Reply Quote
Ahh, right.

Thanks for the info and the link :)


Regards,
Lonewolf10

 

  Please register a new account or log in to comment

  

  

  

 

A.D.A. Amiga Demoscene Archive, Version 3.0