Echo icon indicating copy to clipboard operation
Echo copied to clipboard

Consecutive calling of echo_play_direct()

Open rhargreaves opened this issue 4 years ago • 8 comments

Hi there! I'm trying to make use of Echo to power a real-time PSG audio application. I have a question regarding the correct use of echo_play_direct(). Consider the following code:

#include "echo.h"
#include <genesis.h>

const u8 instrument[]
    = { 0x00, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x08,
          0x08, 0x08, 0x08, 0x0A, 0x0A, 0x0C, 0x0C, 0xFE, 0x0F, 0xFF };

const void* const instrumentList[]
    = { instrument, instrument, instrument, instrument, instrument, instrument,
          instrument, instrument, instrument, NULL };

int main()
{
    u8 test_custom[] = { /* set inst 1 */ 0x48, 0x08,
        /* set psg vol*/ 0x28, 0x00,
        /* note on */ 0x08, 0x38, 0xff };

    u8 test_custom2[] = { /* set inst 2 */ 0x49, 0x08,
        /* set psg vol*/ 0x29, 0x00,
        /* note on */ 0x09, 0x04, 0xff };

    echo_init(instrumentList);
    echo_play_direct(test_custom);
    // VDP_waitVSync();
    echo_play_direct(test_custom2);

    while (TRUE) {
        VDP_waitVSync();
    }
    return 0;
}

I have found that I cannot call echo_play_direct() straight after a previous call to the same function. If I do so, you can hear a high-pitched whine, presumably caused by some corruption. I have to wait some X amount of time (hence the commented call to VDP_waitVSync().

How can I ensure that a consecutive call works correctly?

rhargreaves avatar Feb 29 '20 21:02 rhargreaves

I believe I can use echo_get_status() to know when it is safe to call echo_play_direct() again, but I think there is a bug in the code which causes it to not return the status correctly. I've opened #31 which I believe fixes it.

rhargreaves avatar Feb 29 '20 23:02 rhargreaves

Using echo_get_status is never going to help because echo_play_direct doesn't go through the command queue (which is also why it never becomes busy), rather there's a separate buffer for storing direct events that can hold up to 128 bytes before Echo flushes it the next tick.

So probably the routine is broken as heck :| (and maybe some race condition… really, Echo's communication with the 68000 needs to be redone from scratch at this point)

sikthehedgehog avatar Feb 29 '20 23:02 sikthehedgehog

Ah, I thought this bit of the code would be enough for echo_get_status to return DIRBUSY in the event a play direct event was sitting there waiting for processing:

    if (z80_ram[0x1F00] != 0xFF)
        status |= ECHO_STAT_DIRBUSY;

I was also considering speed up the tick timer to decrease the "wait" time of direct events. For my use case, I don't know ahead of time when I need to play a note or series of notes, so I'm relying on the direct functionality to provide a near-realtime experience. Updating Echo every VBlank isn't snappy enough, so I'd rather be able to at least poll something to know when it's safe to submit another direct event.

rhargreaves avatar Mar 01 '20 00:03 rhargreaves

Oh right, forgot that >_> (was thinking on the other busy flag) Though even then it still shouldn't matter as long as the buffer isn't overflown, and it doesn't look like it should here, so it's more likely that something is going awfully wrong. Assuming Echo is even initialized properly (nobody uses the C API because SGDK comes bundled with XGM instead…)

Also you could send a command that changes timer B (Tanglewood does this to get 50Hz), though honestly you make it sound like what you need is a custom driver with the 68000 driving everything. We really need more sound drivers (Echo is atrocious and I haven't deprecated it yet only because the alternative isn't much better)

sikthehedgehog avatar Mar 01 '20 01:03 sikthehedgehog

Ok thanks for the tips! I may well go with the 68k driving it all because I think that ultimately it will give the most responsive results. I'll have a play and see if I can tweak Echo enough to be useable for now. The EEF format has what I need so I might end up building something that is at least compatible with it.

rhargreaves avatar Mar 01 '20 14:03 rhargreaves

I think I fixed the issue? (didn't really try it though)

Yeah, the way status flags were handled was wrong, but it seems it was also recomputing the length of the direct buffer wrong (including the arguments but not the event opcodes themselves, whoops). Hopefully it works now?

sikthehedgehog avatar Apr 16 '20 04:04 sikthehedgehog

Looks like it works better! It doesn't make a high pitched whine, but the second note is dropped unless I wait for ECHO_STAT_DIRBUSY to clear:

    echo_play_direct(test_custom);
    while (echo_get_status() && ECHO_STAT_DIRBUSY)
        ;
    echo_play_direct(test_custom2);

But I think that's OK.

rhargreaves avatar Apr 22 '20 20:04 rhargreaves

Uuuuuuh I guess that's another thing to fix -_-'

sikthehedgehog avatar Apr 22 '20 23:04 sikthehedgehog