Finding notes sounding at the same time in a different voice in a midi file - midi

I have a midi file consisting of two parts. Now I need to print out, for each note in part 0 (including rests), which note sounds at the same time in part 1 (and the note that proceeds this).
I can go through all of the notes in part 0 with music21, but how do I find the note at that time in part 1. Will I need to use end times? Or is there a function for this?
for thisNote in s.parts[0].notes:
print thisNote.ps

Here is a very interesting function that let me solve this:
secondPart = s.parts[1]
for thisNote in s.parts[0].notes:
sys.stdout.write('at ' + str(thisNote.offset) + ' toppitch: ' + str(thisNote.ps))
soundingNotes = secondPart.getElementsByOffset(thisNote.offset, mustFinishInSpan=False, mustBeginInSpan=False)
try:
if soundingNotes > 0:
basslength = len(soundingNotes)
except:
basslength = 0
if basslength > 1:
print "oh ow, more then one note sounding in the bass."
if basslength > 0:
if soundingNotes[0].isRest:
sys.stdout.write(' bottompitch: R')
else:
sys.stdout.write(' bottompitch: ' + str(soundingNotes[0].ps)) # + ' from ' + str(soundingNotes[0].offset))
# print the previous note
soundingNotes2 = secondPart.getElementsByOffset(thisNote.offset-1, mustFinishInSpan=False, mustBeginInSpan=False)

Related

Matlab: Select a variable name and find the corresponding value

Can somebody explain me how i get some specific values after the = sign? The input File is a .subvar file format.
I dont know how to jump in the right row and column to get the value. Do you have a matlab tutorial link for such a problem.
I need for example two specific values (after the = sign):
The value of $_Wk1_lr_m and $_Wk1_voll_m
!file.version=1.543!
! Testautomatisch
subvargroup.begin ($G_Wk1)
subvar( $_Wk1_lr_C_x, str = ' 0.019 ' )
subvar( $_Wk1_lr_m, str = ' 15601 ' ) ! [kg] lr
subvar( $_Wk1_lr_C_y, str = '-0.007 ' )
subvar( $_Wk1_lr_C_z, str = ' 1.644 ' )
subvar( $_Wk1_voll_m, str = ' 33690 ' ) ! [kg] voll
subvargroup.end ($G_Wk1)
What are the first steps to get the right row and the right column? Thank you and stay at home :)
read the file line by line, match the line format and extract the values using regular expression regexp
fid=fopen('mydata.subvars','rt');
res=struct;
while(~feof(fid))
line=fgetl(fid);
if(regexp(line,'^\s*subvar\(','once'))
val=regexp(line,'\$_(\w+),\s*str\s*=\s*''\s*([0-9.-]+)\s*','tokens');
if(length([val{:}])==2)
res.(val{1}{1})=str2num(val{1}{2});
end
end
end
fclose(fid);
here is the result
>> res
res =
Wk1_lr_C_x: 0.0190
Wk1_lr_m: 15601
Wk1_lr_C_y: -0.0070
Wk1_lr_C_z: 1.6440
Wk1_voll_m: 33690

Matlab; how to extract information from a header's file (text file)

I have many text files that have 35 lines of header followed by a large matrix with data of an image (that info can be ignored and do not need to read it at the moment). I want to be able to read the header lines and extract information contained on those lines. For instance the first few lines of the header are..
File Version Number: 1.0
Date: 06/05/2015
Time: 10:33:44 AM
===========================================================
Beam Voltage (-kV) = 13.000
Filament (W) = 4.052
Cond. (-kV) = 8.885
CenterX1 (V) = 10.7
CenterY1 (V) = -45.9
Objective (%) = 71.40
OctupoleX = -0.4653
OctupoleY = -0.1914
Angle (deg) = 0.00
.
I would like to be able to open this text file and read the vulue of the day and time the file was created, filament power, the condenser voltage, the angle, etc.. and save these in variables or send them to a text box on a GUI program.
I have tried several things but since the values I want to extract some times are after a '=' or after a ':' or simply after a '' then I do not know how to approach this. Perhaps reading each line and look for a match of a word?
Any help would be much appreciated.
Thanks,
Alex
This is not particularly difficult, and one of the ways to do it would be to parse line-by-line as you suggested. Something like this:
MAX_LINES_TO_READ = 35;
fid = fopen('input.txt');
lineCount = 0;
dateString = '';
beamVoltage = 0;
while ~eof(fid)
line = fgetl(fid);
lineCount = lineCount + 1;
%//check conditions for skipping loop body
if isempty(line)
continue
elseif lineCount > MAX_LINES_TO_READ
break
end
%//find headers you are interested in
if strfind(line, 'Date')
%//find the first location of the header separator
idx = find(line, ':', 1);
%//extract substring starting from 1 char after separator
%//note: the trim is to get rid of leading/trailing whitespace
dateString = strtrim(line(idx + 1 : end));
elseif strfind(line, 'Beam Voltage')
idx = find(line, '=', 1);
beamVoltage = str2double(line(idx + 1 : end));
end
end
fclose(fid);

Mapping binary data in perl

I have the following predefined codes that represent an index in a binary bitmap:
0 = standard
1 = special
2 = regular
3 = late
4 = early
5 = on time
6 = generic
7 = rfu
An example value I would take as an input would be 213, which becomes 11010101 in binary. Index 0, 2, 4, 6, and 7 have their bit flipped indicating that this record is:
standard + regular + early + generic + rfu.
I am trying to figure out in perl how to take that binary data and build a string, like mentioned above with code + code + code, etc.
Any help would be greatly appreciated. Thanks.
Edit: My thoughts on how I might approach this are:
Convert decimal to binary
Find length of binary string
Using substr get the value (0 or 1) index by index
If index value = 1 then add relevant code to string
Is there a better way to go about this?
You can test bits on input from 0 to 7, and take only these that are set,
my $in = 213;
my #r = ("standard","special","regular","late","early","on time","generic","rfu");
print join " + ", #r[ grep { $in & (1 << $_) } 0 .. $#r ];
# or
# print join " + ", map { $in & (1<<$_) ? $r[$_] : () } 0 .. $#r;
output
standard + regular + early + generic + rfu

for loop inside of body of email lua script

Basically, I have several devices I need to pull data from. I get multiple emails when the temperature measures are under or over the set limits. I would like to have a for loop to include all current devices states that are under or over limits into one email.
body = for device_name, 1 do
device_name++ -- I get error here because unexpected symbol near 'for'
"Device Name: " ..device_name.. "\nDevice Location: " ..device_location..
"\n--------------------------------------------------------------" ..
"\nCurrent Temperature: " ..temperature.." F".. "\nTemperature Limit: ("..
t_under_limit.. "-" ..t_over_limit.. " F)" .."\n\nCurrent Humidity Level: " ..
humidity .. "%".. "\nHumidity Limit: (" .. h_under_limit.. "-" ..h_over_limit.. "%)"
.. "\n\n-------Time Recorded at: " ..os.date().. "-------"})
end, -- end for
there is no variable++ syntax in lua. you need to do
variable = variable + 1
also, you can't assign some for loop construct to a variable. so this statement
body = for device_name, 1, ...
isn't valid. maybe you meant...
local body = ""
for device_name = 1, 1
device_name = device_name + 1
body = body.. "my custom message stuff here"
end
As previously noted, there is no ++ operator in Lua. Also, the syntax for the for loop is different from what you wrote.
I would like to add that the big concatenation afterwards would be much more readable using string.format. Here is an enhanced version of your code, in the form a a function taking a table devices parameters in input, each element being a subtable:
local report_model = [[
Device Name: %s
Device Location: %s
--------------------------------------------------------------
Current Temperature: %d °F
Temperature Limit: (%d-%d °F)
Current Humidity Level: %d %%
Humidity Limit: (%d-%d %%)
-------Time Recorded at: %s-------]]
function temp_report(devices)
local report = {}
for i=1,#devices do
local d = devices[i]
report[i] = report_model:format(d.name, d.location,
d.temperature, d.t_under_limit, d.t_over_limit,
d.humidity, d.h_under_limit, d.h_over_limit,
os.date())
end
return table.concat(report)
end

Renaming a Word document and saving its filename with its first 10 letters

I have recovered some Word documents from a corrupted hard drive using a piece of software called photorec. The problem is that the documents' names can't be recovered; they are all renamed by a sequence of numbers. There are over 2000 documents to sort through and I was wondering if I could rename them using some automated process.
Is there a script I could use to find the first 10 letters in the document and rename it with that? It would have to be able to cope with multiple documents having the same first 10 letters and so not write over documents with the same name. Also, it would have to avoid renaming the document with illegal characters (such as '?', '*', '/', etc.)
I only have a little bit of experience with Python, C, and even less with bash programming in Linux, so bear with me if I don't know exactly what I'm doing if I have to write a new script.
How about VBScript? Here is a sketch:
FolderName = "C:\Docs\"
Set fs = CreateObject("Scripting.FileSystemObject")
Set fldr = fs.GetFolder(Foldername)
Set ws = CreateObject("Word.Application")
For Each f In fldr.Files
If Left(f.name,2)<>"~$" Then
If InStr(f.Type, "Microsoft Word") Then
MsgBox f.Name
Set doc = ws.Documents.Open(Foldername & f.Name)
s = vbNullString
i = 1
Do While Trim(s) = vbNullString And i <= doc.Paragraphs.Count
s = doc.Paragraphs(i)
s = CleanString(Left(s, 10))
i = i + 1
Loop
doc.Close False
If s = "" Then s = "NoParas"
s1 = s
i = 1
Do While fs.FileExists(s1)
s1 = s & i
i = i + 1
Loop
MsgBox "Name " & Foldername & f.Name & " As " & Foldername & s1 _
& Right(f.Name, InStrRev(f.Name, "."))
'' This uses copy, because it seems safer
f.Copy Foldername & s1 & Right(f.Name, InStrRev(f.Name, ".")), False
'' MoveFile will copy the file:
'' fs.MoveFile Foldername & f.Name, Foldername & s1 _
'' & Right(f.Name, InStrRev(f.Name, "."))
End If
End If
Next
msgbox "Done"
ws.Quit
Set ws = Nothing
Set fs = Nothing
Function CleanString(StringToClean)
''http://msdn.microsoft.com/en-us/library/ms974570.aspx
Dim objRegEx
Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.IgnoreCase = True
objRegEx.Global = True
''Find anything not a-z, 0-9
objRegEx.Pattern = "[^a-z0-9]"
CleanString = objRegEx.Replace(StringToClean, "")
End Function
Word documents are stored in a custom format which places a load of binary cruft on the beginning of the file.
The simplest thing would be to knock something up in Python that searched for the first line beginning with ASCII chars. Here you go:
#!/usr/bin/python
import glob
import os
for file in glob.glob("*.doc"):
f = open(file, "rb")
new_name = ""
chars = 0
char = f.read(1)
while char != "":
if 0 < ord(char) < 128:
if ord("a") <= ord(char) <= ord("z") or ord("A") <= ord(char) <= ord("Z") or ord("0") <= ord(char) <= ord("9"):
new_name += char
else:
new_name += "_"
chars += 1
if chars == 100:
new_name = new_name[:20] + ".doc"
print "renaming " + file + " to " + new_name
f.close()
break;
else:
new_name = ""
chars = 0
char = f.read(1)
if new_name != "":
os.rename(file, new_name)
NOTE: if you want to glob multiple directories you'll need to change the glob line accordingly. Also this takes no account of whether the file you're trying to rename to already exists, so if you have multiple docs with the same first few chars then you'll need to handle that.
I found the first chunk of 100 ASCII chars in a row (if you look for less than that you end up picking up doc keywords and such) and then used the first 20 of these to make the new name, replacing anything that's not a-z A-Z or 0-9 with underscores to avoid file name issues.