CoreMIDI iOS some notes are missing / skipped / not read - ios

When pressing keys simultaneously (I experienced from 3 to 10 keys together ) , on Mac desktop using a piano connected via Bluetooth, it misses some notes. Maybe it is reproducible in iOS too but I haven't tried that out.
I am pretty sure it's a bug in with my Swift code because I used Midi monitor on the same mac simultaneously and Midi monitor finds all the note https://www.snoize.com/midimonitor/ but not CoreMIDI.
I also tried with a USB cable and with USB midi, but I can't reproduce.
Here is the Swift Code:
var client = MIDIClientRef()
var inputPort = MIDIPortRef()
MIDIClientCreate("MIDI Input Client" as CFString, nil, nil, &client)
MIDIInputPortCreate(client, "MIDI Input Port" as CFString, { (packetListPointer,_, _) in
let packets = packetListPointer.pointee
var packet = packets.packet
for _ in 0 ..< packets.numPackets {
let bytes = Mirror(reflecting: packet.data).children.map { $0.value }
// print("Received MIDI message: \(bytes)")
// Extract the relevant bytes from the MIDI message
let statusByte = Int(bytes[0] as! UInt8) // The status byte contains the message type
let noteByte = Int(bytes[1] as! UInt8)// The note byte contains the MIDI note number
// Check if the message is a note on or note off message
let isNoteOn = (statusByte & 0xF0) == 0x90 // The status byte for a note on message starts with 0x90
let isNoteOff = (statusByte & 0xF0) == 0x80 // The status byte for a note off message starts with 0x80
if isNoteOn || isNoteOff {
let noteNumber = Int(noteByte) // Convert the note byte to an integer
let noteName = NoteName(forNoteNumber: noteNumber)
let octave = noteNumber / 12 - 1 // Divide the note number by 12 and subtract 1 to get the octave
let direction = isNoteOn ? "up" : "down" // If it's a note on message, the direction is "up". If it's a note off message, the direction is "down"
print("Note: \(noteName)\(octave) \(direction)")
}
packet = MIDIPacketNext(&packet).pointee
}
}, nil, &inputPort)
// Set up the MIDI input endpoint and connect it to the input port
let sourceCount = MIDIGetNumberOfSources()
for i in 0..<sourceCount {
let src = MIDIGetSource(i)
MIDIPortConnectSource(inputPort, src, nil)
}
func NoteName(forNoteNumber noteNumber: Int) -> String {
let noteNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
let noteIndex = noteNumber % 12
return noteNames[noteIndex]
}
And this prints:
Note: B3 up
Note: A3 up
Note: E3 up
Note: G3 up
Note: F3 up
Note: E4 up
Note: F4 up
Note: D4 up
Note: G3 down
Note: A3 down
Note: F3 down
Note: E3 down
Note: B3 down
Note: D4 down
Note: E4 down
Note: C4 down
Note: G4 down
Note: F4 down
But the Midi Monitor prints:
19:58:58.510 From MIDI Piano Bluetooth Note On 1 B2 45
19:58:58.536 From MIDI Piano Bluetooth Note On 1 A2 70
19:58:58.536 From MIDI Piano Bluetooth Note On 1 E2 64
19:58:58.536 From MIDI Piano Bluetooth Note On 1 G2 70
19:58:58.536 From MIDI Piano Bluetooth Note On 1 F2 80
19:58:58.536 From MIDI Piano Bluetooth Note On 1 C3 43 <- missing
19:58:58.538 From MIDI Piano Bluetooth Note On 1 E3 64
19:58:58.538 From MIDI Piano Bluetooth Note On 1 F3 45 <- missing
19:58:58.538 From MIDI Piano Bluetooth Note On 1 G3 43
19:58:58.539 From MIDI Piano Bluetooth Note On 1 D3 47
19:58:58.780 From MIDI Piano Bluetooth Note Off 1 G2 0
19:58:58.807 From MIDI Piano Bluetooth Note Off 1 A2 0
19:58:58.807 From MIDI Piano Bluetooth Note Off 1 F2 0
19:58:58.807 From MIDI Piano Bluetooth Note Off 1 E2 0
19:58:58.807 From MIDI Piano Bluetooth Note Off 1 B2 0
19:58:58.808 From MIDI Piano Bluetooth Note Off 1 D3 0
19:58:58.808 From MIDI Piano Bluetooth Note Off 1 E3 0
19:58:58.817 From MIDI Piano Bluetooth Note Off 1 C3 0
19:58:58.817 From MIDI Piano Bluetooth Note Off 1 G3 0
19:58:58.818 From MIDI Piano Bluetooth Note Off 1 F3 0
(please ignore the octave shift of one)

Related

Lua Musical Notes to Numbers

I need to convert some musical note inputs representing a chord to numbers above it's root note 0 using Lua.
So from the midi data we get the notes of a C13 Chord
input: C, E, G, A#, D, F, A
as the root note 0 is C we start on the C note,
below we have 2 octaves of a piano keyboard, 12 notes on each where chords are played
0C 1C# 2D 3D# 4E 5F 6F# 7G 8G# 9A 10A# 11B 12C 13C# 14D 15D# 16E 17F 18F# 19G 20G# 21A 22A# 23B
so C is the root note 0
D,F,A are played on the next octave
result: 0,4,7,10,14,17,21
so if we have a D chord
input: D,F#,A
D is the root note 0
all notes played on the first octave
0D 1D# 2E 3F 4F# 5G 6G# 7A 8A# 9B 10C 11C# 12D 13D# 14E 15F 16F# 17G 18G# 19A 20A# 21B 22C 23C#
result: 0,4,7
G#m7#9 Chord
input: G#,B,D#,F#,B
0G# 1A 2A# 3B 4C 5C# 6D 7D# 8E 9F 10F# 11G 12G# 13A 14A# 15B 16C 17C# 18D 19D# 20E 21F 22F# 23G
result: 0,3,7,10,15
Something like this may work:
local function notes2nums(input)
local map = {A = 9, ["A#"] = 10, B = 11, C = 0, ["C#"] = 1, D = 2, ["D#"] = 3, E = 4, F = 5, ["F#"] = 6, G = 7, ["G#"] = 8}
local base, prev
return (input:gsub("([^,]+)", function(note)
local num = map[note] or error(("Unexpected note value '%s'"):format(note))
base = base or num
num = num - base
if prev and num < prev then num = num + 12 end
prev = num
return tostring(num)
end))
end
print(notes2nums("D,F#,A"))
print(notes2nums("C,E,G,A#,D,F,A"))
print(notes2nums("G#,B,D#,F#,B"))
This prints:
0,4,7
0,4,7,10,14,17,21
0,3,7,10,15

What is hexa MIDI message for G2, D♯3, D3 in iOS?

I want to send MIDI notes using HEXA package.
G2, D♯3, D3
using coreMIDI in swift
please See below Midi Packet For above mention Note.
For G2
var packet1:MIDIPacket = MIDIPacket()
packet1.timeStamp = 0
packet1.length = 3
packet1.data.0 = 0x90 // Note On event channel 1
packet1.data.1 = 0x37 // Note C3
packet1.data.2 = 0x7F // Velocity
For D#3
just Update
packet1.data.1 = 0x3F
For D3
just Update
packet1.data.1 = 0x3E
For More Codes, Open this file MidiOutpout In Midi Monitor Application

Comparing signed 64 bit number using 32 bit bitwise operations in Lua

I am using Lua on Redis and want to compare two signed 64-bit numbers, which are stored in two 8-byte/character strings.
How can I compare them using the libraries available in Redis?
http://redis.io/commands/EVAL#available-libraries
I'd like to know >/< and == checks. I think this probably involves pulling two 32-bit numbers for each 64-bit int, and doing some clever math on those, but I am not sure.
I have some code to make this less abstract. a0, a1, b0, b1 are all 32 bit numbers used to represent the msb & lsb's of two 64-bit signed int 64s:
-- ...
local comp_int64s = function (a0, a1, b0, b1)
local cmpres = 0
-- TOOD: Real comparison
return cmpres
end
local l, a0, a1, b0, b1
a0, l = bit.tobit(struct.unpack("I4", ARGV[1]))
a1, l = bit.tobit(struct.unpack("I4", ARGV[1], 5))
b0, l = bit.tobit(struct.unpack("I4", blob))
b1, l = bit.tobit(struct.unpack("I4", blob, 5))
print("Cmp result", comp_int64s(a0, a1, b0, b1))
EDIT: Added code
I came up with a method that looks like it's working. It's a little ugly though.
The first step is to compare top 32 bits as 2 compliment #’s
MSB sign bit stays, so numbers keep correct relations
-1 —> -1
0 —> 0
9223372036854775807 = 0x7fff ffff ffff ffff -> 0x7ffff ffff = 2147483647
So returning the result from the MSB's works unless they are equal, then the LSB's need to get checked.
I have a few cases to establish the some patterns:
-1 = 0xffff ffff ffff ffff
-2 = 0xffff ffff ffff fffe
32 bit is:
-1 -> 0xffff ffff = -1
-2 -> 0xffff fffe = -2
-1 > -2 would be like -1 > -2 : GOOD
And
8589934591 = 0x0000 0001 ffff ffff
8589934590 = 0x0000 0001 ffff fffe
32 bit is:
8589934591 -> ffff ffff = -1
8589934590 -> ffff fffe = -2
8589934591 > 8589934590 would be -1 > -2 : GOOD
The sign bit on MSB’s doesn’t matter b/c negative numbers have the same relationship between themselves as positive numbers. e.g regardless of sign bit, lsb values of 0xff > 0xfe, always.
What about if the MSB on the lower 32 bits is different?
0xff7f ffff 7fff ffff = -36,028,799,166,447,617
0xff7f ffff ffff ffff = -36,028,797,018,963,969
32 bit is:
-..799.. -> 0x7fff ffff = 2147483647
-..797.. -> 0xffff ffff = -1
-..799.. < -..797.. would be 2147483647 < -1 : BAD!
So we need to ignore the sign bit on the lower 32 bits. And since the relationships are the same for the LSBs regardless of sign, just using
the lowest 32 bits unsigned works for all cases.
This means I want signed for the MSB's and unsigned for the LSBs - so chaging I4 to i4 for the LSBs. Also making big endian official and using '>' on the struct.unpack calls:
-- ...
local comp_int64s = function (as0, au1, bs0, bu1)
if as0 > bs0 then
return 1
elseif as0 < bs0 then
return -1
else
-- msb's equal comparing lsbs - these are unsigned
if au1 > bu1 then
return 1
elseif au1 < bu1 then
return -1
else
return 0
end
end
end
local l, as0, au1, bs0, bu1
as0, l = bit.tobit(struct.unpack(">i4", ARGV[1]))
au1, l = bit.tobit(struct.unpack(">I4", ARGV[1], 5))
bs0, l = bit.tobit(struct.unpack(">i4", blob))
bu1, l = bit.tobit(struct.unpack(">I4", blob, 5))
print("Cmp result", comp_int64s(as0, au1, bs0, bu1))
Comparing is a simple string compare s1 == s2.
Greater than is when not s1 == s2 and i1 < i2.
Less than is the real work. string.byte allows to get single bytes as unsigned char. In case of unsigned integer, you would just have to check bytes-downwards: b1==b2 -> check next byte; through all bytes -> false (equal); b1>b2 -> false (greater than); b1<b2 -> true. Signed requires more steps: first check the sign bit (uppermost byte >127). If sign 1 is set but not sign 2, integer 1 is negative but not integer 2 -> true. The opposite would obviously result in false. When both signs are equal, you can do the unsigned processing.
When you can pack more bytes to an integer, it's fine too, but you have to adjust the sign bit check. When you have LuaJIT, you can use the ffi library to cast your string into a byte array into an int64.

How to set 5 bits to value 3 at offset 387 bit in byte data sequence?

I need set some bits in ByteData at position counted in bits.
How I can do this?
Eg.
var byteData = new ByteData(1024);
var bitData = new BitData(byteData);
// Offset in bits: 387
// Number of bits: 5
// Value: 3
bitData.setBits(387, 5, 3);
Yes it is quite complicated. I dont know dart, but these are the general steps you need to take. I will label each variable as a letter and also use a more complicated example to show you what happens when the bits overflow.
1. Construct the BitData object with a ByteData object (A)
2. Call setBits(offset (B), bits (C), value (D));
I will use example values of:
A: 11111111 11111111 11111111 11111111
B: 7
C: 10
D: 00000000 11111111
3. Rather than using an integer with a fixed length of bits, you could
use another ByteData object (D) containing your bits you want to write.
Also create a mask (E) containing the significant bits.
e.g.
A: 11111111 11111111 11111111 11111111
D: 00000000 11111111
E: 00000011 11111111 (2^C - 1)
4. As an extra bonus step, we can make sure the insignificant
bits are really zero by ANDing with the bitmask.
D = D & E
D 00000000 11111111
E 00000011 11111111
5. Make sure D and E contain at least one full zero byte since we want
to shift them.
D 00000000 00000000 11111111
E 00000000 00000011 11111111
6. Work out these two integer values:
F = The extra bit offset for the start byte: B mod 8 (e.g. 7)
G = The insignificant bits: size(D) - C (e.g. 14)
7. H = G-F which should not be negative here. (e.g. 14-7 = 7)
8. Shift both D and E left by H bits.
D 00000000 01111111 10000000
E 00000001 11111111 10000000
9. Work out first byte number (J) floor(B / 8) e.g. 0
10. Read the value of A at this index out and let this be K
K = 11111111 11111111 11111111
11. AND the current (K) with NOT E to set zeros for the new bits.
Then you can OR the new bits over the top.
L = (K & !E) | D
K & !E = 11111110 00000000 01111111
L = 11111110 01111111 11111111
12. Write L to the same place you read it from.
There is no BitData class, so you'll have to do some of the bit-pushing yourself.
Find the corresponding byte offset, read in some bytes, mask out the existing bits and set the new ones at the correct bit offset, then write it back.
The real complexity comes when you need to store more bits than you can read/write in a single operation.
For endianness, if you are treating the memory as a sequence of bits with arbitrary width, I'd go for little-endian. Endianness only really makes sense for full-sized (2^n-bit, n > 3) integers. A 5 bit integer as the one you are storing can't have any endianness, and a 37 bit integer also won't have any natural way of expressing an endianness.
You can try something like this code (which can definitely be optimized more):
import "dart:typed_data";
void setBitData(ByteBuffer buffer, int offset, int length, int value) {
assert(value < (1 << length));
assert(offset + length < buffer.lengthInBytes * 8);
int byteOffset = offset >> 3;
int bitOffset = offset & 7;
if (length + bitOffset <= 32) {
ByteData data = new ByteData.view(buffer);
// Can update it one read/modify/write operation.
int mask = ((1 << length) - 1) << bitOffset;
int bits = data.getUint32(byteOffset, Endianness.LITTLE_ENDIAN);
bits = (bits & ~mask) | (value << bitOffset);
data.setUint32(byteOffset, bits, Endianness.LITTLE_ENDIAN);
return;
}
// Split the value into chunks of no more than 32 bits, aligned.
do {
int bits = (length > 32 ? 32 : length) - bitOffset;
setBitData(buffer, offset, bits, value & ((1 << bits) - 1));
offset += bits;
length -= bits;
value >>= bits;
bitOffset = 0;
} while (length > 0);
}
Example use:
main() {
var b = new Uint8List(32);
setBitData(b.buffer, 3, 8, 255);
print(b.map((v)=>v.toRadixString(16)));
setBitData(b.buffer, 13, 6*4, 0xffffff);
print(b.map((v)=>v.toRadixString(16)));
setBitData(b.buffer, 47, 21*4, 0xaaaaaaaaaaaaaaaaaaaaa);
print(b.map((v)=>v.toRadixString(16)));
}

What is the meaning of this Queue Property (iOS Audio Queues)?

I want to write a player to play the music. I see the code like below:
AudioFileGetPropertyInfo(audioFile,
kAudioFilePropertyMagicCookieData, &size, nil);
if (size > 0) {
cookie = malloc(sizeof(char) * size);
AudioFileGetProperty(audioFile,
kAudioFilePropertyMagicCookieData, &size, cookie);
AudioQueueSetProperty(aduioQueue,
kAudioQueueProperty_MagicCookie, cookie, size);
free(cookie);
}
i don't know why to set the AudioQueueProperty,and what is the means about kAudioQueueProperty_MagicCookie? I can't find the help from the documentation.
who can give a direction to slove the problem.
Actually magic cookie is more than just a signature, it holds some information about the encoder, most useful items are "Maximum Bit Rate" and "Average Bit Rate", specially for a compressed format like AudioFileMPEG4Type. For this specific type magic cookie is same as "esds" box in MPEG-4 data file. You can find the exact bit settings at:
http://xhelmboyx.tripod.com/formats/mp4-layout.txt
8+ bytes vers. 2 ES Descriptor box
= long unsigned offset + long ASCII text string 'esds'
- if encoded to ISO/IEC 14496-10 AVC standards then optionally use:
= long unsigned offset + long ASCII text string 'm4ds'
-> 4 bytes version/flags = 8-bit hex version + 24-bit hex flags
(current = 0)
-> 1 byte ES descriptor type tag = 8-bit hex value 0x03
-> 3 bytes extended descriptor type tag string = 3 * 8-bit hex value
- types are Start = 0x80 ; End = 0xFE
- NOTE: the extended start tags may be left out
-> 1 byte descriptor type length = 8-bit unsigned length
-> 2 bytes ES ID = 16-bit unsigned value
-> 1 byte stream priority = 8-bit unsigned value
- Defaults to 16 and ranges from 0 through to 31
-> 1 byte decoder config descriptor type tag = 8-bit hex value 0x04
-> 3 bytes extended descriptor type tag string = 3 * 8-bit hex value
- types are Start = 0x80 ; End = 0xFE
- NOTE: the extended start tags may be left out
-> 1 byte descriptor type length = 8-bit unsigned length
-> 1 byte object type ID = 8-bit unsigned value
- type IDs are system v1 = 1 ; system v2 = 2
- type IDs are MPEG-4 video = 32 ; MPEG-4 AVC SPS = 33
- type IDs are MPEG-4 AVC PPS = 34 ; MPEG-4 audio = 64
- type IDs are MPEG-2 simple video = 96
- type IDs are MPEG-2 main video = 97
- type IDs are MPEG-2 SNR video = 98
- type IDs are MPEG-2 spatial video = 99
- type IDs are MPEG-2 high video = 100
- type IDs are MPEG-2 4:2:2 video = 101
- type IDs are MPEG-4 ADTS main = 102
- type IDs are MPEG-4 ADTS Low Complexity = 103
- type IDs are MPEG-4 ADTS Scalable Sampling Rate = 104
- type IDs are MPEG-2 ADTS = 105 ; MPEG-1 video = 106
- type IDs are MPEG-1 ADTS = 107 ; JPEG video = 108
- type IDs are private audio = 192 ; private video = 208
- type IDs are 16-bit PCM LE audio = 224 ; vorbis audio = 225
- type IDs are dolby v3 (AC3) audio = 226 ; alaw audio = 227
- type IDs are mulaw audio = 228 ; G723 ADPCM audio = 229
- type IDs are 16-bit PCM Big Endian audio = 230
- type IDs are Y'CbCr 4:2:0 (YV12) video = 240 ; H264 video = 241
- type IDs are H263 video = 242 ; H261 video = 243
-> 6 bits stream type = 3/4 byte hex value
- type IDs are object descript. = 1 ; clock ref. = 2
- type IDs are scene descript. = 4 ; visual = 4
- type IDs are audio = 5 ; MPEG-7 = 6 ; IPMP = 7
- type IDs are OCI = 8 ; MPEG Java = 9
- type IDs are user private = 32
-> 1 bit upstream flag = 1/8 byte hex value
-> 1 bit reserved flag = 1/8 byte hex value set to 1
-> 3 bytes buffer size = 24-bit unsigned value
-> 4 bytes maximum bit rate = 32-bit unsigned value
-> 4 bytes average bit rate = 32-bit unsigned value
-> 1 byte decoder specific descriptor type tag
= 8-bit hex value 0x05
-> 3 bytes extended descriptor type tag string
= 3 * 8-bit hex value
- types are Start = 0x80 ; End = 0xFE
- NOTE: the extended start tags may be left out
-> 1 byte descriptor type length
= 8-bit unsigned length
-> ES header start codes = hex dump
-> 1 byte SL config descriptor type tag = 8-bit hex value 0x06
-> 3 bytes extended descriptor type tag string = 3 * 8-bit hex value
- types are Start = 0x80 ; End = 0xFE
- NOTE: the extended start tags may be left out
-> 1 byte descriptor type length = 8-bit unsigned length
-> 1 byte SL value = 8-bit hex value set to 0x02
"
Magic Cookie that comes from kAudioFilePropertyMagicCookieData starts from ES Descriptor (just ignore the first 4 bytes described in the map and rest will be an exact match to magick cookie).
A sample magic cookie would be like this:
03 80 80 80 22 00 00 00 04 80 80 80 14 40 15 00 18 00 00 00 FA 00 00 00 FA 00 05 80 80 80 02 12 08 06 80 80 80 01 02
Maximum bit rate is at offset 18 -> 0XFA00 (or 64,000)
Average bit rate is at offset 22 -> 0XFA00 (or 64,000)
Although according to Apple documentation, magic cookie is read/write, but I had no chance changing the bit rate before creating or converting files.
Hope that helps someone.
The "magic cookie" is a file type signature consisting of a unique sequence of bytes at the beginning of the file, indicating the file format. The audio queue framework uses this information to determine how to decode or extract audio information from a file stream (instead of using or trusting the file name extension). The code you posted reads this set of bytes from the file, and passes it to the audio queue as a cookie. (It would be a mistake to let them be interpreted as PCM samples instead, for instance).

Resources