|
Author |
Message |
h0ffman
Member |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
Cheers SKP / Dalton, I now have a phat scope running nice and quick on an A600 :)
|
Vektor
Member |
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 |
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 |
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 |
Ahh, right.
Thanks for the info and the link :)
Regards, Lonewolf10
|
|
|