Changeset bb67def in mainline


Ignore:
Timestamp:
2012-07-16T21:06:11Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
389ef25
Parents:
50fa3f7
Message:

hound: Implement audio format covnersion.

No resampling yet.

Location:
uspace/srv/audio/hound
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/audio/hound/audio_format.c

    r50fa3f7 rbb67def  
    3838#include <errno.h>
    3939#include <macros.h>
     40#include <stdio.h>
    4041
    4142#include "audio_format.h"
     
    6364#define int32_t_be2host(x) uint32_t_be2host(x)
    6465#define host2int32_t_be(x) host2uint32_t_be(x)
     66
     67// TODO float endian?
     68#define float_le2host(x) (x)
     69#define float_be2host(x) (x)
     70
     71#define host2float_le(x) (x)
     72#define host2float_be(x) (x)
     73
     74#define from(x, type, endian) (float)(type ## _ ## endian ## 2host(x))
     75#define to(x, type, endian) (float)(host2 ## type ## _ ## endian(x))
     76
     77static float get_normalized_sample(const void *buffer, size_t size,
     78    unsigned frame, unsigned channel, const audio_format_t *f);
    6579
    6680bool audio_format_same(const audio_format_t *a, const audio_format_t* b)
     
    8498        /* This is so ugly it eats kittens, and puppies, and ducklings,
    8599         * and all little fluffy things...
    86          * AND it does not check for overflows (FIXME)*/
    87 #define LOOP_ADD(type, endian, max) \
     100         */
     101#define LOOP_ADD(type, endian, low, high) \
    88102do { \
    89         const type *src_buff = src; \
    90         type *dst_buff = dst; \
    91         for (size_t i = 0; i < size / sizeof(type); ++i) { \
    92                 const float a = type ## _ ## endian ##2host(dst_buff[i]); \
    93                 const float b = type ## _ ## endian ##2host(src_buff[i]); \
    94                 float c = min((a + b), max); \
    95                 if (c <= (float)-max) c = -max + 1.0; \
    96                 dst_buff[i] = host2 ## type ## _ ## endian(c); \
     103        const unsigned frame_size = audio_format_frame_size(f); \
     104        const unsigned frame_count = size / frame_size; \
     105        for (size_t i = 0; i < frame_count; ++i) { \
     106                for (unsigned j = 0; j < f->channels; ++j) { \
     107                        const float a = \
     108                            get_normalized_sample(dst, size, i, j, f);\
     109                        const float b = \
     110                            get_normalized_sample(src, size, i, j, f);\
     111                        float c = (a + b); \
     112                        if (c < -1.0) c = -1.0; \
     113                        if (c > 1.0) c = 1.0; \
     114                        c += 1.0; \
     115                        c *= ((float)(type)high - (float)(type)low) / 2; \
     116                        c += (float)(type)low; \
     117                        if (c > (float)(type)high) { \
     118                                printf("SCALE HIGH failed\n"); \
     119                        } \
     120                        if (c < (float)(type)low) { \
     121                                printf("SCALE LOW failed\n"); \
     122                        } \
     123                        type *dst_buf = dst; \
     124                        const unsigned pos = i * f->channels  + j; \
     125                        if (pos < (size / sizeof(type))) \
     126                                dst_buf[pos] = to((type)c, type, endian); \
     127                } \
    97128        } \
    98129} while (0)
    99130
    100131        switch (f->sample_format) {
    101         case PCM_SAMPLE_UINT8: {
    102                 const uint8_t *src_buff = src;
    103                 uint8_t *dst_buff = dst;
    104                 for (size_t i = 0; i < size; ++i )
    105                         dst_buff[i] += src_buff[i];
    106                 break;
    107                 }
    108         case PCM_SAMPLE_SINT8: {
    109                 const int8_t *src_buff = src;
    110                 int8_t *dst_buff = dst;
    111                 for (size_t i = 0; i < size; ++i)
    112                         dst_buff[i] += src_buff[i];
    113                 break;
    114                 }
     132        case PCM_SAMPLE_UINT8:
     133                LOOP_ADD(uint8_t, le, UINT8_MIN, UINT8_MAX); break;
     134        case PCM_SAMPLE_SINT8:
     135                LOOP_ADD(uint8_t, le, INT8_MIN, INT8_MAX); break;
    115136        case PCM_SAMPLE_UINT16_LE:
    116                 LOOP_ADD(uint16_t, le, UINT16_MAX); break;
     137                LOOP_ADD(uint16_t, le, UINT16_MIN, UINT16_MAX); break;
    117138        case PCM_SAMPLE_SINT16_LE:
    118                 LOOP_ADD(int16_t, le, INT16_MAX); break;
     139                LOOP_ADD(int16_t, le, INT16_MIN, INT16_MAX); break;
    119140        case PCM_SAMPLE_UINT16_BE:
    120                 LOOP_ADD(uint16_t, be, UINT16_MAX); break;
     141                LOOP_ADD(uint16_t, be, UINT16_MIN, UINT16_MAX); break;
    121142        case PCM_SAMPLE_SINT16_BE:
    122                 LOOP_ADD(int16_t, be, INT16_MAX); break;
     143                LOOP_ADD(int16_t, be, INT16_MIN, INT16_MAX); break;
    123144        case PCM_SAMPLE_UINT24_32_LE:
    124         case PCM_SAMPLE_UINT32_LE:
    125                 LOOP_ADD(uint32_t, le, UINT32_MAX); break;
     145        case PCM_SAMPLE_UINT32_LE: // TODO this are not right for 24bit
     146                LOOP_ADD(uint32_t, le, UINT32_MIN, UINT32_MAX); break;
    126147        case PCM_SAMPLE_SINT24_32_LE:
    127148        case PCM_SAMPLE_SINT32_LE:
    128                 LOOP_ADD(int32_t, le, INT32_MAX); break;
     149                LOOP_ADD(int32_t, le, INT32_MIN, INT32_MAX); break;
    129150        case PCM_SAMPLE_UINT24_32_BE:
    130151        case PCM_SAMPLE_UINT32_BE:
    131                 LOOP_ADD(uint32_t, be, UINT32_MAX); break;
     152                LOOP_ADD(uint32_t, be, UINT32_MIN, UINT32_MAX); break;
    132153        case PCM_SAMPLE_SINT24_32_BE:
    133154        case PCM_SAMPLE_SINT32_BE:
    134                 LOOP_ADD(int32_t, be, INT32_MAX); break;
     155                LOOP_ADD(int32_t, be, INT32_MIN, INT32_MAX); break;
    135156        case PCM_SAMPLE_UINT24_LE:
    136157        case PCM_SAMPLE_SINT24_LE:
     
    142163        }
    143164        return EOK;
     165#undef LOOP_ADD
    144166}
    145167
     168/** Converts all sample formats to float <-1,1> */
     169static float get_normalized_sample(const void *buffer, size_t size,
     170    unsigned frame, unsigned channel, const audio_format_t *f)
     171{
     172        assert(f);
     173        if (channel >= f->channels)
     174                return 0.0f;
     175#define GET(type, endian, low, high) \
     176do { \
     177        const type *src = buffer; \
     178        const size_t sample_count = size / sizeof(type); \
     179        const size_t sample_pos = frame * f->channels + channel; \
     180        if (sample_pos >= sample_count) {\
     181                return 0.0f; \
     182        } \
     183        float sample = from(src[sample_pos], type, endian); \
     184        /* This makes it positive */ \
     185        sample -= (float)(type)low; \
     186        if (sample < 0.0f) { \
     187                printf("SUB MIN failed\n"); \
     188        } \
     189        /* This makes it <0,2> */ \
     190        sample /= (((float)(type)high - (float)(type)low) / 2.0f); \
     191        if (sample > 2.0) { \
     192                printf("DIV RANGE failed\n"); \
     193        } \
     194        return sample - 1.0f; \
     195} while (0)
     196
     197        switch (f->sample_format) {
     198        case PCM_SAMPLE_UINT8:
     199                GET(uint8_t, le, UINT8_MIN, UINT8_MAX);
     200        case PCM_SAMPLE_SINT8:
     201                GET(int8_t, le, INT8_MIN, INT8_MAX);
     202        case PCM_SAMPLE_UINT16_LE:
     203                GET(uint16_t, le, UINT16_MIN, UINT16_MAX);
     204        case PCM_SAMPLE_SINT16_LE:
     205                GET(int16_t, le, INT16_MIN, INT16_MAX);
     206        case PCM_SAMPLE_UINT16_BE:
     207                GET(uint16_t, be, UINT16_MIN, UINT16_MAX);
     208        case PCM_SAMPLE_SINT16_BE:
     209                GET(int16_t, be, INT16_MIN, INT16_MAX);
     210        case PCM_SAMPLE_UINT24_32_LE:
     211        case PCM_SAMPLE_UINT32_LE:
     212                GET(uint32_t, le, UINT32_MIN, UINT32_MAX);
     213        case PCM_SAMPLE_SINT24_32_LE:
     214        case PCM_SAMPLE_SINT32_LE:
     215                GET(int32_t, le, INT32_MIN, INT32_MAX);
     216        case PCM_SAMPLE_UINT24_32_BE:
     217        case PCM_SAMPLE_UINT32_BE:
     218                GET(uint32_t, be, UINT32_MIN, UINT32_MAX);
     219        case PCM_SAMPLE_SINT24_32_BE:
     220        case PCM_SAMPLE_SINT32_BE:
     221                GET(int32_t, le, INT32_MIN, INT32_MAX);
     222        case PCM_SAMPLE_UINT24_LE:
     223        case PCM_SAMPLE_SINT24_LE:
     224        case PCM_SAMPLE_UINT24_BE:
     225        case PCM_SAMPLE_SINT24_BE:
     226        case PCM_SAMPLE_FLOAT32:
     227        default: ;
     228        }
     229        return 0;
     230#undef GET
     231}
    146232/**
    147233 * @}
  • uspace/srv/audio/hound/audio_source.c

    r50fa3f7 rbb67def  
    116116                return EINVAL;
    117117        }
    118         if (!audio_format_same(&source->format, f)) {
    119                 log_debug("Format conversion is not supported yet");
     118        if (source->format.sampling_rate != f->sampling_rate) {
     119                log_debug("Resampling is not supported, yet");
    120120                return ENOTSUP;
    121121        }
Note: See TracChangeset for help on using the changeset viewer.