billthefarmer / mididriver

Android midi driver using Sonivox EAS library
176 stars 52 forks source link

Costum soundfont is possible? #21

Closed nnttoo closed 8 years ago

nnttoo commented 8 years ago

thank you for sharing can i load costum soundfont (how)?

billthefarmer commented 8 years ago

I don't thinks so. The soundfonts are built into the source code of the synthesizer.

nnttoo commented 8 years ago

i found this code in eas.h

EAS_LoadDLSCollection()

but i don understand c language,,

billthefarmer commented 8 years ago

I hadn't noticed that, it's not in the docs at https://github.com/android/platform_external_sonivox/tree/master/docs. To test it, you need to add some code to MidiDriver.java:

    public  native boolean loadDLS(String path);

with the other native methods. and add three bits of code to midi.cpp:

EAS_PUBLIC EAS_RESULT (*pEAS_LoadDLSCollection) (EAS_DATA_HANDLE pEASData,
                         EAS_HANDLE streamHandle,
                         EAS_FILE_LOCATOR locator);
// ...
// midi load dls
jboolean
Java_org_billthefarmer_mididriver_MidiDriver_loadDLS(JNIEnv *env,
                             jobject obj,
                             jstring jpath)
{
    jboolean isCopy;
    EAS_RESULT result;
    EAS_FILE file;

    if (pEASData == NULL || midiHandle == NULL)
    return JNI_FALSE;

    file.path = env->GetStringUTFChars(jpath, &isCopy);
    file.fd = 0;

    result = pEAS_LoadDLSCollection(pEASData, midiHandle, &file);

    env->ReleaseStringUTFChars(jpath, file.path);

    if (result != EAS_SUCCESS)
    return JNI_FALSE;

    return JNI_TRUE;
}
// ...
    pEAS_LoadDLSCollection = (EAS_PUBLIC EAS_RESULT (*)
                  (EAS_DATA_HANDLE pEASData,
                   EAS_HANDLE streamHandle,
                   EAS_FILE_LOCATOR locator))
        dlsym(libHandler, "EAS_LoadDLSCollection");
    if (!pEAS_LoadDLSCollection)
    {
        env->ThrowNew(linkageErrorClass,
              "EAS_LoadDLSCollection resolution failed");
        return -1;
    }

The last bit of code goes on the end of `JNI_OnLoad()``. This code builds OK, but I have no idea if it will work. I found this: https://github.com/scummvm/scummvm/blob/master/audio/softsynth/eas.cpp when I was researching this driver. If has a bit of code in it than implies it might not work:

    // TODO doesn't seem to work with midi streams?
    if (ConfMan.hasKey("soundfont")) {
        const Common::String dls = ConfMan.get("soundfont");

        debug("loading DLS file '%s'", dls.c_str());

        EASFile f;
        memset(&f, 0, sizeof(EASFile));
        f.path = dls.c_str();

        res = _loadDLSFunc(_EASHandle, 0, &f);
        if (res)
            warning("error loading DLS file '%s': %d", dls.c_str(), res);
        else
            debug("DLS file loaded");
    }
nnttoo commented 8 years ago

I have tried to compile .so file, but still cannot, maybe I should learn it later, for now can you give .so file that has been compiled with the code above?

billthefarmer commented 8 years ago

OK libmidi.zip

nnttoo commented 8 years ago

unfortunately it does not work, but thanks for your help.

java.lang.UnsatisfiedLinkError: Native method not found: org.billthefarmer.mididriver.MidiDriver.loadDLS:(Ljava/lang/String;)Z

billthefarmer commented 8 years ago

The DLS load code is in branch DLS on here. https://github.com/billthefarmer/mididriver/tree/DLS

nnttoo commented 8 years ago

i have tried this branch, no error, but loadDLS always return false,,
maybe you are right, it is not possible for now?

billthefarmer commented 8 years ago

I have updated the code because the EAS_LoadDLSCollection function here https://github.com/android/platform_external_sonivox/blob/master/arm-wt-22k/lib_src/eas_public.c does two different things.

EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_FILE_LOCATOR locator)
{
    EAS_FILE_HANDLE fileHandle;
    EAS_RESULT result;
    EAS_DLSLIB_HANDLE pDLS;

    if (pStream != NULL)
    {
        if (!EAS_StreamReady(pEASData, pStream))
            return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
    }

    /* open the file */
    if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS)
        return result;

    /* parse the file */
    result = DLSParser(pEASData->hwInstData, fileHandle, 0, &pDLS);
    EAS_HWCloseFile(pEASData->hwInstData, fileHandle);

    if (result == EAS_SUCCESS)
    {
        /* if a stream pStream is specified, point it to the DLS collection */
        if (pStream)
            result = EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_DLS_COLLECTION, (EAS_I32) pDLS);

        /* global DLS load */
        else
            result = VMSetGlobalDLSLib(pEASData, pDLS);
    }

    return result;
}

If the stream is null it does a global DLS load, so I have put another parameter in to do a global load to see if that might work.

 public native boolean loadDLS(String path, boolean global);
billthefarmer commented 8 years ago

DLS .aar files for Cody Eddings... MidiDriver-DLS.aar.zip

CodyEddings commented 8 years ago

I've been unable to load in my custom DLS. So far, i've tried:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        // Instantiate the driver.
        midiDriver = new MidiDriver();
        // Set the listener.
        midiDriver.setOnMidiStartListener(this);

       boolean test = false;
        String path = "android.resource://" + getPackageName() + "/" + R.raw.fury;
        midiDriver.loadDLS(path,test);
        if (test) {
            Toast.makeText(this, "DLS file loaded", Toast.LENGTH_SHORT);
        }
    }

It seems that "test" is always false. I've verified that I have a DLS file (fury.dls) located in the raw directory of my application. Am I using a correct implementation of loadDLS(string path, boolean global) or is it intended to be used differently?

billthefarmer commented 8 years ago

If you look at the comments above you can see that I put in the boolean parameter to determine whether to do a global load or not. I included an extract from the relevant code in the comment.

    if (global)
    result = pEAS_LoadDLSCollection(pEASData, NULL, &file);

    else
    result = pEAS_LoadDLSCollection(pEASData, midiHandle, &file);

    env->ReleaseStringUTFChars(jpath, file.path);

    if (result != EAS_SUCCESS)
    {
    LOG_E(LOG_TAG, "Load DLS collection failed: %ld", result);
    return JNI_FALSE;
    }

return JNI_TRUE;

The return value is the success/fail notification, the boolean global determines what bit of code gets executed. I suggest you try it both ways. I suggest you do...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        // Instantiate the driver.
        midiDriver = new MidiDriver();
        // Set the listener.
        midiDriver.setOnMidiStartListener(this);

       boolean success = false;
       boolean test = false;
        String path = "android.resource://" + getPackageName() + "/" + R.raw.fury;
        success = midiDriver.loadDLS(path,test);
        if (success) {
            Toast.makeText(this, "DLS file loaded (global)", Toast.LENGTH_SHORT);
        }
       success = false;
       test = true;
        String path = "android.resource://" + getPackageName() + "/" + R.raw.fury;
        success = midiDriver.loadDLS(path,test);
        if (success) {
            Toast.makeText(this, "DLS file loaded (not global)", Toast.LENGTH_SHORT);
        }
    }
CodyEddings commented 8 years ago

Unforunately, midiDriver.loadDLS(path,test); returned false whether it was run with true or false for the input global parmeter (called test). Are we out of options?

loki666 commented 8 years ago

Using a file path in res/raw will never works since EAS will try to fopen() the path. You need a file path that point to a file on the filesystem (ie: in /sdcard/). Even like that I couldn't make it work. At best, it load the .DLS file OK, but it doesn't seem to actually use it.

billthefarmer commented 7 years ago

There is a further complication to this, around the time of Android 5.01, they changed the API for EAS_HWOpenFile(), and EAS_FILE_LOCATOR to use callbacks:

Author: Marco Nelissen <marcone@google.com>
Date:   Tue Dec 16 12:45:05 2014 -0800

    Use callbacks for I/O

    Instead of having the Sonivox engine directly open the file and
    use stdio to read from it, use caller-provided callbacks.

My code uses the old version. Now I have updated the driver to include the latest EAS Sonivox sources it's definitely not going to work. The driver doesn't support file IO, so it's not affected. If anyone is still interested in this, I could revert eas_hostmm.c and eas_types.h to the old version. I noticed a revision to DLS code in the commit history:

    Author: Eric Laurent <elaurent@google.com>
    Date:   Thu May 14 09:10:40 2015 -0700

    DLS parser: fix wave pool size check.

    Bug: 21132860.
slesinger commented 7 years ago

I'm interested to make it work. The default guitar sound is far from being usable. Thank you.

billthefarmer commented 7 years ago

You are welcome to fork the driver and have a go. The DLS branch contains the code I wrote to test and includes reverting eas_hostmm.c and eas_types.h to the old version as above.

bmaupin commented 2 years ago

i found this code in eas.h

EAS_LoadDLSCollection()

but i don understand c language,,

It looks like EAS_LoadDLSCollection was removed with this commit message:

Remove unused code from midi engine

(https://android.googlesource.com/platform/external/sonivox/+/af41595537b044618234fe7dd9ebfcc652de1576%5E%21/#F1)

That might explain why it never worked :man_shrugging:

billthefarmer commented 2 years ago

They removed a lot of unused by them code. I put the bits I use back in separately, but the DLS code was still in there when I was attempting to get it to work.

M-HT commented 1 year ago

If anyone is still interested in this, I recently made some changes in this fork of Sonivox EAS library to fix loading/using DLS files (at least some of them) using EAS_LoadDLSCollection. It shouldn't be difficult to adapt the changes to this project. The relevant commits are:

valentinev-celadon commented 6 months ago

@billthefarmer Hi boss. Will there be updates for connecting DLS?

billthefarmer commented 6 months ago

See the README, #43.