Wrong POSITION shown for SMF with multiple tempos (using MCI) - mcisendstring

Is it not possible to get the proper millisecond POSITION value
in Standard MIDI Files having multiple Tempos?
This line
ret = mciSendString("status MCIMIDI position", 0, 0, 0)
works only if the MIDI file has ONE Tempo setting.
How do you deal with multiple Tempos?

Related

Buffer country borders with st_buffer and a SpatialPolygonsDataFrame?

I'm using coordinate_cleaner's country test cc_coun but it's flagging entries with coordinates near to the edges country borders. To try to keep them I wanted to buffer the terrestrial area of countries, essentially expanding their borders a little so that it doesn't flag these entries.
I've tried:
require(rnaturalearth)
world <- ne_countries(scale = "large", returnclass = "sf") %>% st_buffer(dist=.001)
Using st_buffer(dist=.001) does change the geometry, but I noticed whatever I put into dist doesn't matter as it changes it to the same thing regardless (I tried .001, 0.1, 1, 2, and -1, though any minus number removes the geometry altogether).
I found that maybe I need to transform my sf file into something else and then use st_buffer so it's in meters rather than degrees(?). I saw this question/answer but I don't understand it well enough to help my situation: What unit is the `dist` argument in `st_buffer` set to by default?
In the end I'm looking to create a SpatialPolygonsDataFrame reference file to feed into cc_coun. Using the above code I followed on with:
world <- sf:::as_Spatial(world)
coun_test <- cc_coun(x = data,
lon = "Decimal_Long",
lat = "Decimal_Lat",
iso3 = "Country_code",
value = "flagged",
ref = world,
verbose = TRUE)
Which ended up flagging more entries than when I didn't use st_buffer on the reference fine.
In summary, I want to add a buffer to the edge of every country border by around 100 meters in a file I can use as a reference in this test. Is this the best way to go about it or is there a better/easier way? I'd appreciate any advice.
Thank you

Repeating a Function x times in the same Line in Google Sheets

I have been researching a solution to a problem that I just can not seem to avoid, and have yet to find a solution.
In brief, I am trying to calculate unique probabilities that lead to a "1 or 0" for more than one variable, but all in one cell.
Here is my working code line that represents the probability of just one variable:
=sum(if(randbetween(1,100) > subtotal(1,L23), 0, 1))
What I am trying to figure out is how to repeat this function times x, but with it yielding a different randbetween number each time, all in one cell.
As my x variable can represent 10 different independent variables at this time, and stem over 30 specific formula lengths for each IV, utilizing the preset workaround would lead me to creating hundreds of cells of data. I obviously do not want that clutter.
If code worked the way I wanted it to, the best formula-esque way I would describe what I wanted to happen is this:
=sum(repeatuniqueformula(sum(if(randbetween(1,100) > subtotal(1,L23), 0, 1)), x))
Simplified, relevant question gathered from a problem by problem analysis:
How to replicate a function in the function line that allows for the randbetween to recalculate each time.
Sub-information: If you simply multiply the function by lets say 6, it will multiply the answer of the randbetween function without recalculating.
=sum(if(randbetween(1,100) > subtotal(1,L23), 0, 1)*6)
Alternatively, I could do a workaround and create other cells with individual randbetween functions, but that causes a lot of manual work due to having to adjust the number of times a function in a line is repeated.
=sum(if(Q2 > subtotal(1,L15), 0, 1),if(Q3 > subtotal(1,L15), 0, 1),if(Q4 > subtotal(1,L15), 0, 1),if(Q5 > subtotal(1,L15), 0, 1),if(Q6 > subtotal(1,L15), 0, 1),if(Q7 > subtotal(1,L15), 0, 1),if(Q8 > subtotal(1,L15), 0, 1))
The alternative is both cluttery and takes a lot of effort to maintain, as changing the number of "x" will change the amount of
if(Q2 > subtotal(1,L15), 0, 1)
I would need.
In order to get what you want to happen (=sum(repeatuniqueformula(sum(if(randbetween(1,100) > subtotal(1,L23), 0, 1)), x))) you will have to create a custom function by using Google Apps Script, but x should be replaced by number or by a reference to a cell having a value or formula that returns that value.
References
https://developers.google.com/apps-script/guides/sheets
https://developers.google.com/apps-script/guides/sheets/functions

Sending a program change with a program number (patch number)

I have two Roland midi devices that behave the same when I try to send a bank and program change. It always sets it to the first patch of the bank. It won't change the patch I choose in the bank. Pro Logic can, however, switch to different banks.
The following example cause the devices to change to the bank but the program (patch) on the device defaults to the first in that bank and not number 9.
var event = AKMIDIEvent(controllerChange: 0, value: 89, channel: 0)
midiOut.sendEvent(event)
event = AKMIDIEvent(controllerChange: 32, value: 64, channel: 0)
midiOut.sendEvent(event)
event = AKMIDIEvent(programChange: 9, channel: 0)
midiOut.sendEvent(event)
Anyone have experience with sending this MIDI messages?
I was going through the same issue and was about to go crazy. It turns out the Program Change values in various MIDI data specifications, from various vendors, are 1 based. Not 0. Or perhaps it is the AudioKit implementation that is wrong?
So, instead of a programChange value of 9 you should use a value of 8. Here is my code for changing the current instrument on channel 0 to the Bösendorfer grand piano on a Yamaha Clavinova keyboard, where the programChange value in the MIDI data specification is designated as 1.
midiOut.sendControllerMessage(0, value: 108) // MSB sound bank selection
midiOut.sendControllerMessage(32, value: 0) // LSB sound bank selection
midiOut.sendEvent(AKMIDIEvent(programChange: 0, channel: 0)) // Initiate program change based on MSB and LSB selections
While reading various documentation about how MIDI works I also saw some forum posts describing keyboards that expect the LSB bank selection before the MSB bank selection. That is however not my understanding of how MIDI should work, but worth a try if you still cannot make it work with your Roland keyboards.

Cropping MIDI file using AudioKit

I am trying to crop and loop a certain part of a MIDI file using AudioKit.
I am using a sequencer and found a couple of things that are close to what I need, but not exactly.
I found a method in AKSequencer called clearRange. With this method I am able to silence the parts of the MIDI I don't want, but I haven't found a way to trim the sequencer and only keep the part I am interested in. Right now only the part I want has sound but I still get the silent parts.
Is there a way to trim a sequencer or to create a new sequencer with only the portion I want to keep from the original one?
Thanks!
One frustrating limitation of Apple's MusicSequence (which AKSequencer is based on) is that although you can easily set the 'right side' of the looping section, the left side will always loop back to zero and cannot be changed. So to crop from the left side, you need to isolate the section that you want to loop and shift it over so that the start of your loop is at zero.
As of AudioKit 4.2.4, this is possible. Use AKMusicTrack's .getMIDINoteData() to get an array of AKMIDINoteData structs whose content can be edited and then used to replace the original data. If you had a 16 beat track and you wanted to loop the last four beats, you could do something ike this:
let loopStart = 12.0
let loopLength = 4.0
// keep track of the original track contents
let originalLength = 16.0
let originalContents = track.getMIDINoteData()
// isolate the segment for looping and shift it to the start of the track
let loopSegment = originalContents.filter { loopStart ..< (loopStart + loopLength) ~= $0.position.beats }
let shiftedSegment = loopSegment.map { AKMIDINoteData(noteNumber: $0.noteNumber,
velocity: $0.velocity,
channel: $0.channel,
duration: $0.duration,
position: AKDuration(beats: $0.position.beats - loopStart))
}
// replace the track contents with the loop, and assert the looping behaviour
track.replaceMIDINoteData(with: shiftedSegment)
seq.setLength(AKDuration(beats: loopLength))
seq.enableLooping()
// and to get back to the original:
track.replaceMIDINoteData(with: originalContents)
seq.setLength(AKDuration(beats: originalLength))
seq.enableLooping()
If you wanted to looping section to repeat for the length of the original sequence, then you could use the shiftedSegment as a template and build a 16 beat sequence from it.

Lua: How do I read from a list of numbers

I have a function which does all the magic for me and controls a motor.
This reduces my programming to this one line...
Set_RPM_With_Acceleration_Value( 200, 15)
In the example shown, the motor will spin up to 200 RPM, with an acceleration value of 15
I'm testing the stop/start/interrupt/restart capability of the system hardware and software.
I now want to run the test with different values given to the function; e.g.,,,
Set_RPM_With_Acceleration_Value( 200, 15)
Set_RPM_With_Acceleration_Value( 50, 09)
Set_RPM_With_Acceleration_Value( 400, 20)
Set_RPM_With_Acceleration_Value( 500, 25)
I want to encapsulate this into a loop which...
Reads two numbers (from a table ? Idunno, advise me)
Gives me those two numbers in two variables
Lets me call the function using those names, and not hard coded numbers
e.g., where I'm currently doing this...
Set_RPM_With_Acceleration_Value( 200, 15)
I would like to do this...
Set_RPM_With_Acceleration_Value( RPM_Value, Acceleration_Value)
How do I set up the numbers, and how do I read from the table ?
For that matter, is a table the right way to think about this ?
Does there exist such a thing in Lua as a table of tables ?
This will be for automated machine testing. We do NOT want a human involved at the keyboard or mouse.
On the other hand, it is quite desirable for me to hand code the values in the table once, ahead of time, before the script runs. I want to see what happens with various combinations of RPM, Acceleration, Power Drop Outs, etc.
Try this:
V={
200, 15,
50, 09,
400, 20,
500, 25,
}
for i=1,#V,2 do
local RPM_Value = V[i]
local Acceleration_Value = V[i+1]
Set_RPM_With_Acceleration_Value(RPM_Value, Acceleration_Value)
end

Resources