How do i retrieve the note like B4, C5 etc from AudiFileInspector from NAudio - midi

1:1:0 0 NoteOn Ch: 1 B4 Vel:96 Len: 473
1:2:0 480 NoteOn Ch: 1 B4 Vel:96 Len: 473
1:3:0 960 NoteOn Ch: 1 C5 Vel:96 Len: 473
This is what they print out. What I'm looking for is the splitting of data up. I could get the absolute time, but not the value such as B4, C5 and the Len: value, which is 473(varies from different songs)
http://naudio.codeplex.com/downloads/get/523321

It's open source, so you can examine the code in MidiFileInspector.cs, and see that it is just making use of NoteEvent.ToString which in turn makes use of the NoteEvent.NoteName property.

Related

Base 36 counter without I or O

we have a requirement to make our serial numbers Base 36 (0-9,A-Z). My initial thought was store the counter in decimal and convert to hex only when required for display. This makes the counting simple, however there is another requirement to not use I or O because it'll be confused with 1 and 0 on the barcodes human readable portion. This makes it a bit of a nightmare.
Language is unimportant, but the counter itself will be held in SQL Server 2012+.
Anyone have any experiences with this problem?
Edit:
I've rewritten a method I found to test in C#. It allows any string of base characters to be passed in.
ie. string baseChars = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
It's not pretty but its a start!
private string GetCustomBase(int iValue, string baseChars)
{
int baseNum = baseChars.Length;
int value= iValue;
string result = "";
while( value > 0 )
{
result = baseChars[ 0 + (value % baseNum)] + result;
value = value / baseNum;
}
return result;
}
private int GetDecimal(string strValue, string baseChars)
{
int baseNum = baseChars.Length;
string strAmendedValue = strValue;
int iResult = 0;
//Each char one at a time (from right)
for (int i = 0; i < strValue.Length; i++)
{
string c = strValue.Substring(strValue.Length - i -1, 1);
int iPos = baseChars.IndexOf(c); //get actual value (0 = 0, A = 10 etc.)
int iPowerVal = (int)Math.Pow((double)baseNum, (double)(i));
iResult = iResult + (iPowerVal * iPos);
}
return iResult;
}
An implementation of the suggestion in the question comments. As language is unimportant, here's a Ruby version:
class Integer
def to_34_IO_shifted
to_s(34).upcase.tr("IJKLMNOPQRSTUVWX", "JKLMNPQRSTUVWXYZ")
end
end
class String
def from_34_IO_shifted
upcase.tr("JKLMNPQRSTUVWXYZIO", "IJKLMNOPQRSTUVWX10").to_i(34)
end
end
puts 170.times.map { |x| x.to_34_IO_shifted }.join(' ')
x = 73644
x34 = x.to_34_IO_shifted
x10 = x34.from_34_IO_shifted
puts "\n#{x} -> '#{x34}' -> #{x10}"
puts "'10' -> #{'10'.from_34_IO_shifted}"
puts "'IO' -> #{'IO'.from_34_IO_shifted}"
Output:
0 1 2 3 4 5 6 7 8 9 A B C D E F G H J K L M N P Q R S T U V W X Y Z 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 1G 1H 1J 1K 1L 1M 1N 1P 1Q 1R 1S 1T 1U 1V 1W 1X 1Y 1Z 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 2G 2H 2J 2K 2L 2M 2N 2P 2Q 2R 2S 2T 2U 2V 2W 2X 2Y 2Z 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 3G 3H 3J 3K 3L 3M 3N 3P 3Q 3R 3S 3T 3U 3V 3W 3X 3Y 3Z 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 4G 4H 4J 4K 4L 4M 4N 4P 4Q 4R 4S 4T 4U 4V 4W 4X 4Y 4Z
73644 -> '1VQ0' -> 73644
'10' -> 34
'IO' -> 34
EDIT: made it so that I and O are interpreted as 1 and 0, in case someone does misread it.

Wiegand RFID reader VS USB RFID reader Raspberry PI

I have two Raspberry Pis running python code to retrieve the serial number of an RFID tag. One has an RFID reader with a Wiegand interface hooked to GPIO pins and other has an RFID reader that behaves like a keyboard connected over USB. However, I get different numbers from the two reader when scanning the same RFID tag.
For example, for one tag, I get 57924897 from the Raspberry Pi with the Wiegand reader and 0004591983 from the Raspberry Pi with the USB keyboard reader.
Can sombody explain the difference? Are both readers reading the same? Or are they just reading some different parameter?
Looking at those two values, it seems that you do not properly read and convert the value from the Wiegand interface.
The USB keyboard reader reads the serial number in 10 digit decimal form. A Wiegand reader typically trunkaes the serial number into a 26 bit value (1 parity bit + 8 bit site code + 16 bit tag ID + 1 parity bit).
So let's look at the two values that you get:
+--------------+------------+-------------+-----------------------------------------+
| READER | DECIMAL | HEXADECIMAL | BINARY |
+--------------+------------+-------------+-----------------------------------------+
| USB keyboard | 0004591983 | 0046116F | 0000 0000 0100 0110 0001 0001 0110 1111 |
| Wiegand | 57924897 | 373DD21 | 1 1011 1001 1110 1110 1001 0000 1 |
+--------------+------------+-------------+-----------------------------------------+
When you take a close look at the binary representation of those two values, you will see that they correlate with each other:
USB keyboard: 0000 0000 0100 0110 0001 0001 0110 1111
Wiegand: 1 1011 1001 1110 1110 1001 0000 1
So it seems as if the Wiegand value matches the inverted value obtained from the USB keyboard reader:
USB keyboard: 0000 0000 0100 0110 0001 0001 0110 1111
NOT(Wiegand): 0 0100 0110 0001 0001 0110 1111 0
So the inverted value (logical NOT) from the Wiegand interface matches the value read by the USB reader.
Next, let's look at the two parity bits. The data over the Wiegand interface typically looks like:
b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19 b20 b21 b22 b23 b24 b25
PE D23 D22 D21 D20 D19 D18 D17 D16 D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 PO
The first line being the bits numbered as they arrive over the Wiegand wires. The second line being the same bits as they need to be interpreted by the receiver, where PE (b0) is an even parity bit over D23..D12 (b1..b12), PO (b25) is an odd parity bit over D11..D0 (b13..b24), and D23..D0 are the data bits representing an unsigned integer number.
So looking at your number, you would have received:
PE D23 D22 D21 D20 D19 D18 D17 D16 D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 PO
0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 1 1 1 1 0
If we check the parity bits PE and PO, we get:
PE D23........D12
0 0100 0110 0001
contains 4 ones (1), hence even parity is met.
D21.........D0 PO
0001 0110 1111 0
contains 7 ones (1), hence odd parity is met.
So, to summarize the above, your code reading from the Wiegand interface does not properly handle the Wiegand data format. First, it does not trim the parity bits and second, it reads the bits with wrong polarity (zeros are ones and ones are zeros).
In order to get the correct number from the Wiegand reader, you either have to fix you code for reading from the Wiegand interface (to fix polarity, to skip the first and the last bit from the data value, and to possibly check the parity bits). Or you can take the value that you currently get, invert that value, and strip the lower and upper bits. In C, that would look something like this:
int unsigned currentWiegandValue = ...;
int unsigned newWiegandValue = ((~currentWiegandValue) >> 1) & 0x0FFFFFF;

How to use the 'if' statement in matlab?

I have a cell array of size 5x5 as below
B= 00 10 11 10 11
01 01 01 01 11
10 00 01 00 01
10 10 01 01 11
10 10 10 00 10
And two column vectors
S1= 21
23
28
25
43
S2= 96
85
78
65
76
I want to create a new cell array of the same size as B say 5x5 such that it satisfies the following condition
Final={S1 if B{i}=11
S1 if B{i}=10
S2 if B{i}=01
S2 if B{i}=00
So the resulting output would be something like this
Z = s2 s1 s1 s1 s1
s2 s2 s2 s2 s1
s1 s2 s2 s2 s2
s1 s1 s2 s2 s1
s1 s1 s1 s2 s1
ie Z= 96 21 21 21 21
85 85 85 85 23
28 78 78 78 78
25 25 65 65 25
43 43 43 76 43
I tried using the if condition but i get error saying
'Error: The expression to the left of the equals sign is not a valid target for an assignment.'
for i=1:1:128
for j=1:1:16
if fs{i,j}=00
Z{i,j}=S1{i,j}
elseif fs{i,j}= 01
Z{i,j}=S2{i,j}
elseif fs{i,j}= 10
Z{i,j}=S1{i,j}
elseif fs{i,j}= 11
Z{i,j}=S2{i,j}
end
end
I think I'm making a mistake in the if statement as well as the expressions I'm using. Where am i going wrong? Please help thanks in advance.
Use == for comparison and = for assignment. So if fs{i,j}==00, etc.
Edit: Matlab is really designed for highly vectorized operations. Nested loops are slow compared to native functions, and typically can be replaced with vectorized versions. Is there any particular reason why you are using cell arrays instead of matrices, especially when you only have numeric data?
If B, S1, and S2 were matrices your code could be written in one highly efficient line that will run much much faster:
Z = bsxfun(#times, S1, B == 11 | B == 10) + bsxfun(#times, S2, B == 01 | B == 0)
Since B is a cell array you will want to convert it to a matrix using cell2mat unless you'd like to use cellfun.
Instead, you can just call B_mat = cell2mat(B), followed by (B_mat>=10).*repmat(S1,1,5) + (B_mat<10).*repmat(S2,1,5).
It's possible that your cell array actually contains binary values, possibly represented as strings, in which case the conditions used above would need to be changed. Then using cellfun may be necessary.

Create new variable that recognizes changes in a code in Matlab

I have a double matrix B that has in C1 the year 1998 and in C2 a code (unrepeated). Each C2 is given a value in C3.
% C1 C2 C3
B=[ 1998 22 37
1998 34 7
1998 76 12
1998 98 29
1998 107 14
…]
This is how I got to B:
N1=[N{:,1} N{:,2} N{:,3}];
N1=unique(N1(:,1:3),'rows');
N3= unique(N1(:,1:2),'rows');
for m=1:size(N3,1)
N3(m,3)=sum(N1(:,1) == N3(m,1) & N1(:,2)==N3(m,2));
end
B=N3((N3(:,1) == 1998),:);
I have a cell-array A with the years horizontally disposed in R1, un-repeated values in Y, and corresponding codes in the columns that follow. The codes match the ones in C2 from variable B.
A={Y 1996 1997 1998 1999 %R1
1 107 107 22 22
13 98 98 76 1267
… }
Is there a way I could get a new variable that recognizes the change in the codes in variable A, and presents the corresponding values from C3 in B? For instance:
AB={Y Initial C2 Change C2
1 107 14 22 37
13 98 29 76 12 }
AB = {'Y' 'Initial' 'C2' 'Change' 'C2'}; % initialize result cell array
for i=2:size(A,1) % loop through rows of A
indicesOfChanges = find(diff([A{i,2:end}])); % find changes in row
for j=1:length(indicesOfChanges) % for all changes look up the corresponding values
ind1=find(B(:,2)==A{i,indicesOfChanges(j)+1}); % row index in B of value before change
ind2=find(B(:,2)==A{i,indicesOfChanges(j)+2}); % row index in B of value after change
AB{end+1,1} = A{i,1};
AB{end,2} = B(ind1,2);
AB{end,3} = B(ind1,3);
AB{end,4} = B(ind2,2);
AB{end,5} = B(ind2,3);
end
end
Maybe this could be further improved by using a vectorized approach, but as long as your arrays aren't too big it should work fast enough using loops.

Taking only values which form continous range

I have a file with 3 columns ->
A1 0 9
A1 4 14
A1 16 24
A1 25 54
A1 64 84
A1 74 84
A2 15 20
A2 19 50
I want to check if each line (value in col2 and 3) is present already or is in between the range of previous line, if col1 value is equal.
The desired output is ->
A1 0 14
A1 16 54
A1 64 84
A2 15 50
I have tried ->
#ARGV or die "No input file specified";
open $first, '<',$ARGV[0] or die "Unable to open input file: $!";
#open $second,'<', $ARGV[1] or die "Unable to open input file: $!";
$k=0;
while (<$first>)
{
if($k==0)
{
#cols = split /\s+/;
$p0=$cols[0];
$p1=$cols[1];
$p2=$cols[2];
$p3=$cols[2]+1;
}
else{
#new = split /\s+/;
if ($new[0] eq $p0){
if ($new[1]>$p3)
{
print join("\t", #new),"\n";
$p0=$new[0];
$p1=$new[1];
$p2=$new[2];
$p3=$new[2]+1;
}
elsif ($new[2]>=$p2)
{
print $p0,"\t",$p1,"\t",$new[2],"\n";
$p2=$new[2];
$p3=$new[2]+1;
}
else
{
$p5=1;
}
}
else
{
print join("\t", #new),"\n";
$p0=$new[0];
$p1=$new[1];
$p2=$new[2];
$p3=$new[2]+1;
}}
$k=1;
}
and output I am getting is ->
A1 0 14
A1 16 24
A1 16 54
A1 64 84
A1 64 84
A2 15 20
A2 22 50
I am not able to understand why I am getting this wrong output. Also if there is any way that I can erase(or overwrite) the last printed line, then it will be very easy.
First of all, it would be much more simple to help you if you
used strict and warnings, and declared all your variabled close to first use with my
indented your code properly to show the structure
The reason your code fails is that you are printing data under too many conditions. For example you output A1 16 24 when you find it cannot be joined with the previous range A1 4 14 without waiting for it to be extended by the subsequent A1 25 54 (when you correctly extend the range and print it again). A1 64 84 is output twice for the same reason: first because it cannot be merged with A1 25 54, and again because it has been "extended" with A1 74 84. Finally A2 15 20 is output straight away because it has a new first column, even though it is merged with the next line and output again.
You need to output a range only when you have found that it cannot be extended again. That happens when
a new record is found that doesn't overlap the existing data
the end of the file is reached
This code prints output only in those cases an appears to do what you need.
use strict;
use warnings;
my #data;
while (<DATA>) {
if (not #data) {
#data = split;
next;
}
my #new = split;
if ($new[0] eq $data[0] and $new[1] <= $data[2] + 1) {
$data[2] = $new[2];
}
else {
print join("\t", #data), "\n";
#data = #new;
}
print join("\t", #data), "\n" if eof DATA;
}
__DATA__
A1 0 9
A1 4 14
A1 16 24
A1 25 54
A1 52 57
A1 59 62
A1 64 84
A1 74 84
A2 15 20
A2 19 50
OUTPUT
A1 0 14
A1 16 57
A1 59 62
A1 64 84
A2 15 50
You need to have some variables describing currently-accumulated contiguous region. For each line of input, flush the previously-accumulated region if the new input is a new column1 label, or is same label but non-contiguous, or is end-of-file. If it's same label and contiguous yo update the min and max values.
This assumes that columns 1 and 2 are sorted.
The rest is left as an exercise for the reader.