I am trying to extract the tempo of a melody from the first track of a midi file and apply it to the rest of the tracks containing the note events.
Bascically I've been trying to replace the Thread.sleep() method after the noteOn() message which is playing a note for a fixed time interval everytime. Hence I'm losing the tempo of the entire track.
I was successful in extracting the tempo information from the first track from a previously asked question How does Midi TEMPO message apply to other tracks? but am unable to apply it to the rest of the tracks.
Is there a particular function that does that? I tried searching but couldn't find one.
Here is my code for reference.
int trackNumber = 0;
for (Track track : sequence.getTracks()) {
trackNumber++;
System.out.println();
for (int i=0; i < track.size(); i++) {
MidiEvent event = track.get(i);
MidiMessage message = event.getMessage();
if (message instanceof MetaMessage) {
MetaMessage mm = (MetaMessage) message;
if(mm.getType()==SET_TEMPO){
byte[] data = mm.getData();
int tempo = (data[0] & 0xff) << 16 | (data[1] & 0xff) << 8 | (data[2] & 0xff);
int bpm = 60000000 / tempo;
}
}
if (message instanceof ShortMessage) {
ShortMessage sm = (ShortMessage) message;
if (sm.getCommand() == NOTE_ON) {
int key = sm.getData1();
int velocity = sm.getData2();
channels[0].noteOn(key,velocity);
Thread.sleep(280);//Pays all the note for fixed duration
}
else if (sm.getCommand() == NOTE_OFF) {
int key = sm.getData1();
int velocity = sm.getData2();
channels[0].noteOff(key);
}
}
}
System.out.println();
}
}
Events in multiple tracks happen concurrently, so you cannot handle the tracks separately.
You have to either
put all events into a single list, and sort them by their timestamp (but ensure that events with the same time stamp keep their order, so use a stable sorting algorithm); or
have a current position for each track, and when determining which event is the next, search through all the tracks for a yet-unused event with the smallest timestamp.
Please note that the tempo can change during playback, so a single bpm value does not suffice. See How to correctly convert MIDI ticks to milliseconds? and How can I parse a tempo of midi using Java?.
i have a String array with information like this:
name street streetnumber City house flat
jetsons jetstreet 12 london yes no
jetsons jetstreet 10 washingston n y
jetsons jetstreet 10 washingston n y
jetsons jetstreet 10 washingston yes no
ALF alfStreet 3 Shanghai y y
...and so on
now the exercise is to create an new list with unique data which is analyzed.
livingDataArray
analyzedDataList
while(livingDataArray=reader.readLine() != null){
street = livingDataArray[1];
streetNumber = livinDataArray[2];
city = livingDataArray[3;]
if(analyzedDataList.isEmpty()) {
createNewEntry in analyzedDataList(); // that line is fine. ;)
} else {
int analyzedDataSize = analyzedData.size();
for (int i = 0; i <= analyzedDataSize; i++){
if(analyzedData.get(i)[1] == street &&
analyzedData.get(i)[2] == streetNumber &&
analyzedData.get(i)[3] == city ) {
categorize(); // this line is fine also
addToAnalyzedData();
break;
} else if (!(analyzedData.get(i)[1] == street &&
analyzedData.get(i)[2] == streetNumber &&
analyzedData.get(i)[3] == city) && (i+1 ==
livingData.size())) {
categorize();
addToAnalyzedData();
break;
}
}
}
}
My question is that efficient enough to use it for really big data? Like 100.000 rows and more? Because I'm not about the if else statements. Could anybody help me?
String comparison works via equals, not == (How do I compare strings in Java?). Next point: This looks like the implementation in java of a plain SELECT DISTINCT * FROM someWhere-statement in SQL. So why not simply outsource the code to a database? If that's not possible, a Set would be most likely the most efficient collection. Though i'd recommend SQL to improve performance a lot and save resources on your local PC. One final note: Modifying data in a loop over the same data like here:
int analyzedDataSize = analyzedData.size();
for (int i = 0; i <= analyzedDataSize; i++){
...
addToAnalyzedData();
is extremely prone to bugs/exceptions. For e.g. you're retrieving and modifying a collection in the loop mentioned above, without updating the size of the collection. In this example, this behavior won't do any damage, but you should handle this rather carefully.
I am trying to use an iterator on an ArrayList ( to get rid of a for loop, don't ask me why... ), however I need to skip the process of one of the arrays upon a boolean condition , should I still use an index and a break ???
// INTERPOLATION
int i = 0;
Iterator<CircularFifoQueue<SensorEvent>> buf = samplingFifoQueues.iterator();
while (buf.hasNext()) {
if ( i == 2 && !mDeviceSensorGyro) { // skip this queue if no gyroscope in device
break;
}
// proceed
buf.next();
i++;
}
thanks for help
What about this:
// INTERPOLATION
int i = 0;
Iterator<CircularFifoQueue<SensorEvent>> buf = samplingFifoQueues.iterator();
while (buf.hasNext()) {
if ( i != 2 || mDeviceSensorGyro) { // skip this queue if no gyroscope in device
// proceed
}
buf.next();
i++;
}
But I would rather attach some attribute to the queue elements to check for it. Work directly with numbers is bad practice.
I was asked to do a multithreaded simulator of a specific algorithm.
One of the tasks was to compare the regular scheduling results with round robin results.
When I was looking for information about the round robin scheduling method I found vary general explanations and some code examples that I couldn’t find any relation between them and scheduling the threads.
For example this code (found here on stack overflow):
public static void RR3(int numProcess, int[] cpuBurst, int[] arrivalTime){
int quantum = 3,time = 0, temp;
int completionTime = 0;
LinkedList <Integer>process = new LinkedList();
for (int i = 0; i < numProcess; i++) {
process.add(i, cpuBurst[i]);
}
while (process.isEmpty() != true){
for (int j = 0; j < quantum; j++) {
System.out.println(process.getFirst());
if(process.peek() == 0 ){
completionTime = completionTime + time;
process.remove();
}
else{
temp = process.pop();
process.push(temp - 1);
time++;
}
}
process.addLast(process.getFirst());
process.removeFirst();
}
double act = (double) completionTime/numProcess;
System.out.println("-----------------RR3-----------------");
System.out.println(" Act = " + act + "ms");
}
I don't see anything but integers that represent the amount of process, time for each etc., but how do I actually manage their behavior? I dont see any call for a process to run or stop.
You already noticed that this is an abstraction. Namely that there is no real work performed. Instead, the work is just "imitated" by a set of Integers that represent the amount of work.
The question about how to run or stop the processes is somewhat hidden in the algorithm itself: The LinkedList stores the "active" processes. They are all started at the beginning. In each turn, they receive a short time slot in which they can do some of their work. When all their work is done, they are removed from the list.
In the simplest form, when the Integer values are replaced by real tasks, you could replace the line
if(process.peek() == 0 ){ ... }
with something like
Task task = process.peek();
if (task.isFinished()) { ... }
Otherwise (in the else case), when there is work to be done, you could replace the lines
temp = process.pop();
process.push(temp - 1);
with something like
Task task = process.peek();
task.doALittleBitOfWork();
The code that you posted was originally part of a question, so one has to assume that there's still something wrong with it, but maybe it is sufficient to get the basic idea.
I am currently having heavy performance issues with an application I'm developping in natural language processing. Basically, given texts, it gathers various data and does a bit of number crunching.
And for every sentence, it does EXACTLY the same. The algorithms applied to gather the statistics do not evolve with previously read data and therefore stay the same.
The issue is that the processing time does not evolve linearly at all: 1 min for 10k sentences, 1 hour for 100k and days for 1M...
I tried everything I could, from re-implementing basic data structures to object pooling to recycles instances. The behavior doesn't change. I get non-linear increase in time that seem impossible to justify by a little more hashmap collisions, nor by IO waiting, nor by anything! Java starts to be sluggish when data increases and I feel totally helpless.
If you want an example, just try the following: count the number of occurences of each word in a big file. Some code is shown below. By doing this, it takes me 3 seconds over 100k sentences and 326 seconds over 1.6M ...so a multiplicator of 110 times instead of 16 times. As data grows more, it just get worse...
Here is a code sample:
Note that I compare strings by reference (for efficiency reasons), this can be done thanks to the 'String.intern()' method which returns a unique reference per string. And the map is never re-hashed during the whole process for the numbers given above.
public class DataGathering
{
SimpleRefCounter<String> counts = new SimpleRefCounter<String>(1000000);
private void makeCounts(String path) throws IOException
{
BufferedReader file_src = new BufferedReader(new FileReader(path));
String line_src;
int n = 0;
while (file_src.ready())
{
n++;
if (n % 10000 == 0)
System.out.print(".");
if (n % 100000 == 0)
System.out.println("");
line_src = file_src.readLine();
String[] src_tokens = line_src.split("[ ,.;:?!'\"]");
for (int i = 0; i < src_tokens.length; i++)
{
String src = src_tokens[i].intern();
counts.bump(src);
}
}
file_src.close();
}
public static void main(String[] args) throws IOException
{
String path = "some_big_file.txt";
long timestamp = System.currentTimeMillis();
DataGathering dg = new DataGathering();
dg.makeCounts(path);
long time = (System.currentTimeMillis() - timestamp) / 1000;
System.out.println("\nElapsed time: " + time + "s.");
}
}
public class SimpleRefCounter<K>
{
static final double GROW_FACTOR = 2;
static final double LOAD_FACTOR = 0.5;
private int capacity;
private Object[] keys;
private int[] counts;
public SimpleRefCounter()
{
this(1000);
}
public SimpleRefCounter(int capacity)
{
this.capacity = capacity;
keys = new Object[capacity];
counts = new int[capacity];
}
public synchronized int increase(K key, int n)
{
int id = System.identityHashCode(key) % capacity;
while (keys[id] != null && keys[id] != key) // if it's occupied, let's move to the next one!
id = (id + 1) % capacity;
if (keys[id] == null)
{
key_count++;
keys[id] = key;
if (key_count > LOAD_FACTOR * capacity)
{
resize((int) (GROW_FACTOR * capacity));
}
}
counts[id] += n;
total += n;
return counts[id];
}
public synchronized void resize(int capacity)
{
System.out.println("Resizing counters: " + this);
this.capacity = capacity;
Object[] new_keys = new Object[capacity];
int[] new_counts = new int[capacity];
for (int i = 0; i < keys.length; i++)
{
Object key = keys[i];
int count = counts[i];
int id = System.identityHashCode(key) % capacity;
while (new_keys[id] != null && new_keys[id] != key) // if it's occupied, let's move to the next one!
id = (id + 1) % capacity;
new_keys[id] = key;
new_counts[id] = count;
}
this.keys = new_keys;
this.counts = new_counts;
}
public int bump(K key)
{
return increase(key, 1);
}
public int get(K key)
{
int id = System.identityHashCode(key) % capacity;
while (keys[id] != null && keys[id] != key) // if it's occupied, let's move to the next one!
id = (id + 1) % capacity;
if (keys[id] == null)
return 0;
else
return counts[id];
}
}
Any explanations? Ideas? Suggestions?
...and, as said in the beginning, it is not for this toy example in particular but for the more general case. This same exploding behavior occurs for no reason in the more complex and larger program.
Rather than feeling helpless use a profiler! That would tell you where exactly in your code all this time is spent.
Bursting the processor cache and thrashing the Translation Lookaside Buffer (TLB) may be the problem.
For String.intern you might want to do your own single-threaded implementation.
However, I'm placing my bets on the relatively bad hash values from System.identityHashCode. It clearly isn't using the top bit, as you don't appear to get ArrayIndexOutOfBoundsExceptions. I suggest replacing that with String.hashCode.
String[] src_tokens = line_src.split("[ ,.;:?!'\"]");
Just an idea -- you are creating a new Pattern object for every line here (look at the String.split() implementation). I wonder if this is also contributing to a ton of objects that need to be garbage collected?
I would create the Pattern once, probably as a static field:
final private static Pattern TOKEN_PATTERN = Pattern.compile("[ ,.;:?!'\"]");
And then change the split line do this:
String[] src_tokens = TOKEN_PATTERN.split(line_src);
Or if you don't want to create it as a static field, as least only create it once as a local variable at the beginning of the method, before the while.
In get, when you search for a nonexistent key, search time is proportional to the size of the set of keys.
My advice: if you want a HashMap, just use a HashMap. They got it right for you.
You are filling up the Perm Gen with the string intern. Have you tried viewing the -Xloggc output?
I would guess it's just memory filling up, growing outside the processor cache, memory fragmentation and the garbage collection pauses kicking in. Have you checked memory use at all? Tried to change the heap size the JVM uses?
Try to do it in python, and run the python module from Java.
Enter all the keys in the database, and then execute the following query:
select key, count(*)
from keys
group by key
Have you tried to only iterate through the keys without doing any calculations? is it faster? if yes then go with option (2).
Can't you do this? You can get your answer in no time.
It's me, the original poster, something went wrong during registration, so I post separately. I'll try the various suggestions given.
PS for Tom Hawtin: thanks for the hints, perhaps the 'String.intern()' takes more and more time as vocabulary grows, i'll check that tomorrow, as everything else.