JavaScript Sequencer MIDI file timing resolution (PPQN) - javascript

I read a lot about MIDI resolution and studied some codes like Tone.js and heartbeat. But I don't understand why there are different Pulses Per Quarter Note (PPQN) values and what the effect it has on playing notes. When I have 960 PPQN so this means 1 quarter note has 960 ticks, 1 eight note 480 ticks, ect. And if I understand it correctly, the delta time is just a relative value.
What I don't understand right is, what should the PPQN when I play notes in JavScript, and when I set the PPQN why it should have this value? For example I use the WebAudio API for playing notes:
function nextNote() {
var quarterBeat = 60.0/tempo;
nextNoteDuration = nextNoteDuration + (quarterBeat/32);
currentNote++;
}
This way I can play different notes durations. Now when I read the MIDI file, should I just compare the delta time and convert it to my sequencers current playback? For example when I read a MIDI file with this values:
Tempo = 120
PQN = 960
4 Quarter Notes
I read the MIDI file, save the notes in an array (assume the delta time is for each note a 1/4)
duration = [quarterNote, quarterNote, quarterNote, quarterNote]
And play the notes:
while (nextNoteDuration < audioContext.currentTime) {
if (duration[i] %32 == 0) playNote(currentNote, nextNoteDuration);
nextNote();
i++;
}
Should I use PPQN only when exporting a MIDI file? If so, in relation to what should I set the PPQN? I hope someone can explain this to me in more detail.

PPQ is about resolution. More specifically about time resolution.
what should (be?) the PPQN when I play notes in JavScript, and when I set
the PPQN why it should have this value?
When your program plays notes, it may use whatever time units you want or need, for instance milliseconds, nanoseconds, movie frames, ticks. Absolute wall clock or relative times. It depends on your sequencer capabilities and your software features. It is only required to choose a PPQ value when storing MIDI sequences as MIDI files. Of course you need to be able to convert time units when reading/storing MIDI files.
Now when I read the MIDI file, should I just compare the delta time
and convert it to my sequencers current playback?
Of course, if internally your music events use a different time representation, then you need to be able to translate the delta times from the MIDI file to your internal representation.
You are only asking about PPQ, but this value is found only once, at the MIDI file header. The tempo events in contrast may occur multiple times along the file, and it affects to the translation of the next delta times into wall clock times until the next tempo event. If your sequencer/player allows the user to change/add tempo events, it would be a good idea to use relative units instead of wall clock units for internal time representation (or both).
Should I use PPQN only when exporting a MIDI file? If so, in relation
to what should I set the PPQN?
Yes, you need to choose a suitable value for PPQ when you export a MIDI file. If your internal time units are relative (as most sequencers do) then use your internal unit resolution for PPQ. If you convert from wall clock units to delta times, then you need to choose a resolution which your translation loses less details (by quantization). Higher values are better in this sense. Rosegarden stores MIDI files always with 960 PPQ. In contrast, Steinberg's Cubase used 480. I remember using Cakewalk a long time ago having only 120 PPQ, but later versions allowed this value to be changed as a configuration setting. In general you need to accommodate not only all music figures shorter than quarter, including subdivisions like triplets, etc. but you also need to take into account effects like swing that are based on fine time adjustments.

In a standard MIDI file, there’s information in the file header about “ticks per quarter note”, a.k.a. “parts per quarter” (or “PPQ”). For the purpose of this discussion, we’ll consider “beat” and “quarter note” to be synonymous, so you can think of a “tick” as a fraction of a beat. The PPQ is stated in the last word of information (the last two bytes) of the header chunk that appears at the beginning of the file. The PPQ could be a low number such as 24 or 96, which is often sufficient resolution for simple music, or it could be a larger number such as 480 for higher resolution, or even something like 500 or 1000 if one prefers to refer to time in milliseconds.
What the PPQ means in terms of absolute time depends on the designated tempo. By default, the time signature is 4/4 and the tempo is 120 beats per minute. That can be changed, however, by a “meta event” that specifies a different tempo. (You can read about the Set Tempo meta event message in the file format description document.) The tempo is expressed as a 24-bit number that designates microseconds per quarter-note. That’s kind of upside-down from the way we normally express tempo, but it has some advantages. So, for example, a tempo of 100 bpm would be 600000 microseconds per quarter note, so the MIDI meta event for expressing that would be FF 51 03 09 27 C0 (the last three bytes are the Hex for 600000). The meta event would be preceded by a delta time, just like any other MIDI message in the file, so a change of tempo can occur anywhere in the music.
Delta times are always expressed as a variable-length quantity, the format of which is explained in the document. For example, if the PPQ is 480 (standard in most MIDI sequencing software), a delta time of a dotted quarter note (720 ticks) would be expressed by the two bytes 85 50 (hexadecimal).
So, bearing all that in mind, there is a correspondence between delta times expressed in terms of ticks and note values as we think of them in human terms. The relationship depends on the PPQ specified in the header chunk. For example, if the PPQ is 96 (hex 60), then a note middle C on MIDI channel 10 with a velocity of 127 lasting a dotted quarter note (1.5 beats) would be expressed as
00 99 3C 7F // delta time 0 ticks, 153 60 127
90 99 3C 00 // delta time 144 ticks, 153 60 0

Related

H.264 decoding failing to parse unusual frame headers

I'm reading an H.264 stream from a camera on a raspberry pi. I'm trying to pass this to Broadway via websockets to render in a web page.
The stream contains NAL units, and I'm chunking it on the [0,0,0,1] start prefix code, to send and then decode NAL units individually. I think that's working fine, but Broadway can't decode the result I end up with.
Digging into the parsing code I've based this on though, it seems to be expecting the 5th byte (straight after the start prefix code) to be either:
0x65 - an I frame
0x41 - a P frame
0x67 - an SPS frame
0x68 - a PPS frame
I've seen a lot of mention of these elsewhere too. All the units I have coming through though seem to start with (in order):
0x27 0x64 (1st unit)
0x28 0xEE (2nd unit)
0x25 0x88 (3rd unit, then intermittently later on)
0x21 0x9A (every single other unit in the stream)
What do these headers mean in an H.264 stream? Do they suggest something about what I need to do to match Broadway's expectations?
(If the full code would be useful to understand this better, see https://github.com/pimterry/pi-cam/tree/d801de9b)
This was a red herring: the actual issue for me here was that some existing frame dropping logic meant that I wasn't passing Broadway the first few frames in the stream, and it was failing to render. Replaying the SPS and PPS frames for all new connections and making sure they're never dropped has fixed the issue nicely.
I also did work out what these bytes are though, which helped, and may be useful for others for reference:
Hex Binary NAL type Meaning
0x65 = 11 00101 = type 5 Coded slice of an IDR picture (I-frame)
0x41 = 10 00001 = type 1 Coded slice of a non-IDR picture (P-frame)
0x27 = 01 00111 = type 7 Sequence parameter set (B-frame)
0x28 = 01 01000 = type 8 Picture parameter set (B-frame)
0x25 = 01 00101 = type 5 Coded slice of an IDR picture (B-frame)
0x21 = 01 00001 = type 1 Coded slice of a non-IDR picture (B-frame)
Special thanks to Jaromanda X though - the NAL units article [here] and the nal_ref_idc article made working this out much easier.

How to detect the frequence of a sound in JavaScript?

How can I detect if a sound is playing in the hearing range?
For example,
Show a silence icon if:
The range is lower than 20 Hz,
The range is higher than 20 kHz.
instead stream.paused is false.
You can use this pitch detection audio library.
Example:
var voice = new Wad({source : 'mic' });
var tuner = new Wad.Poly();
tuner.add(voice);
voice.play();
tuner.updatePitch() // The tuner is now calculating the pitch and note name of its input 60 times per second. These values are stored in tuner.pitch and tuner.noteName.
var logPitch = function(){
console.log(tuner.pitch, tuner.noteName)
requestAnimationFrame(logPitch)
};
logPitch();
// If you sing into your microphone, your pitch will be logged to the console in real time.
tuner.stopUpdatingPitch(); // Stop calculating the pitch if you don't need to know it anymore.
I don't know if you can find the hz with javascript. You'll probably have to use the web audio API. However, with javascript you can definitely check and set volume on a numeric scale. Check out the details and sample code here: http://www.w3schools.com/tags/av_prop_volume.asp
Example values:
1.0 is highest volume (100%. This is default)
0.5 is half volume (50%)
0.0 is silent (same as mute)

get Math.round to round up to next minute even if over by a second

Related to my previous question javascript math.round and math.floor work fine in IE and Opera but not Chrome, Safari or Firefox. Getting NaN
I have updated fiddle here http://jsfiddle.net/8VmPm/
The reason behind this script may seem a little cloudy so I'll try to explain. CDRs (Call detail records) from a certain network operator come in seconds for voice records and bytes for data records. I'm writing a "calculator" to convert seconds to minutes and bytes to megabytes.
I also took it a step further and added some example plans in there to check for overage.
My problem (which is simply cosmetic, but I am OCD like that) is in the first calculation (Math.round(minusage / 60)) (lines 22 and 23 in fiddle). I need it to round up to the next minute even if the value entered in the Usage Used field is over by 1 second.
Example:
In the Minute Which Plan? dropdown, pick Plan A (500 Minutes)
In the Usage Used field, enter in 30001 (which is 500 minutes and 1 second)
Click the Calculate button
Results in the Usage Summary field will be:
500 minutes used. -1 of 500 minutes remaining
Currently, it will not say, "501 minutes used" until the value entered in Usage Used field is 30030 or greater (for Plan A)
I need it to go to the next minute up even if over by 1 second (otherwise it'll confuse the non-techies who will be using it)
Any help with this matter would be greatly appreciated!
Take a look at Math.ceil(...). It is a JavaScript method for rounding up to the nearest integer. Here is a link to the MDN page.

How could I set a loop in a AudioBufferSourceNode to exact match specific offset in a the underlying buffer?

When creating a sound with AudioBufferSourceNode I can set the offset and the duration in seconds.
I have the offset and duration in sample positions which I suppose I have to convert to time, and I don't know where to start. Is it possible to get an exact match?
There seems there was sample offset and length in an earlier version of web-api but no more.
From the documentation: (w3c)
Please note that as a low-level implementation detail, the AudioBuffer
is at a specific sample-rate (usually the same as the AudioContext
sample-rate), and that the loop times (in seconds) must be converted
to the appropriate sample-frame positions in the buffer according to
this sample-rate.
the match should be exact, just divide your sample-position by the sample-rate,
second_offset = sample_offset / sample_rate
and
second_duration = sample_duration / sample_rate

Render image from audio

Is there a possibility to render an visualization of an audio file?
Maybe with SoundManager2 / Canvas / HTML5 Audio?
Do you know some technics?
I want to create something like this:
You have a tone of samples and tutorials here : http://www.html5rocks.com/en/tutorials/#webaudio
For the moment it work in the last Chrome and the last last Firefox (Opera ?).
Demos : http://www.chromeexperiments.com/tag/audio/
To do it now, for all visitors of a web site, you can check SoundManagerV2.js who pass through a flash "proxy" to access audio data http://www.schillmania.com/projects/soundmanager2/demo/api/ (They already work on the HTML5 audio engine, to release it as soon as majors browsers implement it)
Up to you for drawing in a canvas 3 differents audio data : WaveForm, Equalizer and Peak.
soundManager.defaultOptions.whileplaying = function() { // AUDIO analyzer !!!
$document.trigger({ // DISPATCH ALL DATA RELATIVE TO AUDIO STREAM // AUDIO ANALYZER
type : 'musicLoader:whileplaying',
sound : {
position : this.position, // In milliseconds
duration : this.duration,
waveformDataLeft : this.waveformData.left, // Array of 256 floating-point (three decimal place) values from -1 to 1
waveformDataRight: this.waveformData.right,
eqDataLeft : this.eqData.left, // Containing two arrays of 256 floating-point (three decimal place) values from 0 to 1
eqDataRight : this.eqData.right, // ... , the result of an FFT on the waveform data. Can be used to draw a spectrum (frequency range)
peakDataLeft : this.peakData.left, // Floating-point values ranging from 0 to 1, indicating "peak" (volume) level
peakDataRight : this.peakData.right
}
});
};
With HTML5 you can get :
var freqByteData = new Uint8Array(analyser.frequencyBinCount);
var timeByteData = new Uint8Array(analyser.frequencyBinCount);
function onaudioprocess() {
analyser.getByteFrequencyData(freqByteData);
analyser.getByteTimeDomainData(timeByteData);
/* draw your canvas */
}
Time to work ! ;)
Run samples through an FFT, and then display the energy within a given range of frequencies as the height of the graph at a given point. You'll normally want the frequency ranges going from around 20 Hz at the left to roughly the sampling rate/2 at the right (or 20 KHz if the sampling rate exceeds 40 KHz).
I'm not so sure about doing this in JavaScript though. Don't get me wrong: JavaScript is perfectly capable of implementing an FFT -- but I'm not at all sure about doing it in real time. OTOH, for user viewing, you can get by with around 5-10 updates per second, which is likely to be a considerably easier target to reach. For example, 20 ms of samples updated every 200 ms might be halfway reasonable to hope for, though I certainly can't guarantee that you'll be able to keep up with that.
http://ajaxian.com/archives/amazing-audio-sampling-in-javascript-with-firefox
Check out the source code to see how they're visualizing the audio
This isn't possible yet except by fetching the audio as binary data and unpacking the MP3 (not JavaScript's forte), or maybe by using Java or Flash to extract the bits of information you need (it seems possible but it also seems like more headache than I personally would want to take on).
But you might be interested in Dave Humphrey's audio experiments, which include some cool visualization stuff. He's doing this by making modifications to the browser source code and recompiling it, so this is obviously not a realistic solution for you. But those experiments could lead to new features being added to the <audio> element in the future.
For this you would need to do a Fourier transform (look for FFT) which will be slow in javascript, and not possible in realtime at present.
If you really want to do this in the browser, I would suggest doing it in java/silverlight, since they deliver the fastest number crunching speed in the browser.

Categories