From 2dd06e44bab05da8b3b6cf395131c818a70eb92a Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Tue, 10 Apr 2012 14:46:19 -0700 Subject: [PATCH] Add ability to select between patches in a ROM, and also do cleanups per Bryan's code review. --- android/project.properties | 2 +- android/res/raw/rom1a.syx | Bin 0 -> 4104 bytes .../synthesizer/android/AndroidGlue.java | 31 ++++++++++++++-- .../android/ui/PianoActivity2.java | 33 ++++++++++++++++++ .../android/widgets/piano/PianoView.java | 8 ++--- 5 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 android/res/raw/rom1a.syx diff --git a/android/project.properties b/android/project.properties index 0840b4a..b7c2081 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,4 +11,4 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-15 +target=android-10 diff --git a/android/res/raw/rom1a.syx b/android/res/raw/rom1a.syx new file mode 100644 index 0000000000000000000000000000000000000000..ae79b4627aa29f6388aec5d1e9eb0f887d06cf94 GIT binary patch literal 4104 zcmZ8k+f(9R5^h4o$V3oDCyW^9v zzf(oc_*Gv{cYob|^4|(A7?c$H)nxKQu~T!dpjZ;!Z12^@WI{2bU`d&L1u}{N(6&A# z;tZUpe%7tgnAT~2{trD6HQJ&sp2n~d2>zi7(fw#tFmYCcJ2Xcb?b0gudWK;n4G}Y7 z?1@rvm!U3^1Kc_ONqhz3{{)OrpbHzjaCh&jxBzU-`llKHrg4)A*C1e@3%U)gCeGH( zN%7nU5>)f~E{AJodJ1IdR-)tRnkgO-CQeqqk!WWtSnJz=66NHYL}%K{nJbaw482vH z_(Opx;!mh<{3#>758D>%_pr2XODB@fQiWJ3N9)-=Yk?Q$~M~s8tUot>HPH z@`b1;(UBJ36aAWfrJOqB-xJ&*g$%8CZ#6sh9`fI4`wcO4E}x;=61AIt{S&y9DS7QT zCX;P0BV4v+N(KEVuEf7-DAV2Id_)X&+lWHfG9@zplTQ^$xcP_wJB8w^>)$ler9;G@ zp|c2ibIK{=uk0fJYv=CrNBqwYptK}1e@FMk@P$&7f;T54I#G|Ntl{G{ekA1gM&v*Y z2U8m}@dtwX@djxh{!{;m-;z20GdDUAQl`wc|L8NAhD@hl;vdVDJ~oQt)p4hA{=1o3 z75JZt|H4NZ_13C1sz^fF5ELQN;+y&@P3XV7+;&U^h!S*3Y57&k-F;s>5*<4hsxq1G zB9VX)f=-NUZ;`S-w18`4k#6XbCBg||L8VXL!&&|(>M~TxIk|<|FUmuljl$M*vSCq zUskj@-LZ6-GV585?jF}#4*!Bw(1mXX2vA|^*+-qJ#MT14ga4OEtRUZ9xa zdX0nPQwT$%)ot1HcYZ!f9&bjg_nY@+%bvf7p1K&fs6fZwjM4;|go+eL!T%uqbN*fbrXgwt7<@;m zRw+*>TlOEKT(E1mM+dmjP%j8nH-Rg4s4kOuB;sy!RM0XUsu(}pDk-W1AQkbCY@p0F zORMojH&{O%a5 z=!i^U6AFyKE!@6`ikpSI@nh|5;eL4{Ss#g-}JNqVZa5zd?rAyw{&hmvo zr4q2gDjwJW()_PY!u)mpBmbvs1J>n}p*N(v3jo#S(;)QjEHI`w+^&0Sxe`y1Fh!VE zI0!$s%bVnxRf)5T%fDYr6jCMd|JJIPJBYs#iPYHGvEQTSm3Eklkw{U9S9T9Vyvq!L zVeeG%`vE*DB;LA~ievs^A-Djm6bQ^XibS@Bm>?l06=(Cm9OV9sWBzoj&iiB3 z0GHoiCM7z(lC+}l>8CBYm-^;ED>l+E}0KBHa6wI0ZkNBrY|aTT`^}>Qu04kD$Gzm z_WWC9BFD8#yZnIhkNk^-Fol8nqpE6A&+63eYo-|N6Nby&U!ENfKsMmzb=&P9n9NXC zDJ(U79}+QHRh@;b!)U~j$mu3ZHgV?9+TsuR-_#zOmsQ6rz?7+*B+~ zl2Z))jPgn*0P7RzW8G{fvHu~Dljm?ngXmLYj0(k*A3Hpc_4LtyKAV3@?WSxsZ!XKY zf|cG$h&whlN9XdLk6w0u{^a^Q0O~)`Lov)la62TQ%NRFrrHxJ3f018T;!0159;^82 zoCI3nJh$aaoT~$g`UoP40^t1<4+ZzM*6ls7UmQ`I6h-AXZ#VTx=}GDGE)}_AX*xhd zW^Dc!KKW00ZtS*-Plp<-cnwe6=Km=-1fLh^^gIG1p7hZrOp5sE2HpA(dcmu0&{&4rldV9+>`Khn-t+C|i;`F>K0NB~Zf|+ZOILgKr)rKfu(r>5~sp0dKwUw;s_whoS zc=M=#sWtunlY{uI7Np_j-|TSv8_#R_RGSVn_$PYOzVA$X8TlW}p2a{I?Z!9Y4UK=> zQSq&^3uZWg>an^jfi4=-0mc$71VUTIu?q;rV{E)Fne%sIK`8_6(|x&BHEwG)!$|$_ E|5<8nasU7T literal 0 HcmV?d00001 diff --git a/android/src/com/google/synthesizer/android/AndroidGlue.java b/android/src/com/google/synthesizer/android/AndroidGlue.java index 165d539..e79c87b 100644 --- a/android/src/com/google/synthesizer/android/AndroidGlue.java +++ b/android/src/com/google/synthesizer/android/AndroidGlue.java @@ -1,14 +1,41 @@ package com.google.synthesizer.android; +import com.google.synthesizer.core.midi.MessageOutputProcessor; -public class AndroidGlue { +/** + * JNI container for connecting to C++ synth engine. The actual implementation is in the cpp/src + * subdirectory of the repository, and interfaces with JNI. + * + * This class implements the MessageOutputProcessor interface, so you can use those methods to + * actually send MIDI data. + */ +public class AndroidGlue extends MessageOutputProcessor { + /** + * Create and initialize the engine. This should be done once per process. + */ public native void start(); + + /** + * Start or pause the actual sound generation. + * + * @param isPlaying Whether the sound generation should be enabled or no. + */ public native void setPlayState(boolean isPlaying); + + /** + * Send a MIDI message. Currently supported messages include DX7 sysex data, and note-on/note-off, + * but it will expand. + * + * @param midiData The midi data to send. + */ public native void sendMidi(byte[] midiData); + public void onMessage(byte[] midiData) { + sendMidi(midiData); + } + static { System.loadLibrary("synth"); } } - diff --git a/android/src/com/google/synthesizer/android/ui/PianoActivity2.java b/android/src/com/google/synthesizer/android/ui/PianoActivity2.java index 0ec8fd0..84ac602 100644 --- a/android/src/com/google/synthesizer/android/ui/PianoActivity2.java +++ b/android/src/com/google/synthesizer/android/ui/PianoActivity2.java @@ -16,8 +16,17 @@ package com.google.synthesizer.android.ui; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; + import android.app.Activity; import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; import android.widget.Spinner; import com.google.synthesizer.R; @@ -44,7 +53,31 @@ public class PianoActivity2 extends Activity { androidGlue_ = new AndroidGlue(); androidGlue_.start(); + InputStream patchIs = getResources().openRawResource(R.raw.rom1a); + byte[] patchData = new byte[4104]; + try { + patchIs.read(patchData); + androidGlue_.sendMidi(patchData); + ArrayList patchNames = new ArrayList(); + for (int i = 0; i < 32; i++) { + patchNames.add(new String(patchData, 124 + 128 * i, 10, "ISO-8859-1")); + } + ArrayAdapter adapter = new ArrayAdapter( + this, android.R.layout.simple_spinner_item, patchNames); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + presetSpinner_.setAdapter(adapter); + } catch (IOException e) { + Log.e(getClass().getName(), "loading patches failed"); + } + presetSpinner_.setOnItemSelectedListener(new OnItemSelectedListener() { + public void onItemSelected(AdapterView parent, View view, int position, long id) { + androidGlue_.sendMidi(new byte[] {(byte)0xc0, (byte)position}); + } + public void onNothingSelected(AdapterView parent) { + } + }); piano_.bindTo(androidGlue_); + } @Override diff --git a/android/src/com/google/synthesizer/android/widgets/piano/PianoView.java b/android/src/com/google/synthesizer/android/widgets/piano/PianoView.java index 0099ffb..c6fa73d 100644 --- a/android/src/com/google/synthesizer/android/widgets/piano/PianoView.java +++ b/android/src/com/google/synthesizer/android/widgets/piano/PianoView.java @@ -28,7 +28,7 @@ import android.view.MotionEvent; import android.view.View; import com.google.synthesizer.R; -import com.google.synthesizer.android.AndroidGlue; +import com.google.synthesizer.core.midi.MidiListener; import com.google.synthesizer.core.model.composite.MultiChannelSynthesizer; import com.google.synthesizer.core.music.Note; @@ -360,7 +360,7 @@ public class PianoView extends View { * Connects the PianoView to an AndroidGlue. This should probably be a MidiListener instead, * though... */ - public void bindTo(final AndroidGlue midiSink) { + public void bindTo(final MidiListener midiSink) { this.setPianoViewListener(new PianoViewListener() { { fingerMap_ = new HashMap(); @@ -369,13 +369,13 @@ public class PianoView extends View { noteUp(finger); int midiNote = Note.getKeyforLog12TET(logFrequency); fingerMap_.put(finger, midiNote); - midiSink.sendMidi(new byte[] {(byte) 0x90, (byte) midiNote, 64}); + midiSink.onNoteOn(0, midiNote, 64); } public void noteUp(int finger) { if (fingerMap_.containsKey(finger)) { int midiNote = fingerMap_.get(finger); fingerMap_.remove(finger); - midiSink.sendMidi(new byte[] {(byte) 0x80, (byte) midiNote, 64}); + midiSink.onNoteOff(0, midiNote, 64); } } private Map fingerMap_;