Xcode - OpenAL - Getting the current time of a playing sound - iphone

Hey everyone, I was wondering if someone could point me in the right direction to creating a function in my openAL singleton class that returns the current time of the sound.
Any Ideas? Thanks!
(Current time 'while the sound is playing')

Hi can you elaborate in what you mean by the current time of the sound?
do you mean what the actually time is when the sound is played or how long the actual length of time is of the audio clip? please specify.
If you mean when the actual time the sound was played then you can use
CFAbsoluteTimeGetCurrent()
to get the current time expressed as the number of seconds (as a double value, so fractional seconds will be there) since January 1, 2001 00:00:00 GMT.
so basically what you will get is the current time the moment the function is called.
if you would like to know when an event occurred within your application then you can use the
-[UIEvent timestamp]
property which will be the most accurate representation of when the sound played.
To put either of those functions which ever you decide to choose (if its actually what you are talking about) then you return it like so:
(double)returnTime{
double *timeValue = CFAbsoluteTimeGetCurrent();
return timeValue;
}
And then you can call this function and store the time like so
double *storeValue = [self returnTime];
in one go. You can then use this variable to print it to the console or what ever you like.
Hope this helps. Again please specify what you meant by the current time of the sound.
Pk

Related

Reading cycle time on a TwinCAT 3 PLC

Is there a way for a PLC program to know its own cycle time?
As a workaround, I can just add a persistent variable or a constant to tell it manually, but that's obviously error prone.
To add to Jakob's answer - you can also use GETCURTASKINDEXEX function (Infosys) instead of GETCURTASKINDEX FB. This way you don't have to instantiate it.
_TaskInfo[GETCURTASKINDEXEX()].CycleTime
Will return cycle time as multiples of 100ns (UDINT)
UDINT_TO_LREAL(_TaskInfo[GETCURTASKINDEXEX()].CycleTime) / 10_000_000
Will return cycle time as seconds (LREAL)
For TwinCAT3 this is available in PlcTaskSystemInfo (variable CycleTime).
Combine it with the FB GETCURTASKINDEX to get the data you want.
See one example (though not cycle-time, but still same FB) here at AllTwinCAT.
This is not directly an answer to your question, but can be used to determine the Cycle time.
I like to use the Time() function. It returns a value of data type TIME. It does not represent an absolute time, but can be used to calculate the time between two calls to Time(). In this way you can calculate the Cycle time.
I use it in function blocks (FB) where timing is critical. In this way the FB knows when it was lastly called instead of assuming that it is being run each scan. Even if I or another user of my FB "forgets" to call the FB each scan, the FB still delivers correct outputs.
You can find info on Time() using this link. There is also a function called LTime() which returns a value of data type LTIME, but it seems that Beckhoff did not bother to document this function.

Getting accurate time from FFMPeg with Objective C (Audio Queue Services)

My iPhone app plays an audio file using FFMPeg.
I'm getting the elapsed time (to show to user) from the playing audio (in minutes and seconds after converting from microseconds, given by FFMPeg) like so:
AudioTimeStamp currentTimeStamp;
AudioQueueGetCurrentTime (audioQueue, NULL, &currentTimeStamp, NULL);
getFFMPEGtime = currentTimeStamp.mSampleTime/self.basicAudioDescription.mSampleRate;
self.currentAudioTime = [NSString stringWithFormat: #"%02d:%02d",
(int) getFFMPEGtime / (int)60000000,
(int) ((getFFMPEGtime % 60000000)/1000000)];
Everything works fine, but when I scrub back or forward to play another portion of the song, the elapsed time will go back to zero, no matter the current position. The timer will always zero out.
I know I'm suposed to do some math to keep track of the old time and the new time, maybe constructing another clock or so, perhaps implementing another callback function, etc... I'm not sure what way I should go.
My questions are:
1) What's the best approach to keep track of the elapsed time when going back/forward in a song, avoiding the clock to always going back to zero?
2) Should I look deeply into FFMPeg functions or should I stick with Objective-C and Cocoa Touch for solving this problem?
Please, I need some advices/ideas from experienced programmers. I'm stuck. Thanks beforehand!
If you're doing this to show elapsed time in the media to the user (which the fact you're turning it into a formatted string suggests), then you should instead query the playback system you're using for the time it thinks it is at in the file. The audio queue is completely unaware of your media so you'll have to duplicate work done by the playback system to map it to a media time. Timestamps from the audio queue are more like a high accuracy clock for things like A/V sync.

How to handle class methods being called again before they are finished?

What is the best way to handle this situation on an iPhone device: My program ramps the pitch of a sound between two values. A button pressed calls a method that has a while loop that does the ramping in small increments. It will take some time to finish. In the meantime the user has pressed another button calling the same method. Now I want the loop in the first call to stop and the second to start from the current state. Here is the something like what the method should look like:
-(void)changePitchSample: (float) newPitch{
float oldPitch=channel.pitch;
if (oldPitch>newPitch) {
while (channel.pitch>newPitch) {
channel.pitch = channel.pitch-0.001;
}
}
else if (oldPitch<newPitch) {
while (channel.pitch<newPitch) {
channel.pitch = channel.pitch+0.001;
}
}
}
Now how to best handle the situation where the method is called again? Do I need some kind of mulitthreading? I do not need two processes going at the same time, so it seems there must be some easier solution that I cannot find (being new to this language).
Any help greatly appreciated!
You cannot do this like that. While your loop is running no events will be processed. So if the user pushes the button again nothing will happen before your loop is finished. Also like this you can’t control the speed of your ramp. I’d suggest using a NSTimer. In your changePitchSample: method you store the new pitch somewhere (don’t overwrite the old one) and start a timer that fires once. When the timer fires you increment your pitch and if it is less than the new pitch you restart the timer.
Have a look at NSOperation and the Concurrency Programming Guide. You can first start you operation the increase the pitch and also store the operation object. On the second call you can call [operation cancel] to stop the last operation. Start a second operation to i.e. decrease the pitch and also store the new object.
Btw: What you are doing right now is very bad since you "block the main thread". Calculations that take some time should not be directly executed. You should probably also have a look at NSTimer to make your code independent of the processor speed.
Don't use a while loop; it blocks everything else. Use a timer and a state machine. The timer can call the state machine at the rate at which you want things to change. The state machine can look at the last ramp value and the time of the last button hit (or even an array of UI event times) and decide whether and how much to ramp the volume during the next time step (logic is often just a pile of if and select/case statements if the control algorithm isn't amenable to a nice table). Then the state machine can call the object or routine that handles the actual sound level.

iPhone accelerometer:didAccelerate: seems to not get called while I am running a loop

An accelerometer related question. (Sorry the formatting may not look right, its the first time I am using this site). I got the accelerometer working as expected using the standard code
UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self;
accel.updateInterval = 0.1; //I also tried other update values
I use NSLog to log every time the accelerometer:didAccelerate: method in my class is called. The function gets called as expected and everything works fine till here.
However, when I run a loop, the above method doesn't seem to get called. Something like this
float firstAccelValue = globalAccel; //this is the x-accel value (stored in a global by the above method)
float nextAccelValue = firstAccelValue;
while (nextAccelValue == firstAccelValue){
//do something
nextAccelValue = globalAccel; // note globalAccel is updated by the accelerometer method
}
The above loop never exits, expectedly since the accelerometer:didAccelerate: method is not getting called, and hence globalAccel never changes value.
If I use a fixed condition to break the while loop, I can see that after the loop ends, the method calls work fine again.
Am I missing something obvious here? Or does the accelerometer method not fire when certain processing is being done?
Any help would be greatly appreciated! Thanks!
(Don't compare float with ==.)
The CPU is occupied by the loop and has no time to give you the updated accelerator value.
Since -accelerometer:didAccelerate: is called everytime the acceleration changes, why not just use if?
// in -accelerometer:didAccelerate:
if (fabs(nextAccelValue - firstAccelValue) < 0.0001) {
// do something
nextAccelValue = globalAccel;
}
Thanks much for that! (About the float comparison, yes I understand, it was just an example).
Actually, what I want to do is this: After a button is pressed, I want to obtain the accelerometer value (firstValue) and then wait until it changes (to say a particular value relative to firstValue) and then proceed to do some tasks. As such I was using the while loop. (The loop I show just waits until it changes, but I can put the exact change condition required once it works).
From your answer, I understand that I can perform the task in the -accelerometer:didAccelerate: function itself (since it has access to all the data it needs, I can make it access a variable indicating whether the button was pressed). Thanks very much for that. I guess I can make it work in this way.
But just curious - is there a way to do it otherwise? If too much processing is hogging the CPU, can I force it to update accelerometer somehow? The loop hogging the CPU itself is low priority since it was just my way of waiting until the value changes.
Thanks again!

Tween a value in iPhone objective-C

Is it possible to tween a variable (let's say a float from 0.0 to 2.0 over a period of time) in objective-C?
Something like what TweenMax would do in flash.
I guess the class methods of UIView don't do that. Is it doable maybe with CoreAnimation? Or would someone have to use NSTimer?
Thanks
Use an NSTimer on a selector that increments a member variable from its start value of 0.0 by the increment value.
When the variable reaches the end point (2.0), invalidate the NSTimer instance to finish incrementing.
See the documentation for more information about the method to use.
What are you doing? If you are trying to animate something then you can use CA and it will deal with calculating the intermediary values over time.
If you are trying to do for something not related to views or animation you will need to do it yourself (using a timer, or a custom property implementation that dynamically calculates the value based on the current times when it is accessed).
I've been working on putting something of a framework together recently, part of which is a 'tweener'.
I'm still pretty new to obj c, but so far it seems to be serving my purposes reasonably well. Feel free to have a peek/play!
ShinobiTweener v0.1 for Objective-C