Announcement

Collapse
No announcement yet.

Llama's and Intuition's Techie Thread

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    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...?

    Comment


    • #3
      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.

      Comment


      • #4
        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...?

        Comment


        • #5
          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.

          Comment


          • #6
            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...?

            Comment


            • #7
              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.

              Comment


              • #8
                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...

                Comment


                • #9
                  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."

                  Comment


                  • #10
                    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...?

                    Comment


                    • #11
                      The first thing to do is to leave KDE, try WindowMaker, i used it as basis for working and it leaded me to a successfull GUI without the burden of arts, kde and all this garbage. With DirectFB there's one potential trouble with the gps software which requires an X server

                      Comment


                      • #12
                        Changing the window manager is low priority. That's easily doable. The reason Silverwolf uses KDE is because of some shortcuts in implementing the spectrum analyzer (specifically ripping FFT data from the sound stream). FMOD removes all external reliances on anything to do with sound wrt Silverwolf (except Xine sound output that I'm using for video playback).

                        re Xine output, any forseeable issues with piping raw PCM to FMOD (excluding the obvious preformatting of rate, word size and endianness)? I haven't even looked into it I just thought of it now. I can use a socket intermediary or a handle to stdin (preferrable the former) to get the data to the library.
                        Silverwolf 2 is dead.
                        Silverwolf 3...?

                        Comment


                        • #13
                          lol i know it's easy i think you misunderstood me and FMOD is not all.
                          Starting with Windowmaker or other lightweight window manager from the begining will save time and avoid searching unforeseen troubles later but it's up to you

                          This remembers me another thread about a phone control software.

                          Comment


                          • #14
                            Originally posted by kraft
                            lol i know it's easy i think you misunderstood me and FMOD is not all.
                            Starting with Windowmaker or other lightweight window manager from the begining will save time and avoid searching unforeseen troubles later but it's up to you

                            This remembers me another thread about a phone control software.
                            I'm not starting from scratch (I've been using Silverwolf for over a year now) so it's a moot point. I'm more concerned with FMOD right now. One of the driving concerns I've gotten in e-mails is the install and setup are so complicated and using FMOD will clean up alot of crap and simplify the setup in one fell swoop.
                            Silverwolf 2 is dead.
                            Silverwolf 3...?

                            Comment


                            • #15
                              Llama have you found you need to glean a fairly large array from getSpectrum() to get a reasonably accurate display? Using 64 and graphing the results wasn't nearly as accurate as sampling 1024 then subsampling to 64 (the number of meters in the analyzer). I'm also doing the logarithmic dB conversion on the fly, clipping to -120dB dynamic range (anything beyond that is dreaming anyway )

                              My development platform is a P4 3.6 GHz so it will be interesting to see if the FP unit on the 1.2 GHz C3 can keep up to that many transforms every 100ms...

                              btw FMOD is the cat's <insert favorite expletive here>. It really does work as well as advertised. I'm almost done moving everything over well in advance of what I thought it would take. The hacking and chopping of irrelevant aRts and MPG123 related code is a good thing too.
                              Silverwolf 2 is dead.
                              Silverwolf 3...?

                              Comment

                              Working...
                              X