/*
 * Copyright (c) 2001-2003 Shiman Associates Inc. All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <stdlib.h>
#include "mas_audio_basic.h"

struct mas_data_characteristic*
masc_make_audio_basic_dc( uint8 format, uint32 srate, uint8 resolution, uint8 channels, uint8 endian )
{
    struct mas_data_characteristic* dc;
    char   tstr[256];

    dc = MAS_NEW( dc );
    if ( dc == NULL )
        return NULL;
    
    if ( masc_setup_dc( dc, 5 ) < 0 )
        return NULL;

    switch ( format )
    {
    case MAS_LINEAR_FMT:
        masc_append_dc_key_value( dc, "format", "linear" );
        break;
    case MAS_ULINEAR_FMT:
        masc_append_dc_key_value( dc, "format", "ulinear" );
        break;
    case MAS_ULAW_FMT:
        masc_append_dc_key_value( dc, "format", "ulaw" );
        break;
    case MAS_ALAW_FMT:
        masc_append_dc_key_value( dc, "format", "alaw" );
        break;
    default:
        masc_strike_dc( dc );
        masc_rtfree( dc );
        return NULL;
    }

    sprintf( tstr, "%d", srate );
    masc_append_dc_key_value( dc, "sampling rate", tstr );

    sprintf( tstr, "%d", resolution );
    masc_append_dc_key_value( dc, "resolution", tstr );

    sprintf( tstr, "%d", channels );
    masc_append_dc_key_value( dc, "channels", tstr );

    switch ( endian )
    {
    case MAS_LITTLE_ENDIAN_FMT:
        masc_append_dc_key_value( dc, "endian", "little" );
        break;
    case MAS_BIG_ENDIAN_FMT:
        masc_append_dc_key_value( dc, "endian", "big" );
        break;
    case MAS_HOST_ENDIAN_FMT:
        masc_append_dc_key_value( dc, "endian", "host" );
        break;
    default:
        masc_append_dc_key_value( dc, "endian", "host" );
        break;
    }

    return dc;
}

int32
masc_scan_audio_basic_dc( struct mas_data_characteristic* dc, uint8* format, uint32* srate, uint8* resolution, uint8* channels, uint8* endian )
{
    int i, j, n;
    char* formats[] = { "linear", "ulinear", "ulaw", "alaw", "" };
    char* endiantypes[] =  { "none", "host", "little", "big", "" };

    /*** format */
    i = masc_get_index_of_key(dc, "format");
    if ( i < 0 ) return mas_error(MERR_INVALID);

    /* count the defined formats */
    n = 0;
    while ( *formats[n] != 0 ) n++; 
    j = masc_get_string_index(dc->values[i], formats, n);
    if ( j < 0 ) return j;
    *format = (uint8)j;

    /*** sampling rate */
    i = masc_get_index_of_key(dc, "sampling rate");
    if ( i < 0 ) return mas_error(MERR_INVALID);
    *srate = atoi(dc->values[i]);
    
    /*** resolution */
    i = masc_get_index_of_key(dc, "resolution");
    if ( i < 0 ) return mas_error(MERR_INVALID);
    *resolution = atoi(dc->values[i]);
    
    /*** channels */
    i = masc_get_index_of_key(dc, "channels");
    if ( i < 0 ) return mas_error(MERR_INVALID);
    *channels = atoi(dc->values[i]);
    
    /*** endian */
    i = masc_get_index_of_key(dc, "endian");
    if ( i < 0 ) return mas_error(MERR_INVALID);

    /* count the defined endian types */
    n = 0;
    while ( *endiantypes[n] != 0 ) n++;
    j = masc_get_string_index(dc->values[i], endiantypes, n);
    if ( j < 0 ) return j;
    *endian = (uint8)j;

    return 0; /* no error */
}

int32
masc_get_audio_basic_bpstc( uint8 resolution, uint8 channels )
{
    switch (resolution)
    {
    case 8: return channels;
    case 16: return channels << 1;
    case 20: return channels << 2;
    case 24: return channels << 2;
    case 32: return channels << 2;
    default: return mas_error(MERR_INVALID);
    }
}
