Introducing Absolute Ratio

Let’s define the absolute ratio for positive numbers:

abs_ratio(x) = 1 / x when x < 1, otherwise: x

When x is smaller than 1 return 1 / x, otherwise return x. Here are a few example values:

x abs_ratio(x)
0.5 2
2 2
0.2 5
5 5

And a graph:

Absolute Ratio Graph

Another spelling for the same operator would take 2 positive numbers and give their absolute ratio:

And a graph:

Absolute ratio in 3D

Use case examples

  • Music and audio – an octave of a frequency F is 2F. More generally a harmony of a frequency F is N*F where N is a natural number. To decide if one frequency is a harmony of another we just need to get their absolute ratio and see if it’s whole. E.g. if abs_ratio(F1, F2) == 2 they’re octaves. If abs_ratio(F1, F2) is whole – they’re harmonies.
  • Computer vision – to match shapes that have similar dimensions e.g. their width is only 10% larger or smaller. We don’t care which is the bigger or smaller, we just want to know if 0.91 < W1 / W2 < 1.1 which may be easier to pronounce as abs_ratio(W1, W2) < 1.1
  • Real life – when we see 2 comparable objects we’re more likely to say one is “three times the other” vs “one third the other”. Either way in our brains both statements mean the same concept. We think in absolute ratios.
  • General case – When you want to know if X is K times bigger than Y or vice versa and you don’t care which is the bigger one.

Interesting Properties

  • abs_ratio(Y / X) == abs_ratio(X / Y)
  • log(abs_ratio(X)) = abs(log(X))
  • log(abs_ratio(Y / X)) = abs(log(Y / X)) = abs(log(Y) – log(X))
  • You can see from the above that absolute ratio is somewhat of an absolute value for log-space.

What’s next for absolute ratio

  • I’d love to hear more use cases and relevant contexts.
  • What would be the written symbol or notation?
  • How can we get this operator famous enough to be of use to mainstream minds?
  • About negative numbers and zero – right now that’s undefined as I don’t see a use case for that domain.
  • For some code and graphs in python checkout https://github.com/ubershmekel/abs_ratio

EDIT – I’m growing to like the binary form of the operator more so from now on let’s call it like this in python:

def abs_ratio(a, b):
    return a / b if a > b else b / a

Android API Bugs – AudioRecord

When asking android to record from the mic to a buffer you have to do something like:

mRecorder = new AudioRecord(AudioSource.MIC, RATE, CHANNEL_MODE,
 ENCODING, BUFFER_SIZE);
if (mRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
    // fail and bail
}
mRecorder.startRecording();
bytesRead = mRecorder.read(audioBuffer, offsetInBuffer, readSize);
mRecorder.stop();
mRecorder.release();

Now the bug that drove me mad was that read() returned zero when I left the application (using the home button) and immediately returned to it. Luckily I was toying around with BUFFER_SIZE when I noticed

mRecorder.getState()

failed when BUFFER_SIZE was set to 0×100, I guessed it was too small and indeed one must call getMinBufferSize() to find out the limits of AudioRecord instantiation as documented.

Don’t use getMinBufferSize() + 1 btw as that throws an IllegalArgumentException at AudioRecorder construction:

12-10 21:49:33.359: E/AndroidRuntime(28950): java.lang.IllegalArgumentException: Invalid audio buffer size.

Using something like getMinBufferSize() + 100 does work at first but when you use the home-button to leave and return it causes the read() returning zero bug from time to time. Not always, but from time to time. Also make sure you release() the recorder because forgetting that will also allow you to construct the recorder but reads will fail.

I can’t begin to describe how frustrating finding that bug was.

Now audio programmers should know they’re supposed to read a size that’s a divisor of the buffer size, yes. This doesn’t excuse the API from behaving itself and throwing relevant exceptions and errors that are debuggable and documented. This was SdkLevel 8 btw. Things like this make you feel as though these are the guys that wrote the api:

Eventually the working code will be pushed to the android tuner google code project for your enjoyment.

Duplicating Streams of Audio with Python

This morning I made a python script that uses pyaudio to read from one audio device and pipe to the next, I call it replicate.py.

This is a really old problem for me, ever since I first had 4.1 speakers and winamp only played on the front 2. Nowadays I just want VLC to play on both the TV and the computer speakers without switching between audio output modules in the preferences or fiddling with the default audio output in Windows 7.

PyAudio was really nice and easy to use, I just wish asynch io was added so I could lower the latency a bit as I’m getting 240 ms right now which is very far from perfect.