I am working on a music application, in Scala, to generate MIDI sequences in real time. The MIDI messages are being sent to another application (Ableton DAW) and possibly even external hardware. Accurate timing is very important for this use case, otherwise the resulting music will sound off-time.
I tried using java.util.Timer to schedule notes on different sequences but apparently that timer can drift by hundreds of milliseconds.
What is the most accurate Timer to use in Scala (or Java) is this even a reasonable task to try to accomplish on the JVM? or maybe I'm going about this all wrong?
Usual timer implementations are based on the scheduler.
If you need accuracy, you can roll your own:
def after(when: Duration)(f: => Unit) {
val deadline = when.fromNow
while(! deadline.isOverdue) ()
f
}
This will burn your cpu like crazy, but it doesn't get any more accurate than that.
Related
I'm working on a project where I will have one 24-hours long sound clip which has different phases based on local daytime (morning phase has one sound, transition phases, evening phase, etc.)
so here is what i got now, and it's ok
method that plays the clip (turns current local time in microseconds and sets starting point to match current time - if i start program 13:35 it will start playing mid-day phase of sound which is on that position, and it's ok
void playMusic(String musicLocation){
try{
File musicPath = new File(musicLocation);
if(musicPath.exists())
{
Calendar calendar = Calendar.getInstance();
//Returns current time in millis
long timeMilli2 = calendar.getTimeInMillis();
System.out.println("Time in milliseconds using Calendar: " + (timeMilli2 * 1000)) ;
AudioInputStream audioInput = AudioSystem.getAudioInputStream(musicPath);
Clip clip = AudioSystem.getClip();
clip.open(audioInput);
clip.setMicrosecondPosition(12345678);
clip.start();
clip.loop(Clip.LOOP_CONTINUOUSLY);
System.out.println(clip.getMicrosecondLength());
//setFramePosition
JOptionPane.showMessageDialog(null, "Press OK to stop playung");
}
else
{
System.out.println("no file");
}
}catch(Exception ex){
ex.printStackTrace();
}
}
main method that just calls this method
public static void main(String[] args) {
String filepath = "src/sounds/test_file.wav";
PyramidMethods pyra = new PyramidMethods();
pyra.playMusic(filepath);
}
now this is pretty simple and straightforward, and also what I need, but now what i wonder is the following -> can I and if can, how, add sound effects based on the temperature outside?
so what I was thinking is to open separate thread in main which would regularly check some wheather API and when temperature changes add sound effects like echo, distortion or something else based on temperature change (if it's colder then x it would put echo sound effect on running clip, etc.)
it this even possible in Java? it's my first time using sounds with Java so I am even inexperienced with the search terms here, would someone suggest some other programming language for it?
thanks for your answers in advance.
That must be a huge file!
Yes, Java works quite well for creating and managing soundscapes.
It is possible to play and hear different Clips at the same time. When you play them, Java automatically creates a Thread for that playback, and most operating systems will mix together all the playing threads. At one time there were Linux systems that only allowed a single output. IDK if that is still a limitation or if you are even targeting Linux systems. Also, there is going to be a ceiling on the total number of sound playbacks that an OS will be able to handle cleanly. (Usually what happens is you get dropouts if you overstress the system in this way.)
To manage the sounds, I'd consider using a util.Timer (not the Swing.Timer), and check the time and date (and weather if you have an API for that) with each iteration before deciding what to do with the constituent cues of your mix. Or maybe use an util.concurrent.ExecutorService. If your GUI is JavaFX, an AnimationTimer is also a reasonable choice.
If you do prefer to mix the sound files down to a single output line, this can most easily be done by using a library such as TinySound or AudioCue. With AudioCue (which I wrote) you can both mix down to a single output, and have guaranteed volume, panning and even playback speed management for each sound cue that is part of your "soundscape".
This could help with lowering the total amount of RAM needed to run program. As I show in a demo, one can take a single cue (e.g. a frog croak) and play it multiple times as different volumes, pans, and speeds to create the illusion of a whole pond of frogs croaking. Thus, a single .wav, only a second in length can be used to simulate a .wav that is hours in length.
I think if you want to add effects like echo or distortion, you will have to use a library or write your own. Java supports Processing Audio with Controls, but this is highly dependent upon the OS of the computer being used. Echo and Distortion are not terribly difficult to write though, and could be added to the AudioCue library code if you have incorporated that into your program. (Echo involves adding a time delay, usually using an array to hold sound data until it is time for it to play, and Distortion involves running the PCM sound data through a transform function, such as Math.tanh and a max and min to keep the results within the [-1, 1] range.)
For other possible libraries or languages, I believe both Unity (C#) and Unreal (C++) game engines/environments have extensive array of audio effects implemented, including 3D handling.
I have a scenario where I have some timing data that I get from a MIDI file. When a MIDI note needs to be played, I need to send a command over UDP. Basically, I have instructions that say "play note A, wait 125ms, play note B, wait 300ms, play note C..." and each time I "play note X" I need to send data over UDP. I have tried using both a TimerTask and a simple thread with a loop that check the system time and calculate how much time has elapsed and decide whether or not to play a note based on that, but both methods seem to have timing issues. The TimerTask doesn't run exactly on the specified interval (which was stated in the documentation) so I get erratic messages. The thread works better, but it still hiccups sometimes which I assume is because other threads are getting priority over it.
Is there a better way to send this data with more accurate timing? Is there something I can use like the Clip interface in Java that is used for playing audio?
Any assistance is very much appreciated.
This is an approach just about doomed to failure. Let me count the issues here:
1)Android is not a real time OS. Neither is Linux (which its built on). Expecting ms level timings to happen exactly correctly is never going to work. Even if the clock is accurate enough to interrupt on a 1ms rate, there's no assurance that Linux will schedule your thread for wakeup.
2)TimerTasks aren't promised to be accurate even to the degree limited by 1.
3)You're then sending it somewhere via UDP? A protocol that has no assurance as to delivery or timing, to a receiver who will then do something with it- and that receiver may have additional timing issues of its own.
Throw out this entire approach and start over would be my advice. Every single step of this says bad idea.
I'm looking for a cron scheduling system with the possibility to 'spread out' tasks. Lets say I need to do a bit of work at 'round about' 12 o clock. The 'round about' is defined as lets say +/- 30 minutes. I need such a thing for my automated update task to not have all my millions of customers (joking...) downloading updates at exact the same time and just blowing up my webserver...
I know little about the existing cron libraries in java. I know there are cronj or quarz and dozen other systems - but I can't find out if one of them is able to do what I'm looking for.
At least I can implement such a 'spreading' feature (don't know how to call it better) myself by using a normal cron job and trigger a new Plain-Old-TimerTask with a little bit of Math.round() thingy... But would be nice if there is a native possibility for this.
Thanks and greetings
This looks being easy to implement on your own.
Create a worker thread which gets a random timer, sleeps and wakes up.
How does things like scheduleAtFixedRate work? How does it work behind the scenes and is there a penalty to using it?
More specifically, I have a task that I want to run periodically, say every 12 hours. The period is not strict at all, so my first instinct was to check in every request (tomcat server) if it's been more than >12 hours since the task last executed and if so, execute it and reset the timer. The downside of this is that I have to do a small time check on every request, make sure the task is run only once (using a semaphore or something similar) and the task might not execute in a long time if there's no requests.
scheduleAtFixedRate makes it easier to schedule a recurring task, but since I don't know how it does it, I don't know what the performance impact is. Is there a thread continually checking if the task is due to run? etc.
edit:
In Timer.java, there's a mainLoop function which, in my understanding, is something like this (overly simplified):
while(true) {
currentTime = System.currentTimeMillis();
if(myTask.nextExecutionTime == currentTime) myTask.run();
}
Won't this loop try to run as fast as possible and use a ton of CPU (I know, obviously not, but why)? There's no Thread.sleep in there to slow things down.
You can read the code if you wish to work out how it works.
There is an overhead using ScheduledExecutorService in terms of CPU and memory, however on the scale of hours, minutes, second even milli-seconds, it probably not work worrying about. If you have a task running in the range of micro-seconds, I would consider something more light weight.
In short, the overhead is probably too small for you to notice. The benefit it gives you is ease of use, and it is likely to be worth it.
Does anyone know a Library which provides a Thread.sleep() for Java which has an error not higher than 1-2 Millisecond?
I tried a mixture of Sleep, error measurement and BusyWait but I don't get this reliable on different windows machines.
It can be a native implementation if the implementation is available for Linux and MacOS too.
EDIT
The link Nick provided ( http://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks ) is a really good resource to understand the issues all kinds of timers/sleeps/clocks java has.
To improve granularity of sleep you can try the following from this Thread.sleep page.
Bugs with Thread.sleep() under Windows
If timing is crucial to your
application, then an inelegant but
practical way to get round these bugs
is to leave a daemon thread running
throughout the duration of your
application that simply sleeps for a
large prime number of milliseconds
(Long.MAX_VALUE will do). This way,
the interrupt period will be set once
per invocation of your application,
minimising the effect on the system
clock, and setting the sleep
granularity to 1ms even where the
default interrupt period isn't 15ms.
The page also mentions that it causes a system-wide change to Windows which may cause the user's clock to run fast due to this bug.
EDIT
More information about this is available
here and an associated bug report from Sun.
This is ~5 months late but might be useful for people reading this question. I found that java.util.concurrent.locks.LockSupport.parkNanos() does the same as Thread.sleep() but with nanosecond precision (in theory), and much better precision than Thread.sleep() in practice. This depends of course on the Java Runtime you're using, so YMMV.
Have a look: LockSupport.parkNanos
(I verified this on Sun's 1.6.0_16-b01 VM for Linux)
Unfortunately, as of Java 6 all java sleep-related methods on Windows OS [including LockSupport.awaitNanos()] are based on milliseconds, as mentioned by several people above.
One way of counting precise interval is a "spin-yield". Method System.nanoTime() gives you fairly precise relative time counter. Cost of this call depends on your hardware and lies somewhere 2000-50 nanos.
Here is suggested alternative to Thread.sleep():
public static void sleepNanos (long nanoDuration) throws InterruptedException {
final long end = System.nanoTime() + nanoDuration;
long timeLeft = nanoDuration;
do {
if (timeLeft > SLEEP_PRECISION)
Thread.sleep (1);
else
if (timeLeft > SPIN_YIELD_PRECISION)
Thread.yield();
timeLeft = end - System.nanoTime();
} while (timeLeft > 0);
}
This approach has one drawback - during last 2-3 milliseconds of the wait hit CPU core. Note that sleep()/yield() will share with other threads/processes. If you are willing to compromise a little of CPU this gives you very accurate sleep.
There are no good reasons to use Thread.sleep() in normal code - it is (almost) always an indication of a bad design. Most important is, that there is no gurantee that the thread will continue execution after the specified time, because the semantics of Thread.sleep() is just to stop execution for a given time, but not to continue immedeately after that period elapsed.
So, while I do not know what you try to achieve, I am quite sure you should use a timer instead.
JDK offers the Timer class.
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Timer.html
Reading the docs clearly indicates that beyond the plumbing to make this a generalized framework, it uses nothing more sophisticated than a call to Object.wait(timeout):
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#wait(long)
So, you can probably cut the chase an just use Object#wait yourself.
Beyond those considerations, the fact remains that JVM can not guarantee time accuracy across platforms. (Read the docs on http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#currentTimeMillis())
I think you'll need to experiment with a compromise solution combining Timer and busy polling if you want to want the highest timing precision possible on your platform. Effectively Object#wait(1) -> System#nanoTime -> calculate delta -> [loop if necessary].
If you are willing to roll your own, JNI pretty much leaves it wide open for platform specific solutions. I am blissfully un-aware of Window's internals, but obviously if the host OS does provide sufficiently accurate realtime timer services, the barebones structure of setting up a timerRequest(timedelta, callback) native library shouldn't be beyond reach.
The Long.MAX_VALUE hack is the working solution.
I tried Object.wait(int milis) to replace Thread.sleep, but found that Object.wait is as accurate as Thread.sleep (10ms under Windows). Without the hack, both methods are not suitable for any animation
Use one of the Thread::join overrides on the current thread. You specify the number of milliseconds (and nanoseconds) to wait.
You could try using the new concurrency libraries. Something like:
private static final BlockingQueue SLEEPER = new ArrayBlockingQueue(1);
public static void main(String... args) throws InterruptedException {
for(int i=0;i<100;i++) {
long start = System.nanoTime();
SLEEPER.poll(2, TimeUnit.MILLISECONDS);
long time = System.nanoTime() - start;
System.out.printf("Sleep %5.1f%n", time/1e6);
}
}
This sleeps between 2.6 and 2.8 milliseconds.
Sounds like you need an implementation of real-time Java.