Attend XDA's Second Annual Developer Conference, XDA:DevCon 2014!
5,812,110 Members 39,924 Now Online
XDA Developers Android and Mobile Development Forum

[LiveWallpaper DEV] DeadMau5 Audio Visualizer [v1.4]

Tip us?
 
Metastable
Old
(Last edited by Metastable; 22nd October 2011 at 06:03 PM.)
#1  
Metastable's Avatar
Senior Member - OP
Thanks Meter 130
Posts: 419
Join Date: May 2010
Location: Chicago
Default [LiveWallpaper DEV] DeadMau5 Audio Visualizer [v1.4]

I've been working on a new Live Wallpaper with a DeadMau5 theme to it. Decided to make a build thread because I don't see many around this forum and thought it would be interesting to do.

The goal is to recreate DeadMau5's current concert setup:



It is being coded in pure Java using OpenGL ES 1.0. As I am only starting to use OpenGL ES and I think 1.0 is slightly more beginner friendly due to not needing to create a custom pipeline, I choose 1.0 though may move to 2.0 later.

I initially started by creating an LED class which is basically a primitive cube:
Code:
public class Led{
	 public Led(float width, float height, float depth) {
	        width /= 2;
	        height /= 2;
	        depth /= 2;

	        float tempVertices[] = { -width, -height, -depth, // 0
	                        	  width, -height, -depth, // 1
	                        	  width,  height, -depth, // 2
	                        	 -width,  height, -depth, // 3
	                        	 -width, -height,  depth, // 4
	                        	  width, -height,  depth, // 5
	                        	  width,  height,  depth, // 6
	                        	 -width,  height,  depth, // 7
	        };

	        short tempIndices[] = { 0, 4, 5, 0, 5, 1, 
	        					1, 5, 6, 1, 6, 2, 
	        					2, 6, 7, 2, 7, 3, 
	        					3, 7, 4, 3, 4, 0, 
	        					4, 7, 6, 4, 6, 5, 
	        					3, 0, 1, 3, 1, 2,};
	        
	        vertices = tempVertices;
	        indices = tempIndices;
	    }
	
	public void setColor(float red, float green, float blue, float alpha) {
		super.setColor(red, green, blue, alpha);
	}

        private float red, green, blue, alpha = 0f;
        private float[] vertices;
        private short[] indices;
}

I then created a Panel class which creates a flat array of Leds 10x10 for a total of 100 leds per panel. Then finally with a Cube class that creates an array of Panels, translated and rotated to create the final Cube image, here:




Which I think is decent reproduction of the real thing:



I then set off on being able to display images onto my glorious cube of light. OpenGL allows you to change the color of the elements that you are drawing, in this case cubes.

I contemplated the best approach on doing this, ultimately settling on drawing onto a bitmap and then mapping out my Leds to individual pixels of said bitmap. I draw what I want onto a bitmap of dimensions 119x145. It only needs to be this small because the amount of data that I can display on the cube is limited to how many Leds I use. At the moment there is a total of 7500 Leds in my cube. If I ever decide to increase the amount of Leds per panel I would then need to increase the size of my bitmap.

The process of mapping the actual Leds to pixels took the longest time of the entire project so far. Having to manually map 7500 pixels is not very fun. Originally creating a byte[] containing all the coordinates I was able to start the mapping process, one... pixel... at a time. I eventually ran into a wall because apparently you can only have so many bytes in your constructor, damn. The next logical step was to move over all the mappings onto an external file and then read from it when needed.

So I created this:
Code:
public class PixelMapper {
	public static void main(String[] args) throws IOException {
		InputStream stream = new FileInputStream("C:/Users/Jano/Documents/DeadMau5 Audio Visualizer/cube_mapping.txt");
	    Scanner s = new Scanner(stream);
	    List<Byte> bytes = new ArrayList<Byte>();
	    while (s.hasNextByte()) {
	        bytes.add(s.nextByte());
	    }
	    byte[] byteArray = new byte[bytes.size()];
	    for(int i = 0; i < bytes.size(); i++)
	    	byteArray[i] = bytes.get(i);
	    FileOutputStream out = new FileOutputStream(new File("C:/Users/Jano/Documents/DeadMau5 Audio Visualizer/cube_mapping"));
	    out.write(byteArray);
	    
	    System.out.println("Completed!");
	}
}
This little piece of code does two things, reads a text file containing all of my coordinates and writes them onto a binary file. I had first read straight from the text file in my wallpaper but the process would take way too long, I'm talking 3 minutes plus long. It seems my phone was simply too slow for the task and much prefers reading from a binary file, which completes in under 5 secs.

After all of the grueling mapping that had to be done, I was rewarded with this:


And here it is with a gray background to better see what's going on:


It is not a static image displayed on the cube but a dynamic image that goes to the music being played. I used the Laser Visual that I had developed for my first Live Wallpaper, Epic Audio Visualizer, to provided the lovely images.

Initially the cube would refresh very slowly, perhaps 5-10 fps, as I each Led would draw itself, making OpenGL ES crawl. So I set out to find a way to speed up the process and thus learned about Batchers.

A Batcher takes all of your vertices, in this case 8 per led, and draws them in one OpenGL call. It increased performance greatly but I lost the ability to change the color of each Led, thus no more lovely pictures. That was until I figured I could use OpenGL once again to solve this issue.

OpenGL ES allows you to assign a color to each vertex and create smooth color transitions between vertices. I don't want smooth transitions between Leds, just solid colors for each one. To remedy the problem and created a float[] and when ever I grab a color from the bitmap I copy it to the array 8 times, once per vertex. I'm not entirely sure this is the most efficient process but I couldn't find another solution that said otherwise.

Surprisingly, it worked rather well and I now get ~30 fps, which is what I currently have it hard maxed at.

With that now complete and my cube running smoothly, dancing away to Pandora, I set out to reproduce the VersaTubes(that's what I discovered they are called) in the background. They look like narrow strips of Leds together, so that's what I called my next class, Strip ;].

Similar to my Panel class, it creates an array of Leds width x height. In my case I create 2 different strips, 2x40 and 2x40. From pictures that I have looked it, it looks like the smaller strips are exactly half the size of the larger ones. Getting all of the positioning and adjustments right, I now have a decent reproduction of the VersaTubes.






My next step is going to be mapping out the strips (exciting! /sarcasm), which should not be too bad. I have already figured out that I will be needing a bitmap of dimensions 54x40, which is great because the smaller the bitmap the less time it times to draw onto it and map the colors.

And that is where I am currently in the project. Congrats on reading that giant wall of text and pictures, I hope you found some enjoyment/motivation/ideas/what ever. As you have probably seen, the cube is not a solid object in itself, but I don't plan on allowing it to rotate that far, if at all, so it really isn't visible when it's actually running.

Look for my next update and I will gladly answer any questions. Feel free to comment and give suggestions. Thanks for reading.
The Following 31 Users Say Thank You to Metastable For This Useful Post: [ Click to Expand ]
 
tyl3rdurden
Old
#2  
tyl3rdurden's Avatar
Senior Member
Thanks Meter 30
Posts: 110
Join Date: Sep 2010
Location: Concord, MA / Seoul, Korea
This is amazing and a great read. Thanks for this. Its great inspiration and help. Hope you keep up the good fight.
"Live free, Die hard."

Epic 4G
ROM: Cyanogenmod 7
Theme: Zunesque
A New Launcher UI (WIP): ROU Launcher
Twitter: Horangl3e
 
Metastable
Old
#3  
Metastable's Avatar
Senior Member - OP
Thanks Meter 130
Posts: 419
Join Date: May 2010
Location: Chicago
Thanks, I appreciate the kind words.
 
drknezz
Old
#4  
drknezz's Avatar
Senior Member
Thanks Meter 24
Posts: 216
Join Date: Aug 2010
Location: Western Australia
Man this looks slick as! When do you think you'll have a fully operational version so I can run this beast on my Galaxy S? =D
 
Metastable
Old
#5  
Metastable's Avatar
Senior Member - OP
Thanks Meter 130
Posts: 419
Join Date: May 2010
Location: Chicago
Thanks! I'd say another week at least. After the VersaTubes are done I will be adding the DeadMau5 LED head and then finishing touches, such as spotlights to create a true concert feel.
 
blazelazydays
Old
#6  
blazelazydays's Avatar
Senior Member
Thanks Meter 9
Posts: 148
Join Date: Aug 2011
this is probably the best live wallpaper concept I've seen. can't wait man!

Sent from my Nexus S 4G using XDA App
 
Andy2.2
Old
#7  
Andy2.2's Avatar
Member
Thanks Meter 5
Posts: 67
Join Date: Aug 2010
Location: Belfast
nice, looks really good
 
Metastable
Old
#8  
Metastable's Avatar
Senior Member - OP
Thanks Meter 130
Posts: 419
Join Date: May 2010
Location: Chicago
Quote:
Originally Posted by blazelazydays View Post
this is probably the best live wallpaper concept I've seen. can't wait man!

Sent from my Nexus S 4G using XDA App
Thanks, stay tuned for progress updates.

Quote:
Originally Posted by Andy2.2 View Post
nice, looks really good
Thanks. Nice avatar picture =].
 
killersnowman
Old
(Last edited by killersnowman; 11th August 2011 at 06:37 AM.)
#9  
Senior Member
Thanks Meter 51
Posts: 327
Join Date: Mar 2011
Location: SLO
i just started programming (4 months ago) again after 4 years and all the logic is still there but im a bit rusty on some of the syntax. what does the operator '/=' do?

Code:
                width /= 2;
	        height /= 2;
	        depth /= 2;
i cant remember and any search for '/=' returns nothing usefull. i gotta dig up my Kernighan & Ritchie 'The C Programming Language' book. its got most of the syntac for modern languages in it. (and yes i know you are using java, but java is C like in syntax..)

thanks

/=/=/=/=/=/=/=/=/=\=\=\=\=\=\=\=\=\

nvm, druggggeedd it up from the dregs of my mem

width = width / 2

correct?
 
exb0
Old
#10  
exb0's Avatar
Senior Member
Thanks Meter 411
Posts: 1,762
Join Date: Oct 2010
Location: 3.137136,101.594663
Man can't wait for this!
Current Devices :
LG Nexus 5
LG Nexus 4
Samsung Galaxy Nexus
Sony W810


Ex Devices :
HTC Dream - SOLD
HTC HD2 - Water Damaged :'(
LG Nexus 4 - Stolen </3
HTC Sensation - Retired
Nexus One - Retired
ZTE V9 - Retired


My Google Plus
My Website
Transparent StatusBar Mod Thanks to ZduneX25
Register for Dropbox here

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes