Synchronise to beats per minute / Send quantised messages - java

I'm getting periodic signals (beats per minute) from a Transmitter and now want to call methods in a fraction of the period, e.g. send 1/1, 1/2, 1/4, 1/8, 1/16,.. notes.
My solution for this is to create a thread, do a busy wait and then execute the methods. The problem here is that listening to the signal, processing it and sending it back creates a delay of a few milliseconds (depending on the system).
So now I want to determine the delay between the incoming signal and the periodic signal of the thread and if the delay is != 0, stop the current thread and start a new thread after "bpm - delay" milliseconds. How can this be done ?
Illustration:
transmitter signal: |----|----|----|----|
******runner signal : |----|----|----|----|
delay runner signal by "onePeriod - delay" milliseconds:
transmitter signal: |----|----|----|----|
***"runner signal :**** |----|----|----|----|
Both signals are now in sync.
public class Quantiser implements Receiver{
private int[] bpmsInMillis = new int[4];
private int bpmInMillis=0;
private double smallestNote = 1;
private long period=0;
private long fire=0;
private long prevTimeStamp=0;
private Runnable runny = new Runnable() {
#Override
public void run() {
while(true){
fire = System.nanoTime() + period;
while(System.nanoTime() < fire){} // busy wait
// Call some methods here.
}
}
};
private Thread thread = new Thread(runny);
#Override
public void send(MidiMessage message, long timeStamp) {
// Calculate average bpm
for(int i=0; i<bpmsInMillis.length-1;i++)
bpmsInMillis[i] = bpmsInMillis[i+1];
bpmsInMillis[bpmsInMillis.length-1] = (int) ((timeStamp - prevTimeStamp) / 1000);
bpmInMillis = arithmeticMean(bpmsInMillis);
prevTimeStamp = timeStamp;
period = (long) (bpmInMillis * smallestNote * 1000000);
if(!thread.isAlive()) {
thread.start();
}
/*
else{
Calculate delay between signal and thread-signal.
if(delay != 0){
Delay new thread by "bpm - delay" milliseconds.
Stop old thread.
Start new thread.
}
*/
}
#Override
public void close() {
}

One option would be to implment a Phase-Locked Loop (PLL).
http://en.wikipedia.org/wiki/Phase-locked_loop
Basically, you'll need two threads: One thread sits in a loop waiting for the input beats, and each time it gets a beat, it records the time of arrival.
long time_of_last_beat;
while (true) {
wait_for_next_beat();
time_of_last_beat = System.currentTimeMillis();
}
The other thread sits in a loop that goes sixteen times as fast:
long semiquaver_duration = <starting guess>;
while (true) {
notify_whoever_cares_that_its_time_for_the_next_semiquaver();
Thread.sleep(sixteenth_note_duration);
long phase_error = System.currentTimeMillis() - time_of_last_beat;
semiquaver_duration += estimate_phase_correction(phase_error);
}
I'll leave it to you to write the estimate_phase_correction() function. A linear function of the given error with the right coefficient may be all you need. If you get it right, the 16x loop should "lock in" so that every sixteenth semiquaver happens exactly on the beat.
Improvements:
have the beat loop compute the tempo.Base the starting guess for the semiquaver period on the current tempo.Notice significant (i.e. abrupt) tempo changes and re-set the semiquaver loop as needed.

In general, when I work with sound (usually sampled, not MIDI), I find it more accurate to use frame counts than elapsed time. With elapsed time there are too many unknowns (thread slicing, garbage collection, etc.). Latencies may vary, but 44100 frames (if that is the format) is always 1 sec.
With MIDI, doesn't every event have a field with the time that event is supposed to occur? I've seen readouts with both beats/measures and elapsed-time. I would use that info rather real-time time stamps when figuring any sort of positioning onto an existing Midi stream.
If this is something where the incoming is ASAP/real time, but you want to pass it through quantised, can you put scheduling info on the out-going Midi even if the incoming doesn't have it? Then you'd have a solid reference points for the positioning.
Reference on Real-Time. Low Latency Audio Processing in Java:
https://diuf.unifr.ch/main/pai/sites/diuf.unifr.ch.main.pai/files/publications/2007_Juillerat_Mueller_Schubiger-Banz_Real_Time.pdf

Related

Is there some neat way to make Threads (in Java) wait for theoretical time units as opposed to using Thread.sleep()?

Currently working on a university assessment, so I won't share specifics and I'm not asking for any explanation that will help me solve the main problem. I've already solved the problem, but my solution might be considered a little messy.
Basically, we're working with concurrency and semaphores. There is some shared resource that up to X (where X > 1) number of threads can access at a time and an algorithm which makes it a little more complicated than just acquiring and releasing access. Threads come at a certain time, use the resource for a certain time and then leave. We are to assume that no time is wasted when arriving, accessing, releasing and leaving the resource. The goal is to demonstrate that the algorithm we have written works by outputting the times a thread arrives, accesses the resource and leaves for each thread.
I'm using a semaphore with X number of permits to govern access. And it's all working fine, but I think the way I arrive at the expected output might be a bit janky. Here's something like what I have currently:
#Override
public void run() {
long alive = System.currentTimeMillis();
try { Thread.sleep(arrivalTime * 1000); }
catch (InterruptedException e) {} // no interrupts implemented
long actualArriveTime = System.currentTimeMillis() - alive;
boolean accessed = false;
while (!accessed) accessed = tryAcquire();
long actualAccessTime = System.currentTimeMillis() - alive;
try { Thread.sleep(useTime * 1000); }
catch (InterruptedException e) {} // no interrupts implemented
release();
long actualDepartTime = System.currentTimeMillis() - alive;
System.out.println(actualArriveTime);
System.out.println(actualAccessTime);
System.out.println(actualDepartTime);
}
I do it this way because where the expected output might be:
Thread Arrival Access Departure
A 0 0 3
B 0 0 5
C 2 2 6
... ... ... ...
My output looks something like:
Thread Arrival Access Departure
A 0 0 3006
B 0 0 5008
C 2 2 6012
... ... ... ...
I'm essentially making the time period much larger so that if the computer takes a fews milliseconds to acquire(), for example, it doesn't affect the number much. Then I can round to the nearest second to get the expected output. My algorithm works, but there are issues with this. A: It's slow; B: With enough threads, the milliseconds of delay may build so that I round to the wrong number.
I need something more like this:
public static void main(String[] args) {
int clock = 0;
while (threadsWaiting) {
clock++;
}
}
#Override
public void run() {
Thread.waitUntil(clock == arrivalTime);
boolean accessed = false;
while (!accessed) accessed = tryAcquire();
int accessTime = clock;
int depatureTime = accessTime + useTime;
Thread.waitUntil(clock == departureTime);
release();
System.out.println(arrivalTime);
System.out.println(accessTime);
System.out.println(departureTime);
}
Hopefully that's clear. Any help is appreciated.
Thanks!

Accurate thread loop. Run a task with precise interval

I want my thread to perform an action 4 or 16 times per bpm (beats per minute). This timer is not 100% accurate, after a few seconds it desynchronizes from the metronome I found on youtube, and it gets a little slower than it should.
bpm = (float) my music bpm;
thread = new Thread(()->{
long now ;
long total ;
while (true) {
long bpmTime = (long) ((1000000000*60d)/(bpm*16));
now = System.nanoTime();
bpmTick(); //<-- my task
try {
total = System.nanoTime() - now;
if(total > bpmTime) {
continue;
}
Thread.sleep((bpmTime - (System.nanoTime() - now)) / 1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
I also tried:
Thread.sleep((long)(1000*(60.0/bpm)));
but the same problem occurs
In short, I need a metronome.
Thanks in advance.
What you want to use is a ScheduledExecutorService instance instead. This class can repeat the task in a Thread repeatedly at a fixed rate. The class has a method called scheduleAtFixedRate(task, intialDelay, DelayBetweenExecutions,TimeUnit) just for this purpose.
When the initial delay is set to 0 the task will run as soon as scheduleAtFixedRate is called and will continue doing so until you call shutdown() or shutdownNow() on the service. Here's an example that uses some of your code:
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
int timesPerBPM = 16;
long bpmTime = 900; //or whatever the outcome of your formula is.
Thread thread = new Thread(()->{
for (int i = 0; i < timesPerBPM; i++) //do task 16 times
bpmTick(); //<-- my task
});
executorService.scheduleAtFixedRate(thread, 0, bpmTime, TimeUnit.MILLISECONDS); //This will start immediately because initialDelay is 0.
executorService.shutdown(); //Always shutdown service when done to avoid memory leaks.
The executorService in the below code will run bpmTick() 16 times every 900 milliseconds. If it takes longer then 900 milliseconds to run bpmTick() 16 times the service will wait for the current task to complete until it starts the next repetition. So to keep things synchronized the 16 bpmTick() must always finish within bpmTime milliseconds. If you want to guarantee a 150 millisecond pause between threadtask executions regardless of how long it takes to execute a task then you should use the method scheduleWithFixedDelay() instead.
If you want the service to repeat the task every minute instead of every 900 milliseconds then it is best to change bpmTime to 1 and TimeUnit.MILLISECONDS to TimeUnit.MINUTES.

What is the difference between schedule and scheduleAtFixedRate?

What is the difference between these 2 methods of Timer class :
schedule(TimerTask task, long delay, long period)
and
scheduleAtFixedRate(TimerTask task, long delay, long period)
Documentation doesn't make the difference between them clear.
The documentation does explain the difference:
schedule:
In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well.
So, suppose the delay is 5 seconds, and each task takes 2 seconds, you would get
TTWWWTTWWWTTWWWTT
where T means 1 second for the task execution, and W means 1 second waiting.
But now suppose that a long GC (represented by a G) happens and delays the second task, the third one will start 5 seconds after the start of the second one, as if the long GC didn't happen:
TTWWWGGTTWWWTTWWWTT
The third task starts 5 seconds after the second one.
scheduleAtFixedRate:
In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up.".
So, with the same delay as above, and the same GC, you would get
TTWWWGGTTWTTWWWTT
The third task task starts 3 seconds instead of 5 after the second one, to catch up.
Thanks #Nizet's answer, I have written a sample code for some people who want to practice and learn.
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String args[]){
TimerTest.DelayTask task = new DelayTask();
Timer timer = new Timer();
/**
* Use schedule or scheduletAtFixedrate and check the printed result
*/
timer.schedule(task, 0, 5000);
//timer.scheduleAtFixedRate(task, 0, 5000);
}
public static boolean stop = false;
public static void delayOneSec(String status){
try{
System.out.print(status);
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
static class DelayTask extends TimerTask{
int count = 2;
#Override
public void run() {
// TODO Auto-generated method stub
stop = true;
for(int i = 0; i < count; i++){
TimerTest.delayOneSec("T");
}
if(count == 2){
count = 6;
}else{
count = 2;
}
stop = false;
new PrintW().start();
}
}
static class PrintW extends Thread{
#Override
public void run(){
while(!stop){
TimerTest.delayOneSec("W");
}
}
}
}
The task itself will repeat to take 2 seconds or 6 seconds. Let's see the result of each scenario.
When using timer.schedule(task, 0, 5000);, the output is TTWWWTTTTTTTTWWWTTTTTTTTWWWTTTTTTTT. As you can see, the timer follow the rules like below, wait till period time outs if task finishes in time, launch next task immediately if current task lasts more than period.
When using timer.scheduleAtFixedRate(task, 0, 5000);, the output is TTWWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTT. Things are a little different now. The javadoc
two or more executions will occur in rapid succession to "catch up."
takes effect here. As you can see, ignoring the first TTWWW, every two tasks will print TTTTTTTTWW and it lasts 10 seconds(two periods).
Let's dig into the source code of Timer.
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, period);
}
As you can see, the period is transferred to negative value in schedule method. Let's see what's the difference when scheduling it.
The below code is in the mainloop of TimerThread,
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if (taskFired = (executionTime<=currentTime)) {
if (task.period == 0) { // Non-repeating, remove
queue.removeMin();
task.state = TimerTask.EXECUTED;
} else { // Repeating task, reschedule
queue.rescheduleMin(
task.period<0 ? currentTime - task.period
: executionTime + task.period);
}
}
}
It's where magic happens, for schedule method, the next task execution time is based on the currentTime which is calculated right before the this task runs. That means, every task's execution time only be related with previous task starts time.

How to test task performance, using multitheading?

I have some exercises, and one of them refers to concurrency. This theme is new for me, however I spent 6 hours and finally solve my problem. But my knowledge of corresponding API is poor, so I need advice: is my solution correct or may be there is more appropriate way.
So, I have to implement next interface:
public interface PerformanceTester {
/**
* Runs a performance test of the given task.
* #param task which task to do performance tests on
* #param executionCount how many times the task should be executed in total
* #param threadPoolSize how many threads to use
*/
public PerformanceTestResult runPerformanceTest(
Runnable task,
int executionCount,
int threadPoolSize) throws InterruptedException;
}
where PerformanceTestResult contains total time (how long the whole performance test took in total), minimum time (how long the shortest single execution took) and maximum time (how long the longest single execution took).
So, I learned many new things today - about thread pools, types Executors, ExecutorService, Future, CompletionService etc.
If I had Callable task, I could make next:
Return current time in the end of call() procedure.
Create some data structure (some Map may be) to store start time and Future object, that retuned by fixedThreadPool.submit(task) (do this executionCount times, in loop);
After execution I could just subtract start time from end time for every Future.
(Is this right way in case of Callable task?)
But! I have only Runnable task, so I continued looking. I even create FutureListener implements Callable<Long>, that have to return time, when Future.isDone(), but is seams little crazy for my (I have to double threads count).
So, eventually I noticed CompletionService type with interesting method take(), that Retrieves and removes the Future representing the next completed task, waiting if none are yet present., and very nice example of using ExecutorCompletionService. And there is my solution.
public class PerformanceTesterImpl implements PerformanceTester {
#Override
public PerformanceTestResult runPerformanceTest(Runnable task,
int executionCount, int threadPoolSize) throws InterruptedException {
long totalTime = 0;
long[] times = new long[executionCount];
ExecutorService pool = Executors.newFixedThreadPool(threadPoolSize);
//create list of executionCount tasks
ArrayList<Runnable> solvers = new ArrayList<Runnable>();
for (int i = 0; i < executionCount; i++) {
solvers.add(task);
}
CompletionService<Long> ecs = new ExecutorCompletionService<Long>(pool);
//submit tasks and save time of execution start
for (Runnable s : solvers)
ecs.submit(s, System.currentTimeMillis());
//take Futures one by one in order of completing
for (int i = 0; i < executionCount; ++i) {
long r = 0;
try {
//this is saved time of execution start
r = ecs.take().get();
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
//put into array difference between current time and start time
times[i] = System.currentTimeMillis() - r;
//calculate sum in array
totalTime += times[i];
}
pool.shutdown();
//sort array to define min and max
Arrays.sort(times);
PerformanceTestResult performanceTestResult = new PerformanceTestResult(
totalTime, times[0], times[executionCount - 1]);
return performanceTestResult;
}
}
So, what can you say? Thanks for replies.
I would use System.nanoTime() for higher resolution timings. You might want to ignroe the first 10,000 tests to ensure the JVM has warmed up.
I wouldn't bother creating a List of Runnable and add this to the Executor. I would instead just add them to the executor.
Using Runnable is not a problem as you get a Future<?> back.
Note: Timing how long the task spends in the queue can make a big difference to the timing. Instead of taking the time from when the task was created you can have the task time itself and return a Long for the time in nano-seconds. How the timing is done should reflect the use case you have in mind.
A simple way to convert a Runnable task into one which times itself.
finla Runnable run = ...
ecs.submit(new Callable<Long>() {
public Long call() {
long start = System.nanoTime();
run.run();
return System.nanoTime() - start;
}
});
There are many intricacies when writing performance tests in the JVM. You probably aren't worried about them as this is an exercise, but if you are this question might have more information:
How do I write a correct micro-benchmark in Java?
That said, there don't seem to be any glaring bugs in your code. You might want to ask this on the lower traffic code-review site if you want a full review of your code:
http://codereview.stackexchange.com

Frequency from binary input

Background: I have a IOIO which I am using to measure the output from an photodiode, this is the converted into a digital output. I need to find the frequency at which the signal changes between 1 and 0. Everything I have tryed so far has hanged my test app, any suggestions?
current code:
if(diode == 1 && frequencyFound == false){
startTime = System.currentTimeMillis();
while((frequencyFound == false)){
if(diode == 0){
while(frequencyFound == false){
if(diode == 1){
double endTime = System.currentTimeMillis();
time = endTime - startTime;
frequency = (long) (1.0 / time);
frequencyFound = true;
}
Thread.sleep(100);
}
}
Thread.sleep(100);
}
}
There are a couple of issues here.
First, Android is a multi-tasking system, and you could find your timing thread put to sleep long enough to miss some signal transitions. Is there no way to be notified of a leading (or trailing) edge transition rather than sampling the input in a loop?
What sort of frequency are you looking at? Will a 100 ms sampling interval be fine enough?
Don't count on Thread.sleep() to sleep for exactly the time you specify. If the interval is too short, the system might decide to return immediately or it might round the sleep time up to a larger amount.
Your timing loop won't record the time to any precision better than 100ms (at best), so your estimate for the frequency will be very poor.
Zapl is right, you MUST run this from a separate thread from your UI thread.
Watching for a single transition will give you a very imprecise estimate of the frequency. Try something like this instead:
// Find frequency to the nearest hz (+/- 10%)
// It's assumed that some other process is responsible for updating the "diode"
// variable. "diode" must be declared volatile.
long duration = 1000; // 1 second
final int interval = 100; // sampling inteval = .1 second
int oldState = diode;
int count = 0;
final long startTime = System.currentTimeMillis();
final long endtime = startTime + duration;
while (System.currentTimeMillis() < endtime) {
// count all transitions, both leading and trailing
if (diode != oldState) {
++count;
oldState = diode;
}
Thread.sleep(interval);
}
// find the actual duration
duration = System.currentTimeMillis() - startTime;
// Compute frequency. The 0.5 term is because we were counting both leading and
// trailing edges.
float frequency = 0.5 * count / (duration/1000);
Two more extreme suggestions for working around some of the timing accuracy concerns Edward raised:
Do the measurement of interval times on the IOIO board under interrupts, where you can presumably accomplish (at least near-) real time operations. Report these time measurements to the Android device.
Skip the ioio board and build something simple to route the signal into the headset connector as a tone that turns on or off. Record audio using the built-in timing guarantees of the audio system, and then analyze the audio buffers (real time no longer required) to determine the intervals from the number of intervening audio samples times in units of the (relatively reliable compared to anything you could do in an android app) audio sample rate. You can also get an analog input easily by using the light sensor to vary the frequency of an audio oscillator.

Categories

Resources