Merge "Add support for reading 8-bit PCM"
diff --git a/audio_utils/Android.mk b/audio_utils/Android.mk
index b653f5a..e1102e5 100644
--- a/audio_utils/Android.mk
+++ b/audio_utils/Android.mk
@@ -33,4 +33,6 @@
 LOCAL_C_INCLUDES += \
 	$(call include-path-for, audio-utils)
 
+LOCAL_SHARED_LIBRARIES := libaudioutils
+
 include $(BUILD_STATIC_LIBRARY)
diff --git a/audio_utils/include/audio_utils/sndfile.h b/audio_utils/include/audio_utils/sndfile.h
index eff7067..1d12ae5 100644
--- a/audio_utils/include/audio_utils/sndfile.h
+++ b/audio_utils/include/audio_utils/sndfile.h
@@ -24,9 +24,15 @@
 // no guarantee that it will stay exactly source-code compatible with other libraries.
 
 #include <stdio.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
 
 // visible to clients
+typedef int sf_count_t;
+
 typedef struct {
+    sf_count_t frames;
     int samplerate;
     int channels;
     int format;
@@ -35,8 +41,6 @@
 // opaque to clients
 typedef struct SNDFILE_ SNDFILE;
 
-typedef unsigned sf_count_t;
-
 // Access modes
 #define SFM_READ   1
 
@@ -54,6 +58,8 @@
 void sf_close(SNDFILE *handle);
 
 // Read interleaved frames and return actual number of frames read
-ssize_t sf_readf_short(SNDFILE *handle, short *ptr, size_t desired);
+sf_count_t sf_readf_short(SNDFILE *handle, short *ptr, sf_count_t desired);
+
+__END_DECLS
 
 #endif /* __AUDIO_UTIL_SNDFILE_H */
diff --git a/audio_utils/tinysndfile.c b/audio_utils/tinysndfile.c
index b50ad72..f028685 100644
--- a/audio_utils/tinysndfile.c
+++ b/audio_utils/tinysndfile.c
@@ -15,6 +15,7 @@
  */
 
 #include <audio_utils/sndfile.h>
+#include <audio_utils/primitives.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -86,7 +87,7 @@
         // ignore byte rate
         // ignore block alignment
         unsigned bitsPerSample = little2u(&wav[34]);
-        if (/*bitsPerSample != 8 &&*/ bitsPerSample != 16)
+        if (bitsPerSample != 8 && bitsPerSample != 16)
             break;
         unsigned bytesPerFrame = (bitsPerSample >> 3) * channels;
         if (memcmp(&wav[36], "data", 4))
@@ -96,9 +97,14 @@
         handle->stream = stream;
         handle->bytesPerFrame = bytesPerFrame;
         handle->remaining = dataSize / bytesPerFrame;
+        handle->info.frames = handle->remaining;
         handle->info.samplerate = samplerate;
         handle->info.channels = channels;
-        handle->info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+        handle->info.format = SF_FORMAT_WAV;
+        if (bitsPerSample == 8)
+            handle->info.format |= SF_FORMAT_PCM_U8;
+        else
+            handle->info.format |= SF_FORMAT_PCM_16;
         *info = handle->info;
         return handle;
     }
@@ -114,18 +120,25 @@
     handle->remaining = 0;
 }
 
-ssize_t sf_readf_short(SNDFILE *handle, short *ptr, size_t desiredFrames)
+sf_count_t sf_readf_short(SNDFILE *handle, short *ptr, sf_count_t desiredFrames)
 {
-    if (handle == NULL || ptr == NULL || !handle->remaining)
+    if (handle == NULL || ptr == NULL || !handle->remaining || desiredFrames <= 0)
         return 0;
-    if (handle->remaining < desiredFrames)
+    if (handle->remaining < (size_t) desiredFrames)
         desiredFrames = handle->remaining;
     size_t desiredBytes = desiredFrames * handle->bytesPerFrame;
     // does not check for numeric overflow
     size_t actualBytes = fread(ptr, sizeof(char), desiredBytes, handle->stream);
     size_t actualFrames = actualBytes / handle->bytesPerFrame;
     handle->remaining -= actualFrames;
-    if (!isLittleEndian())
-        swab(ptr, actualFrames * handle->info.channels);
+    switch (handle->info.format & SF_FORMAT_SUBMASK) {
+    case SF_FORMAT_PCM_U8:
+        memcpy_to_i16_from_u8(ptr, (unsigned char *) ptr, actualFrames * handle->info.channels);
+        break;
+    case SF_FORMAT_PCM_16:
+        if (!isLittleEndian())
+            swab(ptr, actualFrames * handle->info.channels);
+        break;
+    }
     return actualFrames;
 }