1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Dismiss Notice

Help on port Alien8 game (FMODex --> SDL_Mixer)

Discussion in 'General Discussions' started by Farox, Sep 4, 2015.

  1. Farox

    Farox Certified Guru

    Joined:
    Jan 8, 2009
    Messages:
    1,919
    Location:
    Italy
    Hi

    it's been some time that i want to port this game, the only thing that have blocked me is that (in)famous FMODex lib that the game use to produce sound/music.

    Alien8 is a game programmed by Ignacio Pérez Gil and available at Retrospec site http://retrospec.sgn.net/game/alien8

    The game is programmed in C using Allegro 4 and FMODex (for the audio part). I have searched on the web but i didn't have found an ARMv7 version compatible with Pandora.

    Now i managed to compile the game using SDL and SDL_Mixer instead of FMODex (with the help of the precious info from Sebt3 FMOD-->SDL previous port)....but... i need some more help as now the soundfx are working good..really good.... instead the music is absent (in part because the code that play music is not converted ).

    The game run fine, i have added Pandora buttons control...but i like to add music playing before release..

    So here is the Audio.c source

    //******************************************************************************
    // audio.c
    // Funciones genericas de sonido.
    // Por Ignacio Pérez Gil 17/03/2008.
    //******************************************************************************

    //******************************************************************************
    // Includes.
    //******************************************************************************
    #include
    #ifdef USE_FMOD
    #include
    #else
    #include
    #include
    #endif
    #include "audio.h"

    //******************************************************************************
    // Declaracion de estructuras de datos y variables globales.
    //******************************************************************************
    DATAFILE *f_msc = NULL;
    DATAFILE *f_audio = NULL;
    #ifdef USE_FMOD
    FMOD_SYSTEM *sistema = NULL;
    FMOD_SOUND *sm = NULL;
    FMOD_CHANNEL *canal_musica = NULL;
    #else
    Mix_Chunk *sm = NULL;
    Mix_Music *canal_musica = NULL;/// a test ..i don't know if right..farox
    #endif

    char musica_sonando=-1;
    const char *msc_fin=NULL;
    unsigned int long_msc_fin;
    unsigned char vol_son=0;
    float vol_mus=0;
    char rep_snd_onda(SAMPLE *onda, char sonido, char bucle);
    struct _voz // Estructura para almacenar los datos de las voces
    {char activa; // Indica si la voz este activa
    // 0-desactivada, 1-normal, 2-bucle, 3-no parar
    int v; // Voz
    } voz[16]={{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
    {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}};

    //******************************************************************************
    // Funcion iniciar_audio()
    // Inicializa el sistema de audio y carga los ficheros de sonidos y musica.
    //******************************************************************************
    void ini_audio(void)
    {
    reserve_voices(16,0);

    install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);

    #ifdef USE_FMOD
    FMOD_System_Create(&sistema);
    FMOD_System_Init(sistema, 16, FMOD_INIT_NORMAL, NULL);
    #else
    SDL_InitSubSystem(SDL_INIT_AUDIO);
    Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 2048);
    #endif

    f_msc = load_datafile("msc.dat");
    f_audio = load_datafile("snd.dat");
    }

    //******************************************************************************
    // Funcion finalizar_audio()
    // Descarga los ficheros de sonidos y musica.
    //******************************************************************************
    void fin_audio(void)
    {
    #ifdef USE_FMOD
    if(musica_sonando>=0) FMOD_Sound_Release(sm);
    FMOD_System_Close(sistema);
    FMOD_System_Release(sistema);
    #else
    if(musica_sonando>=0) Mix_HaltChannel(-1);
    Mix_CloseAudio();
    #endif
    unload_datafile(f_msc);
    unload_datafile(f_audio);
    }

    //******************************************************************************
    // Funcion reproducir_musica(...)
    // Inicia la reproduccion del fichero de musica n.
    //******************************************************************************
    void reproducir_musica(char n)
    {
    if(vol_mus)
    {
    #ifdef USE_FMOD
    FMOD_System_Update(sistema);
    #endif
    if(musica_sonando!=n && n>=0)
    {
    #ifdef USE_FMOD
    FMOD_CREATESOUNDEXINFO inf_tm;
    if(musica_sonando>=0) FMOD_Sound_Release(sm);
    #else
    if(musica_sonando>=0) Mix_HaltChannel(-1);
    #endif
    musica_sonando=n;
    #ifdef USE_FMOD
    memset(&inf_tm, 0, sizeof(FMOD_CREATESOUNDEXINFO));
    inf_tm.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
    #endif
    if(msc_fin)
    {
    #ifdef USE_FMOD
    inf_tm.length=long_msc_fin;
    FMOD_System_CreateStream(sistema, msc_fin, FMOD_HARDWARE | FMOD_LOOP_OFF | FMOD_OPENMEMORY, &inf_tm, &sm);
    #else
    //Mix_PlayMusic(n,-1);
    #endif
    }
    else
    {
    #ifdef USE_FMOD
    inf_tm.length=f_msc[n].size;
    FMOD_System_CreateStream(sistema, (const char *)(f_msc[n].dat), FMOD_HARDWARE | FMOD_LOOP_NORMAL | FMOD_OPENMEMORY, &inf_tm, &sm);
    #else
    Mix_PlayMusic(f_msc[n].dat,-1);
    #endif
    }
    #ifdef USE_FMOD
    FMOD_System_PlaySound(sistema, FMOD_CHANNEL_FREE, sm, 1, &canal_musica);
    FMOD_Channel_SetVolume(canal_musica,vol_mus);
    FMOD_Channel_SetPaused(canal_musica,0);
    #else
    //
    Mix_VolumeMusic(vol_mus);
    #endif
    }
    }
    }

    //******************************************************************************
    // Funcion modificar_volmus(...)
    // Modifica el volumen de la musica.
    //******************************************************************************
    void modificar_volmus(unsigned char vol)
    {
    if(vol<=100)
    {
    vol_mus=vol;
    vol_mus/=100;
    if(musica_sonando>=0)
    {
    if(!vol_mus)
    #ifdef USE_FMOD
    {
    FMOD_Channel_Stop(canal_musica);
    musica_sonando=-1;
    }
    else
    FMOD_Channel_SetVolume(canal_musica,vol_mus);
    #else
    {
    Mix_HaltChannel(-1);
    musica_sonando=-1;
    }
    else
    Mix_VolumeMusic(vol_mus);
    #endif
    }
    }
    }

    //******************************************************************************
    // Funcion parar_musica()
    // Detiene la musica que se este reproduciendo.
    //******************************************************************************
    void parar_musica(void)
    {
    #ifdef USE_FMOD
    if(musica_sonando>=0)
    {
    FMOD_Sound_Release(sm);
    musica_sonando=-1;
    }
    #else
    if(musica_sonando>=0)
    {
    Mix_HaltChannel(-1);
    musica_sonando=-1;
    }
    #endif
    msc_fin=NULL;
    }

    //******************************************************************************
    // Funcion musica_fin(...)
    // Obtiene un puntero a la musica del fin del juego, que hay que reproducir
    // una sola vez.
    //******************************************************************************
    void musica_fin(void *msc_fin_void, unsigned int long_msc_fin_void)
    {
    msc_fin=(const char *)msc_fin_void;
    long_msc_fin=long_msc_fin_void;
    }

    //******************************************************************************
    // Funcion reproducir_sonido(...)
    // Reproduce el sonido indicado, con la opcion de buclearlo.
    //******************************************************************************
    char reproducir_sonido(char sonido, char bucle)
    {
    return rep_snd_onda(NULL,sonido,bucle);
    }

    //******************************************************************************
    // Funcion reproducir_onda(...)
    // Reproduce el sample indicado, con la opcion de buclearlo.
    //******************************************************************************
    char reproducir_onda(SAMPLE *onda, char bucle)
    {
    return rep_snd_onda(onda,0,bucle);
    }

    //******************************************************************************
    // Funcion rep_snd_onda(...)
    // Reproduce el sample o el sonido indicado, con el modo indicado.
    //******************************************************************************
    char rep_snd_onda(SAMPLE *onda, char sonido, char modo)
    {
    char f = -1;

    if(!vol_son) return -1;

    do // Busco la primera voz que no se este usando
    {
    f++;
    if(voz[f].activa==1 || voz[f].activa==3)
    if(voice_get_position(voz[f].v) == -1)
    {
    deallocate_voice(voz[f].v);
    voz[f].activa = 0;
    }
    }while(voz[f].activa && f<15);

    if(voz[f].activa) return -1; // Las 16 voces estan siendo usadas.

    // Ahora f apunta a la voz que vamos a usar para el sonido.
    voz[f].v = allocate_voice(onda?onda:(SAMPLE *)f_audio[sonido].dat);
    if(voz[f].v == -1) return -1;
    voice_set_volume(voz[f].v, vol_son);
    voice_set_playmode(voz[f].v, modo<0?PLAYMODE_PLAY:modo);
    voice_start(voz[f].v);
    if(modo<0)
    voz[f].activa = 3;
    else
    voz[f].activa = (modo==PLAYMODE_PLAY?1:2);

    return f;
    }

    //******************************************************************************
    // Funcion pausar_sonidos()
    // Pone los sonidos bucleados en pausa, y para los demas.
    //******************************************************************************
    void pausar_sonidos(void)
    {
    char f;

    for(f=0;f<16;f++)
    if(voz[f].activa)
    {
    if(voz[f].activa==1 || voz[f].activa==3)
    {// Si la voz este parada o no este bucleada, aprovecho para liberarla.
    deallocate_voice(voz[f].v);
    voz[f].activa = 0;
    }
    else
    voice_stop(voz[f].v);
    }
    }

    //******************************************************************************
    // Funcion reanudar_sonidos()
    // Reanuda la reproduccion de los sonidos pausados.
    //******************************************************************************
    void reanudar_sonidos(void)
    {
    char f;

    for(f=0;f<16;f++)
    if(voz[f].activa)
    voice_start(voz[f].v);
    }

    //******************************************************************************
    // Funcion reiniciar_sonido(...)
    // Vuelve a colocar un sonido al principio.
    //******************************************************************************
    void reiniciar_sonido(char vz)
    {
    if(vz>=0)
    if(voz[vz].activa)
    voice_set_position(voz[vz].v, 0);
    }

    //******************************************************************************
    // Funcion modificar_volson(...)
    // Modifica el volumen maximo de los sonidos.
    //******************************************************************************
    void modificar_volson(unsigned char vol, char vz)
    {
    float fvol=vol*2.55;
    vol_son=(unsigned char)fvol;
    if(vz>=0) voice_set_volume(voz[vz].v, vol_son);
    }

    //******************************************************************************
    // Funcion detener_sonido(...)
    // Detiene un sonido determinado.
    //******************************************************************************
    void detener_sonido(char vz)
    {
    if(vz>=0)
    if(voz[vz].activa)
    {
    deallocate_voice(voz[vz].v);
    voz[vz].activa = 0;
    }
    }

    //******************************************************************************
    // Funcion detener_sonidos(char todos)
    // Detiene todos los sonidos que se estan reproduciendo.
    //******************************************************************************
    void detener_sonidos(char todos)
    {
    char f;
    for(f=0;f<16;f++)
    if(voz[f].activa>0 && (voz[f].activa<3 || todos))
    {
    deallocate_voice(voz[f].v);
    voz[f].activa = 0;
    }
    }

    Thanks
     
    Tags:
  2. ptitSeb

    ptitSeb Serial Porter

    Joined:
    Aug 15, 2012
    Messages:
    7,477
    Location:
    France, near Lyon
    Not easy to debug with just a piece of the code but a few remark already:

    For music, donc use Mix_HaltChannel(-1) that will stop all sound just to stop the music but Mix_HaltMusic()

    The parar_musica() function should be more like


    if(musica_sonando>0) {
    Mix_HaltMusic();
    if (music_sdlmix) Mix_FreeMusic(music_sdlmix);
    musica_sonando = -1;
    music_sdlmix = NULL;
    }

    (don't forget to use -fsigned-char to compile this one, as it looks like musica_sonando is char that can be negative)

    With a new variable


    Music_Mix* music_sdlmix = NULL;

    and for reproducir_musica(char n)

    the second part should be

    Code:
    if(msc_fin)
    {
     #ifdef USE_FMOD
     inf_tm.length=long_msc_fin;
     FMOD_System_CreateStream(sistema, msc_fin, FMOD_HARDWARE | FMOD_LOOP_OFF | FMOD_OPENMEMORY, &inf_tm, &sm);
     #else
     music_sdlmix = Mix_LoadMUS(msc_fin);
     if (music_sdlmix) Mix_Play(music_sdlmix, 1);
    #endif
    }
    else
    {
     #ifdef USE_FMOD
     inf_tm.length=f_msc[n].size;
     FMOD_System_CreateStream(sistema, (const char *)(f_msc[n].dat), FMOD_HARDWARE | FMOD_LOOP_NORMAL | FMOD_OPENMEMORY, &inf_tm, &sm);
     #else
     music_sdlmix = Mix_LoadMUS((const char *)(f_msc[n].dat));
     if (music_sdlmix) Mix_Play(music_sdlmix, -1);
     #endif
    }
    
     

    Also, there is some function to set the lenght of the music played (musica_fin) that is not handled here. But I guess that a start...
     
  3. Farox

    Farox Certified Guru

    Joined:
    Jan 8, 2009
    Messages:
    1,919
    Location:
    Italy
    Thanks seb :)

    I applied your suggested code...but music is not played :(

    If you have time and want to take a look i could upload the complete sources.
     
  4. ptitSeb

    ptitSeb Serial Porter

    Joined:
    Aug 15, 2012
    Messages:
    7,477
    Location:
    France, near Lyon
    You should also make sure SDL Mixer is initialized with the correct music loader, with something like


    Mix_Init(MIX_INIT_FLAC|MIX_INIT_MOD|MIX_INIT_MP3|MIX_INIT_OGG);

     
    Also, when Mix_LoadMUS(...), it would be intersting to check if new music_sdlmix is NULL or not, and printf the Mix_GetError() of the error.
     
    Last edited by a moderator: Sep 5, 2015
  5. Farox

    Farox Certified Guru

    Joined:
    Jan 8, 2009
    Messages:
    1,919
    Location:
    Italy
    Ok i added the Mix_init ( MIX_INIT_MOD|MIX_INIT_MP3|MIX_INIT_OGG) (i don't think i have FLAC music files) and nothing changed.

    Plus i added :

    if (!music_sdlmix) {

    printf ("PlayMusic error SDL_Mixer error: %s\n", Mix_GetError());

    };

    and i have

     
  6. ptitSeb

    ptitSeb Serial Porter

    Joined:
    Aug 15, 2012
    Messages:
    7,477
    Location:
    France, near Lyon
    Ok, so the issue is "just" that "f_msc[n].dat" or "msc_fin" is not the name of the file but something else. For the LoadMUS function, you need the filename. You have to dig out in the source code to find out how to get the correct name..
     
  7. Farox

    Farox Certified Guru

    Joined:
    Jan 8, 2009
    Messages:
    1,919
    Location:
    Italy
    I searched on the entire sources and the 95% of time reproducir_musica is called like this
     

    a few times like:

    or


    For me we need to concentrate on FMOD_System_CreateStream

    I found an interesting blog article about it

    https://katyscode.wordpress.com/2012/10/05/cutting-your-teeth-on-fmod-part-1-build-environment-initialization-and-playing-sounds/

    where it says:

    and the 3th part where it says: https://katyscode.wordpress.com/2013/01/15/cutting-your-teeth-on-fmod-part-3-embedding-sounds-in-your-application-as-resources/

    We need to implement this in SDL/SDL_Mixer but i don't know how to do it.
     
    Last edited by a moderator: Sep 5, 2015
  8. ptitSeb

    ptitSeb Serial Porter

    Joined:
    Aug 15, 2012
    Messages:
    7,477
    Location:
    France, near Lyon
    Ahhh, it's an FMOD_OPENMEMORY, I didn't checked that. We should probably use Mix_LoadMUS_RW instead then.
     
    with something like


    if(msc_fin)
    {
    #ifdef USE_FMOD
    inf_tm.length=long_msc_fin;
    FMOD_System_CreateStream(sistema, msc_fin, FMOD_HARDWARE | FMOD_LOOP_OFF | FMOD_OPENMEMORY, &inf_tm, &sm);
    #else
    SDL_RWops *rw = SDL_RWFromMem(msc_fin, long_msc_fin);
    music_sdlmix = Mix_LoadMUS_RW(rw);
    Mix_PlayMusic(music_sdlmix, 1);
    #endif
    }
    else
    {
    #ifdef USE_FMOD
    inf_tm.length=f_msc[n].size;
    FMOD_System_CreateStream(sistema, (const char *)(f_msc[n].dat), FMOD_HARDWARE | FMOD_LOOP_NORMAL | FMOD_OPENMEMORY, &inf_tm, &sm);
    #else
    SDL_RWops *rw = SDL_RWFromMem(f_msc[n].dat, f_msc[n].size);
    music_sdlmix = Mix_LoadMUS_RW(rw);
    Mix_PlayMusic(music_sdlmix, -1);
    #endif
    }
    (that rw thingy should probably be global and free properly when stopping music...)
     
    Last edited by a moderator: Sep 5, 2015
  9. Farox

    Farox Certified Guru

    Joined:
    Jan 8, 2009
    Messages:
    1,919
    Location:
    Italy
    Uhmm just added and tested but no music....and no error reported.
     
    Last edited by a moderator: Sep 5, 2015
  10. ptitSeb

    ptitSeb Serial Porter

    Joined:
    Aug 15, 2012
    Messages:
    7,477
    Location:
    France, near Lyon
    Did you move the rw variable global, just in case?

    Also, you should test if music_sdlmix is NULL or not after the Mix_LoadMUS_RW
     
    Last edited by a moderator: Sep 5, 2015
  11. Farox

    Farox Certified Guru

    Joined:
    Jan 8, 2009
    Messages:
    1,919
    Location:
    Italy
    rw moved global but nothing changed and no error.

    and now the function is


    if(msc_fin)
    {
    #ifdef USE_FMOD
    inf_tm.length=long_msc_fin;
    FMOD_System_CreateStream(sistema, msc_fin, FMOD_HARDWARE | FMOD_LOOP_OFF | FMOD_OPENMEMORY, &inf_tm, &sm);
    #else
    rw = SDL_RWFromMem(msc_fin, long_msc_fin);
    music_sdlmix = Mix_LoadMUS_RW(rw);

    if (!music_sdlmix) { printf ("PlayMusic error SDL_Mixer error: %s\n", Mix_GetError());}

    Mix_PlayMusic(music_sdlmix, 1);

    #endif
    }
    else
    {
    #ifdef USE_FMOD
    inf_tm.length=f_msc[n].size;
    FMOD_System_CreateStream(sistema, (const char *)(f_msc[n].dat), FMOD_HARDWARE | FMOD_LOOP_NORMAL | FMOD_OPENMEMORY, &inf_tm, &sm);
    #else
    rw = SDL_RWFromMem(f_msc[n].dat, f_msc[n].size);
    music_sdlmix = Mix_LoadMUS_RW(rw);

    if (!music_sdlmix) { printf ("PlayMusic error SDL_Mixer error: %s\n", Mix_GetError());}

    Mix_PlayMusic(music_sdlmix, -1);

    #endif
    }

    Thanks for your patience :)

    i tried to use Mix_LoadWAV_RW (rw,1) instead of Mix_LoadMUS_RW

    result..... i have no music and a message:

    "Unrecognised sound file tipe"
     
    Last edited by a moderator: Sep 6, 2015
  12. ptitSeb

    ptitSeb Serial Porter

    Joined:
    Aug 15, 2012
    Messages:
    7,477
    Location:
    France, near Lyon
    @Farox: on last thing: I think it's working, but just the volume is too low!
     
    You should put


    Mix_VolumeMusic(MIX_MAX_VOLUME*vol_mus);

    Because vol_mus is probably a float [0.0 ; 1.0f] where Mix_VolumeMusic needs an int [0 ; 128]. If it still doesn't work after that, I'll grab the source to try locally.
     
    Last edited by a moderator: Sep 6, 2015
  13. Farox

    Farox Certified Guru

    Joined:
    Jan 8, 2009
    Messages:
    1,919
    Location:
    Italy
    You are right :)   it's working... B)

    I'm very happy.

    Thanks a lot
     
    sebt3 likes this.
  14. ptitSeb

    ptitSeb Serial Porter

    Joined:
    Aug 15, 2012
    Messages:
    7,477
    Location:
    France, near Lyon
    Yeah ! :D
     
  15. ZXDunny

    ZXDunny Advanced Member

    Joined:
    Oct 12, 2010
    Messages:
    2,330
    This gives me the sudden yearning to convert from BASS to SDL_Mixer for PandaBAS. What's the CPU usage like in SDL_Mixer if it's not actually playing anything? Does it run any extra threads waiting for sound to play?

    D.
     
  16. Farox

    Farox Certified Guru

    Joined:
    Jan 8, 2009
    Messages:
    1,919
    Location:
    Italy
    Ok i build a pnd of this game...but is happening a odd thing...the game run, soundfx are playing good...but no music...again? :( (tested on fat sdcard)

    I rerun Codeblocks cli and try to run the game (not the pnd) and all is fine... :mellow:

    Shut down Codeblock and Pandora (just in case) Restart and open a new shell i set the LD_LIBRARY_PATH and run the game i have

    Now what is the cause??

    Sorry i can't help you on this subject.
     
    Last edited by a moderator: Sep 6, 2015
  17. ptitSeb

    ptitSeb Serial Porter

    Joined:
    Aug 15, 2012
    Messages:
    7,477
    Location:
    France, near Lyon
    Probably a missing dependency for mp3 playback, that is probably dynamicaly loaded (so copy_libs.sh or ldd doesn't see it). If you have ssh, just do some lsof to see what are the loaded libs once the game is launched.
     
    Last edited by a moderator: Sep 6, 2015
  18. Farox

    Farox Certified Guru

    Joined:
    Jan 8, 2009
    Messages:
    1,919
    Location:
    Italy
    The only libs that are missing (used ldd alien8) are

    libpulse.so.0

    and

    libpulsecommon-0.9.15.so

    that i added taken from your easyrpgplayer.pnd

    No ssh here...
     
  19. ptitSeb

    ptitSeb Serial Porter

    Joined:
    Aug 15, 2012
    Messages:
    7,477
    Location:
    France, near Lyon
    Try adding "libsmpeg-0.4.so.0".
     
  20. Farox

    Farox Certified Guru

    Joined:
    Jan 8, 2009
    Messages:
    1,919
    Location:
    Italy
    I compared the libs copied to the pnd lib folder with the one required by ldd.(excluding the one presents in nand)

    The only suspicious are: libasound.so.2

    the rest are:

    libdl

    librt

    libts

    libncurses

    libresolv
     

Share This Page

Loading...