opensles: generate channel masks safely by OS version

Indexed channel masks were not supported before N.

Fixes #117
diff --git a/src/opensles/AudioInputStreamOpenSLES.cpp b/src/opensles/AudioInputStreamOpenSLES.cpp
index 71e27a1..ec47ed2 100644
--- a/src/opensles/AudioInputStreamOpenSLES.cpp
+++ b/src/opensles/AudioInputStreamOpenSLES.cpp
@@ -57,9 +57,6 @@
 AudioInputStreamOpenSLES::~AudioInputStreamOpenSLES() {
 }
 
-#define AUDIO_CHANNEL_COUNT_MAX         30u
-#define SL_ANDROID_UNKNOWN_CHANNELMASK  0
-
 int AudioInputStreamOpenSLES::chanCountToChanMask(int channelCount) {
     // from internal sles_channel_in_mask_from_count(chanCount);
     switch (channelCount) {
@@ -67,14 +64,8 @@
             return SL_SPEAKER_FRONT_LEFT;
         case 2:
             return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
-        default: {
-            if (channelCount > AUDIO_CHANNEL_COUNT_MAX) {
-                return SL_ANDROID_UNKNOWN_CHANNELMASK;
-            } else {
-                SLuint32 bitfield = (1 << channelCount) - 1;
-                return SL_ANDROID_MAKE_INDEXED_CHANNEL_MASK(bitfield);
-            }
-        }
+        default:
+            return chanCountToChanMaskDefault(channelCount);
     }
 }
 
diff --git a/src/opensles/AudioOutputStreamOpenSLES.cpp b/src/opensles/AudioOutputStreamOpenSLES.cpp
index 749b509..cf0edaf 100644
--- a/src/opensles/AudioOutputStreamOpenSLES.cpp
+++ b/src/opensles/AudioOutputStreamOpenSLES.cpp
@@ -46,10 +46,10 @@
 constexpr int SL_ANDROID_SPEAKER_7DOT1 = (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT
         | SL_SPEAKER_SIDE_RIGHT);
 
-int AudioOutputStreamOpenSLES::chanCountToChanMask(int chanCount) {
+int AudioOutputStreamOpenSLES::chanCountToChanMask(int channelCount) {
     int channelMask = 0;
 
-    switch (chanCount) {
+    switch (channelCount) {
         case  1:
             channelMask = SL_SPEAKER_FRONT_CENTER;
             break;
@@ -69,6 +69,10 @@
         case  8: // 7.1
             channelMask = SL_ANDROID_SPEAKER_7DOT1;
             break;
+
+        default:
+            channelMask = chanCountToChanMaskDefault(channelCount);
+            break;
     }
     return channelMask;
 }
diff --git a/src/opensles/AudioStreamOpenSLES.cpp b/src/opensles/AudioStreamOpenSLES.cpp
index 6ca4bbf..4a69760 100644
--- a/src/opensles/AudioStreamOpenSLES.cpp
+++ b/src/opensles/AudioStreamOpenSLES.cpp
@@ -49,6 +49,29 @@
     delete[] mCallbackBuffer;
 }
 
+#define AUDIO_CHANNEL_COUNT_MAX          30u
+#define SL_ANDROID_UNKNOWN_CHANNELMASK   0
+
+int AudioStreamOpenSLES::chanCountToChanMaskDefault(int channelCount) {
+    if (channelCount > AUDIO_CHANNEL_COUNT_MAX) {
+        return SL_ANDROID_UNKNOWN_CHANNELMASK;
+    } else {
+        SLuint32 bitfield = (1 << channelCount) - 1;
+// Check for NDK at compile-time.
+#if __ANDROID_API__ >= __ANDROID_API_N__
+        // Check for OS at run-time.
+        if(getSdkVersion() >= __ANDROID_API_N__) {
+            return SL_ANDROID_MAKE_INDEXED_CHANNEL_MASK(bitfield);
+        } else
+#endif
+        {
+            // Indexed channels masks were added in N.
+            // For before N, the best we can do is use a positional channel mask.
+            return bitfield;
+        }
+    }
+}
+
 static bool s_isLittleEndian() {
     static uint32_t value = 1;
     return *((uint8_t *) &value) == 1; // Does address point to LSB?
diff --git a/src/opensles/AudioStreamOpenSLES.h b/src/opensles/AudioStreamOpenSLES.h
index da4eac3..be9a332 100644
--- a/src/opensles/AudioStreamOpenSLES.h
+++ b/src/opensles/AudioStreamOpenSLES.h
@@ -74,6 +74,8 @@
 
 protected:
 
+    int chanCountToChanMaskDefault(int channelCount);
+
     virtual Result onBeforeDestroy() { return Result::OK; };
     virtual Result onAfterDestroy() { return Result::OK; };