This is a bit in depth, and I'm in a bit over my head. I've never used AWK, and the more I try to learn about it (perhaps it's the lateness of the hour) the more frustrating it's getting to be.
I'm trying to write an applescript... script to resize windows across my monitors. Now, I COULD take the easy route and hardcode my monitor dimensions into the script, but instead I decided to try and gather them dynamically. I've managed to find a code snippet that parses a plist and spits out ALMOST-useable info, here's the applescript:
set screenInfo to do shell script "defaults read /Library/Preferences/com.apple.windowserver | awk '
BEGIN { FS=\"= \" }
/Active/ { screens++ }
{ gsub(\";\",\"\",$2) }
/^ *OriginX/ { ox[screens] = $2 }
/^ *OriginY/ { oy[screens] = $2 }
/^ *Width/ { w[screens] = $2 }
/^ *Height/ { h[screens] = $2 }
END {
for (si=1;si<=screens;si++) {
print ox[si],oy[si],w[si],h[si]
}
}'"
return screenInfo
end getScreenInfo
That's working pretty well - in my "result" window, I get the following:
"0 0 1920 1080
\"-1600\" 0 1600 1200
1920 0 1680 1050
0 0 1920 1080
\"-1600\" 0 1600 1200
1920 0 1680 1050
3600 1050 1024 768 "
The first number pair is the coordinates for the top left corner of the monitor, the second number pair is the resolution of that monitor. Such is the case for each monitor - though there are duplicates of monitors 1-3, plus a ghost monitor. I don't really care about that, it should be parse-able.
My problem comes when I try to parse those numbers as ints so I can use them - using something like set theVar to word 1 of paragraph 2 of theString as integer, it parses as 1600, not the -1600 it needs to be. I tried stepping through the entire string, 1 character at a time, to remove the escaping backslashes, but I think those only actually show up in the results window - when I display dialog, they don't show. Even when I don't try to parse it as an integer, just word 1 of paragraph 2 it ignores the - and returns "1600". How else can I parse this? Goodness, I'm not a fan of applescript right now.
You can get the screen resolutions with AppleScriptObjC
use framework "Foundation"
set screenFrames to {}
set screens to current application's NSScreen's screens()
repeat with aScreen in screens
set end of screenFrames to aScreen's frame() as record
end repeat
screenFrames will contain a record for each screen containing records origin with x and y members and size with width and height members.
For example you can get the width of screen 1 with
set screen1Width to width of |size| of item 1 of screenFrames as integer
Related
I have an output file called filename.mat0 which contains a large list of data points for a number of different variables for a number of different time steps. I want to use something like the grep command to retrieve all the instances for a given variable, i.e. variable_A, then sum the total value associated with variable_A, then take an average.
The number of time steps is constant so variable_A, variable_B, etc all appear 100 times in my .mat file.
Please can you suggest the best way to do this?
An example of the output data is:
Timestep1 Variable_A 10
Timestep1 Variable_B 20
Timestep1 Variable_C 30
Timestep2 Variable_A 40
Timestep2 Variable_B 50
Timestep2 Variable_C 60
Timestep3 Variable_A 70
Timestep3 Variable_B 80
Timestep3 Variable_C 90
Desired output:
Variable_A = 40
Referencing to this.
awk should be able to solve the problem. Check the link for how to use awk.
The below command should be okay for your case, but it is not easy to use if there is many Variable .Hope anyone more familiar with awk can suggest how to improve.
awk '{if ($2 == "Variable_A"){ total += $3; count++ }} END { print "Variable_A = " total/count }' sample.mat > avg_a.txt
Above command will do for each row, check if column 2(correspond to $2) equals "Variable_A", if yes, sum the value in column 3(correspond to $3) and add a count. After processing all rows, print the average to a text file.
For further question
In order to show multiple variables average in same file, you can make use of array and for loop in AWK. Add elements to vars for more variables.
awk 'BEGIN {vars[0]="Variable_A"; vars[1]="Variable_B"; vars[2] ="Variable_C" } { for (i in vars) { if ($2 == vars[i]){ total[i] += $3; count[i]++ }}} END { for(i in vars) {print vars[i]" = " total[i]/count[i]}}' sample.mat > avg.txt
I've located a code that I want to use when I'm writing notes on a MUD I play. Lines can only be 79 characters long for each note, so it's a hassle sometimes to write a note unless you're counting characters. The code is below:
function wrap(str, limit, indent, indent1)
indent = indent or ""
indent1 = indent1 or indent
limit = limit or 79
local here = 1-#indent1
return indent1..str:gsub("(%s+)()(%S+)()",
function(sp, st, word, fi)
if fi-here > limit then
here = st - #indent
return "\n"..indent..word
end
end)
end
This would work great; I can type a 300 character line and it will format it to 79 characters, respecting full words.
The problem I'm having, and I cannot seem to figure out how to solve, is that sometimes, I want to add colour codes to the line, and colour codes are not counted against word count. For example:
#GThis is a colour-coded #Yline that should #Bbreak off at 79 #Mcharacters, but ignore #Rthe colour codes (#G, #Y, #B, #M, #R, etc) when doing so.
Essentially, it would strip the colour codes away and break the line appropriately, but without losing the colour codes.
Edited to include what it should check, and what the final output should be.
The function would only check the string below for line breaks:
This is a colour-coded line that should break off at 79 characters, but ignore the colour codes (, , , , , etc) when doing so.
but would actually return:
#GThis is a colour-coded #Yline that should #Bbreak off at 79 #Ncharacters, but ignore
the colour codes (#G, #Y, #B, #M, #R, etc) when doing so.
To complicate things, we also have xterm colour codes, which are similar, but look like this:
#x123
It is always #x followed by a 3-digit number. And lastly, to further complicate things, I don't want it to strip out purpose colour codes (which would be ##R, ##x123, etc.).
Is there a clean way of doing this that I'm missing?
function(sp, st, word, fi)
local delta = 0
word:gsub('#([#%a])',
function(c)
if c == '#' then delta = delta + 1
elseif c == 'x' then delta = delta + 5
else delta = delta + 2
end
end)
here = here + delta
if fi-here > limit then
here = st - #indent + delta
return "\n"..indent..word
end
end
I have audio files, with different durations. They have common content and unique content. E.g. two files, 70 seconds each, last 10 seconds of the first file is the same as first two seconds of the second file. How can I find the exact position of common content (e.g. 60.0 of the first file)?
Sounds a little bit messy, hope the following image can help https://drive.google.com/file/d/0BzBE2Kfw8uQoUWNTN1RXOEtLVEk/view?usp=sharing
So, I'm looking for the red mark - common content starts at 60.0 sec of the first file.
The problem is that I have files with different durations. Sometimes it's 70 seconds long, sometimes one file is 70 seconds, the other is 80 seconds long, etc. Most likely they have 60.0 seconds of unique content, but I'm not sure (it could be 59.9 of unique content, etc.).
Thus, I assume I need to get a short snippet of the second file from first 10 seconds and find it in the first file:
For example, output: 2.5 sec of the second file = 62.5 from the first file - works for me, as well.
THE MAIN GOAL IS TO PLAY FILE AFTER FILE GAPLESS. If I get the values, I'll be able to do this. Sometimes the values can be: 2.5 = 63.7, that's why I need the exact match.
Can anybody help with the code or at least some information of how to compare two snippets of audio content? Thanks in advance!
Wow, that is quite a problem to solve. And I must confess that i've not done anything exactly like this or have any code based suggestions.
All I will say is that if I were looking to try and solve this problem, then I would try and save the audio file as some kind of uncompressed and fixed size (as in a known number of bytes per second) format.
Then you could take a section of one file and byte match it with another, then you would know how many bytes inwards that snippet occurred. Then, knowing the bytes per ms (sort of frame size), you could work out the exact time position.
It's a bit hair brained, but i've used that technique with images before but at least audio is linear!
Here is an approximate example of how I would go about doing the comparison of a sample within a sound file.
- (int)positionOf:(NSData*)sample inData:(NSData*)soundfile {
// the block size has to be big enough to find something genuinely unique but small enough to ensure it is still fast.
int blockSize = 128;
int position = 0;
int returnPosition = INT32_MAX;
// check to see if the block size exceeds the sample or data file size
if (soundfile.length < blockSize || sample.length < blockSize) {
return returnPosition;
}
// create a byte array of the sample, ready to use to compare with the shifting buffer
char* sampleByteArray = malloc(sample.length);
memcpy(sampleByteArray, sample.bytes, sample.length);
// now loop through the sound file, shifting the window along.
while (position < (soundfile.length - blockSize)) {
char* window = malloc(blockSize);
memcpy(window, soundfile.bytes + position, blockSize);
// check to see if this is a match
if(!memcmp(sampleByteArray, window, blockSize)) {
// these are the same, now to check if the whole sample is the same
if ((position + sample.length) > soundfile.length) {
// the sample won't fit in the remaining soundfile, so it can't be this!
free(window);
break;
}
if(!memcmp(sampleByteArray, soundfile.bytes + position, sample.length)) {
// this is an entire match, position marks the start in bytes of the sample.
free(window);
returnPosition = position;
break;
}
}
free(window);
position++;
}
free(sampleByteArray);
return returnPosition;
}
It compiles, didn't have time to setup the scenario to check your exact case, but i'm quite confident this may help.
How to calculate correct PTS value for frame before encoding in FFmpeg C API?
For encoding I'm using function avcodec_encode_video2 and then writing it by av_interleaved_write_frame.
I found some formulas, but none of them work.
In doxygen example they are using
frame->pts = 0;
for (;;) {
// encode & write frame
// ...
frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
}
This blog says that formula must be like this:
(1 / FPS) * sample rate * frame number
Someone uses only frame number to set pts:
frame->pts = videoCodecCtx->frame_number;
Or an alternative way:
int64_t now = av_gettime();
frame->pts = av_rescale_q(now, (AVRational){1, 1000000}, videoCodecCtx->time_base);
And the last one:
// 40 * 90 means 40 ms and 90 because of the 90kHz by the standard for PTS-values.
frame->pts = encodedFrames * 40 * 90;
Which one is correct? I think answer for this question will be helpful for not only for me.
It's better to think about PTS more abstractly before trying code.
What you're doing is meshing 3 "time sets" together. The first is time we're used to, based on 1000 ms per second, 60 seconds per minute, and so on. The second is the codec time for the particular codec you are using. Each codec has a certain way it wants to represent time, usually in a 1/number format meaning that for every second there is "number" amount of ticks. The third format works similar to the second except that it is the time base for the container that you are used.
Some people prefer to start with actual time, others frame count, neither is "wrong".
Starting with a frame count you need to first convert it based on your frame rate. Note all conversions I speak of use av_rescale_q(...). The purpose of this conversion is to turn a counter into time, so you rescale with your frame rate (video steam time base usually). Then you have to convert that into the time_base of your video codec before encoding.
Similarly, with a real time, your first conversion needs to be from current_time - start_time scaled to your video codec time.
Anyone using only frame counter is probably using a codec with a time_base equal to their frame rate. Most codecs do not work like this and their hack is not portable. Example:
frame->pts = videoCodecCtx->frame_number; // BAD
Additionally, anyone using hardcoded numbers in their av_rescale_q is leveraging the fact that they know what their time_base is and this should be avoided. The code isn't portable to other video formats. Instead use video_st->time_base, video_st->codec->time_base, and output_ctx->time_base to figure things out.
I hope understanding it from a higher level will help you see which of those are "correct" and which are "bad practice". There is no single answer, but maybe now you can decide which approach is best for you.
Time is measured not in seconds or milliseconds or any standard unit. Instead, it is measured by the avCodecContext's timebase.
So if you set the codecContext->time_base to 1/1, it means using second for measurement.
cctx->time_base = (AVRational){1, 1};
Assuming you want to encode at a steady fps of 30. Then, the time when a frame is encoded is framenumber * (1.0/fps)
But once again, the PTS is also not measured in seconds or any standard unit. It's measured by avStream's time_base.
In the question, the author mentioned 90k as the standard resolution for pts. But you will see that this is not always true. The exact resolution is saved in avstream. you can read it back by:
if ((err = avformat_write_header(ofctx, NULL)) < 0) {
std::cout << "Failed to write header" << err << std::endl;
return -1;
}
av_dump_format(ofctx, 0, "test.webm", 1);
std::cout << stream->time_base.den << " " << stream->time_base.num << std::endl;
The value of stream->time_stamp is only populated after calling avformat_write_header
Therefore, the right formula for calculating PTS is:
//The following assumes that codecContext->time_base = (AVRational){1, 1};
videoFrame->pts = frameduration * (frameCounter++) * stream->time_base.den / (stream->time_base.num * fps);
So really there are 3 components in the formula,
fps
codecContext->time_base
stream->time_base
so pts = fps*codecContext->time_base/stream->time_base
I have detailed my discovery here
There's also the option with setting it like frame->pts = av_frame_get_best_effort_timestamp(frame) but I'm not sure this is the correct approach either.
I have a VB6 form with a text boxes for minimum and maximum values. The text boxes have a MaxLength of 4, and I have code for the keyPress event to limit it to numeric entry. The code checks to make sure that max > min, however it is behaving very strangely. It seems to be comparing the values in scientific notation or something. For example, it evaluates 30 > 200 = true, and 100 > 20 = false. However if I change the entries to 030 > 200 and 100 > 020, then it gives me the correct answer. Does anyone know why it would be acting this way?
My code is below, I am using control arrays for the minimum and maximum text boxes.
For cnt = 0 To 6
If ParameterMin(cnt) > ParameterMax(cnt) Then
MsgBox ("Default, Min, or Max values out of range. Line not updated.")
Exit Sub
End If
Next cnt
That is how text comparison behaves for numbers represented as variable length text (in general, not just VB6).
Either pad with zeros to a fixed length and continue comparing as text (as you noted)
OR
(preferable) Convert to integers and then compare.
If I understood correctly, you can alter the code to
If Val(ParameterMin(cnt)) > Val(ParameterMax(cnt)) Then
I wish to advise one thing -(IMHO...) if possible, avoid checking data during key_press/key_up/key_down .
Can you change the GUI to contain a "submit" button and check your "form" there ?
Hope I helped...