Page 1 of 15 1234567891011 ... LastLast
Results 1 to 10 of 150

Thread: Llama's and Intuition's Techie Thread

  1. #1
    FLAC TheLlama's Avatar
    Join Date
    Jul 2004
    Location
    All over the world
    Posts
    970

    Llama's and Intuition's Techie Thread

    This thread is for Intuitionsys, me, and others to share technical information while we design our frontends. We will be discussing design decisions, APIs, and various things. Instead of having 10276 random threads we just want to consolidate all the information on this thread.

    First topic of discussion: FMOD.

    This thread is open to everyone.

  2. #2
    Variable Bitrate intuitionsys's Avatar
    Join Date
    Jul 2005
    Location
    Northern Virginia
    Posts
    293
    Quote Originally Posted by TheLlama
    First topic of discussion: FMOD.
    Good idea Llama. I haven't dug deep enough into FMOD yet to mention anything terribly helpful, but I should mention what it will be replacing in Silverwolf and what it will make unnecessary:

    mpg123 will be gone for good along with the xinetd entries and aRts wrapper. This combo works surprisingly well but FMOD is a better solution especially for eventually adding other file types beyond mp3.

    aRts - It was a good idea a while ago but it's a CPU pig and it's latency gets annoying after a while.

    KDE desktop - made aRts and the spectrum analyzer easier to implement but there's alot of unneccessary crap in the background even with everything disabled.

    What I need to do with FMOD is replace mpg123 (and the associated aRts wrapper and xinetd handling for remote control and monitoring). I also need to grab FFT spectrum info for the spectrum analyzer (and doubtless other visualizations later), as well as monitor the song position. I know all this is doable I just have to get at it. The FMOD API docs suck a bit though

    btw I recorded a bunch of videos with the video camera of the system in action and then realized when I brought it in and played it back that the camera was positioned too low and the bottom 10% of the screen was cut off so I'll have to try again tomorrow. The MPEGs will hopefully be available by the end of the week. I know I said that before but I'll really try this time
    Silverwolf 2 is dead.
    Silverwolf 3...?

  3. #3
    FLAC TheLlama's Avatar
    Join Date
    Jul 2004
    Location
    All over the world
    Posts
    970
    Ok, here is some old FMOD code I dug up. I'm going to try and condense it.

    Code:
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <termios.h>
    
    
    #include "/usr/include/fmod.h"
    #include "/usr/include/fmod_errors.h"
    
    int channel = -1;
    
    FSOUND_STREAM	*stream;
    FSOUND_SAMPLE	*sample;
    
    // Called when a stream ends. You'll want to Change 
    // this function to start playing the next track.
    signed char F_CALLBACKAPI end_callback(FSOUND_STREAM *stream, void *buff, int len, void *param)
    {
        if (buff) 	// Sync Point (ignore?)
        {
            printf("\nSYNCHPOINT : \"%s\"\n", buff);
        }
        else 	// Stream Ended
        {
            printf("\nSTREAM ENDED!!\n");
        }
    
        return 1;
    }
    
    // Initializes FMOD
    int init_fmod() 	// Currently Fixed to ALSA and first device
    {
        // -- Init FMOD --
        
        if (FSOUND_GetVersion() < FMOD_VERSION)
        {
    	fprintf(stderr, "FMOD Error: Incorrect FMOD version.\n");
    	return 0;
        }
    
        FSOUND_SetOutput(FSOUND_OUTPUT_ALSA);
    
        if( FSOUND_GetNumDrivers() < 1 )
        {
    	fprintf(stderr, "FMOD Error: Could not find suitable audio driver.\n");
    	return 0;
        }
    
        printf("FMOD: Using %s \n", FSOUND_GetDriverName(0) );
        
        FSOUND_SetDriver(0);
    
        if( !FSOUND_Init(44100, 32, 0) )
        {
    	fprintf(stderr, "FMOD Error: %s\n", FMOD_ErrorString(FSOUND_GetError()) );
    	FSOUND_Close();
    	return 0;
        }
    
    	// Setup Analyser   
    	FSOUND_DSPUNIT *dspSpec = FSOUND_DSP_GetFFTUnit();
    	FSOUND_DSP_SetActive(dspSpec, true);
    
        return 1;
    }
    
    // Start playing the file at the path, filename.
    int start_playing( char *filename)
    {
        if(!strlen(filename))
        	return 0;
    	
        stream = FSOUND_Stream_Open(filename, FSOUND_NORMAL | FSOUND_MPEGACCURATE, 0, 0);
    
        if( !stream )
        {
    	fprintf(stderr, "FMOD Error: %s\n", FMOD_ErrorString(FSOUND_GetError()) );
    	FSOUND_Close();
    	return 0;
        }
    
        // this function may be better in init_fmod()
        FSOUND_Stream_SetEndCallback(stream, EndCallback, 0);
    
        sample = FSOUND_Stream_GetSample(stream);
    
        channel = FSOUND_Stream_PlayEx(FSOUND_FREE, stream, NULL, 1);
        printf("FMOD: Playing on channel: %d\n", channel);
        FSOUND_SetPaused(channel, 0);
    
        return 1;
    }
    
    // Stops the track. Call it by your stop button
    int stop_playing()
    {
        return  FSOUND_Stream_Stop(stream);
    }
    
    // sets the paused status of the stream. 0 unpauses
    // and 1 pauses.  The stream must be playing first.
    void set_paused(signed char p)
    {
        FSOUND_SetPaused(channel, p);
    }
    
    // gets the status of paused. a simple toggle can be written as:
    //   set_paused(!get_paused());
    signed char get_paused()
    {
        return FSOUND_GetPaused(channel);
    }
    
    // My very old (stripped) main, this demonstrates one way you 
    // can have the analyser displayed. Depending on the structure 
    // of your program, what toolkits you are using, etc.. this will 
    // vary greatly.
    int main( int argc, char *argv[])
    {
        int key;
        int cnt=0;
    
    	float *spec;
    
        char buf[100];
        char buf2[100];
    	
        // Init FMOD
        if(!InitFMOD())
        {
    	    printf("FMOD Initialization failed.\n");
    	    return 1;
        }
        
        if(argc > 0)
        {
            start_playing(argv[1]);
        }
        else
        {
        	printf("usage:\ndumbdemo filename\n");
            return 1;
        }
    
        // Here you either want to have some sort of loop that is
        // on a timer and can accept input (using select of some termios)
        // Or, you can stick it in a thread (which is what I do now)
    
        do
        {
            // Handle input etc...
    
    	    switch( keyThatWasJustPressed )
    	    {
    	    case 'p':
    		set_paused( !get_paused() );
    		break;
    	    case '[':
    		FSOUND_Stream_SetTime(stream, FSOUND_Stream_GetTime(stream) - 2000);
    		break;
    	    
    	    case ']':
    		FSOUND_Stream_SetTime(stream, FSOUND_Stream_GetTime(stream) + 2000);
    		break;
    
    	    case 's':
    		stop_playing();
    		break;
    
    	    }
    	}
    
    	// 
    	// UPDATE DATA...
    	//
    	
    	// Write Analyser Data	
    	draw_spectrum_analyzer( FSOUND_DSP_GetSpectrum() );
    
    	// Draw out time 
    	sprintf(buf,"[%02d:%02d/%02d:%02d]",
                FSOUND_Stream_GetTime(stream) / 1000 / 60, 
    	    FSOUND_Stream_GetTime(stream) / 1000 % 60, 
    	    FSOUND_Stream_GetLengthMs(stream) / 1000 / 60, 
    	    FSOUND_Stream_GetLengthMs(stream) / 1000 % 60);
    	draw_some_text(buf,1);
    
        } while ( some_crap() );
    
        // This is the end of the loop or code that should go in a thread
    
        FSOUND_Close();
    
        return 0;
    }
    
    // custom analyzer drawing.  You will want to add a falloff 
    // and possibly peaks to make it look nice. You may also want
    // to split the setting of spectrum data and the actual drawing.
    // However, this code actually does a bit of work. If you look at the 
    // original spectrum data, it is much more concentrated on the low
    // frequencies. So, we need to sample the data exponentially.  The
    // analyzer also looks rather "weak" it helps if we scale it also. The 
    // constants I use to do this have been derived over time and works
    // well for 40 bands. I imagine one could find the regression of my
    // scale arrays and derive their own sets. 
    
    void draw_spectrum_analyzer(float *data)
    {
            const int spacing = 5;	
            const int width = 4;
            const int height = 50;
    
            const int sensitivity = 0.8;
    
    	const float equalizerScale[40] = {9, 10, 11, 12, 12, 13, 13, 17, 20, 22, 23, 26, 28, 32, 36, 44, 52, 56, 60, 65, 70, 80, 90, 100, 110, 125, 140, 140, 140, 140, 150, 150, 150, 250, 150, 150, 150, 160, 160, 160}; 			
            const int analyserScale[40] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 16, 19, 22, 25, 31, 38, 48, 58, 68, 78, 97, 116, 136, 156, 175, 195, 215, 235, 256, 274, 293, 313, 332, 352, 371, 391, 410, 430};
    
            float val;
    
            for(int i=0; i< 40; i++)
    	{
                 // Accumulate the band
                 val = 0;
                 // Sample all the values between this band and the next.
                 for(int i = analyserScale[x]; i < analyserScale[x+1]; i++)
                 {
                     val += data[i] * equalizerScale[x];
                 }
                 // Average it out
                 val /= (analyserScale[x+1]-analyserScale[x]);
              
                 // There was a point when I also scaled on an inverse ln 
                 // (an e^x) scale.
              
                 val *= sensitivity;
    
    	     draw_some_rect(i*spacing, ((1.0 - (value/10.0)) * height) , (i*width), height);
    	}
    }
    The code won't run until you fill in a few blanks. I stripped it down to the essence so it is a pretty minimal C program - not a good full-featured player. Also, FMOD Ex provides C++ bindings that may be easier to work with. It doesn't matter to me since I encapsulate whatever Sound API I'm using behind a class.

  4. #4
    Variable Bitrate intuitionsys's Avatar
    Join Date
    Jul 2005
    Location
    Northern Virginia
    Posts
    293
    Thanks for the post. I plan on using FMOD Ex though and the API is a bit different as you mentioned, but I'll probably find some nuggets I can use in there
    Silverwolf 2 is dead.
    Silverwolf 3...?

  5. #5
    FLAC TheLlama's Avatar
    Join Date
    Jul 2004
    Location
    All over the world
    Posts
    970
    Quote Originally Posted by intuitionsys
    Thanks for the post. I plan on using FMOD Ex though and the API is a bit different as you mentioned, but I'll probably find some nuggets I can use in there
    Yeah, I'm planning on switching to FMOD Ex too. I guess you will still find my code for tweaking the Spectrum data useful.

  6. #6
    Variable Bitrate intuitionsys's Avatar
    Join Date
    Jul 2005
    Location
    Northern Virginia
    Posts
    293
    I've gotten some more FMOD code working now. Nothing ready for primetime yet but I've gotten a handle on the position pointers and spectrum arrays I need. Depending on how much life gets in the way I could have it ready for Silverwolf 1.3 in say a month...

    With such a major change maybe I should just bump it up to 2.0

    btw there's nothing wrong with the FMOD API docs. It was something else I was working on (high data rate satellite data ingest system to be exact) and I got it confused with FMOD. I don't multitask well
    Silverwolf 2 is dead.
    Silverwolf 3...?

  7. #7
    FLAC TheLlama's Avatar
    Join Date
    Jul 2004
    Location
    All over the world
    Posts
    970
    Quote Originally Posted by intuitionsys
    With such a major change maybe I should just bump it up to 2.0
    Perhaps. However, you normally change the major version number when there is a significant change to the user experience. Most people don't care what you are using under the hood, even if it means better performance and more precise code for you.

  8. #8
    Newbie
    Join Date
    Jul 2005
    Posts
    30

    nix nux

    Ok yeah I know nothing about FMOD.

    Obviously for front ends (FE) u need a strong plugin framework, that is the key! too many apps for different folks in this space.

    and that then begs how / what / etc... so I say the killer FE would be done like so:

    1. any custom builds or components can be done in C/C++ or choose-your-flavor
    2. use a flexible UI / windower that has ruby extensions (GTK2, qt4)
    3. use a flexible builder/starter which will tie in the pieces via ruby script
    3. allow for ruby extensions to the app/UI/etc

    then we can get a full wave of ruby scripts to incorporate into the FE and it could grow like a weed (or get smoked). the ruby scripts can even pull in their own compiled pieces if they need them.

    the gps alone provides u with oodles of possible integration points...

  9. #9
    FLAC TheLlama's Avatar
    Join Date
    Jul 2004
    Location
    All over the world
    Posts
    970
    Quote Originally Posted by rocken
    then we can get a full wave of ruby scripts to incorporate into the FE and it could grow like a weed (or get smoked). the ruby scripts can even pull in their own compiled pieces if they need them.

    the gps alone provides u with oodles of possible integration points...
    Yeah, a Pyhon solution would work too. Make the player, library, and other vital portions of the FE in C++ then allow Python scripts as plugins. I'm thinking about doing this eventually. But you know how it is "too many features, too little time."

  10. #10
    Variable Bitrate intuitionsys's Avatar
    Join Date
    Jul 2005
    Location
    Northern Virginia
    Posts
    293
    Quote Originally Posted by TheLlama
    Yeah, a Pyhon solution would work too. Make the player, library, and other vital portions of the FE in C++ then allow Python scripts as plugins. I'm thinking about doing this eventually. But you know how it is "too many features, too little time."
    Too little time is definitely the problem! All the vital portions should definitely be in C/C++ though. Part of the reason for the (at least my) eventual move to FMOD is to remove reliance on other things like aRts, KDE and MPG123. Although my front end has been complete for quite a while there is always room for improvement.

    I also want to be able to get up and running quickly without swsusp2. Although it works well, a cold boot is always best.

    Regarding plugins, I'm both pro and con. Going crazy with plugins (depending on what they are) just seems like overkill. Many things considered plugins are really just glorified applications using interpreted code.

    My goal for Silverwolf, although it works fine now and a few people are using it, is to make it more generic and easily installable without as many prerequisites. I think everyone who has either bought one is technically oriented, and definitely the few who have installed it themselves from scratch, have a very very firm grasp of linux.

    Anway, this is getting to be a novel (negating my excuse about so little time ) so I guess the long and short of it is to just get everything working well and installable by mere mortals (not that Llama and I are immortal ) and worry about Ruby/Python/Pick-your-favorite-scripting-language later.
    Silverwolf 2 is dead.
    Silverwolf 3...?

Page 1 of 15 1234567891011 ... LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •