Make ScoreActivity work again

This patch changes the ScoreActivity (and the ScoreView that powers it)
to use a generic MidiListener rather than the old
MultiChannelSynthesizer, so that it can play with the new C++ based
sound output module.

The instrument selection maps to MIDI channel, which doesn't actually
change instruments (the synth module is not multitimbral), but this
could be made to work.

Also, the score is stored in protocol buffers, and the plan is for those
to go away, probably replaced by JSON, because of code size and build
difficulty.
master
Raph Levien 11 years ago
parent b50e3621fc
commit 599152d660
  1. 1
      android/res/menu/synth_menu.xml
  2. 3
      android/src/com/levien/synthesizer/android/ui/PianoActivity2.java
  3. 12
      android/src/com/levien/synthesizer/android/ui/ScoreActivity.java
  4. 20
      android/src/com/levien/synthesizer/android/widgets/score/PlayTool.java
  5. 18
      android/src/com/levien/synthesizer/android/widgets/score/ScoreView.java
  6. 5
      core/src/com/levien/synthesizer/core/music/ScorePlayer.java

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/settings" android:title="@string/settings" /> <item android:id="@+id/settings" android:title="@string/settings" />
<item android:id="@+id/compose" android:title="@string/compose" />
</menu> </menu>

@ -89,6 +89,9 @@ public class PianoActivity2 extends SynthActivity implements OnSharedPreferenceC
case R.id.settings: case R.id.settings:
startActivity(new Intent(this, SettingsActivity.class)); startActivity(new Intent(this, SettingsActivity.class));
return true; return true;
case R.id.compose:
startActivity(new Intent(this, ScoreActivity.class));
return true;
default: default:
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }

@ -29,16 +29,16 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import com.levien.synthesizer.R; import com.levien.synthesizer.R;
import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
import com.levien.synthesizer.core.music.Music.Score.Builder;
import com.levien.synthesizer.android.Storage; import com.levien.synthesizer.android.Storage;
import com.levien.synthesizer.android.widgets.score.ScoreView; import com.levien.synthesizer.android.widgets.score.ScoreView;
import com.levien.synthesizer.android.widgets.score.ScoreViewToolbar; import com.levien.synthesizer.android.widgets.score.ScoreViewToolbar;
import com.levien.synthesizer.core.midi.MidiListener;
import com.levien.synthesizer.core.music.Music.Score.Builder;
/** /**
* An Activity for editing or playing a score. * An Activity for editing or playing a score.
*/ */
public class ScoreActivity extends SynthesizerActivity { public class ScoreActivity extends SynthActivity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -129,9 +129,9 @@ public class ScoreActivity extends SynthesizerActivity {
} }
} }
@Override protected void onSynthConnected() {
protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) { final MidiListener synthMidi = synthesizerService_.getMidiListener();
scoreView_.bindTo(synth); scoreView_.bindTo(synthMidi);
} }
private ScoreView scoreView_; private ScoreView scoreView_;

@ -100,11 +100,9 @@ public class PlayTool extends ScoreViewTool {
* Returns true iff we need to redraw. * Returns true iff we need to redraw.
*/ */
private boolean onTouchDown(ScoreView view, int finger, int physicalX, int physicalY) { private boolean onTouchDown(ScoreView view, int finger, int physicalX, int physicalY) {
double note = view.getNoteAt(physicalY); int note = (int)Math.floor(view.getNoteAt(physicalY));
double logFrequency = Note.computeLog12TET(((int)note) % 12, ((int)note) / 12); view.getSynthesizer().onNoteOn(view.getCurrentChannel(), note, 64);
view.getSynthesizer().getChannel(view.getCurrentChannel()).setPitch(logFrequency, finger); keysDown_[finger] = note;
view.getSynthesizer().getChannel(view.getCurrentChannel()).turnOn(true, finger);
keysDown_[finger] = (int)note;
return true; return true;
} }
@ -112,9 +110,12 @@ public class PlayTool extends ScoreViewTool {
* Called to handle touch move events. * Called to handle touch move events.
*/ */
private boolean onTouchMove(ScoreView view, int finger, int physicalX, int physicalY) { private boolean onTouchMove(ScoreView view, int finger, int physicalX, int physicalY) {
double note = view.getNoteAt(physicalY); int note = (int)Math.floor(view.getNoteAt(physicalY));
double logFrequency = Note.computeLog12TET(((int)note) % 12, ((int)note) / 12); int oldNote = keysDown_[finger];
view.getSynthesizer().getChannel(view.getCurrentChannel()).setPitch(logFrequency, finger); if (oldNote >= 0) {
view.getSynthesizer().onNoteOff(view.getCurrentChannel(), oldNote, 64);
}
view.getSynthesizer().onNoteOn(view.getCurrentChannel(), note, 64);
keysDown_[finger] = (int)note; keysDown_[finger] = (int)note;
return true; return true;
} }
@ -123,7 +124,8 @@ public class PlayTool extends ScoreViewTool {
* Called to handle touch up events. * Called to handle touch up events.
*/ */
protected boolean onTouchUp(ScoreView view, int finger) { protected boolean onTouchUp(ScoreView view, int finger) {
view.getSynthesizer().getChannel(view.getCurrentChannel()).turnOff(finger); int note = keysDown_[finger];
view.getSynthesizer().onNoteOff(view.getCurrentChannel(), note, 64);
keysDown_[finger] = -1; keysDown_[finger] = -1;
return true; return true;
} }

@ -18,12 +18,6 @@ package com.levien.synthesizer.android.widgets.score;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.levien.synthesizer.R;
import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
import com.levien.synthesizer.core.music.Music.Event;
import com.levien.synthesizer.core.music.Music.Score;
import com.levien.synthesizer.core.music.Note;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
@ -34,6 +28,12 @@ import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import com.levien.synthesizer.R;
import com.levien.synthesizer.core.midi.MidiListener;
import com.levien.synthesizer.core.music.Music.Event;
import com.levien.synthesizer.core.music.Music.Score;
import com.levien.synthesizer.core.music.Note;
/** /**
* ScoreView is a UI widget that allows editing a musical score, as well as live playing. The * ScoreView is a UI widget that allows editing a musical score, as well as live playing. The
* majority of the ScoreView area shows a subsequence of the current musical score. Along the * majority of the ScoreView area shows a subsequence of the current musical score. Along the
@ -684,7 +684,7 @@ public class ScoreView extends View {
* Connects the ScoreView to a Synthesizer for playback. * Connects the ScoreView to a Synthesizer for playback.
* @synth - The synthesizer to connect to. * @synth - The synthesizer to connect to.
*/ */
public void bindTo(final MultiChannelSynthesizer synth) { public void bindTo(final MidiListener synth) {
synthesizer_ = synth; synthesizer_ = synth;
} }
@ -692,7 +692,7 @@ public class ScoreView extends View {
* Returns the synthesizer connected to this ScoreView. * Returns the synthesizer connected to this ScoreView.
* @return the connected synthesizer. * @return the connected synthesizer.
*/ */
public MultiChannelSynthesizer getSynthesizer() { public MidiListener getSynthesizer() {
return synthesizer_; return synthesizer_;
} }
@ -736,7 +736,7 @@ public class ScoreView extends View {
private double cursor_; private double cursor_;
// The synthesizer this control is bound to. // The synthesizer this control is bound to.
private MultiChannelSynthesizer synthesizer_; private MidiListener synthesizer_;
// The listener to notify of events in this control. // The listener to notify of events in this control.
private ScoreViewListener listener_; private ScoreViewListener listener_;

@ -22,6 +22,7 @@ import java.util.ListIterator;
import java.util.PriorityQueue; import java.util.PriorityQueue;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.levien.synthesizer.core.midi.MidiListener;
import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer; import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
import com.levien.synthesizer.core.music.Music.Event; import com.levien.synthesizer.core.music.Music.Event;
import com.levien.synthesizer.core.music.Music.Score; import com.levien.synthesizer.core.music.Music.Score;
@ -71,7 +72,7 @@ public class ScorePlayer {
* @param beatsPerMeasure - the time signature. * @param beatsPerMeasure - the time signature.
* @param listener - the listener to notify of events. * @param listener - the listener to notify of events.
*/ */
public synchronized void startPlaying(MultiChannelSynthesizer synth, public synchronized void startPlaying(MidiListener synth,
Score score, Score score,
double beatsPerMinute, double beatsPerMinute,
int beatsPerMeasure, int beatsPerMeasure,
@ -263,7 +264,7 @@ public class ScorePlayer {
} }
// The synthesizer to use for playing. // The synthesizer to use for playing.
private MultiChannelSynthesizer synth_; private MidiListener synth_;
// The tempo of the song. // The tempo of the song.
private double beatsPerMinute_; private double beatsPerMinute_;

Loading…
Cancel
Save