Limit to AudioMaxAmplitude Speed?

prstein

Member
Licensed User
Longtime User
I've been working with B4A for a few weeks now and wow am I impressed. I could go on and on about that but instead of gushing I'll ask a question.

In a post by stevel05 (here) the function AudioMaxAmplitude is demonstrated. I'm trying to use that to count the number of pulses that come in through the headphone/microphone jack on my DroidX. It works very well and I am indebted to stevel05 and the other posters in this most helpful forum.

However, no matter what I do there appears to be a limit to the number of pulses that can be differentiated in any given time period. The pulses consist of a 3kHz "chirp" with a duration of a little less than a millisecond each. At a low rate (say around 300 per minute and below) they are collected just fine but once the rate exceeds roughly 500 per minute the collected number never gets over indicating ~500 per minute. I think theoretically I should be able to distinguish at least a hundred or so per second or a few thousand in a minute.

I have used the function as shown in stevel05's demo, put it into a very tight loop, put it into it's own thread (thanks for the threading demo agrahm!), and several other variations on those. I can make it count fewer pulses but not more.

So the question is: is there a limit to how quickly AudioMaxAmplitude works or how frequently it can be called? Alternately, is there another method for achieving the same goal, that of counting pulses?

If you've made it this far thanks for reading! Sorry for being a n00b but we've all got to start somewhere...

Best Regards,
Paul
 

stevel05

Expert
Licensed User
Longtime User
Hi Paul,

This is an interesting question and probably inextricably linked to Androids inherently poor access to audio handling.

There should be a better way to do it by monitoring the source data directly, I've read articles that imply it may be possible using a different recording method but haven't got round to trying it yet. It would require a new library and a lot of experimentation.

How far can we push what we have is a different question, as you have put the monitoring in a separate thread, I assume that you no longer use the timer to call AudioMaxAmplitude, but just have it looping.

There is no info in the documentation about limits on calling. As Android is multitasking you are going to hit a limit as to how quickly the process will run while doing other things.

I don't know if you have hit that limit, perhaps someone can comment that has more knowledge of this than me.

If you'd like to post your code (zip the project from the file menu in the IDE first), you may get some ideas for speeding up the routines (if it's possible).

Steve
 
Upvote 0

prstein

Member
Licensed User
Longtime User
Thank you, Steve, for the information. I'll clean up a version of my app to post but it will likely be a little while, probably tomorrow.

An alternative I've thought about but am not sure if it even worth attempting is to "record" a .wav file into a stream (sort of like shown in the Async Streams demo) and parse the raw numbers for the information. It wouldn't matter too much if there were a *little* lag. I fear this would be a little much for a noob to take on--I need to increase my experience a bit first.

Thanks again,
Paul
 
Upvote 0

prstein

Member
Licensed User
Longtime User
AudioPulseCounter demo app

Okay, got it cleaned up more quickly than I anticipated. It requires the AudioRecorder v2.0 library from here. XverhelstX is also deserving of a cookie for submitting this.

Note that this works with the built-in microphone just as well. Tapping on the device you can easily see that more than about 7 or 8 pulses are never counted in a second.

If you are hooking up using a connector you'll need a 4-conductor, 3.5 mm "TRRS" (that's tip ring ring sleeve) plug. Note that the sleeve is the mic input and the closest ring to that is the ground. Limit the incoming pulses to about 100 mV to avoid damaging the internal circuitry.

Suggestions and/or advice are always welcome!

Best Regards,
Paul
 

Attachments

  • AudioPulseCounter.zip
    8.2 KB · Views: 285
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Hi Paul,

The first thing I notice is that you have the timer displaying the counts set to a very low delay, if you only want it to display once a second you can set the timer:

T.Initialize("AmplitudeCheck",1000)

which will give a second delay, so less overhead by not running the sub 100 times a second, and no need to check if a second has elapsed before displaying the data.

It seems smoother on my phone, but I can't generate the input signal to check it accurately.

Steve
 
Upvote 0

prstein

Member
Licensed User
Longtime User
Hi Steve,

Thank you very much for taking a look. The more I think about it the more your suggestion makes sense.

I come into Android from a reasonably long history with programming for PalmOS (R.I.P.) and Windows Mobile. Windows timers, especially, are notoriously inaccurate and I've gotten into the habit of relying instead on the clock time instead.

My understanding is that setting a timer for 1000 msec will give me an elapsed time that is almost always longer than a second, sometimes much longer. Using a short timer to see if a clock second has rolled over results in "seconds" that are sometimes a little long and sometimes a little short but with an average duration of darn near exactly one second. I wouldn't expect there'd be too much overhead from that little check but now that you mention it I haven't actually run any comparisons to see. Or on the accuracy of the Android timer. I should test those before assuming that WinMob practices apply to Android. Android and B4A probably have better implementations than WinMob and eVC!

You have also made me realize that my DroidX is coming up on two years old, absolutely ancient. That may also have some bearing.

Best Regards,
Paul
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Hi Paul,

Yes, setting the timer to 1000 will result in the sub being called with a interval that is always at least a second. How much longer will depend on what else is running on the device, both in your app and any other background tasks.

I would think that if one call is going to be significantly delayed, then it would affect a timer set to 10 ms by a similar amount, thereby negating the benefits of continuous checking.

I haven't done any definitive testing of timers for accuracy but have used them for animating displays, counters etc, and have never noticed any major problems.

I'd be interested to know the outcome if you decide to test this accurately.

My HTC hero is getting a little long in the tooth too, an suffers from lethargy quite often, but I do have newer tablets to test on as well.
 
Upvote 0

prstein

Member
Licensed User
Longtime User
I'd be interested to know the outcome if you decide to test this accurately.

These results are for my DroidX. I've no idea how or if these results would apply to other hardware.

Using a calibrated pulse generator I can confirm that the absolute maximum number of values returned by GetMaxAmplitude is eight in any one second.

Using "T.Initialize("AmplitudeCheck",1000)" as you suggested is pretty much dead on when not much else is going on. When keeping the screen busy I've now seen this take up to 1016 msec.

Using the original method in the demo--checking every 10 msec to see if a clock second has rolled over--results in values from 986 to 1014 but the average is 1000 msec.

Sweet; thanks for getting me to actually test this!

Best Regards,
Paul
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Thanks for sharing, it's always useful to know these things.

It doesn't help you much with your original question though. If you can put up with the delay you could try recording the sound, then analyzing the resulting file. I haven't looked at the file format, but I'm sure it'll be available on the internet.

Steve
 
Upvote 0
Top