package com.moseph.mra.test;
import jade.Boot;
import jade.core.*;
import jade.core.Runtime;
import jade.wrapper.*;
import java.util.*;
import javax.sound.midi.*;
import com.moseph.mra.*;
import com.moseph.mra.agent.*;
import com.moseph.mra.agent.run.AgentRunner;
import com.moseph.mra.midi.*;
import static com.moseph.mra.midi.MidiUtilities.*;
import static java.lang.Math.*;
import junit.framework.TestCase;
/**
* This is a roundtrip test to test the incremental recording system, in a similar manner to that used in the real
* application.
* @author dave
*
*/
public class RecordAgentTest extends TestCase
{
BasicSequencerThread seq;
SongInfo info;
Fragment mainOutput;
Fragment piecewiseOutput = new Fragment();
List<Fragment> bits = new Vector<Fragment>();
RealtimeTrackToFragment rtf;
Sequencer sequencer;
Sequence sequence;
FragmentAdaptor adaptor;
boolean testUniqueNoteEnds = false;
boolean testNoHanging = false;
Track track;
double beatsToRun = 0.0;
double currentPosition = 0.0;
double fragmentSize = 1.0;
double offset = 0.7;
MetaMessage schedMessage;
boolean noteMessages = false;
boolean messageMessages = false;
public void setUp()
{
Conductor.setStoreOutput( true );
BasicSequencerThread.setScaleVelocity( false );
//Create agent arguments which load the record test piece
info = new SongInfo( new TimeSignature( 4,4 ), 120.0f, 384 );
try
{
adaptor = new FragmentAdaptor( null, info, new Fragment() );
} catch ( Exception e )
{
System.out.println( "Couldn't make sequencer for FragmentAdaptor: " + e );
e.printStackTrace();
}
}
public void atestConstantNotesB()
{
fragmentSize = 0.70;
TimerTask[] tasks = { getNoteOnTask( adaptor, 60), getNoteOffTask( adaptor, 60) };
long[][] timings = { { 0, 600 }, { 450, 600 } };
TaskGen g = new TaskGen( sequencer, tasks, timings );
test( 10, g );
}
public void testRandomPitchOverlappingNotes()
{
TimerTask[] tasks =
{
getRandomNoteTask( adaptor, sequencer ),
getRandomNoteTask( adaptor, sequencer ),
getRandomNoteTask( adaptor, sequencer ),
getRandomNoteTask( adaptor, sequencer ),
getRandomNoteTask( adaptor, sequencer ),
getRandomNoteTask( adaptor, sequencer ),
getRandomNoteTask( adaptor, sequencer )
};
long[][] timings = { { 0, 200 }, { 25, 190 }, { 50, 100 }, { 70, 1000 }, { 30, 1500 }, {500,30}, {10, 126} };
TaskGen g = new TaskGen( sequencer, tasks, timings );
test( 18, g );
}
void setupSequencer()
{
}
void test( double time, TaskGen generator )
{
beatsToRun = time;
//Boot the system
BasicSequencerThread.setConnected( false );
List<String> agentDefs = AgentRunner.getStartingAgentDefinitions( "examples/recordTest.mra", false, false, new String[] { "NoDeviceRequest=true", "FragmentSize=" + fragmentSize } );
Boot.main( (String[]) agentDefs.toArray( new String[agentDefs.size()]) );
ContainerController controller = Runtime.instance().createAgentContainer( new ProfileImpl() );
try
{
RecordAgentDetails recDetails = new RecordAgentDetails();
recDetails.setName( "recordAgent" );
recDetails.setInfo( info );
while( ! BasicSequencerThread.isDoneInit() )
{
try
{
Thread.sleep( 100 );
} catch (InterruptedException e)
{
System.out.println( "Couldn't sleep! " + e );
}
}
sequencer = BasicSequencerThread.getSequencerDevice();
sequence = sequencer.getSequence();
track = sequence.createTrack();
sequencer.recordEnable( track, -1 );
sequencer.recordEnable( sequence.getTracks()[0], -1 );
adaptor.setReceiver( sequencer.getReceiver() );
recDetails.setAdaptor( adaptor );
recDetails.setX( 0.0 );
recDetails.setY( 0.0 );
recDetails.setIgnoreNoInputDevice( true );
AgentController a = controller.createNewAgent( "recordAgent", "com.moseph.mra.agent.RecordAgent", new Object[] { recDetails } );
a.start();
} catch( Exception e )
{
System.out.println( "Could not create Record Agent! " + e );
e.printStackTrace();
}
//Create a record agent as part of the system, hooked up to our generators
generator.run();
try
{
long sleepTime = (long)( ( time / 2 + 1 ) * 1000 );
Thread.sleep( sleepTime );
} catch (InterruptedException e)
{
System.out.println( "Couldn't sleep! " + e );
}
endOfRun();
}
void endOfRun()
{
if( sequencer == null ) sequencer = BasicSequencerThread.getSequencerDevice();
sequencer.stop();
Score s = Conductor.getCurrentScore();
double offset = RecordAgent.getPasteOffset();
//Get the output that the agent produced
if( s.getFragments().size() < 1 ) fail( "No output was found!" );
Fragment agentOutput = s.getFragments().get( 0 ).copyChunk( offset, beatsToRun );
agentOutput.setMusician( null );
agentOutput.setInstrument( null );
System.out.println( "+++ Recorded:\n----------\n\n" + agentOutput);
//And the output the sequencer recorded
Fragment recordedOutput = new Fragment();
TrackToFragment ttf = new TrackToFragment( track, info, recordedOutput );
ttf.addToFragment();
recordedOutput = recordedOutput.copyChunk( 0.0, beatsToRun - offset );
System.out.println( "++++ Fragment:\n----------\n\n" + recordedOutput );
//And compare them!
assertEquals( recordedOutput, agentOutput );
}
class TaskGen implements Runnable
{
TimerTask[] tasks;
final Sequencer seq;
long[][] onsets;
public TaskGen( Sequencer seq, TimerTask[] tasks, long[][] onsets )
{
this.seq = seq;
this.tasks = tasks;
this.onsets = onsets;
}
public void run()
{
java.util.Timer t = new java.util.Timer();
for( int i = 0; i < tasks.length; i++ )
{
t.schedule( tasks[i], onsets[i][0], onsets[i][1] );
}
}
}
TimerTask getRandomNoteTask( Receiver recv, final Sequencer sequencer )
{
return new NoteTask( recv )
{
int pitch;
boolean on;
ShortMessage getMessage()
{
if( on )
{
on = false;
if( noteMessages ) System.out.println( "Note on " + info.getTickBeat( sequencer.getTickPosition() ) );
return noteOff( 0, pitch, 100 );
}
else
{
on = true;
if( noteMessages ) System.out.println( "Note on " + info.getTickBeat( sequencer.getTickPosition() ) );
pitch = (int)(random() * 24 ) + 60;
return noteOn( 0, pitch, 100 );
}
}
};
}
TimerTask getNoteOnTask( Receiver recv, final int pitch)
{
return new NoteTask( recv )
{
ShortMessage getMessage()
{
if( noteMessages ) System.out.println( "Note on " + info.getTickBeat( sequencer.getTickPosition() ) );
return noteOn( 0, pitch, 100 );
}
};
}
TimerTask getNoteOffTask( Receiver recv, final int pitch)
{
return new NoteTask( recv )
{
ShortMessage getMessage()
{
if( noteMessages ) System.out.println( "Note off " + info.getTickBeat( sequencer.getTickPosition() ) );
return noteOff( 0, pitch, 100 );
}
};
}
abstract class NoteTask extends TimerTask
{
Receiver rec = null;
boolean OK = true;
public NoteTask( Receiver recv )
{
rec = recv;
if( rec == null ) System.out.println( "Null receiver given!");
}
abstract ShortMessage getMessage();
public void run()
{
try
{
ShortMessage msg = getMessage();
rec.send( msg, -1 );
if( messageMessages ) System.out.println( "Sent message: " + msg + " at " + info.getTickBeat( sequencer.getTickPosition() ) );
}
catch( Exception e )
{
System.err.println( "Couldn't send message!" + e );
e.printStackTrace();
}
}
}
}