English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General

 
 
Thread Tools
Old 14 September 2013, 19:18   #21
8bitbubsy
Registered User
 
8bitbubsy's Avatar
 
Join Date: Sep 2009
Location: Norway
Posts: 1,710
Quote:
Originally Posted by Photon View Post
Here's the code from 1Klång which calculates it realtime to save 10 bytes (i.e. no table at all). D1 contains note 0-11 << 16 + octave 0-n on entry. I might use this in P61_Init actually to save some horrible includes and compile options

Code:
_baseC    =54229
_baseA    =64489
_octBase=_baseC

    move.w #_octBase,d0
    swap d1
    bra.s .jmpin
.octl2:
    mulu #61858,d0            ;exponential: 1/(2^(1/12))*65536
    swap d0
.jmpin:    DBF d1,.octl2
    swap d1                ;!hi word NOT clear. d1=octave

    addq.w #4,d1            ;shift 4 more (prec)
    lsr.w d1,d0            ;shift down by #octaves.
    move.w d0,_prds(a2)        ;prd
Hmm could you convert this to C for me? These "swap" instructions confuses me a bit, like how would I do this in C...
8bitbubsy is offline  
Old 14 September 2013, 23:59   #22
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
Oh. Well, you just multiply 54229 by 61858 / 65536 n times and halve the result o times, where n is the note 0-11 (0 is C, 1 is C#, etc) and o is the octave 0-5.


Code:
uint get1Note(n,o) {
	uint x=54229;
	for (int i=0;i<(n-1);i++) {
		x=(x*61858) >> 16
	}
	x=x >> (o+4); //shift to a range of usable octaves
	return x;
}

uint D1=get1Note(2,1);	//D-note in 2nd octave
"uint" is supposed to mean unsigned 32-bit integer to your compiler.

Last edited by Photon; 15 September 2013 at 12:10.
Photon is offline  
Old 15 September 2013, 00:17   #23
8bitbubsy
Registered User
 
8bitbubsy's Avatar
 
Join Date: Sep 2009
Location: Norway
Posts: 1,710
I made a little snippet out of your example:
Code:
#include <stdio.h>
#include <stdlib.h>

/* note = 0..35 (C-0 .. B-2) */
unsigned short noteToPeriod(char note)
{
    char i;
    char octave;
    unsigned int x;

    octave = note / 12;
    note %= 12;

    x = 54299;
    for (i = 0; i < note; ++i)
        x = (x * 61858) >> 16;

    x = (x + 4) >> octave;

    return x;
}

int main(int argc, char* argv[])
{
    char i;
    for (i = 0; i < 35; ++i)
        printf("%d\n", noteToPeriod(i));

    system("pause");

    return 0;
}
It outputs this:
54303
51255
48378
45663
43100
40681
38398
36243
34209
32289
30477
28766
27151
25627
24189
22831
21550
20340
19199
18121
17104
16144
15238
14383
13575
12813
12094
11415
10775
10170
9599
9060
8552
8072
7619

It should output something spanning from 856 to 113....
8bitbubsy is offline  
Old 15 September 2013, 01:28   #24
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
Yes, add 4 to oct (shift value) not to x

This still puts you 2 octs below the octave you need. 848 is correct, 856 is incorrect

Just put 856<<6 as start x for PT table
/ Sleepy Photon using mobile g'night

Last edited by Photon; 15 September 2013 at 01:34.
Photon is offline  
Old 15 September 2013, 02:29   #25
8bitbubsy
Registered User
 
8bitbubsy's Avatar
 
Join Date: Sep 2009
Location: Norway
Posts: 1,710
Quote:
Originally Posted by Photon View Post
Yes, add 4 to oct (shift value) not to x

This still puts you 2 octs below the octave you need. 848 is correct, 856 is incorrect

Just put 856<<6 as start x for PT table
/ Sleepy Photon using mobile g'night
848 is not right, 856 is.
8bitbubsy is offline  
Old 15 September 2013, 12:54   #26
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
Not if the # DMA cycles is 3546895 and the standard A is 440 Hz.

You can calculate it on your calculator: (the "8" is the number of samples in your waveform.)

notestep = 2^(1/12)=1.0594630943592952645618252949463

prdA = 3546895/440/8

prdA# = prdA/notestep

prdB = prdA#/notestep

prdC = prdB/notestep = 847.32138942651245571147266932506

baseC = prdC*64 = 54228.568923296797165534250836804 ~= 54229.

(Sorry for saying 848 is correct, I had gone to bed so I just halved one of the integers from your ouput there a couple of times I think. )

Last edited by Photon; 15 September 2013 at 13:04.
Photon is offline  
Old 15 September 2013, 19:14   #27
8bitbubsy
Registered User
 
8bitbubsy's Avatar
 
Join Date: Sep 2009
Location: Norway
Posts: 1,710
That's not what I mean. This is not the same values as in the PT period table. I want an accurate PT table output. :P
8bitbubsy is offline  
Old 15 September 2013, 20:31   #28
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
But the values were written by hand, not generated.

You've already spotted the manual errors they made (as, I think, has many a coder who wondered why the base note differed from the one in HRM, not that HRM is perfect either).

Unless the errors are consistent between octaves (higher octave values are all half of the lower), it'll be hard to "save some table words".

If you want compatibility, keep the original table with the errors (I did that in P6108). If you want to be correct, you have my generator (from 1Klång).

The "corrected wrong-base table" seems terrible to me, unless you can point out which of the values in the whole table is the correct one. You picked 856 and corrected the others, but this is arbitrary. What is to say 856 wasn't wrong and C# or A is the correct period to modify the others from?

So anyway, good luck and if I sound like I "come on strong" it's because I do care about some pet subjects on Amiga, music is one of them
Photon is offline  
Old 15 September 2013, 21:43   #29
8bitbubsy
Registered User
 
8bitbubsy's Avatar
 
Join Date: Sep 2009
Location: Norway
Posts: 1,710
Again, I strive for Amiga output accuracy, not note frequency accuracy. By errors, I mean values that mismatched those of the original bad PT table used in the original replayers.
I just wanted the smallest possible way to generate this bad table, that's it. I'm not saying that its values are correct, they are definitely wrong at some points.
8bitbubsy is offline  
Old 16 September 2013, 10:56   #30
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
Well, as I said, check if all matches in the higher octaves match if you shift down (halve) the lower ones.

Else you're out of luck.

You could do the above and perhaps it matches 95% of the values, and you could fix up the ones that don't match exactly by storing the "diff". I don't see how the diffs could be stored in less space, though.
Photon is offline  
Old 29 September 2017, 12:16   #31
Lisiak4
Registered User
 
Join Date: Sep 2017
Location: Czech Republic
Posts: 20
Quote:
Originally Posted by 8bitbubsy View Post

It's supposed to be like this:
Code:
    856,808,762,720,678,640,604,570,538,508,480,453,
    428,404,381,360,339,320,302,285,269,254,240,226,
    214,202,190,180,170,160,151,143,135,127,120,113,0,
Thanks, that's what I was looking for. So far I have values from 127 to 508. I already know how the values continue to reduce the frequency (period 508 and above)

With permission, this extended table will be written on the Czech forum too
Lisiak4 is offline  
Old 11 June 2020, 18:13   #32
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
I came across this thread looking for a solution for generating a table of periods (protracker compatible) and in fact I did not find anything valid available.

The table needs 3*12*16 word values (3 octaves, 12-tone equal temperament scale plus fine-tune from -8 to +7) = 1152 bytes (in fact with the separator it is 1184, but since my player does not use it, I generate only the raw values). Anyway if your module player require the $0 separator, adding it is straightforward.

Of course a table of 1152 bytes may seem little, but in a small intro every byte counts and since the values are somehow related (even if in fact I've not found a general formula.. because some values are wrong) I thought of creating my own generator.

The end result is very good: the code (/ data) is only 190 bytes.
Code:
pt_period_generator

	lea bit+$4a(pc),a1
	moveq	#$128/8-1,d2
.p0     moveq	#8-1,d3
	move.w	-(a1),d0
.p1     moveq	#3,d1
	and.w	d0,d1
	move.w	d1,-(sp)
	lsr.w	#2,d0
	dbf d3,.p1
	dbf d2,.p0

	lea (sp),a1
	moveq	#4,d1
.a0     moveq	#$28-1,d0
.a1     add.w	d1,(a1)+
	dbf d0,.a1
	subq.w	#1,d1
	bne.b	.a0

	moveq	#36-1,d0
	move.w	#907,d1
.c0     moveq	#8-1,d2
	addq.w	#1,d3
.c1     move.w	d1,(a0)
	tst.w	d3
	beq.b	.c2
	move.w	d1,-36*8*2-2(a0)
.c2     sub.w	(sp)+,d1
	lea 36*2(a0),a0
	dbf d2,.c1
	lea -36*8*2+2(a0),a0
	dbf d0,.c0
	lea -36*8*2-2(a0),a0
	moveq	#-1,d3
	not.l	d0
	bne.b	.c0
	
	moveq	#9-1,d1
.u	move.b	fix-1(pc,d1.l),d0
	addq.b	#1,589(a0)
	adda.l	d0,a0
	dbf d1,.u
	rts

fix     dc.b	$6a,$c6,$30,$74,$44,$02,$04,$22
bit	dc.b	$EE,$BA,$AA,$AA,$A6,$9A,$59,$65,$65,$56,$5A,$9B,$56,$67,$19,$5A
	dc.b	$15,$56,$05,$52,$5A,$66,$59,$96,$55,$95,$55,$55,$55,$15,$6A,$66
	dc.b	$99,$9A,$59,$66,$55,$96,$55,$56,$6A,$AB,$6A,$AA,$6A,$9A,$9A,$6A
	dc.b	$66,$66,$99,$99,$96,$66,$56,$59,$65,$65,$65,$59,$55,$59,$55,$55
	dc.b	$55,$55,$55,$55,$52,$15,$51,$55,$15,$44
You can define a bss space as:
Code:
period_table
	ds.w	36*16
and call the routine with:
Code:
	lea     period_table+36*8*2,a0
	bsr	pt_period_generator
Cheers!
ross is offline  
Old 11 June 2020, 18:47   #33
StingRay
move.l #$c0ff33,throat
 
StingRay's Avatar
 
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
I coded a period table generator for one of my 4k intros about 15 years ago. There is no fine tuning or any other "fancy" stuff supported.

Code:
; calc period table
; not 100% correct, e-3,g-3,g#3 too low (-1)
.TAB	lea	mt4k_periodtab(pc),a0
	lea	mt4k_adds(pc),a1
	moveq	#12-1,d7
	move.w	#856,d0			; start value (C-1)
.loop2	move.w	d0,(a0)+
	move.w	d0,d1
	lsr.w	#1,d1			; octave 2
	move.w	d1,12*2-2(a0)
	lsr.w	#1,d1			; octave 3
	move.w	d1,12*2*2-2(a0)
	move.b	(a1)+,d1
	sub.w	d1,d0
	dbf	d7,.loop2 
	rts

mt4k_adds	dc.b	48,46,42,42,38,36,34,32,30,28,27,0
StingRay is offline  
Old 11 June 2020, 19:03   #34
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by StingRay View Post
I coded a period table generator for one of my 4k intros about 15 years ago. There is no fine tuning or any other "fancy" stuff supported.
Module(s) I need to play require fine-tune and fancy stuff
I had to create a fairly elaborate encoder.

ross is offline  
Old 24 June 2020, 23:03   #35
8bitbubsy
Registered User
 
8bitbubsy's Avatar
 
Join Date: Sep 2009
Location: Norway
Posts: 1,710
Adding finetune for periods is easy and doesn't require a full finetuned period table. Just calculate 16 exponential 16-bit mul values and put them in a LUT, then look-up using finetune as index. Then you multiply period by that value and swap the register to get the finetuned period. Though if I remember correctly, the finetuned sections of the ProTracker period table also has mystical off-by-one values. If you want max accuracy, you need to go down another rabbit hole.

Something like this. Not tested, and maybe it compiles into too many bytes for it to be smaller than a full table generator.
Code:
	; d0.w = period, d1.w = finetune (0..15)
getPeriod
	lea	ftuneTab(pc),a0
	add.b	d1,d1
	mulu.w	(a0,d1.w),d0	; expects upper byte of d1.w to be zero
	swap	d0
	rts

	; for (i = 0; i < 16; i++)
	; x=round(65536.0 / exp2(((i^8)-8) / (12.0 * 8.0)));
ftuneTab
	dc.w	65536,65065,64596,64132,63670,63212,62757,62306
	dc.w	69433,68933,68438,67945,67456,66971,66489,66011
EDIT: D'oh... Word overflow in the LUT and MUL. Anyway, you get the idea. So it needs a scale of 15-bit, but that also means you need to do some bitshifting.

Last edited by 8bitbubsy; 24 June 2020 at 23:36.
8bitbubsy is offline  
Old 24 June 2020, 23:35   #36
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
It is the way I tried initially.
Unfortunately, even if in theory it is correct, it produces rounding error or results too far from what they are (full of mistakes..) in the table used by protracker.
So I changed my approach and studied a custom encoder built on how existing data is.
But if you can generate a 'perfect' period+finetute table with code+data <190 then I use it instead of mine
ross is offline  
Old 27 June 2020, 09:56   #37
Siekmanski
Registered User
 
Siekmanski's Avatar
 
Join Date: Nov 2019
Location: Groningen / the Netherlands
Posts: 16
This is the routine I wrote to precalculate the original Protracker mt_PeriodTable.
The size is 127 bytes of code ( Windows x86 MASM assembly ) and the result is 100% exact as the original mt_PeriodTable.
Fully commented, so you could convert it to Amiga assembly.
All rounding errors are restored and put back into the table.

Code:
    mov         edi,offset PeriodTable+576  ; Start at the second half of the Period Table memory buffer
    movss       xmm1,BasePeriod_907         ; 906.9023 -> ( 3546895 / 3911 )
    mov         ebx,093E07E8h               ; Magic repair number for 14 "Tuning -8" mismatches
    mov         dl,2                        ; Split the Period Table in 2 halves
Split_LP2:
    mov         dh,8                        ; 8 fine tune stages per half Period Table
Next_finetune_step2:
    mov         cl,36                       ; 3 octaves ( 3 * 12 notes )
    movss       xmm0,xmm1                   ; Set BasePeriod to next "Tuning" stage
Octaves_LP2:
    cvtss2si    eax,xmm0                    ; Convert float to 32 bit integer
    cmp         dh,8                        ; Are we in "Tuning 0" or "Tuning -8" ?
    jne         finetune_checked
    test        bl,1                        ; Yes, check if we need to repair a period
    jz          repair_checked
    dec         eax                         ; Yes, subtract 1 of the period value
repair_checked:
    shr         ebx,1                       ; Shift through the Magic repair numbers
finetune_checked:
    mov         [edi],ax                    ; Save period value as 16 bit integer
    mulss       xmm0,twelfth_root_of_2_rec  ; Calculate next semitone value in the present octave -> 1/(2^(1/12)) = 0.943874
    add         edi,2                       ; Next period position in the Period Table memory buffer
    dec         cl                          ; Loop 36 times to create 3 octaves per "Tuning" stage
    jnz         Octaves_LP2
    mulss       xmm1,fine_tune_step_rec     ; Calculate next fine tune step -> 1/(2^(1/12/8)) = 0.992806
    dec         dh                          ; Loop 8 times to create 8 "Tuning" stages
    jnz         Next_finetune_step2
    mov         ebx,049F03F4h               ; Magic repair number for 14 "Tuning 0" mismatches
    mov         edi,offset PeriodTable      ; Start at the first half of the Period Table memory buffer
    dec         dl                          ; Goto Pass 2 ( split buffer! )
    jnz         Split_LP2                   ; Code size = 89 bytes and 9 scattered period mismatches left

    mov         ecx,0ff040105h              ; 2 loop and sign pairs
    mov         ebx,0F6744604h              ; Magic repair offset bytes for 5 scattered -1 period value mismatches
    dec         byte ptr[edi+80]            ; Repair 1 ( out of byte range ) +1 period value mismatch
Scattered_LP:
    add         byte ptr[edi+116],ch        ; Repair the -1 and +1 period value mismatches
Sign_switch:
    movzx       eax,bl                      ; Get next byte offset
    add         edi,eax                     ; Calculate the next offset in the Period Table memory buffer
    shr         ebx,8                       ; Shift through the offset bytes
    dec         cl                          ; Loop 5 times for +1 repairs and 3 times for -1 repairs ( plus 1 offset bytes restore loop )
    jnz         Scattered_LP
    mov         ebx,000E8286Ch              ; Magic repair offset bytes for 3 scattered +1 period value mismatches
    shr         ecx,16                      ; Shift to last loop and sign pair, if zero we are done
    jnz         Sign_switch                 ; Total code size = 127 bytes ( -> 100% correct match with original Protracker mt_PeriodTable. )
Siekmanski is offline  
Old 27 June 2020, 11:47   #38
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Siekmanski View Post
This is the routine I wrote to precalculate the original Protracker mt_PeriodTable.
Thanks Siekmansky.

The challenge here is that the routine need to be for a bare 68k (16x16 mul, 32/16 div) and no FP and SIMD units.
Probably your code require a Pentium III processor, a bit too much for us geezer
ross is offline  
Old 27 June 2020, 12:31   #39
Siekmanski
Registered User
 
Siekmanski's Avatar
 
Join Date: Nov 2019
Location: Groningen / the Netherlands
Posts: 16
Maybe you can calculate with 10:22 bit fixed-point instead of floating-point numbers.
And use my algorithm to reduce the code size. ( it only uses multiplications )
The gain is in the algorithm.
Siekmanski is offline  
Old 27 June 2020, 13:08   #40
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Siekmanski View Post
Maybe you can calculate with 10:22 bit fixed-point instead of floating-point numbers.
And use my algorithm to reduce the code size. ( it only uses multiplications )
The gain is in the algorithm.
Yep, I've somewhere in my hdd a test with a pretty similar method
But failed because of the fixed-point math

Maybe on a 020+ or 030+/FPU could succeed, I've not tried.
When I have some time I will do more tests.

ross 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
Looking for the most accurate Paula audio emulation craig64 support.Other 69 23 July 2023 19:36
What is the most accurate speed test for WinUAE? Steve support.OtherUAE 5 04 December 2012 18:04
Calculating percentages in assembly aka bpm and period h0ffman Coders. Asm / Hardware 8 16 September 2012 18:49
Software for generating screenshots and videos Edi (FZ2D) Retrogaming General Discussion 5 08 April 2010 23:34
How accurate is the emulation? manicx support.WinUAE 26 07 July 2003 08:35

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 10:26.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.59793 seconds with 13 queries