AmigaPorts / ACE

Amiga C Engine
Mozilla Public License 2.0
154 stars 25 forks source link

Possibility to play music while systemUse ? #160

Open rveilleux opened 1 year ago

rveilleux commented 1 year ago

Currently in ACE, enabling system (for example when reading files) will "stop" the music from ptPlayer: If the music was already playing, it will start to "stutter" by looping the last buffer, up until SystemUnUse() is called.

Could it be possible to leave some interrupts running even when the System is in use? (I my case, I am trying to PTPLAYER_USE_VBL instead of CIAB-TimerA, but the same problem applies to both cases).

tehKaiN commented 1 year ago

Ideally, ACE should fully work with system enabled, but I really haven't got time to work on it. This needs writing os-friendly interrupt handlers/servers which would work when OS is enabled, switching back to raw interrupt handling functions when it's disabled.

It's a bit tricky to do in a "portable" way - VBCC and Bebbo's compilers allow declaring functions which expect their parameters in specific CPU registers, Bartman's suite not so much. Needs a bit of inline assembly trickery to properly handle input params and return value to handle those interrupts the way OS expects it to.

I remember doing one attempt but I can't see any branch with it. Perhaps I got stuck somewhere and haven't commited anything which would work in at least partial way. If you're willing to tackle it I can give you some hints and elaborate aforementioned stuff a bit more.

rveilleux commented 1 year ago

Yes I would be glad to take a look!

Rem.

On Oct 11, 2022, at 12:25 PM, KaiN @.***> wrote:

 Ideally, ACE should fully work with system enabled, but I really haven't got time to work on it. This needs writing os-friendly interrupt handlers/servers which would work when OS is enabled, switching back to raw interrupt handling functions when it's disabled.

It's a bit tricky to do in a "portable" way - VBCC and Bebbo's compilers allow declaring functions which expect their parameters in specific CPU registers, Bartman's suite not so much. Needs a bit of inline assembly trickery to properly handle input params and return value to handle those interrupts the way OS expects it to.

I remember doing one attempt but I can't see any branch with it. Perhaps I got stuck somewhere and haven't commited anything which would work in at least partial way. If you're willing to tackle it I can give you some hints and elaborate aforementioned stuff a bit more.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.

tehKaiN commented 1 year ago

Okay, so basically it goes like this:

I hope that this wall of text won't spook you out of this. ;) The problem is quite elaborate and it won't be an easy one-hour fix, but it's almost certainly doable with a bit of persistence.

rveilleux commented 1 year ago

Thank you for your explanation: I was able to hack by using AddIntServer(INTB_VERTB, &rvInt3Server); and hacking the ptPlayer to only use vblank (instead of using both vblank + CIA_B_timer_B. Unsure about the exact purpose of this timer B, since the music appears to play fine. In the vblank interrupt I simply do the three steps: intPlay(pCustom); intDmaOn(pCustom); intSetRep(pCustom); But perhaps it is not fully compatible with all use-case. According to my tests, using my OS-friendly IntServer allows my music to continue to play while reading from disk (or harddrive).

tehKaiN commented 1 year ago

Hi,

I've once asked Frank Wille, the author original asm version of ptplayer, about that:

What I wanted to ask you is the nature of timer interrupt B - it's used for dmaon / setrep and it's configured as one-shot to be triggered after 496 ticks. My question is - where does this exact delay come from? Why not launch that code instantly but wait for ~11 scanlines? I tried to look it up on the net but I've only found that P61 replayer uses this delay too. I'm really confused by that - it seems to be one of those "so trivial that it doesn't need explanation" things but I cant figure it out. 😉

The response was:

wanted to ask you is the nature of timer interrupt B - it's used for dmaon / setrep and it's configured as one-shot to be triggered after 496 ticks. My question is - where does this exact delay come from?

A raster line has a DMA slot for each audio channel. Depending on the current AUDxPER of the audio channel some of these DMA slots are not used. For example: when playing a very high frequency the DMA might have to read a new sample every line. But when playing a very low frequency there might be 10 or more raster lines without DMA activity for this channel.

The problem is that changes like DMA-on/off, or setting a new sample-pointer in AUDxLC, are only recognized by Paula when the next sample data are read from Chip-RAM.

So we have to be prepared for the worst case, which means that up to 11 raster lines may pass without DMA-activity (reading a new sample), when playing the lowest note from the lowest Protracker octave.

You could also solve that with audio interrupts, like the audio.device does. But most players just use a constant delay - and the worst players even busy-wait. 😉

Why not launch that code instantly but wait for ~11 scanlines?

Does not work. You have to cut the old sample before starting the new one.

When the player routine sees a new note/sample for a channel it will immediately set the new period and sample pointer. But we don't want to wait until the current instrument has played until the end (some instruments are long), but cut it immediately. So we will disable DMA for the channel at this point.

To make Paula see that DMA-Off we have to wait until the next DMA slot. When we reenable DMA before that point, then it remains unnoticed. This is the reason we have to wait for at least 496 ticks before enabling DMA for the new note/instrument.

Then you have to wait for the next DMA slot again, before you can change the sample pointer and length for the repeat. Otherwise Paula would play the repeat-part immediately.

I guess I should include some of that knowledge inside the code so that this design choice is better documented. So I guess the code works for you because your MOD's instruments have quite high sample rate and the natural time spent on code execution does its work. To make this work properly we'd need to have that CIA interrupt, sadly.

rveilleux commented 1 year ago

Hi KaiN,

According to https://aminet.net/package/mus/play/ptplayer, you are using 576 ticks in your code so it would appear you are using ptplayer at least from version 6.0. But in ptplayer.h, a comment says: // Protracker V2.3B Playroutine Version 5.1 Do you know what version your C source code is based off?

Thank you very much! (Indeed you are right, omitting the timerB is messing up with the playback of many MODs: it will have to revert some of my hacks)

tehKaiN commented 1 year ago

it's based around 5.1 with the only 6.0 change being the 576 tick thingy of which I got tip about from the original author before 6.0 released. ;) There's an ACE branch which has changes up to version 6.2, but it's not tested yet and most probably is bugged and definitely breaks vblank thingy at the moment. When I get back from my leave I'll continue working on it.

rveilleux commented 1 year ago

Hi KaiN,

I think I've fixed at least 3 bugs so far, I will present them to you in pull requests, since I am not 100% sure because I don't have access to ptplayer.asm from 5.1. I only found 6.0 on aminet. (Oops: I just found your repo here https://github.com/tehKaiN/ptplayer while typing this message .. This might come in very handy!) So far it is making my test module sound much better. There is most definitely at least another issue because I'm hearing odd low frequency noise, I'll look into it deeper a bit later. It is really a big undertaking you've accomplished by "uncompiling" ASM back into C! Props for that :)

On Sun, Oct 16, 2022 at 3:36 AM KaiN @.***> wrote:

it's based around 5.1 with the only 6.0 change being the 576 tick thingy of which I got tip about from the original author before 6.0 released. ;) There's an ACE branch which has changes up to version 6.2, but it's not tested yet and most probably is bugged and definitely breaks vblank thingy at the moment. When I get back from my leave I'll continue working on it.

— Reply to this email directly, view it on GitHub https://github.com/AmigaPorts/ACE/issues/160#issuecomment-1279912609, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABTB7KPWEQHKX6BSXCRUQE3WDOV53ANCNFSM6AAAAAARCOQMCU . You are receiving this because you authored the thread.Message ID: @.***>

tehKaiN commented 1 year ago

it's great to hear that!

Unfortunately my asm skills aren't that good and it was quite painful for me to do in the first place. The reason for the translation is that I wanted to have more control over the source code by having it easier to read, but it kinda backfired - now it's riddled with bugs due to inaccurate asm-C translation, but I guess we'll eventually get to the point of it being stable.

It's quite probable that my access to network connection will be limited next week, but I'll try to watch out for your pull requests and accept them as they go.