Variable Length MIDI Duration Algorithm - midi

I'm trying to compile MIDI files, and I reached an issue with the duration values for track events. I know these values (according to this http://www.ccarh.org/courses/253/handout/vlv/) are variable length quantities where each byte is made up of a continuation bit (0 for no following duration byte and 1 for a following duration byte) and the rest of the number in a 7 bit representation.
For example, 128 would be represented as such:
1_0000001 0_0000000
The problem is that I'm having trouble wrapping my head around this concept, and am struggling to come up with an algorithm that can convert a decimal number to this format. I would appreciate it if someone could help me with this. Thanks in advance.

There is no need to re-invent the wheel. The official MIDI specification has example code for dealing with variable length values. You can freely download the specs from the official MIDI.org website.

Related

What value to use for Libopus encoder max_data_bytes field?

I am currently using libopus in order to encode some audio that I have.
When consulting the documentation for how to use the encoder, one of the arguments the encode function takes in is max_data_bytes, a opus_int32 that has the following documentation:
Size of the allocated memory for the output payload. May be used to impose an upper limit on the instant bitrate, but should not be used as the only bitrate control
Unfortunately, I wasn't able to get much out of this definition as to how to set the upper size and the relation of this argument to bitrate. I tried consulting some of the examples provided such as this or this but both have the argument defined as some constant without much information.
Could anyone help me understand the definition of this value, and what number I might be interested in using for it? Thank you!
Depends on encoder version and encoding parameters.
In 1.1.4 the encoder doesn't merge packets and the upper limit should be 1275 byte. For the decoder, if repacketizer is used, you could find some packet up to 3*1275.
Things could be changed in recent version, I'm quite sure that the repacketizer has been somehow merged in the encoder. Look into the RFC.
Just paste here some of my notes from a 1½ years ago...
//Max opus frame size if 1275 as from RFC6716.
//If sample <= 20ms opus_encode return always an one frame packet.
//If celt is used and sample is 40 or 60ms, two or three frames packet is generated as max celt frame size is 20ms
//in this very specific case, the max packet size is multiplied by 2 or 3 respectively

How to render in a specific bit depth?

How can OfflineAudioContext.startRendering() output an AudioBuffer that contains the bit depth of my choice (16 bits or 24 bits)? I know that I can set the sample rate of the output easily with AudioContext.sampleRate, but how do I set the bit depth?
My understanding of audio processing is pretty limited, so perhaps it's not as easy as I think it is.
Edit #1:
Actually, AudioContext.sampleRate is readonly, so if you have an idea on how to set the sample rate of the output, that would be great too.
Edit #2:
I guess the sample rate is inserted after the number of channels in the encoded WAV (in the DataView)
You can't do this directly because WebAudio only works with floating-point values. You'll have to do this yourself. Basically take the output from the offline context and multiply every sample by 32768 (16-bit) or 8388608 (24-bit) and round to an integer. This assumes that the output from the context lies within the range of -1 to 1. If not, you'll have to do additional scaling. And finally, you might want to divide the final result by 32768 (8388608) to get floating-point numbers back. That depends on what the final application is.
For Edit #1, the answer is that when you construct the OfflineAudioContext, you have to specify the sample rate. Set that to the rate you want. Not sure what AudioContext.sampleRate has to do with this.
For Edit #2, there's not enough information to answer since you don't say what DataView is.

Tempo and time signatures from MIDI

I'm currently building a software for displaying music notes from MIDI file. I can get every letter of tones from NoteOn and NoteOff events but I don`t know how I get or how calculate types of notes (whole, half, eigth..) and other time signatures.
How I can get it? I looked for some example but without success.
MIDI doesn't represent notes in absolute quantities, like in classical music. Instead, the length of the note continues until a corresponding note off event is parsed (also it's quite common that MIDI files use a note on event with 0 velocity as a note off, just keep this in mind). So basically you will need to translate the time in ticks between the two events to musical time to know whether use a whole, half, quarter note, etc.
This translation obviously depends on knowing the tempo and time signature, which are MIDI meta events. More information about parsing those can be found here:
http://www.sonicspot.com/guide/midifiles.html
Basically you take the PPQ to find the number of milliseconds per tick, then use the time signature and tempo to find the length of a quarter note in milliseconds. There are some answers on StackOverflow with this conversion, but I'm writing this post on my phone and can't be bothered to look them up right now. :-)
Hope this points you in the right direction!

Best way to send 10,000 doubles over HTTP

I have a client application (iPhone) that collects 10,000 doubles. I'd like to send this double array over HTTP to an appengine server (java). I'm looking for the best way to do this.
Best can be defined as some combination of ease of programming and compactness of representation as the amount of data can be quite high.
My current idea is that I will convert the entire array of doubles to a string representation and send that as a POST parameter, on the server parse the string and convert back to a double array. Seems inefficient though...
Thanks!
I think you kind of answered your own question :) The big thing to beware of is differences between the floating point representation on the device and the server. These days they're both going to be little-endian, (mostly) IEEE-754 compliant. However, there can still be some subtle differences in implementation that might bite, e.g handling of denormals and infinities, but you can likely get away with ignoring them. I seem to recall a few of the edge cases in NEON (used in the iPhone's Cortex A-8) aren't handled the same as x86.
If you do send as a string, you'll end up with a decimal and binary conversion between, and potentially lose accuracy. This isn't that inefficient, though - it's only 10,000 numbers. Unless you're expecting thousands of devices pumping this data at your server non-stop.
If you'd like some efficiency in the wire transfer and on the device side, then one approach is to just send the doubles in their raw binary form. On the server, reparse them to a doubles (Double.longBitsToDouble). Make sure you get the endian-ness right when you grab the data as longs (it'll be fairly obvious when it's wrong).
I guess that there are lots and lots of different ways to do this. If it were me I would probably just serialize to an array of bytes and then base64 encode it, most other mechanisms will significantly increase the volume of data being passed.
10k doubles is 80k binary bytes is about 107k or so characters base64 encoded. Or 3 doubles is 24 binary bytes is 32 base64 characters. There's tons of base64 conversion example source code available.
This is far preferable to any decimal representation conversions, since the decimal conversion is slower and, worse, potentially lossy.
json
for iphone encode with yajl-obj-c
and for java read with jsonarray
If you have a working method, and you haven't identified a performance problem, then the method you have now is just fine.
Don't go trying to find a better way to do it unless you know it doesn't meet your needs.
On inspection it seems that on the java side, a double (64 bytes) will be about 4 characters (16 bytes * 4). Now, when I think of your average double, let's say 10 digits and a decimal point, plus some delimiter like a space of semicolon, you're looking at about 12 characters per decimal. That's only 3x as much.
So you originally had 80k of data, and now you have 240k of data. Is that really that much of a difference?

Problem with very small numbers?

I tried to assign a very small number to a double value, like so:
double verySmall = 0.000000001;
9 fractional digits. For some reason, when I multiplicate this value by 10, I get something like 0.000000007. I slighly remember there were problems writing big numbers like this in plain text into source code. Do I have to wrap it in some function or a directive in order to feed it correctly to the compiler? Or is it fine to type in such small numbers in text?
The problem is with floating point arithmetic not with writing literals in source code. It is not designed to be exact. The best way around is to not use the built in double - use integers only (if possible) with power of 10 coefficients, sum everything up and display the final useful figure after rounding.
Standard floating point numbers are not stored in a perfect format, they're stored in a format that's fairly compact and fairly easy to perform math on. They are imprecise at surprisingly small precision levels. But fast. More here.
If you're dealing with very small numbers, you'll want to see if Objective-C or Cocoa provides something analagous to the java.math.BigDecimal class in Java. This is precisely for dealing with numbers where precision is more important than speed. If there isn't one, you may need to port it (the source to BigDecimal is available and fairly straightforward).
EDIT: iKenndac points out the NSDecimalNumber class, which is the analogue for java.math.BigDecimal. No port required.
As usual, you need to read stuff like this in order to learn more about how floating-point numbers work on computers. You cannot expect to be able to store any random fraction with perfect results, just as you can't expect to store any random integer. There are bits at the bottom, and their numbers are limited.