⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pt23mod.txt

📁 There are _NO_ standard sample rate for the samples used in modules. But most often the samples are
💻 TXT
📖 第 1 页 / 共 2 页
字号:
     35        -5.2             3       -26.6
     34        -5.5             2       -30.1
     33        -5.8             1       -36.1
                                0    Minus infinity

  The reason for the table starting at 0 dB as the convention from
taperecorders of having 0 dB as the optimal recording condition, and
displaying anything worse as a negative number.

  Decibel is a logrithmical unit, just like we feel sound intensity.  It
represent the ratio between two intensities.

  On the other hand, the Amiga volumes represent the linear difference
between sound intensities; this mean that you have less accuracy between
the low volumes than between the high ones.  If you need to, you can safely
remove volume 64 and replace it with volume 63; but you can NOT remove
volume 0 and replace it with volume 1.

  If you are implementing a MOD player for another sound-device, then
remember to check whether it has linear or logarithmic volume control.

  The above table can be calculated from the formula dB=20*log10(Volume/64)
To go the other way, from dB to Amiga volumes, do
Volume=64*10^(dB/20)

  The dB here have to do with ratios of sound, not absolute sound power.
This is the way it is used in recording equipment etc, and not the for
measuring absolute ear-destroying capability.

  If you need to implement volume artificially, just multiply by the volume
and shift right 6 times.
  If you need to mix samples on-the-fly to lower the amount of voices used,
your best bet is probably doing a DCT (Convert the samples to sums of
cosines) on small blocks of the sample (64 bytes?) before playing, and
mixing with the exact position in which you generate a sample.  This is the
only way I can think of to give adequate quality, at least.

-Vishnu of Cryptoburners

***********************************************************************
Protracker V2.3A/3.01 Effect Commands
----------------------------------------------------------------------------
0 - Normal play or Arpeggio             0xy : x-first halfnote add, y-second
1 - Slide Up                            1xx : upspeed
2 - Slide Down                          2xx : downspeed
3 - Tone Portamento                     3xx : up/down speed
4 - Vibrato                             4xy : x-speed,   y-depth
5 - Tone Portamento + Volume Slide      5xy : x-upspeed, y-downspeed
6 - Vibrato + Volume Slide              6xy : x-upspeed, y-downspeed
7 - Tremolo                             7xy : x-speed,   y-depth
8 - NOT USED
9 - Set SampleOffset                    9xx : offset (23 -> 2300)
A - VolumeSlide                         Axy : x-upspeed, y-downspeed
B - Position Jump                       Bxx : songposition
C - Set Volume                          Cxx : volume, 00-40
D - Pattern Break                       Dxx : break position in next patt
E - E-Commands                          Exy : see below...
F - Set Speed                           Fxx : speed (00-1F) / tempo (20-FF)
----------------------------------------------------------------------------
E0- Set Filter                          E0x : 0-filter on, 1-filter off
E1- FineSlide Up                        E1x : value
E2- FineSlide Down                      E2x : value
E3- Glissando Control                   E3x : 0-off, 1-on (use with tonep.)
E4- Set Vibrato Waveform                E4x : 0-sine, 1-ramp down, 2-square
E5- Set Loop                            E5x : set loop point
E6- Jump to Loop                        E6x : jump to loop, play x times
E7- Set Tremolo Waveform                E7x : 0-sine, 1-ramp down. 2-square
E8- NOT USED
E9- Retrig Note                         E9x : retrig from note + x vblanks
EA- Fine VolumeSlide Up                 EAx : add x to volume
EB- Fine VolumeSlide Down               EBx : subtract x from volume
EC- NoteCut                             ECx : cut from note + x vblanks
ED- NoteDelay                           EDx : delay note x vblanks
EE- PatternDelay                        EEx : delay pattern x notes
EF- Invert Loop                         EFx : speed
----------------------------------------------------------------------------
Peter "CRAYON" Hanning /Mushroom Studios/Noxious

For a more complete description see my previous post about the new format.
This format also allow you to have more effects, and several effects on the
same note.  Hopefully, it will soon replace the module format.
 - Vishnu

***********************************************************************

Protracker CIA (Complex Interface Adapter) Timer Tempo Calculations:
--------------------------------------------------------------------
Fcolor                        = 4.43361825 MHz (PAL color carrier frequency)
CPU Clock   = Fcolor * 1.6    = 7.0937892  MHz
CIA Clock   = Cpu Clock / 10  = 709.37892  kHz
50 Hz Timer = CIA Clock / 50  = 14187.5784
Tempo num.  = 50 Hz Timer*125 = 1773447

For NTSC: CPU Clock = 7.1590905 MHz --> Tempo num. = 1789773

 To calculate tempo we use the formula: TimerValue = 1773447 / Tempo
 The timer is only a word, so the available tempo range is 28-255 (++).
 Tempo 125 will give a normal 50 Hz timer (VBlank).

 A normal Protracker VBlank song tempo can be calculated as follows:
 We want to know the tempo in BPM (Beats Per Minute), or rather quarter-
 notes per minute. Four notes makes up a quarternote.
 First find interrupts per minute: 60 seconds * 50 per second = 3000
 Divide by interrupts per quarter note = 4 notes * speed
 This gives: Tempo = 3000/(4*speed)
 simplified: Tempo = 750/speed
 For a normal song in speed 6 this formula gives: 750/6 = 125 BPM

 Lars "ZAP" Hamre/Amiga Freelancers 1990

***********************************************************************

The "PowerPacker" crunching algorithm:

Powerpacker use a variant of Lemel-Ziv compression.  This mean that it in
some cases store strings of bytes as only an offset from the current
position and a counter.  (How LZ could get a patent on this is beyond me!)

A PowerPacked file has the following format:
.dc.b.'PP20'...; Identifier
.dc.l.Efficiency
.... crunched data ...
.dc.l.(Length*256)+NumOfBitsToDiscard

The Efficiency is 4 bytes representing the length of offset from the
current position for different runs of equal bytes.  The first three are
used for runs of from 2 to 4 bytes; the last is used for all runs of 5
bytes and over.
The length is the length of the original, UNcrunched file.
The bits to be discarded are discarded off the END of the crunched data.
 
All bits in the crunched data are stored in reverse order, to permit
decrunching in a buffer where the crunched data are loaded at the start (An
8 byte margin between the start of the file and the decrunching position is
needed, though).  This mean you have to get bits in the reverse order when
decrunching, and when I refer to "Get A Bit" or Get Eight Bits" or
something, that is the LAST bit or bits from the source.  Kinda obvious
isn't it? ;-)

This means that also when a full set of 8 bits are read from the file,
their bit order are reversed.

The varying efficiencies used by PowerPacker are as follows:
Fast:      9, 9, 9, 9
Medicore:  9,10,10,10
Good:      9,10,11,11
Very Good: 9,10,12,12
Best:      9,10,12,13


                         The Decrunching Algorithm

WritePointer is a pointer to the position in memory where decrunched bytes
 are currently written.

Decrunch:
REPEAT
  Get A Bit (X);
  IF X=0 THEN Copy bytes from source;
  Copy string from already decrunched part of file;
    (* Done no matter what the state of X *)
UNTIL WritePointer<=Start Of Decrunchbuffer;
END.


Copy bytes from source:
BEGIN
  n:=0;
  REPEAT
    Get Two Bits (X);
    n:=n+X;
  UNTIL X<>3;
  Copy n+1 bytes as bits from Crunched Data to WritePointer;
  (* At this stage, the bytes get their order of bits reversed; and
     WritePointer DECREASES *)
END;

Copy string from already decrunched part of file:
BEGIN
  Get Two Bits(n);
  OffsetLen:=Efficiency[n];
  IF n<>3 THEN Get OffsetLen Bits (X)
  ELSE
  BEGIN
    Get One Bit (X);
    IF X=0 THEN Get Seven Bits (X) ELSE Get OffsetLen Bits (X);
    REPEAT
      Get Three Bits (Y);
      n:=n+Y;
    UNTIL Y<>7;
  END;
  Copy n+2 bytes from WritePointer+X;
   (* Here it is copied reversely through memory; X is constant, while
      WritePointer decreases. *)
END;

If you can't read this, the original decrunchroutine follows here, in 68000
assembler.  It was NOT commented before I cleared it up with macros...
So complaints about the comments must go to me, too!

Registers used are (in the main decrunch routine):
d0 - Counter for number of bits to fetch with the READD1 macro.
d1 - Return register for the READBIT macros.
d2 - Used as counter register for the copy routines.
d3 - Used as offset for the oldstring copy routine.
d5 - Used to store the longword currently read bits from.
d7 - Used for storing the number of bits left in d5.
     0 means one bit left, read new longword to d5 when d7 wraps to
     negative.
a0 - Pointer to current longword of source (the one in d5).
a1 - Current position in the buffer to decrunch to.
a2 - Start of buffer to decrunch to.  Used only for checking whether the
     decrunching is through.
a5 - Pointer to efficiency array.

Things to consider:
Bits are shifted from d5 to d1 with code like this
.lsr.l.#1,d5
.addx.l.d1,d1
shifting bits from the BOTTOM of d5 into the BOTTOM of d1, reversing the
order of the bits as they go from d5 to d1.
The predecrement mode, as in
.move.b.d1,-(a1)
decrement a1 BEFORE writing d1.

***********************************************************************
;
; PowerPacker Decrunch assembler subroutine V1.1
;
; call as:
;    DecrunchBuffer (endcrun, buffer, efficiency);
;                      a0       a1        d0
; with:
;    endcrun   : UBYTE * just after last byte of crunched file
;    buffer    : UBYTE * to memory block to decrunch in
;    efficiency: Longword defining efficiency with wich file was crunched
;
; NOTE:
;    Decrunch a few bytes higher (safety margin) than the crunched file
;    to decrunch in the same memory space. (64 bytes suffice)
;

Decrunch:
.lea.myBitsTable(pc),a5.; Efficiency array
.move.l.d0,(a5)...; Store efficiency for this file.
.move.l.a1,a2...; Store start of decrunch memory.
.move.l.-(a0),d5..; Get length & number of bits to 
.moveq.#0,d1...;  trash...
.move.b.d5,d1...; Copy number of bits to trash...
.lsr.l.#8,d5...; Find length of decrunched file...
.add.l.d5,a1...; And end of decrunch buffer.
.move.l.-(a0),d5..; First longword of crunched data.
.lsr.l.d1,d5...; Skip unused bits...
.moveq.#32-1,d7..; Number of bits in longword...
.sub.b.d1,d7...; And be sure to read another when 
.....;  d5 is spent!

LoopCheckCrunch:...; The decrunch loop.
.READBIT....; State of bit is returned in d1
.bne.s.CrunchedBytes..; and Z flag
NormalBytes:
.moveq.#0,d2
Read2BitsRow:
.READBITS #2,d1...; Get length of run-1
.add.w.d1,d2...; Loop until not %11, increasing
.cmp.w.#3,d1...; all the time... (Sort of Huffman
.beq.s.Read2BitsRow..; on the run lengths...)
.ReadNormalByte:...; REPEAT
.READBITS #8,d1...; Get from crunched data...
.move.b.d1,-(a1)..; Store...
.dbf.d2,.ReadNormalByte.; UNTIL d2<0
.cmp.l.a1,a2...; End of crunch?
.bcs.s.CrunchedBytes..; Nope, now do crunched bytes...
.rts....; Chicken out - FINITO!

CrunchedBytes:
.READBITS #2,d1...; Get 2 bits of runlength-2
.moveq.#0,d0
.move.b.(a5,d1.w),d0..; Get number of bits offset for
.move.w.d1,d2...; this runlength
.addq.w.#1,d2...; Runlength always 2+
.cmp.w.#3+1,d2...; Did data indicate longer run?
.bne.s.ReadOffset..; Nope....
.READBIT....; Is the longer run with offsetlen
.bne.s..LongBlockOffset.; from Efficiency?
.moveq.#7,d0...; Nope, hard code length 7
.LongBlockOffset:
.READD1....; Get offset...
.move.w.d1,d3
Read3BitsRow:
.READBITS #3,d1...; Get more string length...
.add.w.d1,d2...; Increase until stop indicated...
.cmp.w.#7,d1...; By not having the max value.
.beq.s.Read3BitsRow
.bra.s.DecrunchBlock..; And start the copying.
ReadOffset:
.READD1....; Get offset for short run...
.move.w.d1,d3...; and use it!
DecrunchBlock:
.move.b.(a1,d3.w),-(a1)..; Loop the copy...
.dbf.d2,DecrunchBlock.; One time more than the initial d2
EndOfLoop:
_pp_DecrunchColor:
.move.w.a1,$dff1a2..; Set colour
.cmp.l.a1,a2...; Check if we have reached/passed 
.bcs.LoopCheckCrunch..;  lower limit...
.rts....; Yeah - chicken out!

myBitsTable:
.dc.b.$09,$0a,$0b,$0b..; Efficiency table
***********************************************************************

That's all for now - hope you don't mind...
If you want to use the PowerPacker decrunching routine, I suggest instead
using powerpacker.library if you are on the Amiga; if it is for a demo, I
suggest using another cruncher, for instance CrunchMaster.  It has better
compression ratios than PowerPacker.

Vishnu CRB           Feel free to e-mail me.
steinarm@ifi.uio.no  "...all the modern inconveniences..." (Mark Twain)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -