Thursday, December 20, 2012

eDocReader for Android devices

For the last couple of months i could not contribute much to my blog as i was busy in developing an android app which can show the streaming of a device-agnostically encoded video from a server. Moreover, most of my time is now dedicated to my family. However, in my pass time i have developed an eDocReader for Android devices. The research was done earlier and this is the result. The app needs to be polished for qualifying as a professional App. However, this can be the beginning. Eventually i will open the source code. The app supports .ODF, .ODT,.PDF, .DOC, .XML, .HTML, .RTF, .EPUB, .TXT formats. It also supports .ods, .xls and .odp files though in a bit coarse way.

You can install it from Google Play or you can download the app from this link.


You can also download it through




Thursday, September 20, 2012

I have found my idol...


I think i have found my idol. He is more a technologist than a businessman. He is not a multi billionaire. Hence wherever he goes the cameras of the press don't flash. He does not carry  any air around himself. He is a completely family man. Moreover he is a happy person contended with the great contribution he has made to the digital world. He is still young and hence i can idolize him for longer period. In simple words he is like one of us but has attained great heights in life... Probably he is the person whose name came to my mind after Swami Vivekananda. He is none other than Linus Torvalds, the creator of the world of linux.

Here is an excerpt from the book Just For Fun which describes him nicely in simple words...“Most acclaimed technologists - even most of the unacclaimed ones - have this immediate desire to let you know how brilliant they are. And that they are critical in a mission that is far more important than say, the struggle for the world peace. That was not the case with Linus. In fact, his lack of ego seemed downright disarming.... Linus appeared to be above it all. Above the New Agers. Above the high-tech billionaires. He seemed less like a reindeer caught in the global headlights than a delightful alien beamed down to show us the madness of our selfish ways”. Can i find such an unassuming idol in anybody else?

Monday, June 4, 2012

Google's Protocol Buffer Format - an Android app to convert GPX data to PBF...

i don’t want to give gyan on Google’s protocol buffer format. Please refer to https://developers.google.com/protocol-buffers/ for all the details. When i studied PBF, i developed an Android app which will convert a GPX file into a PBF file. The GPX file has been downloaded from the internet and it is called fells_loop.gpx. i have put it in the asset folder of my Android app. the generated fells_loop.pbf file has been stored in the SD card in the temp folder. with that i have also created a text file called debug.txt in the same folder. this file gives an human readable form of what has been stored in the PBF file.

for simplicity i have serialized just the latitude and longitude of the GPX file into the PBF file.


please find the source code here.

i have taken the help of a google-code project to build the Android app.

i hope this discussion will help all the programmers who are hooked to Google products and Android.

Sunday, June 3, 2012

Android graphics and animation - pendulum motion and circular motion...

Note : Based on the same animation principles, i have developed this Android game which can be found at Google Play store at
https://play.google.com/store/apps/details?id=com.somitsolutions.training.android.bouncingball

When i was given a task to simulate different functionalities of physics/mechanics, i pondered on it for sometimes. Then i thought to create a simple example app to showcase the concept. this app actually animates the simple pendulum motion on android. it was done using android canvas and sufaceview. you can download the source code from here. the apk is here.

i took the initial angle of the pendulum as PI/4. here is the screen capture of the pendulum motion in the emulator.





the entire locus of the pendulum with respect to time has been divided in 6 parts.

  • the first half of the left to right movement
  • the middle position of the pendulum while moving from left to right
  • the second half of the left to right movement
  • the first half of the right to left movement
  • the middle position of the pendulum while moving from right to left
  • the second half of the right to left movement

the formula of the simple pendulum motion that i have used to calculate the X-Y co-ordinates of the pendulum is

d⍬ = dt/squrt(l/g) where d⍬ is the delta angle shift of the pendulum in the delta time dt.

the crux of this app lies in the class called Panel which is defined as follows:


   
class Panel extends SurfaceView implements SurfaceHolder.Callback{
     
     
     public PendulamThread _thread;
     
     public Panel(Context context) {
      super(context);
       
      
      getHolder().addCallback(this);
      _thread = new PendulamThread(getHolder(), this);
     }

     public void surfaceChanged(SurfaceHolder holder, int format, int width,
       int height) {
      // TODO Auto-generated method stub
      
     }

     public void surfaceCreated(SurfaceHolder holder) {
      // TODO Auto-generated method stub
      
       _thread.setRunning(true);
             _thread.start();
      
     }

     public void surfaceDestroyed(SurfaceHolder holder) {
      // TODO Auto-generated method stub
      
       _thread.setRunning(false);
      
     }
     
     @Override
        public void onDraw(Canvas canvas) {
      
       canvas.drawColor(Color.BLACK);
       anchorX = getWidth()/2;
       
       anchorY = getHeight()/4;
       
       //if(!theCenterBeingDrawn){
       canvas.drawCircle(anchorX - 3, anchorY - 4, 7, mPaint);
        
       
       
       //First Half ... Left To Right
       if(leftToRightMovement == true &&
 rightToLeftMovement ==false && 
atTheMiddlePositionWhileLeftToRight == false &&
atTheMiddlePositionWhileRightToLeft == false &&
firstHalf == true && secondHalf == false){
       
        angleInThePreviousStep = angle;
           
                 angle = angle - dt/Math.sqrt(length/9.81);
                 
                 
           
                 if(angle >0.01){
                  ballX = anchorX - (int)length*(Math.sin(angle));
            
            ballY = anchorY + (int)length*(Math.cos(angle));
                  
            canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                  
                  canvas.drawCircle((float)ballX , (float)ballY , 14, mPaint );
                 }
                 
                 else{
                  atTheMiddlePositionWhileLeftToRight = true;
                  atTheMiddlePositionWhileRightToLeft = false;
                  leftToRightMovement = true;
                  rightToLeftMovement = false;
                  firstHalf = false;
                  secondHalf = false;
                 }
                  
              
                 
                 return;
                 
       }
       //First Half Left To Right end
       
       //AtTheMiddle while Left To right
       if(atTheMiddlePositionWhileLeftToRight == true &&
 leftToRightMovement == true && 
rightToLeftMovement == false && 
atTheMiddlePositionWhileRightToLeft  == false &&
 firstHalf ==false && secondHalf == false){
       
        angle = 0;
        angleInThePreviousStep = 0;
        flag = true;
        angleAccel = 0;
        angleVelocity = (Math.sqrt(2*9.81*length));
        ballX = anchorX;
        ballY = anchorY + length;
        canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                 
                 canvas.drawCircle((float)ballX ,(float)ballY , 14, mPaint );
                 
                 atTheMiddlePositionWhileLeftToRight = false;
                 leftToRightMovement = true;
                 rightToLeftMovement = false;
                 atTheMiddlePositionWhileRightToLeft = false;
                 firstHalf = false;
                 secondHalf = true;
                 
                
                 return;
       }
       //at the middle while left to right end
       
       //Left to Right second half
       if(leftToRightMovement == true &&
 rightToLeftMovement == false && 
atTheMiddlePositionWhileLeftToRight == false &&
 atTheMiddlePositionWhileRightToLeft ==false &&
 firstHalf == false && secondHalf == true){
        
        double velocityAtTheBeginning = angleVelocity;//not sure if doing the right thing... forgot mechanics
                
        
        angle += dt/(Math.sqrt(length/9.81));
        
         
        if((initialAngle- angle)>0.01){
        
           ballX = anchorX + (int) (Math.sin(angle) * length); //greater than anchorX
           ballY = anchorY + (int) (Math.cos(angle) * length);//less than anchorY
            
           canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                     
                 canvas.drawCircle((float)ballX , (float)ballY , 14, mPaint );
                 
        }
        else{
        atTheMiddlePositionWhileLeftToRight = false;
                  leftToRightMovement = false;
                  rightToLeftMovement = true;
                  atTheMiddlePositionWhileRightToLeft = false;
                  firstHalf = true;
                  secondHalf = false;
                  angle = initialAngle;
        }
                 return;
       }
       
       //left to right second half end
       
       ////right to left first half
       if(leftToRightMovement == false &&
 rightToLeftMovement ==true && 
atTheMiddlePositionWhileLeftToRight == false && 
atTheMiddlePositionWhileRightToLeft == false && 
firstHalf == true && secondHalf == false){
        
        angleInThePreviousStep = angle;
           
                 angle = angle - dt/Math.sqrt(length/9.81);
                 
                 
           
                 if(angle >0.01){
                  ballX = anchorX + (int)length*(Math.sin(angle));
            
            ballY = anchorY + (int)length*(Math.cos(angle));
                  
            canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                  
                  canvas.drawCircle((float)ballX , (float)ballY , 14, mPaint );
                 }
                 
                 else{
                  atTheMiddlePositionWhileLeftToRight = false;
                  atTheMiddlePositionWhileRightToLeft = true;
                  leftToRightMovement = false;
                  rightToLeftMovement = true;
                  firstHalf = false;
                  secondHalf = false;
                 }
                  
                 return;
                 
       }
       
       //Right to left first half end
             
       
       ///at the middle while right to left
       if(atTheMiddlePositionWhileLeftToRight == false && leftToRightMovement == false && 
rightToLeftMovement == true && 
atTheMiddlePositionWhileRightToLeft  == true && 
firstHalf ==false && secondHalf == false){
        
        angle = 0;
        //angleInThePreviousStep = 0;
        //flag = true;
        angleAccel = 0;
        angleVelocity = (Math.sqrt(2*9.81*length));
        ballX = anchorX;
        ballY = anchorY + length;
        canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                 
                 canvas.drawCircle((float)ballX ,(float)ballY , 14, mPaint );
                 
                 atTheMiddlePositionWhileLeftToRight = false;
                 leftToRightMovement = false;
                 rightToLeftMovement = true;
                 atTheMiddlePositionWhileRightToLeft = false;
                 firstHalf = false;
                 secondHalf = true;
                 
                
                 return;
       }
       //at the middle while right to left end
       
       
       
      
       ///Right to left second half
       if(leftToRightMovement == false &&
 rightToLeftMovement == true && 
atTheMiddlePositionWhileLeftToRight == false && 
atTheMiddlePositionWhileRightToLeft ==false && 
firstHalf == false && secondHalf == true){
        
        double velocityAtTheBeginning = angleVelocity;//not sure if doing the right thing... forgot mechanics
                
        
        angle += dt/(Math.sqrt(length/9.81));
        
         
        if((initialAngle - angle)>0.01){
        
           ballX = anchorX - (int) (Math.sin(angle) * length); //greater than anchorX
           ballY = anchorY + (int) (Math.cos(angle) * length);//less than anchorY
            
           canvas.drawLine(anchorX, anchorY,(float)ballX,(float)ballY,mPaint);
                     
                 canvas.drawCircle((float)ballX , (float)ballY , 14, mPaint );
                 
        }
        else{
         atTheMiddlePositionWhileLeftToRight = false;
                  leftToRightMovement = true;
                  rightToLeftMovement = false;
                  atTheMiddlePositionWhileRightToLeft = false;
                  firstHalf = true;
                  secondHalf = false;
                  angle = initialAngle;
        }
                 return;
       }        
     }
     
    }//onDraw



The thread function has been defined as follows:


class PendulamThread extends Thread {
        private SurfaceHolder _surfaceHolder;
        private Panel _panel;
        private boolean _run = false;

        public PendulamThread(SurfaceHolder surfaceHolder, Panel panel) {
            _surfaceHolder = surfaceHolder;
            _panel = panel;
        }

        public void setRunning(boolean run) {
            _run = run;
        }

        public SurfaceHolder getSurfaceHolder() {
            return _surfaceHolder;
        }

        @Override
        public void run() {
            Canvas c;
            while (_run) {
                c = null;
                try {
                    c = _surfaceHolder.lockCanvas(null);
                    synchronized (_surfaceHolder) {
                        _panel.onDraw(c);
                        Thread.sleep(50);
                       //c.drawColor(Color.BLACK);
                       // _panel.postInvalidateDelayed(10);
                    }
                }
                 catch(InterruptedException e){
                         
                 }
                     
                finally {
                }
                    // do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        _surfaceHolder.unlockCanvasAndPost(c);
                     }
                 }
             }
        }

And the Activity class is like the below:

package com.somitsolutions.android.pendulamsimulation;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class PendulamSimulationActivity extends Activity {
 
 //private Paint mPaint;
 private boolean leftToRightMovement = true;
 private boolean rightToLeftMovement = false;
 private boolean atTheMiddlePositionWhileLeftToRight = false;
 private boolean atTheMiddlePositionWhileRightToLeft = false;
 private boolean firstHalf = true;
 private boolean secondHalf = false;
 private volatile double ballX = 0;
 private volatile double ballY = 0;
 
 //private boolean theCenterBeingDrawn = false;
 
 double angleAccel = 0.0;
 double angleVelocity = 0;
 double dt = 0.15;
 
 private boolean flag = false;
 
 boolean flagCondition = false;
 
 private int anchorX;
 private int anchorY;
 public static double initialAngle = Math.PI/4;
 public static double angle = Math.PI/4;
 double angleInThePreviousStep = Math.PI/4;
 
 private static final int length = 150;
 
 private Paint mPaint;
 
 private Paint mRefreshPaint;
 
 //SurfaceHolder surfaceHolder;
 
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        Panel p = new Panel(this);
       
        mPaint = new Paint();
  mPaint.setColor(Color.YELLOW);
  
  mRefreshPaint = new Paint();
  mRefreshPaint.setColor(Color.BLACK);
  
        setContentView(p);
        
    }
.......
.......
.......
    ///Panel and Pendulum Thread classes go here

i would like to share some issues that i faced while doing this animation. as all of you know that the simple animation is done by removing the trace of a moving object by repainting the previous position with the background color. i was trying to do the same thing by repainting only that part of the screen which was occupied by the pendulum before moving to a new position. however, it was not giving proper result. when i was scratching my head over the issue, suddenly i saw a simple line in android documentation that says if somebody wants to repaint only a portion of the screen, the result may be undefined. so its better to repaint the whole screen for proper animation. and it solved my problem. and hence the first line of the onDraw() is canvas.drawColor(Color.BLACK).

similarly, using the same principles, i have simulated the circular motion. the apk for the same can be download from here. the screen capture of this app is like the following:

i am also trying to do some experimentation with the simulation of different physics functionality using the game engine called Cocos2D. here is the screen capture of one of such experimentation which simulates the circular motion.

hopefully this article will be able to throw some lights on android graphics and animation. 
with this positive hope i would like to end this discussion.

Tuesday, January 17, 2012

FFT based simple Spectrum Analyzer with Source Code

i am writing this blogpost to pay homage to my alma mater... i was not at my level best to understand all aspects of Electonics & Telecommunication, the Microprocessor, the Digital Communication, the Digital Signal processing as taught by my professors... however, after so many years while playing around with different software, i understand how valuable was their contribution to make me an engineer. i remember, how important was the lesson of digital communication, and digital signal processing taught by Dr. T.K.Sen... i remember how important was the lesson of Microprocessor taught by A.R.... i remember how important was the lectures of Maths during our engineering course... i remember how important were the concepts of Fourier Transformation, FFT, DFT, Laplace Transformation, Matrix algebra and Complex Algebra...Hats off to all those professors who in spite of all odds helped a small town boy see the outer world...

You can install this FFT based simple Spectrum Analyzer with a sampling frequency of 8 KHz and audio encoding as 16 bit PCM from google play at https://play.google.com/store/apps/details?id=com.somitsolutions.android.spectrumanalyzer
i was so excited when i finished the coding part (of course with the help of Google...) and saw its working on a real device...

here are the a screenshot i have taken from an Android device...


and here (https://gitlab.com/som.mukhopadhyay/FFTBasedSpectrumAnalyzer) goes the source code which may help someone interested in Android...