vgmrips

The forum about vgm files
It is currently 2018-12-15, 14:01:56

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 48 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject:
PostPosted: 2016-10-15, 16:58:23 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
non correct....
Debug Hex(GetOPNNote($13+12, 3335)) shows $FFF and then 3335 shows $800...


Top
 Profile  
 
 Post subject:
PostPosted: 2016-10-16, 15:18:28 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
so! introduce gems case GetOPNNote procedure :)

Code:
Procedure.i GetOPNNote(Note.i, Pitch.w)
 
  Protected.d FreqHz, CurNote, PitchCoef
  Protected.i BlkNum, FNum, CurBlkNum
 
  PitchCoef = Pitch / 256
  If PitchCoef < 1 And PitchCoef > -1
   
    If PitchCoef < 0 And (Note = 12 Or Note = 24 Or Note = 36 Or Note = 48 Or Note = 60 Or Note = 72 Or Note = 84)
     
      Note = Note - 1
      Pitch = 256 + Pitch ;(Pitch is a - value, so 256 + Pitch means 256 - Pitch)
     
      ret = GetOPNNote(Note, Pitch)
     
    Else
     
      CurNote = Note + Pitch / 256
 
      FreqHz = 440 * Pow(2, (CurNote - 69) / 12)
 
      BlkNum = Note / 12 - 1 ; octave without pitch

      If BlkNum < 0
        BlkNum = 0
      ElseIf BlkNum > 7
        BlkNum = 7
      EndIf 
 
      FNum = Round((144 * FreqHz / 7670454) * Pow(2, 21 - BlkNum), #PB_Round_Nearest)
      If FNum < 0
        FNum = 0
      EndIf
 
      ;count main value
      ret = FNum + (BlkNum * $800)
     
    EndIf
   
  Else
   
    Note + Pitch / 256
    Pitch - (Int(Pitch / 256) * 256)
   
    ret = GetOPNNote(Note, Pitch)
   
  EndIf
 
  ;set gems limit
  If ret > $3CBF
    ret = $3CBF
  ElseIf ret < $0142
    ret = $0142
  EndIf
 
  ProcedureReturn ret

EndProcedure


it work almost perfect, exept this thing:
GetOPNNote($13+12, 272) shows as $0C02, but GEMS shows as $0C01. for me this $0001 is not very critical and i am no hear this small change in sound, but for perfect match it need to fixed too :) now i have no idea where it is can be fixed.


it is rounding :)
Code:
FNum = Round((144 * FreqHz / 7670454) * Pow(2, 21 - BlkNum), #PB_Round_Down)

round to down if fix problem.

ops. not fix :))) another place now count wrong. need to more tune round procedure :)


Top
 Profile  
 
 Post subject:
PostPosted: 2016-10-17, 11:21:29 

Staff Staff
Programmers Programmers
Musicians Musicians
Contributors Contributors
Reverse engineers Reverse engineers
Offline
User avatar

Joined: 2011-12-01, 20:20:07
Posts: 3025
Location: Germany
My function handles negative pitch bends perfectly fine, so there should be no reason to check for negative pitch bends.
It also has no problem handling pitch bends that are larger than a semitone. (I ported this from an FM MIDI player I wrote before.)

Also, you didn't port it correctly. (which is, I need to admit, due to weird VB6's syntax I used in that line).
A normal slash (/) is the usual division, but a backslash (\) performs an integer division. (i.e. it discards the decimal part of the result)
Code:
BlkNum = (Note \ 12) - 1
translates into
Code:
BlkNum = Int(Note / 12) - 1

The checks for 0 and $7FF are there to prevent FNum from going out of range and should be left intact. They only ever have an effect if you are at octave/BlkNum 0 and 7.

GEMS uses frequency lookup tables, btw. I don't know how they were generated, but those tables often differ a bit from the actual calculated result.


Top
 Profile  
 
 Post subject:
PostPosted: 2016-10-19, 21:17:34 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
i am late see your post :) by shell's code i make this function, that have tables. values of tables was get by your procedure :))) and it work fine. i check some cases, where my was mistake this new one count fine. and even this new one no need to make +12 for note value. i just get ready for use note and pitch from code files (gems log)

Code:
Global Dim table(12)

table(0) = $0284
table(1) = $02AA
table(2) = $02D3
table(3) = $02FE
table(4) = $032B
table(5) = $035B
table(6) = $038E
table(7) = $03C5
table(8) = $03FE
table(9) = $043B
table(10) = $047B
table(11) = $04BF
table(12) = $0508

Procedure.i GetOPNNote(note.i, pitch.w)
    note_p = pitch / 256   
    pitch = pitch - note_p * 256
   
    If pitch < 0
      note_p = note_p - 1;
      pitch = pitch + 256;
    EndIf
   
    note = note + note_p
    If note < 0
      pitch = 0;
      note = 0 ;
    ElseIf note > 95
      note = 95
      pitch = 255     
    EndIf
    Block = note / 12
    note = note - Block * 12;
    a = table(note)
    b = table(note+1)
    FNum = a + ((b-a)*pitch)/256 + Block * 2048
   
    ProcedureReturn FNum
   
EndProcedure


i know some case, that will broke this system :) when modulation work - it can have a big values for pitch. but .w type of variable have small limit for it -32768 to +32767. so it can be easy overlimit, that will make wrong count. i will need to make some recount note value for correct count, when this value is overlimit by modulation procedures... it can wait.


now i want to ask question about PSG. i remember your explanations:
1. Attack Phase [volume up With Attack Rate until Attack Level],
2. Decay Phase [volume down With Decay Rate until Sustain Level],
3. Sustain Phase [volume down With SustainRate Until 0]
actually... no, the Sustain Rate is fixed To 0 in GEMS, so the volume
stays at its level there.

Anywhere in this, a "Key Off" breaks into the
4. Release Phase [volume down With Release Rate Until 0]
With "volume 0" I mean "silence" here, so For the PSG it's actually value $F


so can i hope all this talking about same delay 1, as modulation do? i mean for example: Attack Rate = 3, Attack Level = 9 it will means:
delay 1, volume 0, delay 1, volume 3, delay 1, volume 6, delay 1, volume 9, delay 1,...
shell says PSG have 1/60 of second some timer, or whatever it is... but if PSG have his own timer - it is some unlogic and probably will have some asynchronously, becouse this timer is not obey to tempo. but if 1 tik of PSG instrument = 1 delay, as modulation do - no asynchronously and tempo is always same for FM and PSG. i will make as delay 1, and will compare with gems. i will record sound in emulators and read logs for this. but want to know sure :) delay 1 or not delay - that is a question :))))

probably i am never finish all my ideas :))))


Top
 Profile  
 
 Post subject:
PostPosted: 2016-10-20, 12:07:38 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
test shows it is 1/60 sec, not delay 1 :((( Attack Rate $FF, Attack Level $09, Sustain Level $0A
Code:
10000000
11110
0 ch, freq 480
0 ch, vol 9 - work of Attack Rate?
pause
0 ch, vol 9 - Attack Level
pause
0 ch, vol 10 - Sustain Level?
pause - hold Sustain Level, until note is key off, or start new note
pause - and this holding is 5 delays duration. it means 3 pauses = 1 delay for this case (40bpm)
pause
pause
pause
pause
pause
pause
pause
pause
pause
pause
pause
pause
pause
10000101
11100
0 ch, freq 453
0 ch, vol 9
pause


it means for PSG instrument work organization i will need additional thread, that will work with 1/60 sec pause in repeat. heh... i thought make all of it in main thread with delay 1 pauses in a repeat.


Top
 Profile  
 
 Post subject:
PostPosted: 2016-10-20, 12:23:53 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
this PSG no have some formula for frequency count from gems note value? or i need to make table of values?
Code:
 note $20   1017
 note $21   1017
 note $22   960
 note $23   906
 note $24   855
 note $25   807
 note $26   762
 note $27   719
 note $28   679
 note $29    641
 note $2A    605
 note $2B   571
 note $2C   539
 note $2D   508
 note $2E   480
 note $2F   453


and same with Attack Rate. have it some formulas? or i will need make table for all 31 cases of AR?
Code:
$1F - 31 - 14,  12,  10,  8,  6   4   2   0   0
$1B - 27 - 14,  12,  10,  9,  7,  5,  4,  2,  0,  0
$0A - 10 - 15,  14,  14, 13, 12, 12, 11, 10, 10,  9,  9,  8,  7,  7,  6,  5,  5,  4,  4,  3,  2,  2,  1,  0,  0,  0

(between of values 1/60 sec pause)


Top
 Profile  
 
 Post subject:
PostPosted: 2016-10-21, 17:39:44 

Staff Staff
Programmers Programmers
Musicians Musicians
Contributors Contributors
Reverse engineers Reverse engineers
Offline
User avatar

Joined: 2011-12-01, 20:20:07
Posts: 3025
Location: Germany
For your first question, I'll just quote the original GEMS source code:
Code:
* fmftbl contains a 16 bit freq number for each half step in a single octave (C-C)

fmftbl      dw   644,682,723,766,811,859,910,965,1022,1083,1147,1215,1288

* psgftbl contains the 16 bit wavelength numbers for the notes A2 thru B7 (33-95)

psgftbl      dw          03F9H, 03C0H, 038AH   ; A2 > B2

      dw   0357H, 0327H, 02FAH, 02CFH   ; C3 > B3
      dw   02A7H, 0281H, 025DH, 023BH
      dw   021BH, 01FCH, 01E0H, 01C5H

      dw   01ACH, 0194H, 017DH, 0168H   ; C4 > B4
      dw   0153H, 0140H, 012EH, 011DH
      dw   010DH, 00FEH, 00F0H, 00E2H

      dw   00D6H, 00CAH, 00BEH, 00B4H   ; C5 > B5
      dw   00AAH, 00A0H, 0097H, 008FH
      dw   0087H, 007FH, 0078H, 0071H

      dw   006BH, 0065H, 005FH, 005AH   ; C6 > B6
      dw   0055H, 0050H, 004CH, 0047H
      dw   0043H, 0040H, 003CH, 0039H

      dw   0035H, 0032H, 002FH, 002DH   ; C7 > B7 (not very accurate!)
      dw   002AH, 0028H, 0026H, 0023H
      dw   0021H, 0020H, 001EH, 001CH

      dw   001CH            ; extra value for interpolation of B7

For your second question, you need to know that ADSR calculations usually work with step values that are added to (attack) or subtracted from (decay/sustain/release) the accumulator value. (That's a system completely different to defining delays between frames.)
An example:
Attack Rate $18 means that the "volume" values for the ticks/frames are: $18, $30, $48, $60, etc. (until the Attack Level is reached)
Also, since PSG volumes are only 4 bits, ADSR usually use 4.4 bit fixed point values for internal calculations. (If you don't know what "fixed point" means, you should look up "fixed-point arithmetic".)

Small note: For basic understanding, you should think of the accumulator value starting at 0 (silence) and go up to $FF (maximum volume) going back down to 0. (see this picture)
However, GEMS seems to use inverted level values (i.e. max. volume = $00, silence = $FF), probably because it matches the PSG's volume scale better. That way is a bit less intuitive though and not as easy to understand, IMO.


Top
 Profile  
 
 Post subject:
PostPosted: 2016-10-24, 11:47:15 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
you are right, i am not understand, as always :) so i am go to long way as Terminator. set notes, compile rom, play at emulator and collect all PSG notes values. and as i can see - it is same as your table for PSG :)

then about attack rate and other this. my investigation shows - all this rate have same mathematiks. it is 1 to 31 values for ways slow up or slow down and 32 value - $FF - when no have this rate and max volume emmidatly. then i start to collect some data - what value of rate make what. and get some "arrays":
Code:
$1F - 31 - 14, 12, 10,  8,  6   4   2   0   0
$1C - 28 - 14, 12, 10,  8,  7,  5,  3,  1,  0,  0

between values 1/60 sec. when i get a few this "arrays" i am look very carefully and make some formula:
Code:
counterd.d     = 255 / (ARvalue * 15)

then just repeat fill array by values so many time, as int of counterd shows, and 0.x is move to next counterd. when i see arrays - it was very close to original. i was happy - for me it is big victory. but then for fun i remade 15 into 16... unlogic? yes! :) but it works :))) arrays become 100% match :) i am as always not expect that :))) i become more happy, that i was before :)
Code:
Procedure FillARarray(ARvalue.i, ALvalue.i)
 
  ReDim PSGInstARValues(0)
 
  If ARvalue = $FF Or ARvalue = 32; 0 AR, top volume immediatly
    PSGInstARValues(0) = ALvalue
  Else
    counterd.d     = 255 / (ARvalue * 16)
    countershift.d = counterd
   
    For i = 15 To ALvalue Step -1
     
      counteri = Int(countershift)
     
      If counteri > 0
        startnumarray = ArraySize(PSGInstARValues())
        ReDim PSGInstARValues(startnumarray + counteri)
        For k = startnumarray To startnumarray + counteri
          PSGInstARValues(k) = i
        Next
      EndIf
     
      countershift = countershift - counteri ; get 0.x value
      countershift + counterd                ; 0.x + how it names...
     
    Next
   
  EndIf
 
EndProcedure


prototype of this works... not very fine - some times is crash, becouse this array... i very glad to kick out this array and make somehow count values when it plays - hot count, but i have no idea how. so now it is arrays. second problem - i have no idea how to repeat this dinamic allocations of channels for play. now it is support only 1 channel and i make PSG instrument tester:
https://www.dropbox.com/s/qy7q8p7b1qysl ... r.zip?dl=1

no need to load, just make some changes and press play button. and it not support noise type - just tone. what do you think? :)


Top
 Profile  
 
 Post subject:
PostPosted: 2016-10-30, 15:02:52 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
i am still didnt find problem... some how and somewhere some instruments is sets uncorrect. clear to hear it - play 004 track. is some: "tudum" - it is wrong sound.


Attachments:
test.zip [709.16 KiB]
Downloaded 53 times
Top
 Profile  
 
 Post subject:
PostPosted: 2016-11-01, 13:56:39 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
problem was in modulation. i thought modulation work only for 1 note, that come after declare modulation, but it plays until damp modulation will declare (00 00 00 modulation file), or probably when instrument is change. this moment about instrument change is stop modulation - need to recheck in tests for sure know.


Top
 Profile  
 
 Post subject:
PostPosted: 2016-11-24, 14:19:24 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
stuck :) samples, modulations and PSG notes and instruments still not done, and i dont khow when i can made it :)
https://www.youtube.com/watch?v=WKjbf65l_Hc


Top
 Profile  
 
 Post subject:
PostPosted: 2016-12-04, 19:45:53 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
probably i am not understand explanation correct... i mean about converting from register into note + pitch values. my code is:
Code:
Global stopflag = 5

Global Dim table(12)

table(0) = $0284
table(1) = $02AA
table(2) = $02D3
table(3) = $02FE
table(4) = $032B
table(5) = $035B
table(6) = $038E
table(7) = $03C5
table(8) = $03FE
table(9) = $043B
table(10) = $047B
table(11) = $04BF
table(12) = $0508

; get note and pitch values from registers
Procedure.i ReturnNoteAndPitch(A4A0.i, reqursivemarker.i=0)
 
  If reqursivemarker
    Debug "reqursive call"
    stopflag - 1
  EndIf
 
  Octave = A4A0 / 2048
  Debug "Octave " + Str(Octave)
 
  Residue = A4A0 - (Octave * 2048)
  Debug "Residue " + Str(Residue)
 
  If Residue < $0284
    Residue * 2 + (2048 * (Octave - 1))
    If stopflag = 0 ; will be removed. now it made stop reqursive, when it stuck   
    Else            ; will be removed
    tmp = ReturnNoteAndPitch(Residue, 1)
    EndIf           ; will be removed
  Else
    For i = 11 To 0 Step -1
      If Residue >= table(i)
        note = i
        Break
      EndIf
    Next 
 
    ;from this place i try to revert procedure for get note and pitch
    ;and probably i need to move this part code inside cycle before break
                                 ;FNum = a + ((b-a)*pitch)/256
    A4A0 = Residue - table(note) ;= ((b-a)*pitch)/256 
    A4A0 * 256                   ;= (b-a)*pitch 
    pitchval.f = A4A0 / (table(note+1) - table(note))
    A4A0 = Round(pitchval, #PB_Round_Up)
 
    ;this place is mix 2 values into 1, becouse procedurereturn can have 1 value
    tmp = (note + 12 * Octave) << 16
    tmp + A4A0

  EndIf
 
  ProcedureReturn tmp
 
EndProcedure

;note 11 is $04BF
;note 12 is $0A84
;note 13 is $0AAA

Debug "$0AAA" ; for test
NAP = ReturnNoteAndPitch($0AAA)
Debug "note $" + Hex(NAP >> 16)    ; will show 13
Debug "pitch $" + Hex(NAP & $FFFF) ; will show 0 - all correct

Debug ""

Debug "$0721"
NAP = ReturnNoteAndPitch($0721)
Debug "note $" + Hex(NAP >> 16)    ; will show note $B
Debug "pitch $" + Hex(NAP & $FFFF) ; will show pitch $85C - it is very big pitch value

Debug ""

Debug "$1269"
NAP = ReturnNoteAndPitch($1269)    ; will use reqursive
Debug "note $" + Hex(NAP >> 16)    ; will show note $17
Debug "pitch $" + Hex(NAP & $FFFF) ; will show pitch $43 - looks fine. this value $1269 make problem last time, when you explain how to make recount and from that time it works fine.

Debug ""

Debug "$01C8"
NAP = ReturnNoteAndPitch($01C8)    ; non stop reqursive
Debug "note $" + Hex(NAP >> 16)
Debug "pitch $" + Hex(NAP & $FFFF)
;debug window content for this case:
;$01C8
;Octave 0
;Residue 456
;reqursive call
;Octave 0
;Residue -1136
;reqursive call
;Octave -2
;Residue -224
;reqursive call
;Octave -3
;Residue -448
;reqursive call
;Octave -4
;Residue -896
;note $0
;pitch $0


so this case have two problem with $0721 and $01C8 - they both lays over notes limit ($0284 to $0508). this $0721 have very big pitch value. can it be recount as $1269 case? problem is $0721 cant to be shift down per 1 octave. and how to correct count $01C8? it is lower, than lower note. i want to curse Jocker - it is his song have this values.


Top
 Profile  
 
 Post subject:
PostPosted: 2017-01-02, 13:12:56 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
unpack arhive - it is Ti_'s Dune compiler. launch DUE file.
set chancel, when he ask path to emulator

VGM2GEMS still not finish, DAC sample detection still not finish, PSG note and instrument detections not finish, slide effect for FM not finish, MIDI2GEMS not pluged too.

sample editor - done
FM instrument editor - almost done, i want to plug .y12 files from KMOD too. now it is GEMS raw and VGM MM vgi support.
PSG player - done
FM player - almost done (DAC samples detection need)
(this editor can be call by right mouse button click on track in a list of Dune's tracks)


Attachments:
Dune.zip [5.81 MiB]
Downloaded 60 times
Top
 Profile  
 
 Post subject:
PostPosted: 2017-01-07, 17:13:04 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
ValleyBell, where i have mistake?

when you launch it - it will be empty window. press 5 ch button. it will fill list with registers, then press Play - first time it will be "knock knock" sound. it is wrong. press second time play - it will be play correct, as Alien 3 will shot with grenade launcher.

close programm, open again, but this time press All log and press play. as with 5 ch first time it will be "knock knock", press play second - it will be play as "tone, tone" - not as rocket launcher shot.

what it can be? registers always same. but first time it is one sound, second - another, with full log - even third sound. where can be my mistake?

$22 - no have any $23 and etc per channel - it is always $22. same is $27. same is for $2A and 2B. but for $B0 Feedback, Algorithm it can be $B0 - 1ch, $B1 - 2ch, $B2 - 3ch. $1B0 - 4ch, $1B1 - 5ch, $1B2 - 6ch. correct?

same is for $B4 Left/Right, AMS, FMS

same is for $30 and to $80. but some how command for all channel is change sound for 5 channel. where this mistake can be?


************* later
i see some strange registers: "$33, $0" and "$133, $0". and many other place. but they not change sound. sound change this one:
"$A6, $2C" - why he make effect for 5 channel? it is 6 channel.


************* more later
ValleyBell knows everything :) problem is in a GYM. setting frequency of note must have order: first A4, then A0. but GYM can have first A0, then much later A4. so for fix this problem i heed to write both register, even when comes only one of them.

for example: comes A4 - i need to set both. A4 and 0 for A0. then if comes A0 - i need to set first old A4, then this new value for A0.

i am go to check this :)


************* finish him
it woooooork :) la la la la la


Attachments:
opn debug.zip [36.3 KiB]
Downloaded 51 times
Top
 Profile  
 
 Post subject:
PostPosted: 2017-07-02, 13:59:43 
Offline

Joined: 2015-08-08, 13:56:52
Posts: 51
as you know, i am trying to create special code-player. this code is unpacked GEMS data by splitter programm created by shell. it need to test sound before compilation of rom. without it you will need a lot of clicking :) build GEMS by combaine programm - build rom of Dune - launch it in emulator - wait untill stars is flyaway - move to options - set track for playing. and you will know about one note plays incorrect :) you fix it... and start all actions from begining. it is suks! that is why i am start make this code player - for closer demonstration, how it will be play in emulator.

ValleyBell give OPN.dll - it plays FM part + samples part, Shiru (VGM MM creator) - give PSG core, wilbert is make convert this PSG core to my language of programming. so my pants was a full of happy.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 48 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group
[ Time : 0.092s | 14 Queries | GZIP : On ]