unmo3 as a library?

Started by saga, 26 Oct '08 - 22:31

Ian @ un4seen

That's strange, as the library should be thread-safe. I quickly tried reproducing the problem with the following code, but it never happened.

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "unmo3.h"

void *buf;
unsigned len;

DWORD WINAPI threadproc(void *p)
{
while (1) {
void *buf0=buf;
unsigned len0=len;
int r=UNMO3_Decode(&buf0, &len0, 0);
printf("%d: unmo3=%d\n", (int)p, r);
if (!r) UNMO3_Free(buf0);
}
return 0;
}

int main(int argc, char **argv)
{
FILE *f;
if (argc<2) return 0;
f=fopen(argv[1], "rb");
if (!f) return 0;
len=filelength(fileno(f));
buf=malloc(len);
fread(buf, len, 1, f);
fclose(f);
CreateThread(0, 0, threadproc, (void*)0, 0, 0);
CreateThread(0, 0, threadproc, (void*)1, 0, 0);
getchar();
return 0;
}

Can you produce the problem with something that?

kode54

I am using version 2.4.0.3, and I am also calling LoadLibrary/GetProcAddress/FreeLibrary from each thread which unpacks an MO3. It was the original way I dealt with bundling the library in my component's directory before the player started adding the components' own directories to the DLL search path in turn while each component is being loaded. I suppose I could change that now.

Ian @ un4seen

Quote from: kode54 on 13 Dec '13 - 04:51I am using version 2.4.0.3

Ah, I think that would explain it. Thread-safety was added in 2.4.0.4. To ensure that the correct DLL version is loaded, you could check for the presence of the UNMO3_GetVersion function, which was also added in 2.4.0.4.

kode54

The problem isn't that someone is providing the wrong version, since I bundle my own copy. I just neglected to update the component. Let me take care of that right now.

Dr. Fiemost

Is this library supposed to support mp3 samples? I get mostly silent output from the mo3 I've tried.

saga

#30
You're right, MP3 sample support seems to be broken in the latest version indeed!
Here's an example file to demonstrate the problem.
I also noticed that a previous version of unmo3.dll (dated 2011) had a problem with this particular MO3 file; the belltree sample had some silence in the loop part of the sample. This doesn't happen in the latest XMPlay however, so it's probably already fixed.

Ian @ un4seen

Oops! There were some changes in the MP3 decoder, which the UNMO3 code hadn't been updated for yet. Here's an update that should sort it...

   www.un4seen.com/stuff/unmo3lib.zip

Let me know if it still gives you any trouble.

saga

Yup, that seems to fix the problem. Thanks for the quick fix!

Dr. Fiemost


saga

Since libopenmpt can use the unmo3 library as a "plug-in" to decode MO3 files, a couple of Android libopenmpt users have asked if this feature could be made on Android as well. Ian, would it be possible to port the library to Android as well?

CasualBoy

I am second to Saga proposal.
I would like to see Mo3 supported in my Android phone. ;D

Ian @ un4seen

Quote from: saga on  6 Feb '15 - 22:04Since libopenmpt can use the unmo3 library as a "plug-in" to decode MO3 files, a couple of Android libopenmpt users have asked if this feature could be made on Android as well. Ian, would it be possible to port the library to Android as well?

I'll look into building an Android version this week. Have you already implemented the dynamic library loading for Android in your code? I recall that is a bit tricky/messy because the app's "lib" folder isn't in Android's library search path, so you need to provide the full path, which is tricky/messy to get in native code.

Quote from: CasualBoy on  7 Feb '15 - 14:08I would like to see Mo3 supported in my Android phone. ;D

If you happen to just want to play MO3 files, that is possible with the BASS library.

saga

We didn't have a look yet, but I'll try to ask the people who're interested in the feature if they can help out. My own experience with Android is rather limited.

Ian @ un4seen

OK. An Android version of the unmo3 library has now been added...

   www.un4seen.com/stuff/unmo3lib.zip

It's untested so far, so let me know if you have any trouble with it. As I mentioned, loading it in native code may be tricky due to the issue of getting the full path. It'll probably be simplest to load it from Java first, and then the native code shouldn't need the full path to access it.

System.loadLibrary("unmo3");

haspor

#39
Hi,

I tested the library and it seems to be produce too much decoded data. Decode function returned success but the filesize became over 15MB (encoded size is 473484 bytes). The real decoded size is around 4.7MB. Also the filesize and decoded contents change if you decode the same data several times in a row. Tested on Android x86.

Ian @ un4seen

That's strange. I tried unmo3'ing a few files just now (on an ARMv7 device), and that seemed to go fine. In case the problem is something file-specific, please upload a MO3 file that you're having the problem with to have a look at here...

   ftp.un4seen.com/incoming/

haspor

Hi,

this is the file: /incoming/BeyondNetwork.mo3

haspor

#42
Hi,

I uploaded Android ARMv7 device decoded file of BeyondNetwork.mo3:

 * ftp.un4seen.com/incoming/BeyondNetwork_AndroidARM_decoded.it

The decoded filesize is at least correct.

I decoded the BeyondNetwork.mo3 with unmo3.exe and compared it to the ARM decoded file. The beginning seems to be almost correct but starting from offset 0x46da2 its just zeroes.

Ian @ un4seen

I was able to reproduce the problem in an x86 Android emulator. Here's an update that seems to be working properly...

   www.un4seen.com/stuff/unmo3lib.zip

Let me know if it's still not working properly there.

haspor

Hi,

I will test. I noticed the ARMv7 version is still the same. Could you provide some simple example how to get it working on ARMv7? Android.mk file + how to properly access the library functions.


Ian @ un4seen

In my tests, I was just reading the MO3 file to memory, passing that memory block to UNMO3_Decode, and then writing the returned memory block to a new file. That's all in native code, using fopen/etc for the file stuff.

haspor

Hi,

that's exactly what I did.

fopen, fread, decode and write back to a new file.

I suppose there is just one way to load the .so file and call its functions.

How is it even possible to fail then...I'll paste my code here later

haspor

#47
Hi,

tried the new version, little improvement. The decoded size is now correct but the file data is now equal to data I get when decoding with Android ARMv7a device -> at the beginning its ok but later it gets corrupted. I used the beyondnetwork.mo3 file.

How did you verify the decoded data is ok? Did you try to play the decoded file? Do verify that the data is equal to unmo3.exe decoded content please. Also check the offset i mentioned above.

Ian @ un4seen

Yep, the unmo3'd file seems to be fine here, ie. it sounds fine when played and there isn't the block of 0s that's in the file you uploaded. Do you get the block of 0s with other MO3 files too? I wonder if the problem is that the new file content hasn't been fully flushed to disk; are you calling fclose to close the file? If that's not it, you could check whether the memory block actually contains 0 before it is written. For example...

for (int a=0x46da2; a<length; a++) {
if (buffer[a]!=0) {
__android_log_print(ANDROID_LOG_DEBUG, "unmo3", "not 0 at %x", a);
break;
}
}

haspor

#49
Here is my Android.mk file:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := unmo3
LOCAL_SRC_FILES := unmo3lib/$(TARGET_ARCH_ABI)/libunmo3.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := unmo3unpacker
LOCAL_SRC_FILES := unmo3test.cpp
LOCAL_SHARED_LIBRARIES := unmo3
include $(BUILD_SHARED_LIBRARY)

Here's the C code that suppose to decode the .mo3 stuff:

#include <stdlib.h>
#include <stdio.h>
#include <jni.h>
#include "com_example_unmo3test_MainActivity.h"

extern "C" {
}

#define WINAPI
#include "unmo3.h"

JNIEXPORT jint JNICALL Java_com_example_unmo3test_MainActivity_load_1and_1unpack(JNIEnv *env, jobject obj)
{
    int result;
    unsigned int filesize = 0;
    int comp_size = 0;
    void * filedata;
    FILE * file = NULL;
    FILE * file2 = NULL;

    filedata = malloc(6000000);

    file = fopen("/mnt/sdcard/Music/BeyondNetwork.mo3", "rb");
    fseek(file, 0, SEEK_END);
    comp_size = ftell(file);
    fseek(file, 0, SEEK_SET);

    fread(filedata, 1, comp_size, file);
    result = UNMO3_Decode(&filedata, &filesize, 1); <----- 2nd param must be comp_size and 3rd set to 0
    file2 = fopen("/mnt/sdcard/Music/output.it", "wb");
    fwrite(filedata, 1, filesize, file2); <------ filesize has to be comp_size instead of filesize
    fclose(file2);
    fclose(file);
    UNMO3_Free(filedata);

    return 1;
}

That's it. Let me know what's wrong with it. Also before the offset 0x46da2 the data is also corrupted, random dword sized blocks are zero.

EDIT: the code problem is solved now. I marked the errors there.