]> code.delx.au - pulseaudio/blobdiff - src/pulse/sample.c
mainloop: fix detection of rt clocks
[pulseaudio] / src / pulse / sample.c
index dd68ac17ba4fa636d7dabc426a7d959c8205c6c0..9698d8a55099a849438dad810869f2a08871bb33 100644 (file)
@@ -1,11 +1,12 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
+
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
+  by the Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <math.h>
 #include <string.h>
 
+#include <pulse/timeval.h>
+#include <pulse/i18n.h>
+
+#include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+
 #include "sample.h"
 
+static const size_t size_table[] = {
+    [PA_SAMPLE_U8] = 1,
+    [PA_SAMPLE_ULAW] = 1,
+    [PA_SAMPLE_ALAW] = 1,
+    [PA_SAMPLE_S16LE] = 2,
+    [PA_SAMPLE_S16BE] = 2,
+    [PA_SAMPLE_FLOAT32LE] = 4,
+    [PA_SAMPLE_FLOAT32BE] = 4,
+    [PA_SAMPLE_S32LE] = 4,
+    [PA_SAMPLE_S32BE] = 4,
+    [PA_SAMPLE_S24LE] = 3,
+    [PA_SAMPLE_S24BE] = 3,
+    [PA_SAMPLE_S24_32LE] = 4,
+    [PA_SAMPLE_S24_32BE] = 4
+};
+
+size_t pa_sample_size_of_format(pa_sample_format_t f) {
+    pa_assert(f >= 0);
+    pa_assert(f < PA_SAMPLE_MAX);
+
+    return size_table[f];
+}
+
 size_t pa_sample_size(const pa_sample_spec *spec) {
-    assert(spec);
 
-    switch (spec->format) {
-        case PA_SAMPLE_U8:
-        case PA_SAMPLE_ULAW:
-        case PA_SAMPLE_ALAW:
-            return 1;
-        case PA_SAMPLE_S16LE:
-        case PA_SAMPLE_S16BE:
-            return 2;
-        case PA_SAMPLE_FLOAT32LE:
-        case PA_SAMPLE_FLOAT32BE:
-            return 4;
-        default:
-            assert(0);
-            return 0;
-    }
+    pa_assert(spec);
+    pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
+
+    return size_table[spec->format];
 }
 
 size_t pa_frame_size(const pa_sample_spec *spec) {
-    assert(spec);
+    pa_assert(spec);
+    pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
 
-    return pa_sample_size(spec) * spec->channels;
+    return size_table[spec->format] * spec->channels;
 }
 
 size_t pa_bytes_per_second(const pa_sample_spec *spec) {
-    assert(spec);
-    return spec->rate*pa_frame_size(spec);
+    pa_assert(spec);
+    pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
+
+    return spec->rate * size_table[spec->format] * spec->channels;
 }
 
 pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) {
-    assert(spec);
+    pa_assert(spec);
+    pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
 
-    return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate);
+    return (((pa_usec_t) (length / (size_table[spec->format] * spec->channels)) * PA_USEC_PER_SEC) / spec->rate);
 }
 
 size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
-    assert(spec);
+    pa_assert(spec);
+    pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
 
-    return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec);
+    return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) * (size_table[spec->format] * spec->channels);
+}
+
+pa_sample_spec* pa_sample_spec_init(pa_sample_spec *spec) {
+    pa_assert(spec);
+
+    spec->format = PA_SAMPLE_INVALID;
+    spec->rate = 0;
+    spec->channels = 0;
+
+    return spec;
 }
 
 int pa_sample_spec_valid(const pa_sample_spec *spec) {
-    assert(spec);
+    pa_assert(spec);
 
-    if (spec->rate <= 0 ||
+    if (PA_UNLIKELY (spec->rate <= 0 ||
+        spec->rate > PA_RATE_MAX ||
         spec->channels <= 0 ||
         spec->channels > PA_CHANNELS_MAX ||
         spec->format >= PA_SAMPLE_MAX ||
-        spec->format < 0)
+        spec->format < 0))
         return 0;
 
     return 1;
 }
 
 int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) {
-    assert(a && b);
+    pa_assert(a);
+    pa_assert(b);
+
+    pa_return_val_if_fail(pa_sample_spec_valid(a), 0);
+
+    if (PA_UNLIKELY(a == b))
+        return 1;
 
-    return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels);
+    pa_return_val_if_fail(pa_sample_spec_valid(b), 0);
+
+    return
+        (a->format == b->format) &&
+        (a->rate == b->rate) &&
+        (a->channels == b->channels);
 }
 
 const char *pa_sample_format_to_string(pa_sample_format_t f) {
@@ -101,39 +145,55 @@ const char *pa_sample_format_to_string(pa_sample_format_t f) {
         [PA_SAMPLE_S16BE] = "s16be",
         [PA_SAMPLE_FLOAT32LE] = "float32le",
         [PA_SAMPLE_FLOAT32BE] = "float32be",
+        [PA_SAMPLE_S32LE] = "s32le",
+        [PA_SAMPLE_S32BE] = "s32be",
+        [PA_SAMPLE_S24LE] = "s24le",
+        [PA_SAMPLE_S24BE] = "s24be",
+        [PA_SAMPLE_S24_32LE] = "s24-32le",
+        [PA_SAMPLE_S24_32BE] = "s24-32be",
     };
 
-    if (f >= PA_SAMPLE_MAX)
+    if (f < 0 || f >= PA_SAMPLE_MAX)
         return NULL;
 
     return table[f];
 }
 
 char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
-    assert(s && l && spec);
+    pa_assert(s);
+    pa_assert(l > 0);
+    pa_assert(spec);
+
+    pa_init_i18n();
 
     if (!pa_sample_spec_valid(spec))
-        snprintf(s, l, "Invalid");
+        pa_snprintf(s, l, _("(invalid)"));
     else
-        snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
+        pa_snprintf(s, l, _("%s %uch %uHz"), pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
 
     return s;
 }
 
 char* pa_bytes_snprint(char *s, size_t l, unsigned v) {
+    pa_assert(s);
+    pa_assert(l > 0);
+
+    pa_init_i18n();
+
     if (v >= ((unsigned) 1024)*1024*1024)
-        snprintf(s, l, "%0.1f GiB", ((double) v)/1024/1024/1024);
+        pa_snprintf(s, l, _("%0.1f GiB"), ((double) v)/1024/1024/1024);
     else if (v >= ((unsigned) 1024)*1024)
-        snprintf(s, l, "%0.1f MiB", ((double) v)/1024/1024);
+        pa_snprintf(s, l, _("%0.1f MiB"), ((double) v)/1024/1024);
     else if (v >= (unsigned) 1024)
-        snprintf(s, l, "%0.1f KiB", ((double) v)/1024);
+        pa_snprintf(s, l, _("%0.1f KiB"), ((double) v)/1024);
     else
-        snprintf(s, l, "%u B", (unsigned) v);
+        pa_snprintf(s, l, _("%u B"), (unsigned) v);
 
     return s;
 }
 
 pa_sample_format_t pa_parse_sample_format(const char *format) {
+    pa_assert(format);
 
     if (strcasecmp(format, "s16le") == 0)
         return PA_SAMPLE_S16LE;
@@ -141,18 +201,79 @@ pa_sample_format_t pa_parse_sample_format(const char *format) {
         return PA_SAMPLE_S16BE;
     else if (strcasecmp(format, "s16ne") == 0 || strcasecmp(format, "s16") == 0 || strcasecmp(format, "16") == 0)
         return PA_SAMPLE_S16NE;
+    else if (strcasecmp(format, "s16re") == 0)
+        return PA_SAMPLE_S16RE;
     else if (strcasecmp(format, "u8") == 0 || strcasecmp(format, "8") == 0)
         return PA_SAMPLE_U8;
-    else if (strcasecmp(format, "float32") == 0 || strcasecmp(format, "float32ne") == 0)
-        return PA_SAMPLE_FLOAT32;
+    else if (strcasecmp(format, "float32") == 0 || strcasecmp(format, "float32ne") == 0 || strcasecmp(format, "float") == 0)
+        return PA_SAMPLE_FLOAT32NE;
+    else if (strcasecmp(format, "float32re") == 0)
+        return PA_SAMPLE_FLOAT32RE;
     else if (strcasecmp(format, "float32le") == 0)
         return PA_SAMPLE_FLOAT32LE;
     else if (strcasecmp(format, "float32be") == 0)
         return PA_SAMPLE_FLOAT32BE;
-    else if (strcasecmp(format, "ulaw") == 0)
+    else if (strcasecmp(format, "ulaw") == 0 || strcasecmp(format, "mulaw") == 0)
         return PA_SAMPLE_ULAW;
     else if (strcasecmp(format, "alaw") == 0)
         return PA_SAMPLE_ALAW;
+    else if (strcasecmp(format, "s32le") == 0)
+        return PA_SAMPLE_S32LE;
+    else if (strcasecmp(format, "s32be") == 0)
+        return PA_SAMPLE_S32BE;
+    else if (strcasecmp(format, "s32ne") == 0 || strcasecmp(format, "s32") == 0 || strcasecmp(format, "32") == 0)
+        return PA_SAMPLE_S32NE;
+    else if (strcasecmp(format, "s32re") == 0)
+        return PA_SAMPLE_S24RE;
+    else if (strcasecmp(format, "s24le") == 0)
+        return PA_SAMPLE_S24LE;
+    else if (strcasecmp(format, "s24be") == 0)
+        return PA_SAMPLE_S24BE;
+    else if (strcasecmp(format, "s24ne") == 0 || strcasecmp(format, "s24") == 0 || strcasecmp(format, "24") == 0)
+        return PA_SAMPLE_S24NE;
+    else if (strcasecmp(format, "s24re") == 0)
+        return PA_SAMPLE_S24RE;
+    else if (strcasecmp(format, "s24-32le") == 0)
+        return PA_SAMPLE_S24_32LE;
+    else if (strcasecmp(format, "s24-32be") == 0)
+        return PA_SAMPLE_S24_32BE;
+    else if (strcasecmp(format, "s24-32ne") == 0 || strcasecmp(format, "s24-32") == 0)
+        return PA_SAMPLE_S24_32NE;
+    else if (strcasecmp(format, "s24-32re") == 0)
+        return PA_SAMPLE_S24_32RE;
 
     return -1;
 }
+
+int pa_sample_format_is_le(pa_sample_format_t f) {
+    pa_assert(f >= PA_SAMPLE_U8);
+    pa_assert(f < PA_SAMPLE_MAX);
+
+    switch (f) {
+        case PA_SAMPLE_S16LE:
+        case PA_SAMPLE_S24LE:
+        case PA_SAMPLE_S32LE:
+        case PA_SAMPLE_S24_32LE:
+        case PA_SAMPLE_FLOAT32LE:
+            return 1;
+
+        case PA_SAMPLE_S16BE:
+        case PA_SAMPLE_S24BE:
+        case PA_SAMPLE_S32BE:
+        case PA_SAMPLE_S24_32BE:
+        case PA_SAMPLE_FLOAT32BE:
+            return 0;
+
+        default:
+            return -1;
+    }
+}
+
+int pa_sample_format_is_be(pa_sample_format_t f) {
+    int r;
+
+    if ((r = pa_sample_format_is_le(f)) < 0)
+        return r;
+
+    return !r;
+}