Jump to content

Photo

Compressed samples..

Less memory less CPU time :)

26 replies to this topic

#1 andym00 OFFLINE  

andym00

    Stargunner

  • 1,036 posts
  • Location:A geordie cowfield...

Posted Fri Mar 2, 2012 5:06 AM

In addition to all the pulse sound stuff I've been doing some thinking about regular sample playback..
The idea is pretty simple, and surprisingly works very well..

It saves memory, and also saves CPU time, lots of CPU time in the case of higher sample rates..

Instead of the conventional packed nybbles of samples, packing 2 4 bits samples into one byte, I had the idea of storing a length in one of the nybbles..

Now, you might think this is a bit silly, but you'd be wrong :)

In a bunch of 15.6K 4bit samples, every single one of them compresses to less, not one is bigger..
In the below data, remember that the source size listed on each sample is as 8bit samples, so the regular 4bit version is half that size.. I've not been delicate about what I've given it, and it's a right old mixture..

Now, look at the numbers.. It's giving you some quite cool results..
The individual drums sounds compress amazingly well, 6:1 in some cases!!
General, very noisy, speech does okay, in the region of 1.5:1
A recording of some SID music, 2:1
So there you have it.. A lovely simple way to get more samples in your games, with less CPU overhead :)

Playback is dead simple, you just use the POKEY timers, or 6522/6 to set the delay after setting each sample..
So, the playback code is literally..
lax SampleData
and #$0f
ora #$10
sta AUDCx
lda LSR4,x
sta AUDFx
I'll knock up some tests today when I've got a few hours, but the playback scheme is exactly what I'm doing in the Pulse sounds stuff I've been working on..
Granted, this really only works well for one channel of sample playback, but there's means and ways to mix compressed sample data in realtime ;)

Anyway.. Thought I'd share this...
No doubt someone will be along in a second to piss on the bonfire..
But until then..

Loaded 'samples\606BASS.pcm' size 3800 bytes
4 bit length - Compressed size: 328 bytes

Loaded 'samples\606CHAT.pcm' size 3500 bytes
4 bit length - Compressed size: 1258 bytes

Loaded 'samples\606CYMB.pcm' size 15000 bytes
4 bit length - Compressed size: 6760 bytes

Loaded 'samples\606HTOM.pcm' size 5000 bytes
4 bit length - Compressed size: 580 bytes

Loaded 'samples\606LTOM.pcm' size 5000 bytes
4 bit length - Compressed size: 544 bytes

Loaded 'samples\606SNAR.pcm' size 4374 bytes
4 bit length - Compressed size: 1034 bytes

Loaded 'samples\Jeff-Evolver6581r4.pcm' size 320000 bytes
4 bit length - Compressed size: 77292 bytes

Loaded 'samples\die_hard_yippee2.pcm' size 591830 bytes
4 bit length - Compressed size: 149822 bytes

Loaded 'samples\circle_is_complete_x.pcm' size 240744 bytes
4 bit length - Compressed size: 94618 bytes

Loaded 'samples\apxtwin.pcm' size 1239887 bytes
4 bit length - Compressed size: 492018 bytes

Total source size: 2429135 bytes
4bit size: 824254 bytes

If you got this far, then I also did a bunch of tests that also used different bit sizes for the lengths, a little more work decoding..
Interestingly the best bit size is 3bits.. On average it's about 10% better than 4bits, but that means you have 8 length values packed into 3 bytes, then the 8 samples packed as nybbles, so every 8 samples you'd need to unravel the next 8 length values.. Not a biggy, but not as elegant as 4 bits, and for only a small gain..

I also did results with other convenient bits sizes that work well, namely, 1, 2, 3, 4, 6, 8 bit lengths values..
Here's the results for all of them in case you're curious..

Loaded 'samples\606BASS.pcm' size 3800 bytes
1 bit length - Compressed size: 1215 bytes
2 bit length - Compressed size: 763 bytes
3 bit length - Compressed size: 490 bytes
4 bit length - Compressed size: 328 bytes
6 bit length - Compressed size: 210 bytes
8 bit length - Compressed size: 205 bytes
Loaded 'samples\606CHAT.pcm' size 3500 bytes
1 bit length - Compressed size: 1357 bytes
2 bit length - Compressed size: 1198 bytes
3 bit length - Compressed size: 1198 bytes
4 bit length - Compressed size: 1258 bytes
6 bit length - Compressed size: 1480 bytes
8 bit length - Compressed size: 1746 bytes
Loaded 'samples\606CYMB.pcm' size 15000 bytes
1 bit length - Compressed size: 6261 bytes
2 bit length - Compressed size: 5682 bytes
3 bit length - Compressed size: 6125 bytes
4 bit length - Compressed size: 6760 bytes
6 bit length - Compressed size: 8290 bytes
8 bit length - Compressed size: 9915 bytes
Loaded 'samples\606HTOM.pcm' size 5000 bytes
1 bit length - Compressed size: 1625 bytes
2 bit length - Compressed size: 1059 bytes
3 bit length - Compressed size: 742 bytes
4 bit length - Compressed size: 580 bytes
6 bit length - Compressed size: 500 bytes
8 bit length - Compressed size: 577 bytes
Loaded 'samples\606LTOM.pcm' size 5000 bytes
1 bit length - Compressed size: 1623 bytes
2 bit length - Compressed size: 1042 bytes
3 bit length - Compressed size: 710 bytes
4 bit length - Compressed size: 544 bytes
6 bit length - Compressed size: 455 bytes
8 bit length - Compressed size: 519 bytes
Loaded 'samples\606SNAR.pcm' size 4374 bytes
1 bit length - Compressed size: 1558 bytes
2 bit length - Compressed size: 1212 bytes
3 bit length - Compressed size: 1067 bytes
4 bit length - Compressed size: 1034 bytes
6 bit length - Compressed size: 1153 bytes
8 bit length - Compressed size: 1366 bytes
Loaded 'samples\Jeff-Evolver6581r4.pcm' size 320000 bytes
1 bit length - Compressed size: 113287 bytes
2 bit length - Compressed size: 82620 bytes
3 bit length - Compressed size: 72915 bytes
4 bit length - Compressed size: 77292 bytes
6 bit length - Compressed size: 95088 bytes
8 bit length - Compressed size: 114073 bytes
Loaded 'samples\die_hard_yippee2.pcm' size 591830 bytes
1 bit length - Compressed size: 210877 bytes
2 bit length - Compressed size: 164604 bytes
3 bit length - Compressed size: 147731 bytes
4 bit length - Compressed size: 149822 bytes
6 bit length - Compressed size: 177745 bytes
8 bit length - Compressed size: 212863 bytes
Loaded 'samples\circle_is_complete_x.pcm' size 240744 bytes
1 bit length - Compressed size: 95233 bytes
2 bit length - Compressed size: 84858 bytes
3 bit length - Compressed size: 86459 bytes
4 bit length - Compressed size: 94618 bytes
6 bit length - Compressed size: 117175 bytes
8 bit length - Compressed size: 140556 bytes
Loaded 'samples\apxtwin.pcm' size 1239887 bytes
1 bit length - Compressed size: 485787 bytes
2 bit length - Compressed size: 431052 bytes
3 bit length - Compressed size: 442900 bytes
4 bit length - Compressed size: 492018 bytes
6 bit length - Compressed size: 612777 bytes
8 bit length - Compressed size: 735333 bytes
Total source size: 2429135 bytes
1bit size: 918823 bytes
2bit size: 774090 bytes
3bit size: 760337 bytes
4bit size: 824254 bytes
6bit size: 1014873 bytes
8bit size: 1217153 bytes

If raw compression was your goal then you could easily implement a single player to handle all of those modes, wouldn't be a huge job at all..
But personally, I think the simplicity of the 4bit length wins the race :)

#2 Heaven/TQA ONLINE  

Heaven/TQA

    Quadrunner

  • 8,883 posts
  • Location:Baden-Württemberg, Germany

Posted Fri Mar 2, 2012 6:29 AM

interesting... keep it coming... maybe my last chance to have samples in the Gridrunner build (which waits for release).

#3 andym00 OFFLINE  

andym00

    Stargunner

  • Topic Starter
  • 1,036 posts
  • Location:A geordie cowfield...

Posted Fri Mar 2, 2012 6:44 AM

It'll benefit.. There's no trade off for this method.. It really is less memory, less CPU time :)
Just fired it up for the first time after hacking together when I should have been doing other things ;)
Here's a simple 15.6K test.. Not the best sample, but it'll do to test the encoder and things..
You can see each colour change is an IRQ, whereas with normal playback every line would have an IRQ..

The first colour is just where the IRQ enters, the grey colour (if you've got enough overscan) is the sample being set..
Just jiggling the IRQ timing to find the best setting, and least wastage..

This sample is 14K in raw 4bit packed mode, and with this method, 6KB :)

Attached Files

  • Attached File  main.xex   5.92KB   92 downloads


#4 Rybags OFFLINE  

Rybags

    Quadrunner

  • 12,694 posts
  • Location:Australia

Posted Fri Mar 2, 2012 7:01 AM

3 bit length parm could mean using 5 bits for the sample value (multi-voice playback)

I was looking earlier at the C64MP3 demo - it acheives some pretty good compression, it might be worth attempting a port to A8.
http://noname.c64.or...lease/?id=87985
Source code is also available from http://www.ejeson.se...y_Tufvesson.zip (10 Meg download)

I've also had a few ideas about compression for normal 4-bit stuff but not really gotten around to trying them out.

. delta stepping instead of discrete sample values
. RLE similar to your method
. simple compression, e.g. into 3 bits with 6 or 7 most common values represented and remainder represented as extended bitstreams.

. mixture of all these mentioned.

The "sucky" thing about using 4 bit sampling vs 8 bit (aside from the obvious) is that the fast/simple compression methods available usually don't give near as much saving as you can get using them on 8 bit samples.

#5 andym00 OFFLINE  

andym00

    Stargunner

  • Topic Starter
  • 1,036 posts
  • Location:A geordie cowfield...

Posted Fri Mar 2, 2012 7:25 AM

Oh, I wasn't saying this the means to the best possible compression, just this offers less memory, and less CPU time than normal methods.. And there's no downsides to it, no quality loss, less memory, less cpu time.. It's not often you can say that about something ;)

Anything more complex is going to eat time, and I'm loving this whole 15.6K playback with less interrupts thing right now..

The issue with anything more than 4 bits is I think you won't get enough repeats to justify it, and also the other methods of playback, like Phaerons ~6.9(ish) bit playback method is that I don't see how you can change the timer values like you would need to.. Though I've not looked at exactly what he does with that..

The C64MP3/Cubase64 stuff is stunning to say the least, but it's not my cup of tea.. I'd much rather be synthesising stuff on the fly..

I just thought given everyone plays samples the same way, that it'd be useful.. I mean sheddy could retrofit it to SH easily enough, giving more cpu, less memory.. Heaven could easily use it.. Anyone playing samples the standard way gets an instant improvement..

What's interesting though.. Encoding synthesised sounds like from my Pulse stuff, encodes stupidly well, as you would imagine.. So you could have a mountain of pre-synthesised pulse sounds, that are stored as samples like this, with very little memory footprint at all.. For reference, when the Pulse stuff is in full flow, with too many high notes, it's often only generating hundreds of samples a second, which would take no memory to store.. So you could have pre-synthesised sounds, done updating voices at many 100's of Hz for faster pitch sweeps and FX, and store with with little memory, and very little overhead to playback, I mean, very very little due to the low number of waveform changes per second..

Again, this one, big fuzzy noisy thing it is, still compresses to only 48K, which isn't too shabby for 8.5 seconds of 15Khz audio, admittedly it's only acheiving a 1.5:1 compression ratio..

Also, you can get some bonkers effects out of it by simply adding values to the length value when you write to the timer, instead of just shifting it to adjust the base sample rate :)

Attached Files

  • Attached File  main.xex   46.8KB   108 downloads


#6 JAC! OFFLINE  

JAC!

    Stargunner

  • 1,043 posts
  • Always looking for GFX and MSX for my demos
  • Location:Lebach, Germany

Posted Sat Mar 3, 2012 11:22 AM

Really nice approach. I wonder how the quality is with GR.0 screen on.

Edited by JAC!, Sat Mar 3, 2012 11:22 AM.


#7 JamesD OFFLINE  

JamesD

    River Patroller

  • 4,787 posts

Posted Sat Mar 3, 2012 1:55 PM

Oh, I wasn't saying this the means to the best possible compression, just this offers less memory, and less CPU time than normal methods.. And there's no downsides to it, no quality loss, less memory, less cpu time.. It's not often you can say that about something ;)
...
Again, this one, big fuzzy noisy thing it is, still compresses to only 48K, which isn't too shabby for 8.5 seconds of 15Khz audio, admittedly it's only acheiving a 1.5:1 compression ratio..

Also, you can get some bonkers effects out of it by simply adding values to the length value when you write to the timer, instead of just shifting it to adjust the base sample rate :)

The demo sounds pretty decent. It does have some hiss but nothing terrible.

It seems to me the MSX guys were using some sort of algorithm that would pick the most accurate values during compression.
I can't remember what it was called but I believe it reduced the error in the compressed waveform and had less hiss or bad harmonics during playback.
I'm pretty sure it was on http://www.msx.org and it was probably used for PCM compression, other than that I don't remember much.
<edit>
There is a distinct possibility that it is related to the logarithmic nature of the AY sound chip.

Edited by JamesD, Sat Mar 3, 2012 2:27 PM.


#8 phaeron OFFLINE  

phaeron

    Stargunner

  • 1,173 posts
  • Location:USA

Posted Sat Mar 3, 2012 4:29 PM

This thread gave me another idea for lowering IRQ overhead.

The idea is that if we can set up two samples at a time instead of one, we can halve the IRQ overhead. Turns out there is a way, due to the quirk where channels 3+4 are inverted from 1+2 after a write to STIMER. The idea is that to set the channels to square wave mode ($Ax) instead of volume only mode, set channels 1+3 to one period and timer 4 to two periods. After the write to STIMER, only channel 3 is active with the first sample, and after one period both timers 1 and 3 roll over, causing channel 3 to deactivate and channel 1 to activate with the second sample. Attached is a test (requires 128K for full audio). According to the profiler this leaves 80-90% of the CPU available at a 7.8KHz sample rate (two scanlines).

What I haven't figured out yet is if this can be adapted to also handle RLE. The problem is that we'd need one-shots driving both channels 1 and 3, and the only way I know of to do that is to use 16-bit linked mode which then leaves no timer for sample playback. I have a suspicion that there might be a way to use high-pass mode to toggle two channels with one set of timers, though. andym00's trick of using INC instead of ASL to hit IRQEN lets us switch the IRQ from timer 4 to timer 2, which means there's a possibility that channels 3+4 could run in 16-bit mode to provide the first delay between the two samples and toggle both channels 1 and 3 via high pass, and then channel 2 could run with the sum of the delay for both samples to retrigger the IRQ. I need to double-check the high pass circuitry to figure out exactly how this might work.

Attached Files



#9 Rybags OFFLINE  

Rybags

    Quadrunner

  • 12,694 posts
  • Location:Australia

Posted Sat Mar 3, 2012 7:13 PM

That's pretty cool.

One problem I see with RLE and this method though - the natural decay that occurs in the amplitude level for normal square waveforms.

What about if it used a mix of forced volume + this method? If an RLE run starts, set a longer timer and use volume-only, otherwise use the 2 puretones.

#10 Heaven/TQA ONLINE  

Heaven/TQA

    Quadrunner

  • 8,883 posts
  • Location:Baden-Württemberg, Germany

Posted Sun Mar 4, 2012 12:56 AM

that's sound good. Phaeron, but there is no compression yet?

and what do you mean by 2 scan lines?

#11 phaeron OFFLINE  

phaeron

    Stargunner

  • 1,173 posts
  • Location:USA

Posted Sun Mar 4, 2012 1:34 AM

that's sound good. Phaeron, but there is no compression yet?


No, not yet. This method can't be used directly with the run-length compression because the timers can roll over again and swap back before the second delay expires. For digitized sound samples, though, I'm not sure that the run-length encoding is advantageous anyway. It needs to exceed 2:1 to beat 4-bit encoding and andym00 is only seeing 1.5:1. It may be that the way to go is delta encoding with bit packing -- slow, but there's plenty of CPU available.

and what do you mean by 2 scan lines?


Playing a sample every scanline gets you 15.7KHz sample playback, since 1.79MHz / 114 = 15.7KHz. The program I posted plays a sample every two scanlines, or 7.8KHz.

#12 emkay OFFLINE  

emkay

    Quadrunner

  • 7,065 posts
  • What's up?
  • Location:Holy Grail ;)

Posted Sun Mar 4, 2012 2:21 AM

In addition to all the pulse sound stuff I've been doing some thinking about regular sample playback..
The idea is pretty simple, and surprisingly works very well..

It saves memory, and also saves CPU time, lots of CPU time in the case of higher sample rates..

Saves CPU by what? Packing/Depacking costs CPU time.

Instead of the conventional packed nybbles of samples, packing 2 4 bits samples into one byte, I had the idea of storing a length in one of the nybbles..

Now, you might think this is a bit silly, but you'd be wrong :)


It's just like FLAC works, just in a reduced "size" .

In a bunch of 15.6K 4bit samples, every single one of them compresses to less, not one is bigger..
In the below data, remember that the source size listed on each sample is as 8bit samples, so the regular 4bit version is half that size.. I've not been delicate about what I've given it, and it's a right old mixture..

Now, look at the numbers.. It's giving you some quite cool results..
The individual drums sounds compress amazingly well, 6:1 in some cases!!

Nothing special. Low sounds have less differences in high frequency ranges.

General, very noisy, speech does okay, in the region of 1.5:1

Seems so.

A recording of some SID music, 2:1

Hehe.... So SID music has less high sounds than avrage speech.


So there you have it.. A lovely simple way to get more samples in your games, with less CPU overhead :)


No, you won't get more samples in games with that solution. It's already hard to recognize the content, and 15kHz will get extremely jittered with a full gamescreen on.

Playback is dead simple, you just use the POKEY timers, or 6522/6 to set the delay after setting each sample..
So, the playback code is literally..

lax SampleData
and #$0f
ora #$10
sta AUDCx
lda LSR4,x
sta AUDFx
I'll knock up some tests today when I've got a few hours, but the playback scheme is exactly what I'm doing in the Pulse sounds stuff I've been working on..
Granted, this really only works well for one channel of sample playback, but there's means and ways to mix compressed sample data in realtime ;)

Anyway.. Thought I'd share this...
No doubt someone will be along in a second to piss on the bonfire..


Well, to stop a forest fire, because the bonfire is done wrong, and no other water is near...

Keeping Gr.0 on with 40 bytes + PM DMA, would be a good choice from scratch... for example.

#13 Rybags OFFLINE  

Rybags

    Quadrunner

  • 12,694 posts
  • Location:Australia

Posted Sun Mar 4, 2012 2:40 AM

Saves CPU by what? Packing/Depacking costs CPU time.


"same" sample values consecutively means the next timer IRQ is skipped, so potentially lots of time is saved.
Packing costs CPU - care factor zero. That's a worry when compiling resources, the end user doesn't cop any of it.

It's not "just like FLAC" - FLAC uses RLE to flag alike blocks and it's only one strategy it uses to reduce size.


Re the storing AUDF values. When a Timer IRQ starts, the next one is already ticking down.
AUDF changes don't take effect until the counter underflows again.
So, I suspect you'd need the repeat data to appear one sample early.

#14 roland p OFFLINE  

roland p

    Stargunner

  • 1,866 posts
  • $23
  • Location:The Netherlands

Posted Sun Mar 4, 2012 3:04 AM

It seems to me the MSX guys were using some sort of algorithm that would pick the most accurate values during compression.
I can't remember what it was called but I believe it reduced the error in the compressed waveform and had less hiss or bad harmonics during playback.
I'm pretty sure it was on http://www.msx.org and it was probably used for PCM compression, other than that I don't remember much.
<edit>
There is a distinct possibility that it is related to the logarithmic nature of the AY sound chip.

You meant this:http://www.msx.org/f...amples-poor-psg ?

#15 emkay OFFLINE  

emkay

    Quadrunner

  • 7,065 posts
  • What's up?
  • Location:Holy Grail ;)

Posted Sun Mar 4, 2012 3:05 AM

Alike what's been done.

If someone has a better solution than this one...



(Clean digis + fullscreen movement...)

I'd really say "wow"

#16 JamesD OFFLINE  

JamesD

    River Patroller

  • 4,787 posts

Posted Sun Mar 4, 2012 7:32 AM

It seems to me the MSX guys were using some sort of algorithm that would pick the most accurate values during compression.
I can't remember what it was called but I believe it reduced the error in the compressed waveform and had less hiss or bad harmonics during playback.
I'm pretty sure it was on http://www.msx.org and it was probably used for PCM compression, other than that I don't remember much.
<edit>
There is a distinct possibility that it is related to the logarithmic nature of the AY sound chip.

You meant this:http://www.msx.org/f...amples-poor-psg ?

I think that's one of many threads dealing with it. Searching the site with Viterbi will probably turn up any relevant discussions.

#17 Sheddy OFFLINE  

Sheddy

    Dragonstomper

  • 601 posts
  • Location:UK

Posted Sun Mar 4, 2012 7:57 AM

How do things fare with DLIs going on? - The incredibly frustrating NMI hardware bug ( http://www.atariage....interrupt%20nmi) meant I decided to use combined channels for precise IRQ timing to try avoid the darn NMIs 99.99% of the time in the end.
If the RLE can be combined more efficiently with 16-bit timer as well... :thumbsup:
Edit: I've assumed your using 64Hz mode though. If all sound was done in 15.??Hz mode that wouldn't be a problem...?

Edited by Sheddy, Sun Mar 4, 2012 8:03 AM.


#18 Rybags OFFLINE  

Rybags

    Quadrunner

  • 12,694 posts
  • Location:Australia

Posted Sun Mar 4, 2012 8:11 AM

That's still a barrier to progress.

In 15 KHz or 1.79 Mhz mode we have precise control over where the IRQ occurs but the high price of that is that your remaining audio possibilities become somewhat limited.

With a 64 KHz voice, 2 solutions come to mind:
1. Have a double DLI - if the first DLI triggers, temporarily disable DLI so the second one doesn't. VCOUNT checking needed to work out which DLI got through.
2. Have the AUDF value of the Timer change through 2 or more values such that it avoids the danger cycles that can mask a DLI. Possibly use a second timer routine with a little added delay to compensate for the shorter time delays.

Or option 3 - have the IRQ check VCount and perform what the DLI otherwise would have done, although that adds unwanted overhead.

Another option which can work in some instances, e.g. a screen kernal - double DLI, disable the IRQ and just perform the work the IRQ otherwise would have done. Although careful coding needed since the DLI might occur partway through the IRQ routine.

I've also come up with a better solution to the VBI headache which should allow long running VBIs with next to zero impact on timers.

#19 Bryan OFFLINE  

Bryan

    Quadrunner

  • 8,516 posts
  • Cruise Elroy = 4DB7
  • Location:Puriscal, Costa Rica

Posted Sun Mar 4, 2012 9:35 AM

It isn't that bad. Just make your IRQ's check NMI status and run the NMI code if it's not clear. Then clear it and run the IRQ code. As long as all your NMI code clears the status (instead of letting it expire), you'll always know when you have an unprocessed one.

#20 Rybags OFFLINE  

Rybags

    Quadrunner

  • 12,694 posts
  • Location:Australia

Posted Sun Mar 4, 2012 9:53 AM

Can't say I've tried that technique.

IIRC, NMIST bits stay latched until you clear them or the other NMI type resets it.
No great drama, just a STA NMIRES in the NMI to take care of it.

#21 emkay OFFLINE  

emkay

    Quadrunner

  • 7,065 posts
  • What's up?
  • Location:Holy Grail ;)

Posted Sun Mar 4, 2012 10:22 AM

That's still a barrier to progress.

In 15 KHz or 1.79 Mhz mode we have precise control over where the IRQ occurs but the high price of that is that your remaining audio possibilities become somewhat limited.


And what is preventing our holy ghost to use one channel at 1.79MHz and the three others at 64kHz clocking?
One channel digitals with a max. of 7500KHz and three channels for the "main" ?
As we've learned, one digi channel can build easily 3 other channel.... seems very limited ;)

#22 Rybags OFFLINE  

Rybags

    Quadrunner

  • 12,694 posts
  • Location:Australia

Posted Sun Mar 4, 2012 11:38 AM

1 channel @ 1.79 = an IRQ about every 259 cycles maximum. Barely over 2 scanlines.
Not possible in all situations, so 2 joined channels to give lower frequency = remaining audio limited.

#23 Bryan OFFLINE  

Bryan

    Quadrunner

  • 8,516 posts
  • Cruise Elroy = 4DB7
  • Location:Puriscal, Costa Rica

Posted Sun Mar 4, 2012 12:19 PM

It should be as simple as starting your IRQ handler by checking NMIST. If you get nothing then you continue. It's simplest if you don't use VBI's at all but launch your VB routine from the last DLI. Then you only have to check for bit 7. The NMI routine then needs to do a STA NMIRES. Actually, you could use the NMIST as a flag to return to the IRQ routine like this:

EDITED: Discovered a flaw in my original technique: We need to check NMIST twice! It might be even more effective to space the 1st and 2nd check out by one extra instruction. What we want to see is an NMI that wasn't cleared and is being ignored by the CPU.

IRQhandler
  pha			;make A available
  lda NMIST	   ;get DLI flag
  and NMIST	   ;we have to check NMIST twice in case it's serviced after the previous instruction
  bmi NMIhandler2
  txa
  pha
  tya
  pha
IRQhandler2
  ... (IRQ code)
  ...
  ... (end of IRQ code)
  pla
  tay
  pla
  tax
  pla
  rti

NMIhandler
  sta NMIRES  ;clear the NMI status
  pha
NMIhandler2
  txa
  pha
  tya
  pha
  ...  (NMI code)
  ...
  ...  (end of NMI code)
  asl NMIST		;Get DLI flag and clear it in one instruction
  bcs IRQhandler2   ;jump back to IRQ routine if we came from there
  pla
  tay
  pla
  tax
  pla
  rti


Seems nice & neat to me. You could also duplicate the NMI code inside the IRQ code and simply jump over it.

#24 emkay OFFLINE  

emkay

    Quadrunner

  • 7,065 posts
  • What's up?
  • Location:Holy Grail ;)

Posted Sun Mar 4, 2012 12:49 PM

1 channel @ 1.79 = an IRQ about every 259 cycles maximum. Barely over 2 scanlines.
Not possible in all situations, so 2 joined channels to give lower frequency = remaining audio limited.


So Sheddy's solution for Digis ingame still seems the best solution?

#25 emkay OFFLINE  

emkay

    Quadrunner

  • 7,065 posts
  • What's up?
  • Location:Holy Grail ;)

Posted Sun Mar 4, 2012 2:04 PM

What's about caluclating with the given cycles per frame and to use POKEY with 64kHz?
In the visible range, DLIs do the replaying of the samples, and with the last DLI, the POKEY timer gets activated to fill up the needed count of replay changes in the VBI time?




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users