OSDN Git Service

Snap for 5706862 from e907286277a038c0bed1916c5dfcb56a15c58349 to qt-c2f2-release
[android-x86/system-media.git] / audio_utils / tinysndfile.c
index 30befc5..e94bb65 100644 (file)
  * limitations under the License.
  */
 
+#include <system/audio.h>
 #include <audio_utils/sndfile.h>
 #include <audio_utils/primitives.h>
+#ifdef HAVE_STDERR
 #include <stdio.h>
+#endif
 #include <string.h>
 #include <errno.h>
 
@@ -63,7 +66,9 @@ static SNDFILE *sf_open_read(const char *path, SF_INFO *info)
 {
     FILE *stream = fopen(path, "rb");
     if (stream == NULL) {
+#ifdef HAVE_STDERR
         fprintf(stderr, "fopen %s failed errno %d\n", path, errno);
+#endif
         return NULL;
     }
 
@@ -78,20 +83,28 @@ static SNDFILE *sf_open_read(const char *path, SF_INFO *info)
     size_t actual;
     actual = fread(wav, sizeof(char), sizeof(wav), stream);
     if (actual < 12) {
+#ifdef HAVE_STDERR
         fprintf(stderr, "actual %zu < 44\n", actual);
+#endif
         goto close;
     }
     if (memcmp(wav, "RIFF", 4)) {
+#ifdef HAVE_STDERR
         fprintf(stderr, "wav != RIFF\n");
+#endif
         goto close;
     }
     unsigned riffSize = little4u(&wav[4]);
     if (riffSize < 4) {
+#ifdef HAVE_STDERR
         fprintf(stderr, "riffSize %u < 4\n", riffSize);
+#endif
         goto close;
     }
     if (memcmp(&wav[8], "WAVE", 4)) {
+#ifdef HAVE_STDERR
         fprintf(stderr, "missing WAVE\n");
+#endif
         goto close;
     }
     size_t remaining = riffSize - 4;
@@ -102,28 +115,38 @@ static SNDFILE *sf_open_read(const char *path, SF_INFO *info)
         unsigned char chunk[8];
         actual = fread(chunk, sizeof(char), sizeof(chunk), stream);
         if (actual != sizeof(chunk)) {
+#ifdef HAVE_STDERR
             fprintf(stderr, "actual %zu != %zu\n", actual, sizeof(chunk));
+#endif
             goto close;
         }
         remaining -= 8;
         unsigned chunkSize = little4u(&chunk[4]);
         if (chunkSize > remaining) {
+#ifdef HAVE_STDERR
             fprintf(stderr, "chunkSize %u > remaining %zu\n", chunkSize, remaining);
+#endif
             goto close;
         }
         if (!memcmp(&chunk[0], "fmt ", 4)) {
             if (hadFmt) {
+#ifdef HAVE_STDERR
                 fprintf(stderr, "multiple fmt\n");
+#endif
                 goto close;
             }
             if (chunkSize < 2) {
+#ifdef HAVE_STDERR
                 fprintf(stderr, "chunkSize %u < 2\n", chunkSize);
+#endif
                 goto close;
             }
             unsigned char fmt[40];
             actual = fread(fmt, sizeof(char), 2, stream);
             if (actual != 2) {
+#ifdef HAVE_STDERR
                 fprintf(stderr, "actual %zu != 2\n", actual);
+#endif
                 goto close;
             }
             unsigned format = little2u(&fmt[0]);
@@ -137,36 +160,49 @@ static SNDFILE *sf_open_read(const char *path, SF_INFO *info)
                 minSize = 40;
                 break;
             default:
+#ifdef HAVE_STDERR
                 fprintf(stderr, "unsupported format %u\n", format);
+#endif
                 goto close;
             }
             if (chunkSize < minSize) {
+#ifdef HAVE_STDERR
                 fprintf(stderr, "chunkSize %u < minSize %zu\n", chunkSize, minSize);
+#endif
                 goto close;
             }
             actual = fread(&fmt[2], sizeof(char), minSize - 2, stream);
             if (actual != minSize - 2) {
+#ifdef HAVE_STDERR
                 fprintf(stderr, "actual %zu != %zu\n", actual, minSize - 16);
+#endif
                 goto close;
             }
             if (chunkSize > minSize) {
                 fseek(stream, (long) (chunkSize - minSize), SEEK_CUR);
             }
             unsigned channels = little2u(&fmt[2]);
-            if (channels != 1 && channels != 2 && channels != 4 && channels != 6 && channels != 8) {
+            if ((channels < 1) || (channels > FCC_8)) {
+#ifdef HAVE_STDERR
                 fprintf(stderr, "unsupported channels %u\n", channels);
+#endif
                 goto close;
             }
             unsigned samplerate = little4u(&fmt[4]);
             if (samplerate == 0) {
+#ifdef HAVE_STDERR
                 fprintf(stderr, "samplerate %u == 0\n", samplerate);
+#endif
                 goto close;
             }
             // ignore byte rate
             // ignore block alignment
             unsigned bitsPerSample = little2u(&fmt[14]);
-            if (bitsPerSample != 8 && bitsPerSample != 16 && bitsPerSample != 32) {
-                fprintf(stderr, "bitsPerSample %u != 8 or 16 or 32\n", bitsPerSample);
+            if (bitsPerSample != 8 && bitsPerSample != 16 && bitsPerSample != 24 &&
+                    bitsPerSample != 32) {
+#ifdef HAVE_STDERR
+                fprintf(stderr, "bitsPerSample %u != 8 or 16 or 24 or 32\n", bitsPerSample);
+#endif
                 goto close;
             }
             unsigned bytesPerFrame = (bitsPerSample >> 3) * channels;
@@ -180,6 +216,9 @@ static SNDFILE *sf_open_read(const char *path, SF_INFO *info)
             case 16:
                 handle->info.format |= SF_FORMAT_PCM_16;
                 break;
+            case 24:
+                handle->info.format |= SF_FORMAT_PCM_24;
+                break;
             case 32:
                 if (format == WAVE_FORMAT_IEEE_FLOAT)
                     handle->info.format |= SF_FORMAT_FLOAT;
@@ -190,11 +229,15 @@ static SNDFILE *sf_open_read(const char *path, SF_INFO *info)
             hadFmt = 1;
         } else if (!memcmp(&chunk[0], "data", 4)) {
             if (!hadFmt) {
+#ifdef HAVE_STDERR
                 fprintf(stderr, "data not preceded by fmt\n");
+#endif
                 goto close;
             }
             if (hadData) {
+#ifdef HAVE_STDERR
                 fprintf(stderr, "multiple data\n");
+#endif
                 goto close;
             }
             handle->remaining = chunkSize / handle->bytesPerFrame;
@@ -211,8 +254,10 @@ static SNDFILE *sf_open_read(const char *path, SF_INFO *info)
             }
         } else {
             // ignore unknown chunk
+#ifdef HAVE_STDERR
             fprintf(stderr, "ignoring unknown chunk %c%c%c%c\n",
                     chunk[0], chunk[1], chunk[2], chunk[3]);
+#endif
             if (chunkSize > 0) {
                 fseek(stream, (long) chunkSize, SEEK_CUR);
             }
@@ -220,11 +265,15 @@ static SNDFILE *sf_open_read(const char *path, SF_INFO *info)
         remaining -= chunkSize;
     }
     if (remaining > 0) {
+#ifdef HAVE_STDERR
         fprintf(stderr, "partial chunk at end of RIFF, remaining %zu\n", remaining);
+#endif
         goto close;
     }
     if (!hadData) {
+#ifdef HAVE_STDERR
         fprintf(stderr, "missing data\n");
+#endif
         goto close;
     }
     (void) fseek(stream, dataTell, SEEK_SET);
@@ -250,15 +299,18 @@ static SNDFILE *sf_open_write(const char *path, SF_INFO *info)
     int sub = info->format & SF_FORMAT_SUBMASK;
     if (!(
             (info->samplerate > 0) &&
-            (info->channels > 0 && info->channels <= 8) &&
+            (info->channels > 0 && info->channels <= FCC_8) &&
             ((info->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV) &&
-            (sub == SF_FORMAT_PCM_16 || sub == SF_FORMAT_PCM_U8 || sub == SF_FORMAT_FLOAT)
+            (sub == SF_FORMAT_PCM_16 || sub == SF_FORMAT_PCM_U8 || sub == SF_FORMAT_FLOAT ||
+                sub == SF_FORMAT_PCM_24 || sub == SF_FORMAT_PCM_32)
           )) {
         return NULL;
     }
     FILE *stream = fopen(path, "w+b");
     if (stream == NULL) {
+#ifdef HAVE_STDERR
         fprintf(stderr, "fopen %s failed errno %d\n", path, errno);
+#endif
         return NULL;
     }
     unsigned char wav[58];
@@ -287,6 +339,12 @@ static SNDFILE *sf_open_write(const char *path, SF_INFO *info)
     case SF_FORMAT_FLOAT:
         bitsPerSample = 32;
         break;
+    case SF_FORMAT_PCM_24:
+        bitsPerSample = 24;
+        break;
+    case SF_FORMAT_PCM_32:
+        bitsPerSample = 32;
+        break;
     default:    // not reachable
         bitsPerSample = 0;
         break;
@@ -319,7 +377,9 @@ static SNDFILE *sf_open_write(const char *path, SF_INFO *info)
 SNDFILE *sf_open(const char *path, int mode, SF_INFO *info)
 {
     if (path == NULL || info == NULL) {
+#ifdef HAVE_STDERR
         fprintf(stderr, "path=%p info=%p\n", path, info);
+#endif
         return NULL;
     }
     switch (mode) {
@@ -328,7 +388,9 @@ SNDFILE *sf_open(const char *path, int mode, SF_INFO *info)
     case SFM_WRITE:
         return sf_open_write(path, info);
     default:
+#ifdef HAVE_STDERR
         fprintf(stderr, "mode=%d\n", mode);
+#endif
         return NULL;
     }
 }
@@ -368,7 +430,7 @@ sf_count_t sf_readf_short(SNDFILE *handle, short *ptr, sf_count_t desiredFrames)
     size_t actualBytes;
     void *temp = NULL;
     unsigned format = handle->info.format & SF_FORMAT_SUBMASK;
-    if (format == SF_FORMAT_PCM_32 || format == SF_FORMAT_FLOAT) {
+    if (format == SF_FORMAT_PCM_32 || format == SF_FORMAT_FLOAT || format == SF_FORMAT_PCM_24) {
         temp = malloc(desiredBytes);
         actualBytes = fread(temp, sizeof(char), desiredBytes, handle->stream);
     } else {
@@ -392,6 +454,10 @@ sf_count_t sf_readf_short(SNDFILE *handle, short *ptr, sf_count_t desiredFrames)
         memcpy_to_i16_from_float(ptr, (const float *) temp, actualFrames * handle->info.channels);
         free(temp);
         break;
+    case SF_FORMAT_PCM_24:
+        memcpy_to_i16_from_p24(ptr, (const uint8_t *) temp, actualFrames * handle->info.channels);
+        free(temp);
+        break;
     default:
         memset(ptr, 0, actualFrames * handle->info.channels * sizeof(short));
         break;
@@ -413,7 +479,7 @@ sf_count_t sf_readf_float(SNDFILE *handle, float *ptr, sf_count_t desiredFrames)
     size_t actualBytes;
     void *temp = NULL;
     unsigned format = handle->info.format & SF_FORMAT_SUBMASK;
-    if (format == SF_FORMAT_PCM_16 || format == SF_FORMAT_PCM_U8) {
+    if (format == SF_FORMAT_PCM_16 || format == SF_FORMAT_PCM_U8 || format == SF_FORMAT_PCM_24) {
         temp = malloc(desiredBytes);
         actualBytes = fread(temp, sizeof(char), desiredBytes, handle->stream);
     } else {
@@ -423,11 +489,8 @@ sf_count_t sf_readf_float(SNDFILE *handle, float *ptr, sf_count_t desiredFrames)
     handle->remaining -= actualFrames;
     switch (format) {
     case SF_FORMAT_PCM_U8:
-#if 0
-        // TODO - implement
         memcpy_to_float_from_u8(ptr, (const unsigned char *) temp,
                 actualFrames * handle->info.channels);
-#endif
         free(temp);
         break;
     case SF_FORMAT_PCM_16:
@@ -439,6 +502,10 @@ sf_count_t sf_readf_float(SNDFILE *handle, float *ptr, sf_count_t desiredFrames)
         break;
     case SF_FORMAT_FLOAT:
         break;
+    case SF_FORMAT_PCM_24:
+        memcpy_to_float_from_p24(ptr, (const uint8_t *) temp, actualFrames * handle->info.channels);
+        free(temp);
+        break;
     default:
         memset(ptr, 0, actualFrames * handle->info.channels * sizeof(float));
         break;
@@ -460,7 +527,7 @@ sf_count_t sf_readf_int(SNDFILE *handle, int *ptr, sf_count_t desiredFrames)
     void *temp = NULL;
     unsigned format = handle->info.format & SF_FORMAT_SUBMASK;
     size_t actualBytes;
-    if (format == SF_FORMAT_PCM_16 || format == SF_FORMAT_PCM_U8) {
+    if (format == SF_FORMAT_PCM_16 || format == SF_FORMAT_PCM_U8 || format == SF_FORMAT_PCM_24) {
         temp = malloc(desiredBytes);
         actualBytes = fread(temp, sizeof(char), desiredBytes, handle->stream);
     } else {
@@ -470,11 +537,8 @@ sf_count_t sf_readf_int(SNDFILE *handle, int *ptr, sf_count_t desiredFrames)
     handle->remaining -= actualFrames;
     switch (format) {
     case SF_FORMAT_PCM_U8:
-#if 0
-        // TODO - implement
         memcpy_to_i32_from_u8(ptr, (const unsigned char *) temp,
                 actualFrames * handle->info.channels);
-#endif
         free(temp);
         break;
     case SF_FORMAT_PCM_16:
@@ -486,6 +550,10 @@ sf_count_t sf_readf_int(SNDFILE *handle, int *ptr, sf_count_t desiredFrames)
     case SF_FORMAT_FLOAT:
         memcpy_to_i32_from_float(ptr, (const float *) ptr, actualFrames * handle->info.channels);
         break;
+    case SF_FORMAT_PCM_24:
+        memcpy_to_i32_from_p24(ptr, (const uint8_t *) temp, actualFrames * handle->info.channels);
+        free(temp);
+        break;
     default:
         memset(ptr, 0, actualFrames * handle->info.channels * sizeof(int));
         break;
@@ -554,3 +622,21 @@ sf_count_t sf_writef_float(SNDFILE *handle, const float *ptr, sf_count_t desired
     handle->remaining += actualFrames;
     return actualFrames;
 }
+
+sf_count_t sf_writef_int(SNDFILE *handle, const int *ptr, sf_count_t desiredFrames)
+{
+    if (handle == NULL || handle->mode != SFM_WRITE || ptr == NULL || desiredFrames <= 0)
+        return 0;
+    size_t desiredBytes = desiredFrames * handle->bytesPerFrame;
+    size_t actualBytes = 0;
+    switch (handle->info.format & SF_FORMAT_SUBMASK) {
+    case SF_FORMAT_PCM_32:
+        actualBytes = fwrite(ptr, sizeof(char), desiredBytes, handle->stream);
+        break;
+    default:    // transcoding from other formats not yet implemented
+        break;
+    }
+    size_t actualFrames = actualBytes / handle->bytesPerFrame;
+    handle->remaining += actualFrames;
+    return actualFrames;
+}