Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consecutive calling of echo_play_direct() #30

Open
rhargreaves opened this issue Feb 29, 2020 · 8 comments
Open

Consecutive calling of echo_play_direct() #30

rhargreaves opened this issue Feb 29, 2020 · 8 comments

Comments

@rhargreaves
Copy link

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
Copy link
Author

rhargreaves commented Feb 29, 2020

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.

@sikthehedgehog
Copy link
Owner

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)

@rhargreaves
Copy link
Author

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.

@sikthehedgehog
Copy link
Owner

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)

@rhargreaves
Copy link
Author

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.

@sikthehedgehog
Copy link
Owner

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?

@rhargreaves
Copy link
Author

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.

@sikthehedgehog
Copy link
Owner

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants