Playing MODs and multi samples

All 680x0 related coding posts in this section please.

Moderators: simonsunnyboy, Mug UK, Zorro 2, Moderator Team

TAD_uk
Retro freak
Retro freak
Posts: 12
Joined: Sat Jan 03, 2009 10:08 pm

Playing MODs and multi samples

Postby TAD_uk » Mon Jan 05, 2009 7:41 pm

Hi ST people!

This is my first post for the forum, hope it helps someone out there.

Here is a brief outline how *most* multi-sample playback routines work on the beloved ST (the number of hours I spent on optimizing them and counting clock-cycles when I should have been sleeping. lol).

The Quest for sound:

1) Playing a sample to the ST sound-chip
2) Playing a sample at different frequencies (or at least, making it sound like it being played at a different frequency)
3) Mixing these multiple samples together
4) Looping the sample
5) Volume control
6) CPU time


Common solutions:

1) Playing a sample to the ST sound-chip

There are a small number of issues which need to be solved here:
1a) Read one 8-bit sample and update sample address pointer
1b) Because the YM sound-chip has 3 voices each with only 4-bit volume level and the volume levels are non-linear you need to do some conversion in order to fake an 8-bit output level. This normally means a table look-up to get the 3 values for each of the 3 YM volume levels and writing them to the YM chip.
1c) Repeating these steps every (for example) 15 KHz

2) Playing a sample at different frequencies (or at least, making it sound like it being played at a different frequency)

The first output routines simply read a 8-bit sample from memory and output to the YM every (for example) 15 KHz. If they wanted it played back at 30KHz then the output routine ran at 30 KHz (usually killing all 100% CPU time).

But if you think of the output as being two parts
(a) The replay routine frequency which could be 7.5 KHz
(b) The sample "stepping" frequency which could be any number.

If we have a 15 KHz sample(the frequency it was sampled at) and a 7.5 KHz replay routine then we need to play every second 8-bit sample (0, 2, 4, 6, 8 etc..) in order to make this sample sound correct in terms of speed and time duration. Of course the final sound quality is lower than if it used a 15 KHz replay routine and stepped through the sample one byte at a time. BUT, we by using 7.5 KHz replay routine we are using 50% fewer CPU time a 15 KHz replay would :)

By using 'stepping' we can playback samples at different frequencies while keeping the replay routine running at a constant KHz speed :)

There are 4 different ways to perform this stepping:
1) Use fixed-point maths (e.g. 16 bit offset + 16 bit fraction - Quartet used Data register + Swap to perform this)
2) Use a list of offsets/increments to adjust the sample address pointers (used by TCB mod player)
3) Use multiple versions of the same sample (used by TCB in the Spreadpoint demo)
4) Another method I used :)

3) Mixing these multiple samples together

This basically involves taking each 8-bit sample from 1-4 voices and ADD-ing them together.

moveq #0, d0
moveq #0, d1
move.b (a0)+, d0 ; voice 0 sample byte
move.b (a1)+, d1 ; voice 1 sample byte
add.w d1, d0
move.b (a2)+, d1 ; voice 2 sample byte
add.w d1, d0
move.b (a3)+, d1 ; voice 3 sample byte
add.w d1, d0

; Now convert D0 --> YM volume levels

4) Looping the sample

Earlier sample replay routines used a compare to check the address register has hit the end of the sample. Quartet used 16.16 fixed-point maths to store the sample offset position and the fraction part used to 'step' through the sample and IIRC used -VE offset to detect and loop the samples.

A faster way is to pre-loop part of the samples in memory (say, 1KB of loop) and then detect + correct the sample address pointers/offsets in your VBL mod player interrupt. This avoids having the very slow compare + branches instructions in the replay/mixer routine.

5) Volume control

Take an 8-bit sample and perform a table look-up to calculate the scaled 8-bit based on the desired volume level. Most MOD player avoid this to save precious CPU clock cycles.


6) CPU time

The actual MOD player code is pretty fast 4-10 scanlines (dealing with the sequence playing). The replay routine is the real killer since it needs to do so much work for each and every voice you have.

In early days coders tried to put everything inside the replay routine (fetching, mixing, stepping, looping and YM output) but this killed too much CPU time since 30-50% of the routine's time is wasted on saving/restoring all the 1-4 voices and the address/data registers. Protracker used a method I liked to call the 'Blitz' method. This involved performing all the replay routines in two different places. The VBL could be used to fetch, mix, step, loop all the 1-4 voices and write the result to a buffer. A 'normal' 15KHz ONE-voice sample output routine can then be used to play this resulting buffer. This saved an incredible amount of CPU time.


Cheers

TAD_uk

distantminds
Obsessive compulsive Atari behavior
Obsessive compulsive Atari behavior
Posts: 108
Joined: Thu Sep 29, 2005 5:03 pm

Re: Playing MODs and multi samples

Postby distantminds » Mon Jan 05, 2009 8:31 pm

thanks I enjoyed that :D

so what was your stepping method then? ;)

TAD_uk
Retro freak
Retro freak
Posts: 12
Joined: Sat Jan 03, 2009 10:08 pm

Re: Playing MODs and multi samples

Postby TAD_uk » Mon Jan 05, 2009 10:54 pm

My stepping method was to generate code to perform the stepping using combinations of (IIRC) MOVEP, MOVE.B and MOVE.W together with optional offsets (if needed). It did mean a lot more memory than a pure data solution using a list of word steps (just like the TCB tracker), but it did save many clock cycles :) since the offsets are fetched as part of the instruction:

instead of this:

MOVE.B (A0), D0
ADD.W (A4)+, A0
.. repeat ..

You could have this:
MOVE.B xxxx(A0), D0

or even this:
MOVEP.L xxxx(A0), D0

So the above can read sample bytes 0, 2, 4, 6 (a step of 2.0)

Most of this is from memory (18 years ago) so I hope the description/68000 examples are correct.

I'm sure there are much faster ways to perform the fetch/step/mixer operations (mostly based on WORD operations).


cheers

TAD_uk

User avatar
bullis1
Fuji Shaped Bastard
Fuji Shaped Bastard
Posts: 2301
Joined: Tue Dec 12, 2006 2:32 pm
Location: Canada
Contact:

Re: Playing MODs and multi samples

Postby bullis1 » Tue Jan 06, 2009 8:28 pm

Thanks for these posts TAD. This topic has always been interesting to me and your tests are no exception.
Member of the Atari Legend team

User avatar
MiggyMog
Atari Super Hero
Atari Super Hero
Posts: 867
Joined: Sun Oct 30, 2005 4:43 pm
Location: Scotland

Re: Playing MODs and multi samples

Postby MiggyMog » Thu Jan 08, 2009 11:04 pm

On the MSX there was a viterbi optimisation routine used for playing samples done not so long ago :- http://www.msx.org/PCM-Encoder-0.01.newspost3520.html

It would be interesting to know if this has been used/converted to the ST given that the soundchip is an AY-8912

the z80 /C code is included incase anyone can easily convert it?
('< o o o o |''| STM,2xSTFM,2xSTE+HD,C-Lab Falcon MK2+HD,Satandisk,Ultrasatandisk,Ethernat.

User avatar
nativ
Fuji Shaped Bastard
Fuji Shaped Bastard
Posts: 4106
Joined: Mon Jul 30, 2007 10:26 am
Location: South West, UK

Re: Playing MODs and multi samples

Postby nativ » Thu Jan 08, 2009 11:09 pm

Might tie in nicely with a Spectrum emulator update too!!


:O)

CheeriO
Atari STFM 512 / STe 4MB / Mega ST+DSP / Falcon 4MB 16Mhz 68882 - DVD/CDRW/ZIP/DAT - FDI / Jaguar / Lynx 1&2 / 7800 / 2600 / XE 130+SD Card // Sega Dreamcast / Mega2+CD2 // Apple G4

http://soundcloud.com/nativ ~ http://soundcloud.com/nativ-1 ~ http://soundcloud.com/knot_music
http://soundcloud.com/push-sounds ~ http://soundcloud.com/push-records

User avatar
Nyh
Atari God
Atari God
Posts: 1496
Joined: Tue Oct 12, 2004 2:25 pm
Location: Netherlands

Re: Playing MODs and multi samples

Postby Nyh » Thu Jan 08, 2009 11:24 pm

MiggyMog wrote:On the MSX there was a viterbi optimisation routine used for playing samples done not so long ago :- http://www.msx.org/PCM-Encoder-0.01.newspost3520.html

It would be interesting to know if this has been used/converted to the ST given that the soundchip is an AY-8912

the z80 /C code is included incase anyone can easily convert it?

The is no need to convert any code. You just have to enter the ST values for clock and update times for the channels and the routine will calculate the optimum for the ST:
-cpuf <freq> CPU frequency of the CPU (Hz)
Default: 3579545

-dt1 <tstates> CPU Cycles between update of channel A and B
-dt2 <tstates> CPU Cycles between update of channel B and C
-dt3 <tstates> CPU Cycles between update of channel C and A
The replayer sampling base period is
T = dt1+dt2+dt3
Defaults (depends on rto):
ratio = 1 : dt1=32, dt2=27, dt3=266 => 11014Hz
ratio = 2 : dt1=156,dt2=27, dt3=141 => 22096Hz
ratio = 3 : dt1=73, dt2=84, dt3=87 => 44011Hz

Note that the replayed sampling base period depends
on the replayer and how many samples it will play
in each PSG tripplet update. The default settings
are based on:
1 : replayer_core11025 which plays one sample per
psg tripplet update
2 : replayer_core22050 which plays two sample per
psg tripplet update
3 : replayer_core44100 which plays three sample
per psg tripplet update


So write your player routine and let the program calculate the optimum output. I think sound quality improvement on the ST won't be very spectacular because the ST can update the PSG registers much faster as the Z80 on the MSX.

Hans Wessels

ppera

Re: Playing MODs and multi samples

Postby ppera » Fri Jan 09, 2009 5:38 pm

I used stepping of 2 by PSG playback of 25033 sample, intended for STE DMA audio, to save some CPU time. And must say that it is almost unnoticeable difference in quality in sompare to 25033 playback via PSG). Because quality is already poor, and can not be something good with YM. Biggest problem is quantization error - analog circuits of YM have no so accurate volume levels, and mixing 3 channels can not help much. Then we have a lot of noise. Especially on Falcon, just to mention. Actually, it is relative easy to playback with sample rate even over 30KHz, and having some 50% pf CPU time free with careful coding and using of registers, but I don't see much sense.

TAD_uk
Retro freak
Retro freak
Posts: 12
Joined: Sat Jan 03, 2009 10:08 pm

Re: Playing MODs and multi samples

Postby TAD_uk » Sat Jan 10, 2009 11:39 am

If you want to step through sample (or in fact any fixed-point values such as polygon edges) you can use something like this to build a list of integer values quickly:


Using 16.16 fixed point maths to store the position (offset.part = 32 bits) and step (integer.fraction = 32 bits) a 'normal' 16.16 fixed point add.l would be like this:

d0 = (offset.0) << 16 + (part)
d4 = (integer.0) << 16 + (fraction)

add.l d4, d0

but you'll need a swap to access the top 31..16 bits of d0 (the offset.0 value)

swap d0 ; swap offset <--> part
move.w d0, (a0)+ ; store the offset value
swap d0 ; restore d0 value

If you are careful you can also chain multiple ADDX together for more than 1 polygon edge OR sample voice step.

(example from my memory, so hopefully correct)

move.w d0-d3, (a0)+ ; store the integer offsets d0,d1,d2,d3
addx.l d4, d0
addx.l d5, d1
addx.l d6, d2
addx.l d7, d3

the set up of the d4 to d7 register use bits 31-16 as fractional step and bits 15-0 as the integer step BUT not in the normal way !!

If you set up your registers something like this:-

d0 = (part.1) << 16 + (offset.0)
d1 = (part.2) << 16 + (offset.1)
d2 = (part.3) << 16 + (offset.2)
d3 = (part.0) << 16 + (offset.3)


and STEP value like this:-

d4 = (fraction.1) << 16 + (integer.0)
d5 = (fraction.2) << 16 + (integer.1)
d6 = (fraction.3) << 16 + (integer.2)
d7 = (fraction.0) << 16 + (integer.3)

NOTE: The part.0 ... part.3 and fraction.0 ... 3 are 'out of sync' so one ADDX will increment both integer.X value as well as fraction.x+1 value.

Hope this all makes sense.

Cheers

TAD_uk

ppera

Re: Playing MODs and multi samples

Postby ppera » Mon Jan 12, 2009 1:30 pm

TAD_uk : can you post here some concrete, short code ? I think that it would be much more explaining.

User avatar
oberje
Atari freak
Atari freak
Posts: 58
Joined: Sat Jan 10, 2009 2:38 pm
Location: Sussex, UK
Contact:

Re: Playing MODs and multi samples

Postby oberje » Mon Feb 02, 2009 8:21 am

Interesting. I second that, do you have an example you can show?

R.
oberje

EDIT: Poor punctuation!


Social Media

     

Return to “680x0”

Who is online

Users browsing this forum: No registered users and 3 guests