[ Content | Sidebar ]

LibGDX: Demos on Github

March 12th, 2013

I have made a start on fully Mavenizing my LibGDX demos and placed them up on Github.

The good news is that the core netthreads-libgdx library and the demos have been converted to use the latest version of LibGDX (0.9.9 at the time of writing). Taking the latest build from the LibGDX repo should mean that it will be easier to keep these up to date with changes to Scene2d etc.

I used the LibGDX archetype so you should have no problems building these once you have jumped through a few (minor I hope) hoops to install some dependencies on non-maven-available jar files like the tween-engine and fixtureatlas. There are detailed instructions. If you are having problems make a comment/email me or raise an issue on the issues list.

The core library is here. You will need this for the demos.

The demos up so far are:

Simple Shooter

This is the same simple shmup as before but with a lot of code tidied up. It is here.

Menu

Simple Shooter

Main

Simple Shooter

Box2d-Test

A straightforward Box2d demo with a central rotating fixture, falling objects and nice fading labels. It is here.

box2d-test
 

Box2d-Bumpers

Bumper walls, anti-gravity, tumbling blocks and flashing psychedelics..what’s not to like? Shows how to detect collisions between box2d elements and how to handle them.

box2d-bumpers

Putting these all the once place I have discovered a ton of bugs which I have had a chance to go through and fix. Later demos fixed stuff which I never went back and applied to the earlier ones like SimpleShooter so this has been a great exercise. It’s even given me a bit of a kick to write some more.

NOTE: All the LibGDX demos linked on this blog go to GitHub now. It is easier to manage them all in the one place. The new demos have a bunch of new concepts in them like the removal of the old Singleton patterns with Google Guice managing this stuff instead. Also it’s Maven from here on. If you are familiar with the old code and build mechanism then you’ll just have to come along for the ride. I promise you’ll learn stuff that will benefit you.

JavaFX: Java OSC library and JavaFX-based OSC Router

March 5th, 2013

As part of my Tonome LibGDX project I decided to convert the LibGDX application to use OSC messages instead of triggering samples internally to the application.

Tonome2

The application could broadcast OSC note on and off messages to a Puredata instance and map that down to MIDI with a Puredata script. The first part of that was to use a Java OSC library that I would build into the application.

I had a look at the existing Java OSC libraries available but I couldn’t use them as they relied on creating a new instance of each message for each message sent. This is a no no with Android as you would have the garbage collector running. The OSC specification is up on the OSC website so why not try and write my own using a pooled approach where we reuse messages sent. The result is the osc-common and osc-network components.

osc-common

This is an almost fully compliant implementation of the OSC message spec. There are bits missing but for my purposes nothing essential.

The library like all the components is fully mavenised and has unit tests to ensure the output of the objects comes out as expected using the encode and decoder components.

Technically you can flood your client app with messages unless you set the pool size to a maximum but hopefully that won’t be an issue if the throughput is high enough. I guess that remains to be seen in the real world. It’s not been an issue for me yet.

osc-network

This implements a client and server implementation for the encoder and decoder components. It uses NETTY a super fast networking library for all the networking parts and is unique in that I have not seen any examples of NETTY4 using UDP to implement anything like this. This was a big sticking point in the development as I wanted to use NETTY4 but it was still in beta at the time with not many source code examples. There might be more recent version of NETTY but I’ll leave it as it is for now.

I got this component working with my Tonome project against the Puredata script that I had written but I found out that Puredata would choke when sent a lot of messages. Initially my heart sank I as I could see that I would have to write my own application to do this. But any failure is an opportunity right? My Swing skills are non-existent but my Flex skill are strong so I figured I would try to look for a Java UI library that would fit my needs. After looking around I noticed Pivot and JavaFX (which had just reached version 2 at that point). Rather than go straight in I thought I would prototype something easier (and more useful) so I embarked on trying to put a front-end on my Mavenize command line tool instead.

Pivot was eventually thrown out instead of JavaFX which I have successfully used to put a useful UI onto my application for converting any existing Java project to the Maven file structure. Once I had the skills I sat down and started to develop an application which uses the osc-common and osc-network libraries to route OSC messages to MIDI. That application is osc-router.

osc-router

oscrouterfx
The osc-router will listen to OSC messages sent to it on the chosen port and then you can assign labels to the message value received. You can’t edit the labels whilst the tool is in ‘listen’ mode but once you pause you can set them. The interface lets you route the messages (as long as they have the expected note-on and note-off values) to a specified MIDI device. It will let you save and load your settings.

This is very much a work in progress. There are possibly latency issues to do with the fact I am creating other objects to represent the incoming messages. I think there is a rewrite of the message path on the books.

The project has been put up onto GitHub here.

Lot’s of interesting JavaFX stuff to look at including file open/save dialogs,  editable label cells, combobox selection cells, icon status cells and a background service. The application also sports a message cache, MIDI device handling  and lots more. I’m also  using XStream to persist the the OSC message values and label settings to an XML file which has proved to be quite seamless.

Update #1

  • I have modified the application to load a default message configuration file. This is for illustration so you can see how the UI works without having to have an OSC producing tool.
  • I am in the process of posting the Tonome OSC code up on Github as well.

Update #2

The Tonome OSC-aware application is now up on Github. You can find it here. It runs on Android but there are still a few issues to iron out like the inability to edit the hostname and port values. It is here.

If you run it from the desktop it will connect to the stated hostname and port that the OSC-Router application is setup for. I have altered the router to load up the Tonome message definition by default. All you need to do it map the note on/off message and route them to a midi target.

More details in further posts.

JavaFX: Mavenize-FX – GitHub

March 3rd, 2013

The mavenize-fx project is now up on GitHub. This will be the new home for the project.

jfx1

I have left the google code site up to host executables only.

You can download an executable JAR file from here.

I have used the 32 bit JDK so I think it should run on any x86 based platform.

JavaFX: Mavenize-FX

December 21st, 2012

As part of learning JavaFX I decided to put a nice UI onto my existing ‘mavenize’ tool. This is currently a command line tool and does what it says in tin, so to speak. To find out more about this you can read the original post here. I modified the original component to allow a ‘listener’ to attach itself to the processing section. The mavenize process calls back into the listener to notify of what it was currently doing. I wanted the UI to reflect the changes being made (not as simple as it sounds as we will discover).

What I wanted for the user interface was:

  • Source and target folder selection.
  • Choice of package type.
  • Choice of version number.
  • A list which shows the projects being processed.
  • A big button which you hit to kick the process off.

So here it is:

jfx1

I will discuss each feature in turn and what was interesting about it. Here is a rough class diagram of how the various components are connected.

mavenize_class

I have numbered the parts of the interface I want to focus on.

jfx2

Here goes…

(1) Inputs

These are the source and target directories. They are standard TextField controls and are populated from the choice of folder made using the java directory chooser. They are not populated on startup. You will need to choose a folder for each. It can’t be the same folder. If you do not populate or make them the same you will get an Alert box popping up.

jfx3

This is one thing which I was a bit non-plussed about. There doesn’t seem to be a standard Alert box for JavaFX. I ended up rolling my own from suggestions I found on StackOverflow. I have some ideas to improve my implementation to make it much nicer. I always liked the Flex alert which defocussed the whole screen and had a message in the middle. I think it would be nice to have something like that.

(2) Browse Buttons.

When these are clicked we use the folder chooser.


// At the top of the controller class.
@FXML
private TextField sourceInput;

@FXML
private Button sourceButton;

// The method.
public void sourceButtonAction(ActionEvent event)
{
	Window window = getWindow(sourceButton);

	if (window != null)
	{
		File directory = directoryChooser.showDialog(window);

		if (directory != null)
		{
			sourceInput.setText(directory.getPath());
		}
	}
}

The DirectoryChooser object is created in the constructor and shared between the source and target button handlers. Straightforward stuff.

(3) Process button.

This is an interesting one and brings in a bit of an overlap to the table view. When this button is pressed it will validate the UI inputs and if fine then it will call a method from the MavenizeClient class.

public void activateButtonAction(ActionEvent event)
{
	logger.debug("activateButtonAction");

	String sourcePath = sourceInput.getText();
	String targetPath = targetInput.getText();
	String versionText = versionInput.getText();

	if (sourcePath == null || sourcePath.isEmpty())
	{
		// Alert
		Alert alert = new Alert(stage, ApplicationMessages.MSG_ERROR_INVALID_SOURCE);

		alert.showAndWait();
	}
	else if (targetPath == null || targetPath.isEmpty())
	{
		// alert
		Alert alert = new Alert(stage, ApplicationMessages.MSG_ERROR_INVALID_TARGET);

		alert.showAndWait();
	}
	else if (versionText == null || versionText.isEmpty())
	{
		// alert
		Alert alert = new Alert(stage, ApplicationMessages.MSG_ERROR_INVALID_VERSION);

		alert.showAndWait();
	}
	else if (sourcePath.equals(targetPath))
	{
		Alert alert = new Alert(stage, ApplicationMessages.MSG_ERROR_INVALID_PATHS);

		alert.showAndWait();
	}
	else
	{
		// Process
		mavenizeClient.process(sourceInput.getText(), targetInput.getText(), versionInput.getText(), packageCombo.getValue());
	}
}

The MavenizeClient will start the background service which performs our potentially long running process.

public boolean process(String sourcePath, String targetPath, String version, String packaging)
{
	boolean status = true;

	if (sourcePath == null || sourcePath.length() == 0 || targetPath == null || targetPath.length() == 0)
	{
		throw new IllegalArgumentException();
	}
	else
	{
		mavenizeService.setSourcePath(sourcePath);
		mavenizeService.setTargetPath(targetPath);
		mavenizeService.setVersion(version);
		mavenizeService.setPackaging(packaging);

		mavenizeService.reset();

		mavenizeService.start();
	}

	return status;
}

Note the call to ‘reset’ before we call ‘start’ on the service. We need to this as each run has an internal status. Once complete we cannot call ‘start’ again without resetting the status.

The service has an ‘active’ property which we ultimately ‘bind’ the button ‘enabled’ status to so that as long as the service is running the button will be disabled. This is the power of binding and is a very elegant means to do this sort of thing.

(4) Table View.

This binding worked fine between the process button and the service active status. Not so for the TableView and the associated ObservableList. Here are the main points:

  • Create an ObservableList in the controller to act as the ‘model’.
  • The ObserveableList is passed by reference to the service.
  • The service updates the list with new data objects and alters the properties of the object as the proocess runs.
  • The properties of the data object are ‘bound’ to columns in the TableView which (technically) should update.

Now, I wasn’t actually expecting this to  work. Can you really update a bound list in a background thread? Well, yes so it seems..sort of.  The problem is this – the TableView does update (just to be on the safe side I used a synchronised version of the ObservableList) but it is not consistent. The TabelView was updating or not updating the list on a purely random basis. In short, we can’t expect the view to refresh itself when we are adding stuff to the bound list in a thread which is not the UI thread. It works perfectly if you fill and update the data items in the UI thread.

After a lot of head scratching I implemented a method to force the view to update. This must be kicked off using the runLater mechanism otherwise it would be modifying the scene view directly and throw a massive wobbly. It gets called whenever an item is added to the list or modified. This is a bit of a crufty solution but it works! If you examine the class diagram above you will see that the service is given a reference to the ImplementsRefresh interface.

@Override
public void refresh()
{
	Platform.runLater(new Runnable()
	{
		public void run()
		{
			ObservableList<TableColumn<ProjectResult, ?>> columns = dataTable.getColumns();
			TableColumn<ProjectResult, ?> column = columns.get(0);

			if (column != null)
			{
				column.setVisible(false);
				column.setVisible(true);
			}
		}
	});

}

Binding a list to a table in this way is a really cool feature.

(5) Icon cell.

So I am thinking that I want is a column with icons which will change according to a bound property in the data item.

Here is the data item

package com.netthreads.javafx.mavenize.model;

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
 * Project result bean.
 *
 */
public class ProjectResult
{
	public static final String ATTR_GROUP_ID = "groupId";
	public static final String ATTR_ARTIFACT_ID = "artifactId";
	public static final String ATTR_FILE_PATH = "filePath";
	public static final String ATTR_FILE_COUNT = "fileCount";
	public static final String ATTR_STATUS = "status";
	public static final String ATTR_WORKING = "working";

	public static final String TITLE_GROUP_ID = "groupId";
	public static final String TITLE_ARTIFACT_ID = "artifactId";
	public static final String TITLE_FILE_PATH = "File Path";
	public static final String TITLE_FILE_COUNT = "File Count";
	public static final String TITLE_STATUS = "Status";
	public static final String TITLE_WORKING = "~";

	public static final String STATUS_CREATE = "Creating";
	public static final String STATUS_COPY = "Copying";
	public static final String STATUS_FILE = "Add File";
	public static final String STATUS_POM = "Pom";

	public static final int WORKING_READY = 0;
	public static final int WORKING_BUSY = 1;
	public static final int WORKING_DONE = 2;

	private StringProperty groupIdProperty;
	private StringProperty artifactIdProperty;
	private StringProperty filePathProperty;
	private IntegerProperty fileCountProperty;
	private StringProperty statusProperty;
	private IntegerProperty workingProperty;

	/**
	 * Construct results.
	 *
	 */
	public ProjectResult()
	{
		groupIdProperty = new SimpleStringProperty(this, ATTR_GROUP_ID);
		artifactIdProperty = new SimpleStringProperty(this, ATTR_ARTIFACT_ID);
		filePathProperty = new SimpleStringProperty(this, ATTR_FILE_PATH);
		fileCountProperty = new SimpleIntegerProperty(this, ATTR_FILE_COUNT);
		statusProperty = new SimpleStringProperty(this, ATTR_STATUS);
		workingProperty = new SimpleIntegerProperty(this, ATTR_WORKING);

		groupIdProperty.set("");
		artifactIdProperty.set("");
		filePathProperty.set("");
		fileCountProperty.set(0);
		statusProperty.set("");
		workingProperty.set(WORKING_READY);
	}

	public final String getGroupId()
	{
		return groupIdProperty.get();
	}

	public final void setGroupId(String groupId)
	{
		this.groupIdProperty.set(groupId);
	}

	public final String getArtifactId()
	{
		return artifactIdProperty.get();
	}

	public final void setArtifactId(String artifactId)
	{
		this.artifactIdProperty.set(artifactId);
	}

	public final String getFilePath()
	{
		return filePathProperty.get();
	}

	public final void setFilePath(String filePath)
	{
		this.filePathProperty.set(filePath);
	}

	public final int getFileCount()
	{
		return fileCountProperty.get();
	}

	public final void setFileCount(int fileCount)
	{
		this.fileCountProperty.set(fileCount);
	}

	public String getStatus()
	{
		return statusProperty.get();
	}

	public void setStatus(String status)
	{
		this.statusProperty.set(status);
	}

	public int getWorking()
	{
		return workingProperty.get();
	}

	public void setWorking(int working)
	{
		this.workingProperty.set(working);
	}

	/**
	 * Properties.
	 *
	 */

	/**
	 * Return property.
	 *
	 * @return The property.
	 */
	public final StringProperty groupIdProperty()
	{
		return groupIdProperty;
	}

	/**
	 * Return property.
	 *
	 * @return The property.
	 */
	public StringProperty artifactIdProperty()
	{
		return groupIdProperty;
	}

	/**
	 * Return property.
	 *
	 * @return The property.
	 */
	public StringProperty filePathProperty()
	{
		return filePathProperty;
	}

	/**
	 * Return property.
	 *
	 * @return The property.
	 */
	public IntegerProperty fileCountProperty()
	{
		return fileCountProperty;
	}

	/**
	 * Return property.
	 *
	 * @return The property.
	 */
	public IntegerProperty workingProperty()
	{
		return workingProperty;
	}

}

So the table column definition looks like this:

// Working indicator
TableColumn<ProjectResult, Integer> workingCol = new TableColumn<ProjectResult, Integer>(ProjectResult.TITLE_WORKING);
workingCol.setCellValueFactory(new PropertyValueFactory<ProjectResult, Integer>(ProjectResult.ATTR_WORKING));

// Custom Cell factory converts index to image.
workingCol.setCellFactory(new Callback<TableColumn<ProjectResult, Integer>, TableCell<ProjectResult, Integer>>()
{
	@Override
	public TableCell<ProjectResult, Integer> call(TableColumn<ProjectResult, Integer> item)
	{
		WorkingTableCell cell = new WorkingTableCell();
		return cell;
	}
});

The WorkingTableCell class takes the integer value you set in the workingProperty of the ProjectResult data object and sets the appropriate icon.


package com.netthreads.javafx.mavenize.controller;

import java.io.InputStream;

import javafx.scene.control.TableCell;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;

import com.netthreads.javafx.mavenize.app.ApplicationStyles;
import com.netthreads.javafx.mavenize.model.ProjectResult;

/**
 * Working status custom cell.
 *
 */
public class WorkingTableCell extends TableCell<ProjectResult, Integer>
{
	private String[] ICONS =
	{
	        "/bullet_white.png", "/bullet_red.png", "/bullet_green.png"
	};

	private ImageView imageView;
	private HBox hBox;

	/**
	 * Construct cell image holder.
	 *
	 */
	public WorkingTableCell()
	{
		imageView = new ImageView();

		hBox = new HBox();
		hBox.getChildren().add(imageView);
		hBox.getStyleClass().add(ApplicationStyles.STYLE_WORKING_STATUS_CELL);
	}

	/**
	 * This will take the value and lookup the appropriate icon for display in
	 * the cell.
	 */
	@Override
	protected void updateItem(Integer item, boolean empty)
	{
		super.updateItem(item, empty);

		if (!empty)
		{
			if (item < ICONS.length)
			{
				String iconName = ICONS[item];

				InputStream stream = getClass().getResourceAsStream(iconName);
				Image goImage = new Image(stream);

				imageView.setImage(goImage);

				setGraphic(hBox);
			}
		}
	}

}

I wanted the icon image to be centred in the cell. I’m unsure if there is a programmatic way to do this but I figured I coud do it by defining a style and setting it to the holding HBox.

.workingStatusCell {
	-fx-alignment : center;
	-fx-fill-height : true;
}

And that’s it. I am going to publish the code onto either Google code or github but in the meantime here is the code. As usual Apache 2.0 licence.

JavaFX: Pivot and JavaFX

December 19th, 2012

I have been trying out both Pivot and JavaFX as means to write a user interface for my proposed tool to route OSC messages to Midi (see previous post).

Rather than jump straight in with something which needs lots of features I decided to try something simple. My mavenize tool needs a front end so I thought that would be a good candidate. Mavenize takes a source and target directory and produces a ‘mavenized’ version of the source project in the target folder. It will create the appropriate folders and move all the files into the appropriate place. It is the dogs-bollocks and I have used it a lot to save me lots of boring graft. Stop being a mug and just download the command line version from here and better still there is a version with a proper UI coming in the next post.

Since I was once a big Flex user I decided to look at the two SDK’s available for Java which use a ‘flex’-like approach. These are Apache Pivot and JavaFX that is now part of the standard Java 7 SDK. Both of these have the UI layout and components defined in an XML file and the logic for the UI in the code. Also, these SDK’s embody the concept of a scene-graph for assembling the interface components which at least promises to deliver something more elegant than the somewhat old-skool collection of composite objects which make up Swing.

pivot1

I put a basic Pivot version together fairly quickly. I am not entirely sure why they need to have their own version of the collection classes, I am not going to speculate as I am sure there is a good reason. This put me off for a start. Does the world need another set of collection classes beyond those tried and trusted from the JDK? This is a desktop app and they were always going to have to use the JDK. As you can see from the screenshot below there was also a custom file chooser dialog. Somewhat frustrating.

pivot2

Also, as I was trying to write a desktop application I was a bit confused by the data model that the table view used. It turned out to be a list of maps which was fine but I couldn’t find a single example of how to use this in a programmatic way outside the bxml examples. I figured it out the end but was left with a sense that this is glaring gap in their otherwise exhaustive set of examples. If you try to use a framework and suddenly find yourself rushing towards an edge case that is a bad sign.

I am not going to spend much time on my Pivot version of the application. The framework is usable but pales into insignificance against JavaFX in terms of ease of use.

So, then I decided to take a look at JavaFX. I have to say I am pleasantly surprised. The scene graph and concept of data binding is very close to Flex. So much so that I think I might be a bit miffed if I was Adobe. There is a lot of (ahem) influence from Flex in the feature set. The scene builder tool is probably one of the nicest UI builder tools I have ever used with lots of cleverness to help you layout your user interface. Here is screenshot of the finished tool.

javafx1

There is a whole bunch of JavaFX goodness here where I have solved the issue of updating the table view from a background service and have a nice custom cell with selectable images. I put the last one in because I knew I would need it for my proposed OSC router application.

I am going to outline what I did in the next post.

Java OSC: Midi Definitions

September 21st, 2012

I thought I would put up an example of my OSC java library sending messages to the pure data instance but I discovered a problem. If you send lots of OSC messages to pure data without a decent interval pure data crashes. Not good. So I have reluctantly started what I didn’t want to do which is to write my own decoder. I imagine this to be a bit like Osculator. Believe me this is pain in the backside as I know nothing about java GUI. I saw a funny comment recently which stated that Swing is ‘distilled mediocrity’ which is just about sums up my feelings about it.

Don’t get me started on oscVstBridge which I couldn’t get to work despite downloading the core java VST client and a major amount of faffing about.

Here is some definitions which I had to hunt down and build myself as I couldn’t find any code which would suffice. Each note in NOTE_NAMES has a corresponding value in NOTE_VALUES.

	/**
	 * All MIDI note names.
	 */
	public static final String[] NOTE_NAMES =
	{
	        "C-1", "C#-1", "D-1", "D#-1", "E-1 ", "F-1 ", "F#-1", "G-1 ", "G#-1", "A-1 ", "A#-1", "B-1 ", "C0", "C#0", "D0", "D#0", "E0", "F0", "F#0", "G0", "B8", "G#0", "A0", "A#0", "B0", "C1", "C#1", "D1", "D#1", "E1", "F1", "F#1", "G1", "G#1", "A1", "A#1", "B1", "C2", "C#2", "D2", "D#2", "E2", "F2", "F#2", "G2", "G#2", "A2", "A#2", "B2", "C3", "C#3", "D3", "D#3", "E3", "F3", "F#3", "G3", "G#3", "A3", "A#3", "B3", "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", "C5", "C#5",
	        "D5", "D#5", "E5", "F5", "F#5", "G5", "G#5", "A5", "A#5", "B5", "C6", "C#6", "D6", "D#6", "E6", "F6", "F#6", "G6", "G#6", "A6", "A#6", "B6", "C7", "C#7", "D7", "D#7", "E7", "F7", "F#7", "G7", "G#7", "A7", "A#7", "B7", "C8", "C#89", "D8", "D#8", "E8", "F8", "F#8", "G8", "G#8", "A8", "A#8", "C9", "C#91", "D9", "D#9", "E9", "F9", "F#9", "G9"
	};
	
	/**
	 * All MIDI note values.
	 */
	public static final int[] NOTE_VALUES =
	{
	        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 120, 121,
	        122, 123, 124, 125, 126, 127
	};

This is all the MIDI note definitions and corresponding values in some handy Java. I was using this to send each note in turn as a test. Feel free to convert this to your language of choice. You can’t stick a license on a list of numbers or can you.

LibGDX:Audio – Tonome OSC version

September 13th, 2012

Ah sweet synthesized music! Here is a screenshot of my Tonome LibGDX application sending OSC Bundle messages to a instance of pure data. The pure data instance is broadcasting the OSC Bundle contents as Midi note out messages to a bank of Crystal synths running inside Podium. Each VST synth instance has been assigned a different Midi channel where each channel is associated with a different panel on the Tonome application. Neat!

Tonome_osc

This has been my project for the last couple of weeks.

I am going to tidy up the code somewhat and publish this next. I’ll expand a bit on the implementation as well. There is all sorts of stuff in the code like my own java OSC implementation, netty, pure data and google Guice would you believe.

LIBGDX – Demos Update to 0.9.6

September 2nd, 2012

I have finally updated all the LibGDX demos to the latest release version of LibGDX as of today (0.9.6).

Here are the links

Tonome – A tonematrix style sample player here.

Box2D with Scene2D – Bumpers demo here.

Box2D with Scene2D – Simple fixture demo here.

Game Test – Simple shoot-em-up with settings panel and slide transitions here.

The update was fairly painless with a few things to note:

  • LibGDX 0.9.6 now deals correctly with the ‘finish’ method and actions. The ‘finish’ method is now called on every associated action when an actor is marked for removal. This is important as the overridden ‘finish’ is where we put our actions back into the appropriate pools. Prior to this fix I was having to sub-class actor to implement this myself.
  • The tween engine has been updated also to version 6.3.3. The only change I had to make was alter the callback mechanism.  I still can’t see a way to re-initialise a composited tween but I need to investigate further .
  • I note there is event management in the yet unpublished version of Scene2d. This promises to be interesting but it’s not in 0.9.6 which is what we are using here.  I am not going to go near any of that stuff until a proper release is made.

Some of the demos have a maven pom file.Technically these are purely for illustration as they don’t pull the libGDX files from any repository just locally. I use them to generate the project files for the maven style layout (resources directory etc).

Note

These demos have all been updated, mavenized and are now up on Github. There has been a ton of fixes and improvements.

JAVA: MAVENIZE – Update

July 16th, 2012

Whilst this component hasn’t exactly set the internets on fire can I give another shout out for my ‘mavenize‘ tool. This is a command line tool for ‘mavenizing’ java projects. I have found myself using this a fair bit when I am looking to bring older components into a existing maven java project and it can save a fair bit of faffing around.

Using it is as simple as:

java -jar mavenize-1.0.2.jar -iC:\Development\java\project\original -oC:\Development\java\project\mavenized

I have made some minor recent fixes. If you are interested in looking for a good example of the use of the org.apache.commons.io.DirectoryWalker class then you should take a look at the source code.

LibGDX – Audio – Tonome

June 24th, 2012

Tonome is an matrix style sample player in the same vein as Tonematrix and Monome. This version is the result of a lot of attempts to get something which is usable. I think this is close but not quite there yet but I’m going to release the code as I’m tired of playing around with it and want to leave it for a while.

Source code here.

You can get a flavour of what’s involved from these screenshots below.

Tonome2

Features include:

  • Multiple panels with a nice sliding transition between them including a new diagonal transition.
  • Matrix buttons  with a toggle action so that as you slide over the buttons you are either setting or clearing. The buttons will also flash as the assigned sound is being played.
  • Bar display to show which bar is currently being played.
  • Touch buttons to navigate between panels which are animated to flash along to the bar display.

Tonome2

I couldn’t decided on how to present the settings for volume and BPM so I have placed them into a fairly boring setting view for the moment. There should be some kind of slide in panel which has these on the main interface but I’ll put that off for the moment. You can exit the touch panels by ESC on PC and the ‘back’ key on the phone.

Tonome4

The assigned samples are fixed for the moment as this is still technically a demo/prototype. You can see in the code where they are inserted if you want to change them.

I have only tried this in the emulator for the moment as my Nexus phone won’t talk to my PC anymore :( The android project is bundled with the source. The emulator gives me a laughable 4fps which is unusable so there may be an issue with running it on a real phone. If it works can someone tell me.

Note Choice

I studied tonematrix to see what notes the application used as they have been chosen specifically to go together. These are A3,B3,D3,E3,G3,A4,B4,D4..and so on.

Sample Choice

Tonome3

I spent ages trawling freesound to try and get some decent samples that sounded good together. I can’t say I have succeeded. This stuff is hard. I went through a ton of them before selecting the final choice. I’m still unhappy with how they sound. A future plan is to forego samples altogether and instead have OSC support but in the meantime the samples demonstrate the intention of how to build up a composition  from the different panels. There are two panels with ‘lead’ type sounds, one bass panel and one drum machine panel with some nice samples from a TR909.

There is a subtlety in the sample choice which I should point out as you are bound to notice it. The samples on the second (right) panel appear to play together in polyphony okay. There is always going to be a slight delay in the launching of each sample but if your lucky it shouldn’t be noticeable. The samples on the first panel, on the other hand, don’t seem to sit so well together once you start to bunch them up on the same bar. For the first 4 notes on my PC it plays fine but thereafter increasing the number of simultaneous notes makes a scratching sound appear. I am convinced this is something to do with the sample itself as the other samples don’t exhibit this behaviour. If I get a chance I will try and fix this somehow. You can always insert your own samples. If you get some decent ones and want to share then drop me a line.

OSC Support

I think there the core of a nice control panel for audio here. It would require proper message support for OSC messages but should be doable. I haven’t managed to find a suitable OSC  library (with the appropriate license) yet but I will keep looking.

Re-pitching Audio Samples

I tried to use SoundTouch to re-pitch a selected audio sample but could only get it to work on the desktop version as I put together a kind of hacky solution.

  • Loading the base sample and re-pitching.
  • Creating a WAV file sample image with the re-pitched data  in memory.
  • Creating a Sound class but hi-jacking the file load to pull the data from my in-memory WAV file image.

This actually worked really well but only for the Desktop since Android uses SoundPool to manage audio samples. You can find the code in a class called “AudioHelper”. As I say it never made the final cut but might prove useful if you are targeting a desktop application only.

Source code here. As usual Apache 2.0 license.

 

Update #1

I am in the process of implementing OSC support. When I get this working the plan is to show how to hook the panel up to MIDI. I’ll probably drop the sample playing aspect if this as well as make the UI look a bit nicer.