Search This Blog

Thursday, July 12, 2012

Suicide for the strobe/flashlight app on Google

I decided to pull the silicon fish blinky app off the market.  At the bottom are the comments I was getting.  I can't handle the shame.  I wasn't able to test the app on other platforms because I didn't have any extra phones.  I've since got a motorola droid 4 and the LG doubleplay that I found and repaired.   If I get some spare time I'll get the app working on those and republish it.  Fun while it lasted.  Lesson learned, don't do a flashlight app unless you have access to a lot of phones because the LEDs work differently on different devices.    I gave it away free and still got trashed.  I put a disclaimer.  Oh well.

At the end I had over 2900 installs, but as near as I can tell only 300 active users after 6 months on the market.  And in case you were wondering, never made $0.01 on it.  The only way to make money is to put ads or charge for the app, neither was I willing to do.  It was a project for fun, not for public abuse.

You can still download it direct to your phone from my download page, as long as you check the box in your settings->applications->unknown sources menu on your android device.  That allows you to install apps from other than the google market.  Just navigate your phone to
http://code.google.com/p/arduino-java-xyzcnc/downloads/list and then click on SiFishBlinky.apk


or go directly to:
http://arduino-java-xyzcnc.googlecode.com/files/SiFishBlinky.apk

Here is my wall of shame  :-#


      David on Sunday, July 8, 2012 at 22:23 Huawei M865C (hwm865c) Version 1.9.16
Crap Learn to finish and test drive before Publishing
      Ben on Monday, June 4, 2012 at 22:59 Samsung Droid Charge (SCH-I510) Version 1.9.16
Does not work for Droid Charge Does not activate LED on the Droid Charge, thus making this a useless app for that device.
      George on Sunday, June 3, 2012 at 22:42 Samsung SAMSUNG-SGH-I777 (SGH-I777)
Doesn't work
      Jason on Thursday, May 24, 2012 at 01:19 Motorola DROID4 (cdma_maserati)
Does not work for droid 4
      Jon on Sunday, May 6, 2012 at 21:02 Motorola XT910 (umts_spyder)
Bad Doesnt work
      Austin on Monday, April 23, 2012 at 12:17 Motorola DROID RAZR (cdma_spyder)
Gay Doesn't turn on. There is no zero star option by the way.
      Joel on Wednesday, April 4, 2012 at 07:25 Acer Picasso (picasso) French
Acer A500 N'a pas fonctionné.
      Nahuel on Tuesday, March 27, 2012 at 21:49 Samsung Sidekick 4G (SGH-T839) Version 1.9.16
Jo Ho
      Brendan on Saturday, March 17, 2012 at 21:04 LGE Bryce (bryce) Version 1.9.16
:( Wont even turn on
      on Sunday, February 19, 2012 at 18:29 Samsung Galaxy Exhibit (SGH-T679) Version 1.9.15
GREAT Idea and no stinking ads NO ads or tracking but it just dosent work for my phone. Thanks, wish all app developers had your attitude.
      Lemuel on Saturday, February 18, 2012 at 23:58 Motorola Droid X (cdma_shadow) Version 1.9.15
A+ Can you change the background to plain black? to save battery.
      Ari on Friday, February 17, 2012 at 01:45 Motorola Droid X (cdma_shadow) Version 1.9.15
Cool app Works well, I like the fact that you can create custom patters. I also like the strobe light
      on Friday, February 10, 2012 at 19:24 Samsung Galaxy Ace (GT-S5830) Version 1.9.15 Czech
Nefunguje Naprosto nefunkční
      Daniel on Wednesday, February 8, 2012 at 01:14 LGE Optimus 2X (p999) Version 1.9.14
Sucks Doesn't work on my phone waste of time
      Zeneth on Sunday, February 5, 2012 at 12:52 Motorola Droid X (cdma_shadow) Version 1.9.14
Thanks A+

Monday, July 9, 2012

XFX 4890 Graphics card fan replacement - Shameful hack

Because of my sense of humor, I'll share my fix for a bad fan on my XFX Radeon 4890 graphics card, otherwise known as a VGA cooling fan.  Why did I do something this lame?... here is the story.




The fan began making noise, which my son ignored for many months.  Eventually the machine started randomly rebooting.   Finally it started rebooting after about every 1 minute of operation and I had to give in and figure out what was wrong.    The card was smokin' hot and the fan was not turning.  Obvious.   Here is what the card looks like with the factory fan.



I went online, and searched for a replacement fan.  Not much out there, and most of the fans did not have dimensions, or the reviews said they didn't fit.  Really hard to figure out what to buy.  I finally bought this one.  It looked like the one I had from the picture:



Doh.  Total fail.   It came in a tiny envelope and here it is next to the fan from the 4890.   WAYYYY to small.


I had no confidence that any of the other fans out there were the right size either.   I could play dialing for donuts and keep buying fans until one fit.  Nahhhhh.

Measuring the fan against a standard case fan, I saw that they were the same size.   Originally I thought I'd hack something together and ordered this case fan.



You may be able to see that the fan has three plastic spokes that attach it to the case, that could easily be clipped to remove the fan, which appears to be exactly the same size as the fan I'm replacing.  However i'd be stuck trying to figure out how to attach it to the metal heat sink with no screw holes.  Glue wouldn't work here, it would be too hot.




Since the computer case is fairly empty, and the PCI slot next door is open, I had room to simply glue the case fan over the hole to the VGA card.   I spliced the red and black wires into the old fan's connector since the case fan's connector wasn't the same size.



As soon as the glue dries it's going into the machine.  I'll update the post with how it works out.  Crossing my fingers.



Turned out if you look, the video card had a plastic film still on it from the factory, that I never had peeled off.  So my glued-on fan fell off immediately.  If you look you can see that the sticker on the top of the card is a bit hazy.  Duh.  I peeled off the protective film and used some JB weld epoxy this time.  I didn't drill holes in the black cover, because there is a metal heat sink directly underneath it.

Now I'll try again when the new glue is dry....

Success!  Here it is back in the computer.  You can see the case fan glommed on the side of the video card. Luckily that slot is not used, and the fan is away from the CPU side where it might have collided with the motherboard chipset cooler.





The computer is up and running and seems fine under normal load.  W00t!  $6 case fan saves the day.

Tom

Tuesday, June 19, 2012

Windows Security Suite virus - The most concentrated evil juice there is

My son somehow picked up Windows Protection Suite
on his PC.  It started with a a pop up, and ended up hijacking all the browsers and making
them non functional, shut off the firewall and disabled the antivirus.   It had tricked him into
clicking a dialog that downloaded the software.  Then it pretends to be a security suite and asks you for your credit card number to upgrade it to save you from all these threats it is pretending to have detected (which it caused).  Reasonable attempts to kill processes and remove files were useless, it repaired itself on reboot.   I was able to temporarily restore Chrome by renaming the file back, but that only lasted about a minute before it was swapped back. It disables virus scanner anew every time you attempt to re-install it from USB.    I was unable to do a system restore either.  I don't know how they managed  to hose that up too.  msconfig of the startup sequence didn't help either. I advocate extreme violence  against the authors of this program.


This is not my screenshot, because my PC was dead, but it looked pretty much like this.

Windows Security Suite snapshot


Some links I found.
http://www.geek.com/articles/chips/dealing-with-the-windows-security-suite-2009113/
http://www.bleepingcomputer.com/virus-removal/remove-windows-protection-suite
http://www.2-viruses.com/remove-windows-protection-suite
http://virus.geeksailor.com/how-to-uninstall-remove-security-suite-virus-removal-guide-2/
Some web searches recommended Malwarebytes and rkill.   I think they are written by Malwarebytes, to sell their software.    After initial resistance I tried Malwarebytes and rkill and it didn't work at all.  After giving in and following their directions,  I ended up with a PC that would not boot at all.   I could not even boot it from the CD or USB stick with either windows or Linux.  I've never seen this before, I've always been able to boot from linux USB, but this time, halfway through the boot, the PC goes black and reboots. A windows install from CDROM also stops after the initial load and the PC reboots.  Holy crap.

Don't waste your time if this happens to you.  This is the most evil virus I've ever seen.  I doubt that you will ever be able to clean it out.

Now I'm buying a new hard drive and starting from scratch.   My plan is to take the old hard drive out to a Linux machine and extract some of the data I want from it then reformat it.  It will never touch a windows machine again.   I will update the post once the hard drive is replaced.    Hopefully it has not done hardware damage or screwed with the BIOS too.  I will dedicate my life to tracking these people down if it has.


Update... the computer is back up and running.
The computer hard drive and all the data was a total loss.   Started over with a new drive.  However it turned out a bad fan on the video card was the true cause of the constant rebooting, and the reason even loading ubuntu didn't work.  <Red Faced>.  Odd how this problem popped up just as the computer got this crippling virus, maybe something about the virus caused the video card to work extra hard and fail, or just plain coincidence.  However when you have two problems at once, debugging and fixing become 10 times as difficult.   I solved the problem by pulling memory modules and cards one at a time until the machine was stable, since I knew the virus was gone when I replaced the hard drive.


I still think this virus is one of the worst I've ever seen, but it's not conclusive that it caused hardware damage as well.

Sunday, June 17, 2012

Telemetry logger android app


In order to make some augmented reality apps, and some other cool robot and telemetry apps, I decided to make a small app that reads out all the accelerometer, gyroscope, compass, etc sensors and logs the values to the SD card.   From there I can analyze the data and see what sort of performance to expect.

Here are some links with information I found,
http://www.sensorplatforms.com/native-sampling
http://www.sensorplatforms.com/smartphone-performance-fundamentals-sensor-sampling
http://developer.android.com/reference/android/hardware/SensorManager.html

Hard to tell what are real sensors and what are virtual.  this was the best article I found on what is actually in the phone.
http://www.mobiledevmag.com/2011/07/using-available-sensors-in-the-android-platform-current-limitations-and-expected-improvements%E2%80%A8/

Here is how to dump the sensors on the phone


SensorManager myManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        List<Sensor> sensorList = myManager.getSensorList(Sensor.TYPE_ALL);
        StringBuilder sensorString = new StringBuilder("");
        for(int i=0; i<sensorList.size(); i++) {
            sensorString.append("Type: "+sensorList.get(i).getType()).append(" ---------\n");
            sensorString.append(sensorList.get(i).getVendor()).append("\n");
            sensorString.append(sensorList.get(i).getName()).append("\nResolution: ");
            sensorString.append(sensorList.get(i).getResolution() ).append("\n");
        }


That gives me this data on my motorola droid 2 global


SiFish Android Sensor Log
Android Sensors Found:
Type: 1 ---------
Kionix
KXTF9 3-axis Accelerometer
Resolution: 0.009810001
Type: 2 ---------
Asahi Kasei
AK8975 3-axis Magnetic field sensor
Resolution: 0.0625
Type: 8 ---------
Intersil
ISL29030 Proximity sensor
Resolution: 100.0
Type: 3 ---------
Asahi Kasei
AK8975 Orientation sensor
Resolution: 0.015625
Type: 5 ---------
Intersil
ISL29030 Light sensor
Resolution: 1.0
Type: 9 ---------
Google Inc.
Gravity Sensor
Resolution: 0.009810001
Type: 10 ---------
Google Inc.
Linear Acceleration Sensor
Resolution: 0.009810001
Type: 11 ---------
Google Inc.
Rotation Vector Sensor
Resolution: 5.9604645E-8

The key code is pretty simple to access the sensors.  This may not be the most efficient or fastest code yet, it is my starting point

In your onCreate do this:


mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);       mSensorManager.registerListener(mSensorListener1, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST);  
private final SensorEventListener mSensorListener1 = new SensorEventListener() {
   public void onSensorChanged(SensorEvent se) {
     text1.setText(se.sensor.getName());      Ax = se.values[0];      Ay = se.values[1];      Az = se.values[2];      long timestamp = se.timestamp;      aXProgress.setProgress((int) Ax + 50);      aYProgress.setProgress((int) Ay + 50);      aZProgress.setProgress((int) Az + 50);
                            if (sdcard.sd_ok & logging) {     sdlog(timestamp);     }    }
 public void onAccuracyChanged(Sensor sensor, int accuracy) {  }};



Writing to the SD card turned out to be more work than I thought.  It really is pretty easy, but I got hung up on a couple things.
  • AndroidManifest.xml has to have this line in it, or it will not throw errors, it just won't work.     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
  • File names should avoid  "." and ":"    I was trying to time stamp the file names and put in a ":".  Failed.
  • When the phone is plugged into the PC, the SD card is shared and you can't write to it.  You have to load your app, then unplug, and run it again to make it work.
  • I used buffered stream to keep the app from waiting for the SD card, but if you don't do a flush() it doesn't write until the buffer is full.
  • If you get exceptions like "Permission Denied"  you have to collect them and find a way to view them or display them back to the user


This is the class I wrote to handle the SD card communication


public class SDcard { File sdCard = Environment.getExternalStorageDirectory(); File dir = new File (sdCard.getAbsolutePath() + "/sifish"); File destinationFile; BufferedOutputStream buffer; public String messages; public boolean sd_ok = false; public boolean checkSD() { sd_ok = false; messages = "SD card is ".concat(Environment.getExternalStorageState()).concat("\n"); if (Environment.getExternalStorageState().equalsIgnoreCase("mounted")) { sd_ok = true; } return sd_ok; } public boolean openSDFile(String filename) { boolean success = true; //messages = "SD card is ".concat(Environment.getExternalStorageState()).concat("\n"); sdCard = Environment.getExternalStorageDirectory(); dir = new File (sdCard.getAbsolutePath() + "/sifish");  dir.mkdirs(); success = dir.canWrite(); sd_ok = success; if (!success) { messages = messages.concat("Error - Can't write to "+dir.getAbsolutePath()+" directory on SD card\n"); sd_ok=false; }
try { destinationFile = new File(dir, filename.concat((String) android.text.format.DateFormat.format("_yyyyMMdd_hhmmss", new java.util.Date())).concat(".csv")); buffer = new BufferedOutputStream(new FileOutputStream(destinationFile)); messages = messages.concat("Opened "+destinationFile.getName()+"\n"); } catch (Exception e) {   messages = messages.concat("Error - Can't open file "+destinationFile.getName()+" on SD card\n");   //messages = messages.concat(e.getMessage());   messages = messages.concat(e.toString()).concat("\n");   success = false;   sd_ok = false; } return success; } public boolean closeSDFile() { boolean success = true; try { buffer.flush(); //buffer.close(); } catch (Exception e) {   messages = messages.concat("Error - Can't close file on SD card\n");   messages = messages.concat(e.toString()).concat("\n");   //messages = messages.concat(e.getMessage());   success = false; } sd_ok = false; return success;
//destinationFile.close(); } public boolean writeSDFile(String data) { boolean success = true; try { //byte[] dataByte = Base64.decode(data, Base64.DEFAULT); char[] dataChar = data.toCharArray(); for (int i=0; i<data.length(); i++) { buffer.write(dataChar[i]);   } //buffer.flush();   //doesn't write until buffer is flushed } catch (Exception e) { messages = messages.concat("Error - Can't write to SD card file "); messages = messages.concat(e.toString()).concat("\n"); success = false; sd_ok = false; } return success; } public void dirSD() { sdCard.listFiles(); }

I'm going to clean this up and publish it to android market, but meanwhile I posted the apk file to my download page.   The data is saved to your sdcard when you run a log, under the "sifish" directory.  It creates a csv file with all the data from all the sensors on the phone.

The screenshots from the emulator don't do it justice, since the emulator has no sensors and no data shows up.




Just surf your android phone to this page:
http://code.google.com/p/arduino-java-xyzcnc/downloads/list

and download
AccelerationLogger.apk

Then look on your SD card for the output files.








Thursday, June 7, 2012

Found/Fixed an LG C729 android phone with broken screen




I found this on the street in front of my house.   It is a nice android phone that had been
run over by a car.   I couldn't believe my luck.  The screen is broken badly. This is the most fantastic thing I ever found.    The screen is splintered and I got some shards in my finger trying to see if the touch pad works.  It doesn't at all.  That is the biggest problem.  The back won't stay on and the battery is pretty roughed up too.




I set out to find out what data I could pull off the phone and what functionality I could use.  I'm a hardware experimenter, and I'd like to use it for telemetry, robot control, etc.  For that I don't need a screen, the sensors, camera, GPS and USB interface alone make it very powerful.    It has an SD card it in, a SIM card too.   Who does it belong to?   If it were an iPhone, I'd buy a screen replacement kit, but this is a fairly obscure LG C729 .
http://www.globaldirectparts.com/OEM-LG-DoublePlay-C729-Main-LCD-Screen-p/lg977470.htm
This looks like a very dicey site.  But it led me to a part number, then
http://www.ebay.com/itm/US-OEM-Tmobile-LG-Double-Play-C729-Big-Outter-LCD-Display-Screen-Part-Tools-/221039061735


Looked up model, it is an LG Doubleplay from T Mobile.  Runs Android 2.3.4  It is a practically new phone. I can't imagine why whoever dropped it and ran it over didn't come back for it.




I found the SD card was unformatted and had no data on it.  I guess the phone was pretty new.
The SIM card from Tmobile... is it still active?   I can see that the phone is saying no signal, emergency calls only, so it's cancelled as I'd expect it to be.   The phone sat around for a couple weeks before I got a chance to play with it.

A little fiddling and I was able to put the battery in, and connect the USB and power it up.   The backlight comes on and with the battery in in actually boots.   It makes sounds.  This phone seems good except for the screen.  For some reason it didn't work the first time I tried, but later it did boot.   Plug it into the USB and screen lights up but is pretty bad shape.    I think the screen lock is on, and since the touch pad is smashed, I can't unlock it with a swipe.



Another lucky part is this wacky phone has a second touch screen inside the keyboard.  That touch screen actually works still and is not broken.  However it doesn't fully run the phone.  I can open text messaging but not the contact list to see who's phone it is.



When it first booted, I was able to operate the phone.  After a while it went to screen lock due to inactivity and I can't see a way to get it out of that mode.   It is hard to turn the phone off again, because long button hold brings up a menu that I can't operate to do a shutdown.  I did find the physical keyboard space and return allow me to navigate the power down menu.  W00t!   Any other phone and I'd be nowhere, but this oddball has a physical keyboard.

Android Java SDK talks to the phone, it seems to load apps I program in, when the power is off!  When turned on I can't go through the menus to set the phone menu option to allow Settings->Applications->developement which allows USB loading of programs.   When powered on I can't talk to it with eclipse.  Very strange.  This is a major obstacle to using the phone as a hobby robot.

I thought I would need to write an app to unlock the screen when the touch swipe won't work
http://stackoverflow.com/questions/2891337/turning-on-screen-programmatically
newKeyguardLock = km.newKeyguardLock(HANDSFREE); newKeyguardLock.disableKeyguard();
However I found that opening the phone keyboard unlocks the screen.  Awesome.  That doesn't work with my droid.


At this point I'm a little stalled.  I can't program the phone with custom apps, because it isn't in developer mode.   A simple menu option that I can't get to without the touch screen.  I can't use WiFi because I can't get to the settings page.  Maybe I can program it through the USB, if only I could get to developer mode.


I may go back and buy a new screen.  Bad news is I need a screen AND a touchpad/glass to fully fix this thing.  I don't want to order direct from China.  That usually works, would save $10, but takes forever.

It would take $60 to completely repair this phone.  After that it could be unlocked and used as a phone.  If I only replaced the touch screen/glass, it would be $30.  Does that make sense if I've got it open should I go for 100% fixed?

I was curious is the ESN was good.   How you do it appears to vary with company.  Can't find much on Tmobile.  I don't plan to activate it, but it would be nice to know in case I do.
http://www.checkesn.com/how-it-works/

I opted to repair the screen and digitizer.  Partially for practice, part because I wanted a GSM phone for a trip to Europe coming up, and part because I'm finding I'm pretty stuck without any touch input.   I could have just replaced the digitizer and glass, but while I was in there, I decided to go for it.  I bought the parts from Ebay on the links above from "gadgetFix" because they shipped from the US.  It took about 4 days to get here.

Here is what I got.  Came in a little envelope.  No instructions :(



I took the battery out of the phone first

I hate instruction videos because you have to watch them slowly and waste time finding out if they are any good.  Just write instructions people!!
http://www.youtube.com/watch?v=jsspvoCF1Jg
This doesn't seem to apply very well because this is a slider phone, and taking the back off is pointless.  They do use a heat gun to melt the adhesive.   This may be necessary.
http://www.repairsuniverse.com/lg-take-apart-repair-guides.html

This is a little closer to the mark
http://www.repairsuniverse.com/lg-ally-screen-replacement-take-apart-repair-guide.html
This does show you have to start at the back, remove the motherboard, etc until you get to removing the screen.  No heat on this one at least.

I pried off the rubber bumps on the back of the screen and removed the two philips head screws.
I can pry up one side of the screen, but I can't get in. 


close up of the screw once the rubber bump is off







 I guess I have to take the screws out of the back and start prying up the mother board.
I'm not showing the photo of the back, because the photo has the MEID in the picture.  Just take out all the small phillips head screws you see.


Pryed off the back and pulled out the keypads from each side.  This allows you to wedge a screw driver in sideways and access the other two screws on the back of the sliding screen.   You have to pry up the circuit board a bit and slide the screen around until you can just wedge in the screwdriver and remove the two screws opposite the ones that are easily available under the rubber bumps.



Couldn't photo that step because it took both hands :).



Prying open the screen section.  There is a flex circuit board wiring that ties it all together.  it is taped to the back of the LCD.  Peeling it off the old LDC was scary stuff.  The connectors are the silver rectangles.  They pop off with a tiny bit of prying.  There is one for the LCD and one for the digitizer.  Just look at the new parts and you'll see where they connect.



Old screen was glued in and was a mess of broken glass.  Easy to get cut.



Peeled it out, but it's not all out yet.  Need to save the plastic bezel.  Too bad, it's pretty messy.



Plugged it back together, put back the back part of the phone so I could power it up.  Holy crap! It's alive!!!


The touch screen works, the LCD lights, the home button works.  The physical keys still work. This thing is fully functional.   Removing the sim was a mistake, when it was put back in, it wiped the phone.  No worries, I had already read the email when the screen was broken and it was totally lame stuff.



Still need to figure out how to put the front panel back together and scrape out all the old broken glass.
I'm kind of surprised the thing works, it took a ton of prying and poking to get to this point.

If you want to do this on your own phone, that you want to be good as new, geez, good luck.   I only had the nerve to do this because the phone was junk and I had wasted $$ on replacement parts and didn't want to let them go to waste.   I may never get it all back together good as new.

Monday, April 30, 2012

Dependency walker handy utility


I was helped out of a jam by a free utility dependencywalker

I've been using libusb for instrument control from Java on windows.  Recently I had a machine
that just would not run the GUI control program that works on my other machines.   In netbeans I'd get this error:

C:\Program Files\Java\jdk1.6.0_24\jre\bin\LibusbJava.dll: Can't find dependent libraries

Google let me to stackoverflow and then to this handy utility
http://www.dependencywalker.com/

It opens the dll and shows you all the functions inside and the dependancies.  It told me immediately
that I was missing libusb0.dll.  

LibusbJava.dll
-Kernel32.DLL
-MSVCRT.DLL
-LIBUSB0.DLL

I had already found libusb0.dll on the web, and didn't know if i needed it.  Now I know I do.  I put it along with libusbjava.dll in the Java bin directory in my jdk.
C:\Program Files\Java\jdk1.6.0_24\jre\bin

It didn't work.   I ran dependencywalker again, and
I immediately noticed it was 64 bit not 32 bit dll.  Netbeans is 32 bit so it was the wrong version.

Downloaded it again.  You can get libusb-win32 from here
http://sourceforge.net/apps/trac/libusb-win32/wiki

Tried again.  Didn't work.  Read the readme, found out that libusb0.dll needs to be in the
Windows/system32/ directory.   Bingo, now it works!

This probably should have happened when I ran
\libusb-win32-bin-1.2.6.0\bin\inf-wizard,  but it seems it didn't.



Wednesday, March 28, 2012

Importing Java source code to eclipse from netbeans

A friend wrote a Java program for analysis with a GUI, etc and I needed to import the source, edit it, compile, etc.

These are the steps to get it up and running in Eclipse.  I've been using eclipse lately instead of netbeans, no comment on which is better, but Eclipse is up and running on my machine and seems lighter on my laptop.



  • ·         Download and unzip eclipse, windows 32 or 64 bit whatever your machine can run
o   You may need to download java re from oracle if you don’t already have it on your machine http://download.cnet.com/Java-Runtime-Environment-JRE/3001-2378_4-10009607.html?spi=b4caa20b0a59eef280e6db2bbc380730  You may have to tell eclipse where the JRE is also.  File->Properties-> Java Build Path-> Libraries, add library. Often C:\Program Files\Java\


  • ·         Unzip the file and click on eclipse icon
  • ·         Set your workspace to a directory where you want to keep your projects
  • ·         Go to workbench in the opening GUI
  • ·         File->New->Java Project
  • ·         Name the project and set JRE to JavaSE-1.6 or whatever you have installed
  • ·         You will see the project appear in the browser with a src and the JRE system library as sub folders
  • ·         Right click on the project src folder and create a new package, call it the same as at the top of the Java files, “backplane2”
  • ·         Select and drag all the .java files onto the src/package name you just created in the Package Explorer” tree on the left.   You will get a [+] and a dialog will pop up asking if you want to copy the files.  Click OK
  • ·         You shouldn’t see any red marks on the java files if all the files and package names are clean
  • ·         Create a run Configuration
o   Run->Run Configurations
o   Java Application
o   New (icon in upper left)
o   Browse and select the project name and Main Class for your project you created
o   Click “Include system libraries when searching”
·      

  •             If you have a GUI  Form file in your source, you can right click on it, select Edit With->Windows Builder to enable the editor to let you edit the file with the graphical GUI builder instead of just the text editor.

  •       Resolve any errors that appear in the files by right clicking, etc.  You may find you are missing a file, need to import a library, etc.  Right click will tell you what's wrong.




Friday, March 23, 2012

Speech Jammer Android App

I saw this whacko japanese article, and decided it might be a fun Android app to build.  I'm still on my Android app jag, maybe someday soon I'll get back to hardware.

http://www2.electronicproducts.com/How_to_build_a_SpeechJammer_Gun-article-fajb_speechjammer_march2012-html.aspx
and
http://arxiv.org/abs/1202.6106v2
Japanese speech jammer gun

Basically if you hear an echo of your own voice within a certain delay range, it bugs you so much, that you stop talking.   This is a way to interrupt a speaker who is droning on and on.  I'll let you figure out when this possibly could be an appropriate action on your part, but hey, that's not my problem.  Maybe if it was your phone you could claim it was some weird accident or tech freak out.  If you have one of these ridiculous devices in the picture, I'm sure you'd find yourself kicked out of whatever venue you were in.

I saw this, and it seems like a silly nerdy project, but it seemed (wrongly) that any android device can record, delay and play back an echo with an adjustable delay.  The only question is if the processing time can be made short enough.  An Arduino could probably do it too.  There may be some minimum delay acheivable, and I may get echos.   I'll have to see.    Of course they had a directional microphone and a directional speaker which I won't have.   But my solution will be free and fun.   Depending on how it works out, I might build an Arduino version with better sound hardware.

The basic app here will record with the mic, process the sound, then play it back.  The fun will be in what processing I do.   This could be a voice changer, or a speech jammer, etc.

First I need to be able to record audio in real time.   I don't want to write audio to the SD card, I just want to fill a small buffer with it and feed it back to AudioTrack.

Took the code from the first answer in this post.  A few tweaks and it compiled.

http://stackoverflow.com/questions/4525206/android-audiorecord-class-process-live-mic-audio-quickly-set-up-callback-func


At first it didn't work, it always failed to initialize Audio recorder, until, duh, I added the permission line to the manifest to allow use of the recorder.  Then recording began to work.

        <uses-permission android:name="android.permission.RECORD_AUDIO"/>

Allright, now it looks like it's recording, no errors, and I printed the buffer size to the Log and it appears to fill.   Now I have to figure out how to access the data and delay and pass it to AudioTrack.

I duplicated the AudioIn Thread class with an AudioOut thread.  I moved the buffer up to be a global variable so both threads could talk to it.  After some horsing around with buffer sizes, I got this code to work, the audio "echo" works and sounds good.  There were some interesting results.


//private short[][]   sound_buffers  = new short[256][160]; 
private short sound[] = new short[1000];



private ToggleButton mToggle;
private TextView mTextView;
public boolean stopped = true;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mToggle = (ToggleButton) findViewById(R.id.toggleButton1);
        mToggle.setChecked(false);
        mTextView = (TextView) findViewById(R.id.textViewEquation);
mTextView.setText("OFF");
// Hook up button presses to the appropriate event handlers.
   ((ToggleButton) findViewById(R.id.toggleButton1)).setOnClickListener(mToggleListener);
 
        
    }
    
    
    /** Called when the activity is exited */
    public void onDestroy(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        stopped = true;
mTextView.setText("OFF");
        
    }
    
    /** Called when the activity is paused. */
    public void onPause(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        stopped = true;
mTextView.setText("OFF");
        
    }
    
   



 /**

     * A call-back for when the user presses the toggle button
     */
    OnClickListener mToggleListener = new OnClickListener() {
        public void onClick(View v) {
     

    stopped = true;
    mTextView.setText("OFF");
 
        //check if light is off, if so, turn it on
        if (mToggle.isChecked()) { //turn on the light
        stopped = false;  //allows the loop in the child thread to run
        mTextView.setText("ON");
       
              try {   
              new AudioIn().start();
             } catch(Throwable x) { 
               Log.d("Record","Error reading voice audio",x);
             }
                     
              try {   
              new AudioOut().start();
             } catch(Throwable x) { 
               Log.d("Playback","Error playing voice audio",x);
             }    
                     
        }
        }
    };


    
    
    
    private class AudioIn extends Thread { 


        private AudioIn() { 
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
                start();
             }


        @Override
        public void run() { 
               AudioRecord recorder = null;
               int         ix       = 0;
               stopped = false;


               try { // ... initialise


                     int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);


                      recorder = new AudioRecord(AudioSource.MIC,
                                                 8000,
                                                 AudioFormat.CHANNEL_IN_MONO,
                                                 AudioFormat.ENCODING_PCM_16BIT,
                                                 N*2);   


                      recorder.startRecording();


                      // ... loop


                      while(!stopped) { 
                         short[] buffer = sound_buffers[ix++ % sound_buffers.length];


                         N = recorder.read(buffer,0,buffer.length);                     
                     }
                } catch(Throwable x) { 
                  Log.d("Record","Error reading voice audio",x);
                } finally { 
                  //close(recorder);
                  recorder.release();
                  stopped = true;
                }
            }


         private void close() { 
             stopped = true;
           }


       }
    
    private class AudioOut extends Thread { 


        private AudioOut() { 
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
                start();
             }


        @Override
        public void run() { 
        int sampleRate = 8000;
        AudioTrack player = null;
        int ix  = 0;
        int written = 0;
        stopped = false;


               try { // ... initialise
              
              int N = AudioTrack.getMinBufferSize(8000,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);
              //int N= 10000;
              
              player  = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT, N,
                AudioTrack.MODE_STREAM);
              
              player.play();


                      // ... loop


                      while(!stopped) { 
                     
                     short[] buffer = sound_buffers[ix++ % sound_buffers.length];


                     written = player.write(buffer, 0, buffer.length);                        
                     }
                } catch(Throwable x) { 
                  Log.d("Playback","Error playing audio",x);
                } finally { 
                  //close
                player.stop();
                stopped = true;
                }
            }


         private void close() { 
             stopped = true;
           }


       }


The interesting result is probably what you might have predicted.  You say a word.   Ten seconds later you hear it played back, which the phone hears and and plays it back again on top of the first sound ten seconds later, then again, and again getting louder each time until is is impossibly loud and you turn it off.  So the processing is going to have to do echo cancelling or only record when it's not playing.  This will require some interesting processing.  I'm not sure how the speaker phone works, or if it just is half duplex and blanks the recording while playing audio.

The delay is about 10 seconds between speaking and hearing your voice back.  That is because there is an array of buffers, providing a lot of lag.  If that is what you are going for, fine, but I wanted a short delay so I replaced the array with a single buffer.

I was a little surprised that this worked just fine.

As a global variable I defined a small buffer

private short sound[] = new short[1000];

Then in the Audio In loop above I loaded it
        recorder.read(sound,0,sound.length);

And finally in Audio out loop above I read it and played it back
        player.write(sound, 0, sound.length);


That worked, and shortened the delay, but now you HAVE to use headphones with the phone or the echos max out the phone in a few seconds. The delay seems to be half a second, and that is as short as it is going to get given that I have the buffers set to min buffer size.

You could use the directional mike and speaker, and hope you don't create feedback. There is probably echo cancelling libraries out there,  However that may be more trouble than this silly app may be worth.   So I'm going to post this dual record/playback thread code and move on to other projects.