I suppose it should be done with IMediaSeeking SetPositions, but I don't know how define parameters inside.
There is no dedicated method to step back in DirectShow (as such existing for stepping forward). Yes you can use IMediaSeeking::SetPositions, however but note that it is not DirectShow itself who implement it, but actual underlying filters, so support for re-positioning depends on filters and implementation, and may be limited to, for example, stepping through key frames (splice points) only. DirectShow.NET is onyl a wrapper over DirectShow and it also does not add anything on top what DirectShow offers for stepping.
IBasicVideo *pBasicVideo=NULL;//Interface to the Ibasic Video
HRESULT hr;
REFTIME pavgfrt=0;//Get the reftime variable
REFERENCE_TIME pnowrt=0;//Get the reference time variable
pBasicVideo->get_AvgTimePerFrame(&pavgfrt);
pBasicVideo->get_AvgTimePerFrame(&pavgfrt);//Get the avg time per frame in seconds
pSeek->GetCurrentPosition(&pnowrt);//Get the current time in the unit of 100 nanoseconds
REFERENCE_TIME temp=pnowrt;//store it in a temp variable
REFERENCE_TIME temp1=(REFERENCE_TIME)(pavgfrt*10000000);//convert avg time into the format of current time
pnowrt=temp+temp1;//Add to framestep forward and subtract to framestep backward
pSeek->SetPositions(&pnowrt,AM_SEEKING_AbsolutePositioning, NULL,AM_SEEKING_NoPositioning);//Set the seeking position to the new time
pnowrt=0;//Reset the time variable
This works for me in C++. Wrapping this code in C# may not be difficult for you. Hope this helps.
Related
Well I know animator system in Unity is very useful for many things but I find myself having my own state machine in the code and somehow the state machine that the animator provides is not accurate due to blend time maybe I dont know, so I find often my character being in state 2 in the animator state machine and state 0 in my own state machine and its crazy as I cant seem to make it match in limit cases when its about to end the action. So I would like to know if there is a way to just say with code "play this animation from frame A to frame B" and loop it or not loop, that would be much better for me, of course I will lose all the blend features but really I will be better, all I can fin in the docs refer to using the animator so far. Thanks a lot for any help regarding this =)
Edit: Forgot to add that I found Animation.Play but apparently this only play animation saved on separate files like when we use the Animation timeline to record a certain motion, but I have a character with a lot of frames there and I dont think it serves in this case (or in my tests it never finds the specified animation at least, maybe i miss somethnig)
before anything, you can your own state machine with Animator. in fact, you don't need to two different state machine for your purposes. (Watch this video here)
and about your question, I found a good answer here: Link
From what I've seen you can either do AnimationState.normalizedTime
which returns the progress of an animation on a scale of 0 to 1. So if
you have a 30 frame animation and you want frame 15, you can do if
(normalizedTime == 0.5)* Or the better and more reliable option is to
use AnimationEvents that fire on specific frames.
*You won't really be able to do this if we're dealing in floats--You can only get the approximate value or you'll have to check greater
then or equal to 0.4 AND less then or equal to 0.6 because the
animation could go faster than the current frame rate or the
normalized time value could be 0.50000001 because of the nature of
float values.
Recently, I was trying to answer another SO question about loading the frames (Bitmap and duration) of animated GIFs. The code can be found on pastenbin.
While doing additional tests on this code before moving it into my dev library, I noticed that there is a problem with this line of code:
//Get the times stored in the gif
//PropertyTagFrameDelay ((PROPID) 0x5100) comes from gdiplusimaging.h
//More info on http://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
var times = img.GetPropertyItem(0x5100).Value;
When running this on Windows .Net using this (example GIF), the array is of the same size as the amount of frames in the animated GIF and filled with the durations of the frames. In this case a byte[20] which converts to (BitConverter.ToInt32()) 5 durations:
[75,0,0,0,125,0,0,0,125,0,0,0,125,0,0,0,250,0,0,0]
On MonoMac however, this line of code for the same example GIF returns a byte[4] which converts to only one duration (the first):
[75,0,0,0]
I tested this for 10 different GIF's and the result is always the same. On Windows all durations are in the byte[], while MonoMac only lists the first duration:
[x,0,0,0]
[75,0,0,0]
[50,0,0,0]
[125,0,0,0]
Looking at the Mono System.Drawing.Image source code, the length seem to be set in this method, which is a GDI wrapper:
status = GDIPlus.GdipGetPropertyItemSize (nativeObject, propid,out propSize);
However, I don't really see any problems, not with the source as with my implementation. Am I missing something or is this a bug?
I don't see anything wrong in the mono source either. It would have been helpful if you would have posted one of the sample images you tried. One quirk about the GIF image format is that the Graphics Control Extension block that contains the frame time is optional and may be omitted before an image descriptor. Non-zero odds therefore that you have GIF files that just have one GCE that applies to all the frames, you are supposed to apply the same frame time to every frame.
Do note that you didn't get 4 values, the frame time is encoded as a 32-bit value and you are seeing the little endian encoding for it in a byte[]. You should use BitConverter.ToInt32(), as you correctly did in your sample code.
I therefore think you should probably use this instead:
//convert 4 bit value to integer
var duration = BitConverter.ToInt32(times, 4*i % times.Length);
Do note that there's another nasty implementation detail about GIF frames, frames #2 and up do not have to be the same size as the frame #1. And each frame has a metadata field that describes what should be done with the previous frame to merge it with the next one. There are no property IDs that I know of to obtain the frame offset, size and undraw method for each frame. I think you need to render each frame into a bitmap yourself to get a proper sequence of images. Very ugly details, GIF needs to die.
If you look into libgdiplus you will see that the properties are always read from the active bitmap:
if (gdip_bitmapdata_property_find_id(image->active_bitmap, propID, &index) != Ok) {
You can set the active bitmap by calling Image.SelectActiveFrame and then mono will return the correct durations, one by one. Since this is an incompatibility with windows, I'd call it a mono bug. As a simple workaround, you can of course just check the array length and handle both cases. This will be better than a check for mono, because if mono gets fixed this will continue to work.
Not sure if this is a Farseer thing to do with inertia, or if it's my code, but I've simplified the code quite a bit and I can't find it.
Scenario: I've got a Body, with a Mass of 10(kg I assume). I use ApplyLinearImpulse and I scoot the object to the right using a vector like (1,0) and constant like 5.
Problem: It does move to the right, but it seems to be capped. The LinearVelocity property does go up as I increase the value fed to ApplyLinearImpulse, but the actual change in Position does not. As soon as I call world.step(msDelta), the LinearVelocity drops back to some tiny value.
Am I doing this wrong, or is there an internal cap based on my mass?
There is a maximum movement limit of 2.0 units per time step, set in the file b2Settings.h in the Box2D source code. You can change this value (b2_maxTranslation) if you need to, just be aware that the values in this file are tuned to work well together so you may get other problems if you change it too much.
Note that this is a #define'd constant used throughout Box2D so you'll need to recompile the library itself to make the change take effect fully. I don't know enough about Farseer to tell you whether this is easy or not :)
Generally if you feel the need to change this value you might like to first consider scaling all your physics dimensions down so that your bodies don't need to move faster than 2 physics units per time step.
You might be interested in some other common 'gotchas' here: http://www.iforce2d.net/b2dtut/gotchas
I need to display a set of signals. Each signal is defined by millions of samples. Just processing the collection (for converting samples to points according to bitmap size) of samples takes a significant amount of time (especially during scrolling).
So I implemented some kind of downsampling. I just skip some points: take every 2nd, every 3rd, every 50th point depending on signal characteristics. It increases speed very much but significantly distorts signal form.
Are there any smarter approaches?
We've had a similar issue in a recent application. Our visualization (a simple line graph) became too cluttered when zoomed out to see the full extent of the data (about 7 days of samples with a sample taken every 6 seconds more or less), so down-sampling was actually the way to go. If we didn't do that, zooming out wouldn't have much meaning, as all you would see was just a big blob of lines smeared out over the screen.
It all depends on how you are going to implement the down-sampling. There's two (simple) approaches: down-sample at the moment you get your sample or down-sample at display time.
What really gives a huge performance boost in both of these cases is the proper selection of your data-sources.
Let's say you have 7 million samples, and your viewing window is just interested in the last million points. If your implementation depends on an IEnumerable, this means that the IEnumerable will have to MoveNext 6 million times before actually starting. However, if you're using something which is optimized for random reads (a List comes to mind), you can implement your own enumerator for that, more or less like this:
public IEnumerator<T> GetEnumerator(int start, int count, int skip)
{
// assume we have a field in the class which contains the data as a List<T>, named _data
for(int i = start;i<count && i < _data.Count;i+=skip)
{
yield return _data[i];
}
}
Obviously this is a very naive implementation, but you can do whatever you want within the for-loop (use an algorithm based on the surrounding samples to average?). However, this approach will make usually smooth out any extreme spikes in your signal, so be wary of that.
Another approach would be to create some generalized versions of your dataset for different ranges, which update itself whenever you receive a new signal. You usually don't need to update the complete dataset; just updating the end of your set is probably good enough. This allows you do do a bit more advanced processing of your data, but it will cost more memory. You will have to cache the distinct 'layers' of detail in your application.
However, reading your (short) explanation, I think a display-time optimization might be good enough. You will always get a distortion in your signal if you generalize. You always lose data. It's up to the algorithm you choose on how this distortion will occur, and how noticeable it will be.
You need a better sampling algorithm, also you can employ parallel processing features of c#. Refer to Task Parallel Library
I'm trying to determine the "beats per minute" from real-time audio in C#. It is not music that I'm detecting in though, just a constant tapping sound. My problem is determining the time between those taps so I can determine "taps per minute" I have tried using the WaveIn.cs class out there, but I don't really understand how its sampling. I'm not getting a set number of samples a second to analyze. I guess I really just don't know how to read in an exact number of samples a second to know the time between to samples.
Any help to get me in the right direction would be greatly appreciated.
I'm not sure which WaveIn.cs class you're using, but usually with code that records audio, you either A) tell the code to start recording, and then at some later point you tell the code to stop, and you get back an array (usually of type short[]) that comprises the data recorded during this time period; or B) tell the code to start recording with a given buffer size, and as each buffer is filled, the code makes a callback to a method you've defined with a reference to the filled buffer, and this process continues until you tell it to stop recording.
Let's assume that your recording format is 16 bits (aka 2 bytes) per sample, 44100 samples per second, and mono (1 channel). In the case of (A), let's say you start recording and then stop recording exactly 10 seconds later. You will end up with a short[] array that is 441,000 (44,100 x 10) elements in length. I don't know what algorithm you're using to detect "taps", but let's say that you detect taps in this array at element 0, element 22,050, element 44,100, element 66,150 etc. This means you're finding taps every .5 seconds (because 22,050 is half of 44,100 samples per second), which means you have 2 taps per second and thus 120 BPM.
In the case of (B) let's say you start recording with a fixed buffer size of 44,100 samples (aka 1 second). As each buffer comes in, you find taps at element 0 and at element 22,050. By the same logic as above, you'll calculate 120 BPM.
Hope this helps. With beat detection in general, it's best to record for a relatively long time and count the beats through a large array of data. Trying to estimate the "instantaneous" tempo is more difficult and prone to error, just like estimating the pitch of a recording is more difficult to do in realtime than with a recording of a full note.
I think you might be confusing samples with "taps."
A sample is a number representing the height of the sound wave at a given moment in time. A typical wave file might be sampled 44,100 times a second, so if you have two channels for stereo, you have 88,200 sixteen-bit numbers (samples) per second.
If you take all of these numbers and graph them, you will get something like this:
(source: vbaccelerator.com)
What you are looking for is this peak ------------^
That is the tap.
Assuming we're talking about the same WaveIn.cs, the constructor of WaveLib.WaveInRecorder takes a WaveLib.WaveFormat object as a parameter. This allows you to set the audio format, ie. samples rate, bit depth, etc. Just scan the audio samples for peaks or however you're detecting "taps" and record the average distance in samples between peaks.
Since you know the sample rate of the audio stream (eg. 44100 samples/second), take your average peak distance (in samples), multiply by 1/(samples rate) to get the time (in seconds) between taps, divide by 60 to get the time (in minutes) between taps, and invert to get the taps/minute.
Hope that helps