Exemple #1
0
static int calculate_header_and_footer(scarletbook_output_format_t *ft)
{
    form_dsd_chunk_t *form_dsd_chunk;
    property_chunk_t *property_chunk;
    uint8_t          *write_ptr, *prop_ptr;
    scarletbook_handle_t *sb_handle = ft->sb_handle;
    dsdiff_handle_t  *handle = (dsdiff_handle_t *) ft->priv;

    if (!handle->header)
        handle->header = (uint8_t *) calloc(DSDFIFF_BUFFER_SIZE, 1);
    if (!handle->footer)
        handle->footer = (uint8_t *) calloc(DSDFIFF_BUFFER_SIZE, 1);

    write_ptr = handle->header;

    // The Form DSD Chunk is required. It may appear only once in the file.
    form_dsd_chunk            = (form_dsd_chunk_t *) handle->header;
    form_dsd_chunk->chunk_id  = FRM8_MARKER;
    form_dsd_chunk->form_type = DSD_MARKER;
    write_ptr                 = (uint8_t *) handle->header + FORM_DSD_CHUNK_SIZE;

    // The Format Version Chunk is required and must be the first chunk in the Form DSD
    // Chunk. It may appear only once in the Form DSD Chunk.
    {
        format_version_chunk_t *format_version_chunk = (format_version_chunk_t *) write_ptr;
        format_version_chunk->chunk_id        = FVER_MARKER;
        format_version_chunk->chunk_data_size = CALC_CHUNK_SIZE(FORMAT_VERSION_CHUNK_SIZE - CHUNK_HEADER_SIZE);
        format_version_chunk->version         = hton32(DSDIFF_VERSION);
        write_ptr                            += FORMAT_VERSION_CHUNK_SIZE;
    }

    // The Property Chunk is required and must precede the Sound Data Chunk. It may appear
    // only once in the Form DSD Chunk.
    {
        prop_ptr                      = write_ptr;
        property_chunk                = (property_chunk_t *) write_ptr;
        property_chunk->chunk_id      = PROP_MARKER;
        property_chunk->property_type = SND_MARKER;
        write_ptr                    += PROPERTY_CHUNK_SIZE;
    }

    // The Sample Rate Chunk is required and may appear only once in the Property Chunk.
    {
        sample_rate_chunk_t *sample_rate_chunk = (sample_rate_chunk_t *) write_ptr;
        sample_rate_chunk->chunk_id        = FS_MARKER;
        sample_rate_chunk->chunk_data_size = CALC_CHUNK_SIZE(SAMPLE_RATE_CHUNK_SIZE - CHUNK_HEADER_SIZE);
        sample_rate_chunk->sample_rate     = hton32(SACD_SAMPLING_FREQUENCY);
        write_ptr                         += SAMPLE_RATE_CHUNK_SIZE;
    }

    // The Channels Chunk is required and may appear only once in the Property Chunk.
    {
        int              i;
        uint8_t          channel_count    = sb_handle->area[ft->area].area_toc->channel_count;
        channels_chunk_t * channels_chunk = (channels_chunk_t *) write_ptr;
        channels_chunk->chunk_id        = CHNL_MARKER;
        channels_chunk->chunk_data_size = CALC_CHUNK_SIZE(CHANNELS_CHUNK_SIZE - CHUNK_HEADER_SIZE + channel_count * sizeof(uint32_t));
        channels_chunk->channel_count   = hton16(channel_count);

        switch (channel_count)
        {
        case 2:
            channels_chunk->channel_ids[0] = SLFT_MARKER;
            channels_chunk->channel_ids[1] = SRGT_MARKER;
            break;
        case 5:
            channels_chunk->channel_ids[0] = MLFT_MARKER;
            channels_chunk->channel_ids[1] = MRGT_MARKER;
            channels_chunk->channel_ids[2] = C_MARKER;
            channels_chunk->channel_ids[3] = LS_MARKER;
            channels_chunk->channel_ids[4] = RS_MARKER;
            break;
        case 6:
            channels_chunk->channel_ids[0] = MLFT_MARKER;
            channels_chunk->channel_ids[1] = MRGT_MARKER;
            channels_chunk->channel_ids[2] = C_MARKER;
            channels_chunk->channel_ids[3] = LFE_MARKER;
            channels_chunk->channel_ids[4] = LS_MARKER;
            channels_chunk->channel_ids[5] = RS_MARKER;
            break;
        default:
            for (i = 0; i < channel_count; i++)
            {
                sprintf((char *) &channels_chunk->channel_ids[i], "C%03i", i);
            }
            break;
        }

        write_ptr += CHANNELS_CHUNK_SIZE + sizeof(uint32_t) * channel_count;
    }

    // The Compression Type Chunk is required and may appear only once in the Property
    // Chunk.
    {
        compression_type_chunk_t *compression_type_chunk = (compression_type_chunk_t *) write_ptr;
        compression_type_chunk->chunk_id         = CMPR_MARKER;
        if (ft->dsd_encoded_export)
        {
            compression_type_chunk->compression_type = DSD_MARKER;
            compression_type_chunk->count = 14;
            memcpy(compression_type_chunk->compression_name, "not compressed", 14);
        }
        else
        {
            compression_type_chunk->compression_type = DST_MARKER;
            compression_type_chunk->count = 11;
            memcpy(compression_type_chunk->compression_name, "DST Encoded", 11);
        }

        compression_type_chunk->chunk_data_size = CALC_CHUNK_SIZE(COMPRESSION_TYPE_CHUNK_SIZE - CHUNK_HEADER_SIZE + compression_type_chunk->count);
        write_ptr += CEIL_ODD_NUMBER(COMPRESSION_TYPE_CHUNK_SIZE + compression_type_chunk->count);
    }

    // The Loudspeaker Configuration Chunk is optional but if used it may appear only once in
    // the Property Chunk.
    {
        uint8_t channel_count = sb_handle->area[ft->area].area_toc->channel_count;
        loudspeaker_config_chunk_t *loudspeaker_config_chunk = (loudspeaker_config_chunk_t *) write_ptr;
        loudspeaker_config_chunk->chunk_id        = LSCO_MARKER;
        loudspeaker_config_chunk->chunk_data_size = CALC_CHUNK_SIZE(LOADSPEAKER_CONFIG_CHUNK_SIZE - CHUNK_HEADER_SIZE);

        switch (channel_count)
        {
        case 2:
            loudspeaker_config_chunk->loudspeaker_config = hton16(LS_CONFIG_2_CHNL);
            break;
        case 5:
            loudspeaker_config_chunk->loudspeaker_config = hton16(LS_CONFIG_5_CHNL);
            break;
        case 6:
            loudspeaker_config_chunk->loudspeaker_config = hton16(LS_CONFIG_6_CHNL);
            break;
        default:
            loudspeaker_config_chunk->loudspeaker_config = hton16(LS_CONFIG_UNDEFINED);
            break;
        }

        write_ptr += LOADSPEAKER_CONFIG_CHUNK_SIZE;
    }

    // all properties have been written, now set the property chunk size
    property_chunk->chunk_data_size = CALC_CHUNK_SIZE(write_ptr - prop_ptr - CHUNK_HEADER_SIZE);

    // Either the DSD or DST Sound Data chunk is required and may appear
    // only once in the Form DSD Chunk. The chunk must be placed after the Property Chunk.
    if (ft->dsd_encoded_export)
    {
        dsd_sound_data_chunk_t * dsd_sound_data_chunk;
        dsd_sound_data_chunk                  = (dsd_sound_data_chunk_t *) write_ptr;
        dsd_sound_data_chunk->chunk_id        = DSD_MARKER;
        dsd_sound_data_chunk->chunk_data_size = CALC_CHUNK_SIZE(handle->audio_data_size);

        write_ptr += CHUNK_HEADER_SIZE;
    }
    else
    {
        dst_sound_data_chunk_t *dst_sound_data_chunk;
        dst_frame_information_chunk_t *dst_frame_information_chunk;

        dst_sound_data_chunk                  = (dst_sound_data_chunk_t *) write_ptr;
        dst_sound_data_chunk->chunk_id        = DST_MARKER;

        write_ptr += DST_SOUND_DATA_CHUNK_SIZE;

        dst_frame_information_chunk           = (dst_frame_information_chunk_t *) write_ptr;
        dst_frame_information_chunk->chunk_id = FRTE_MARKER;
        dst_frame_information_chunk->frame_rate = hton16(SACD_FRAME_RATE);
        dst_frame_information_chunk->num_frames = hton32(handle->frame_count);
        dst_frame_information_chunk->chunk_data_size = CALC_CHUNK_SIZE(DST_FRAME_INFORMATION_CHUNK_SIZE - CHUNK_HEADER_SIZE);

        dst_sound_data_chunk->chunk_data_size = CALC_CHUNK_SIZE(handle->audio_data_size + DST_FRAME_INFORMATION_CHUNK_SIZE);
        write_ptr += DST_FRAME_INFORMATION_CHUNK_SIZE;
    }

    // start with a new footer
    handle->footer_size = 0;

    // DST Sound Index Chunk
    if (!ft->dsd_encoded_export && handle->frame_count > 0)
    {
        size_t frame;
        dst_sound_index_chunk_t *dst_sound_index_chunk;
        uint8_t *dsti_ptr;

        // resize the footer buffer
        handle->footer = realloc(handle->footer, DSDFIFF_BUFFER_SIZE + handle->frame_indexes_allocated * DST_FRAME_INDEX_SIZE);

        dsti_ptr = handle->footer + handle->footer_size;

        dst_sound_index_chunk                 = (dst_sound_index_chunk_t *) dsti_ptr;
        dst_sound_index_chunk->chunk_id       = DSTI_MARKER;

        dsti_ptr += DST_SOUND_INDEX_CHUNK_SIZE;

        for (frame = 0; frame < handle->frame_count; frame++)
        {
            dst_frame_index_t *dst_frame_index = (dst_frame_index_t *) dsti_ptr;
            dst_frame_index->length = hton32(handle->frame_indexes[frame].length);
            dst_frame_index->offset = hton64(handle->frame_indexes[frame].offset);
            dsti_ptr += DST_FRAME_INDEX_SIZE;
        }

        dst_sound_index_chunk->chunk_data_size = CALC_CHUNK_SIZE(handle->frame_count * DST_FRAME_INDEX_SIZE + DST_SOUND_INDEX_CHUNK_SIZE - CHUNK_HEADER_SIZE);
        handle->footer_size += CEIL_ODD_NUMBER(dsti_ptr - handle->footer - handle->footer_size);
    }

    // edit master information
    {
        uint8_t * em_ptr  = handle->footer + handle->footer_size;
        edited_master_information_chunk_t *edited_master_information_chunk = (edited_master_information_chunk_t *) em_ptr;
        edited_master_information_chunk->chunk_id = DIIN_MARKER;
        em_ptr += EDITED_MASTER_INFORMATION_CHUNK_SIZE;

        if (handle->edit_master)
        {
            int track;
            uint64_t abs_frames_start = 0, abs_frames_stop = 0;

            {
                // id is optional, but SADiE seems to require it
                edited_master_id_chunk_t *emid_chunk = (edited_master_id_chunk_t *) em_ptr;
                emid_chunk->chunk_id = EMID_MARKER;
                emid_chunk->chunk_data_size = CALC_CHUNK_SIZE(EDITED_MASTER_ID_CHUNK_SIZE - CHUNK_HEADER_SIZE);
                //strcpy(emid_chunk->emid, guid()); // TODO?, add guid functionality
                em_ptr += EDITED_MASTER_ID_CHUNK_SIZE;
            }

            for (track = 0; track < sb_handle->area[ft->area].area_toc->track_count; track++)
            {
                area_tracklist_time_t *time;
                uint16_t track_flags_stop, track_flags_start;

                time = &sb_handle->area[ft->area].area_tracklist_time->start[track];
                abs_frames_start = TIME_FRAMECOUNT(time);
                track_flags_start = time->track_flags_tmf4 << 0 
                    | time->track_flags_tmf1 << 1
                    | time->track_flags_tmf2 << 2
                    | time->track_flags_tmf3 << 3;

                time = &sb_handle->area[ft->area].area_tracklist_time->duration[track];
                abs_frames_stop = abs_frames_start + TIME_FRAMECOUNT(time);
                track_flags_stop = time->track_flags_tmf4 << 0 
                    | time->track_flags_tmf1 << 1
                    | time->track_flags_tmf2 << 2
                    | time->track_flags_tmf3 << 3;

                if (track == 0)
                {
                    // setting the programstart to 0 always seems incorrect, but produces correct results for SADiE
                    em_ptr = add_marker_chunk(em_ptr, ft, 0, MARK_MARKER_TYPE_PROGRAMSTART, track_flags_start);
                }

                em_ptr = add_marker_chunk(em_ptr, ft, abs_frames_start, MARK_MARKER_TYPE_TRACKSTART, track_flags_start);

                if (track == sb_handle->area[ft->area].area_toc->track_count - 1 
                 || (uint64_t) TIME_FRAMECOUNT(&sb_handle->area[ft->area].area_tracklist_time->start[track + 1]) > abs_frames_stop)
                {
                    em_ptr = add_marker_chunk(em_ptr, ft, abs_frames_stop, MARK_MARKER_TYPE_TRACKSTOP, track_flags_stop);
                }
            }
        }
        // Audiogate supports, Title and Artist information through an EM Chunk
        else
        {
            marker_chunk_t *marker_chunk = (marker_chunk_t *) em_ptr;
            area_tracklist_time_t *area_tracklist_time_duration = &sb_handle->area[ft->area].area_tracklist_time->duration[ft->track];
            marker_chunk->chunk_id = MARK_MARKER;
            marker_chunk->chunk_data_size = CALC_CHUNK_SIZE(EDITED_MASTER_MARKER_CHUNK_SIZE - CHUNK_HEADER_SIZE);
            marker_chunk->hours = hton16(area_tracklist_time_duration->minutes / 60);
            marker_chunk->minutes = area_tracklist_time_duration->minutes % 60;
            marker_chunk->seconds = area_tracklist_time_duration->seconds;
            marker_chunk->samples = hton32(area_tracklist_time_duration->frames * SAMPLES_PER_FRAME * 64);
            marker_chunk->offset = 0;
            marker_chunk->mark_type = hton16(MARK_MARKER_TYPE_INDEX_ENTRY);
            marker_chunk->mark_channel = hton16(COMT_TYPE_CHANNEL_ALL);
            marker_chunk->track_flags = 0;
            marker_chunk->count = 0;
            em_ptr += EDITED_MASTER_MARKER_CHUNK_SIZE;
        }

        {
            artist_chunk_t *artist_chunk = (artist_chunk_t *) em_ptr;
            char *c = 0;

            if (!handle->edit_master)
                c = sb_handle->area[ft->area].area_track_text[ft->track].track_type_performer;

            if (!c)
            {
                master_text_t *master_text = &sb_handle->master_text;

                if (master_text->album_artist)
                    c = master_text->album_artist;
                else if (master_text->album_artist_phonetic)
                    c = master_text->album_artist_phonetic;
                else if (master_text->disc_artist)
                    c = master_text->disc_artist;
                else if (master_text->disc_artist_phonetic)
                    c = master_text->disc_artist_phonetic;
                else if (master_text->album_title)
                    c = master_text->album_title; 
                else if (master_text->album_title_phonetic)
                    c = master_text->album_title_phonetic;
                else if (master_text->disc_title)
                    c = master_text->disc_title; 
                else if (master_text->disc_title_phonetic)
                    c = master_text->disc_title_phonetic;
            }

            if (c)
            {
                char *track_artist;
                int len;

                track_artist = charset_convert(c, strlen(c), "UTF-8", "ISO-8859-1");

                len = strlen(track_artist);
                artist_chunk->chunk_id = DIAR_MARKER;
                artist_chunk->chunk_data_size = CALC_CHUNK_SIZE(EDITED_MASTER_ARTIST_CHUNK_SIZE + len - CHUNK_HEADER_SIZE);
                artist_chunk->count = hton32(len);
                em_ptr += EDITED_MASTER_ARTIST_CHUNK_SIZE;
                memcpy(em_ptr, track_artist, len);
                em_ptr += CEIL_ODD_NUMBER(len);
                free(track_artist);
            }
        }

        {
            title_chunk_t   *title_chunk = (title_chunk_t *) em_ptr;
            char *c = 0;

            if (!handle->edit_master)
                c = sb_handle->area[ft->area].area_track_text[ft->track].track_type_title;

            if (!c)
            {
                master_text_t *master_text = &sb_handle->master_text;

                if (master_text->album_title)
                    c = master_text->album_title; 
                else if (master_text->album_title_phonetic)
                    c = master_text->album_title_phonetic;
                else if (master_text->disc_title)
                    c = master_text->disc_title; 
                else if (master_text->disc_title_phonetic)
                    c = master_text->disc_title_phonetic;
            }

            if (c)
            {
                int len;
                char *track_title;

                track_title = charset_convert(c, strlen(c), "UTF-8", "ISO-8859-1");
                len = strlen(track_title);

                title_chunk->chunk_id = DITI_MARKER;
                title_chunk->chunk_data_size = CALC_CHUNK_SIZE(EDITED_MASTER_TITLE_CHUNK_SIZE + len - CHUNK_HEADER_SIZE);
                title_chunk->count = hton32(len);
                em_ptr += EDITED_MASTER_TITLE_CHUNK_SIZE;
                memcpy(em_ptr, track_title, len);
                em_ptr += CEIL_ODD_NUMBER(len);
                free(track_title);
            }
        }

        edited_master_information_chunk->chunk_data_size = CALC_CHUNK_SIZE(em_ptr - handle->footer - handle->footer_size - CHUNK_HEADER_SIZE);
        handle->footer_size += CEIL_ODD_NUMBER(em_ptr - handle->footer - handle->footer_size);
    }

    // Now we write the COMT comment chunk to the footer buffer
    {
        time_t           rawtime;
        struct tm        * timeinfo;
        comment_t        * comment;
        char             data[512];
        char            *title;
        uint8_t          * comment_ptr  = handle->footer + handle->footer_size;
        comments_chunk_t *comment_chunk = (comments_chunk_t *) comment_ptr;
        comment_chunk->chunk_id    = COMT_MARKER;
        comment_chunk->numcomments = hton16(2);

        comment_ptr += COMMENTS_CHUNK_SIZE;

        time(&rawtime);
        timeinfo = localtime(&rawtime);

        comment                    = (comment_t *) comment_ptr;
        comment->timestamp_year    = hton16(sb_handle->master_toc->disc_date_year);
        comment->timestamp_month   = sb_handle->master_toc->disc_date_month;
        comment->timestamp_day     = sb_handle->master_toc->disc_date_day;
        comment->timestamp_hour    = 0;
        comment->timestamp_minutes = 0;
        comment->comment_type      = hton16(COMT_TYPE_FILE_HISTORY);
        comment->comment_reference = hton16(COMT_TYPE_CHANNEL_FILE_HISTORY_GENERAL);
        title = (char *) get_mtoc_title_text(sb_handle);
        title = charset_convert(title, strlen(title), "UTF-8", "ISO-8859-1");
        sprintf(data, "Material ripped from SACD: %s", title);
        free(title);
        comment->count = hton32(strlen(data));
        memcpy(comment->comment_text, data, strlen(data));

        comment_ptr += CEIL_ODD_NUMBER(COMMENT_SIZE + strlen(data));

        comment                    = (comment_t *) comment_ptr;
        comment->timestamp_year    = hton16(timeinfo->tm_year + 1900);
        comment->timestamp_month   = timeinfo->tm_mon;
        comment->timestamp_day     = timeinfo->tm_mday;
        comment->timestamp_hour    = timeinfo->tm_hour;
        comment->timestamp_minutes = timeinfo->tm_min;
        comment->comment_type      = hton16(COMT_TYPE_FILE_HISTORY);
        comment->comment_reference = hton16(COMT_TYPE_CHANNEL_FILE_HISTORY_CREATING_MACHINE);
        sprintf(data, SACD_RIPPER_VERSION_INFO);
        comment->count = hton32(strlen(data));
        memcpy(comment->comment_text, data, strlen(data));

        comment_ptr += CEIL_ODD_NUMBER(COMMENT_SIZE + strlen(data));

        comment_chunk->chunk_data_size = CALC_CHUNK_SIZE(comment_ptr - handle->footer - handle->footer_size - CHUNK_HEADER_SIZE);
        handle->footer_size           += CEIL_ODD_NUMBER(comment_ptr - handle->footer - handle->footer_size);
    }

    // we add a custom (unsupported) ID3 chunk to maintain all track information
    // within one file
    if (handle->edit_master)
    {
        int track;

        for (track = 0; track < sb_handle->area[ft->area].area_toc->track_count; track++)
        {
            chunk_header_t *id3_chunk;
            int            id3_chunk_size;
            uint8_t          * id3_ptr  = handle->footer + handle->footer_size;
            id3_chunk                  = (chunk_header_t *) id3_ptr;
            id3_chunk->chunk_id        = MAKE_MARKER('I', 'D', '3', ' ');
            id3_chunk_size             = scarletbook_id3_tag_render(sb_handle, id3_ptr + CHUNK_HEADER_SIZE, ft->area, track);
            id3_chunk->chunk_data_size = CALC_CHUNK_SIZE(id3_chunk_size);

            id3_ptr += CEIL_ODD_NUMBER(CHUNK_HEADER_SIZE + id3_chunk_size);

            handle->footer_size += CEIL_ODD_NUMBER(id3_ptr - handle->footer - handle->footer_size);
        }
    }
    else
    {
        chunk_header_t *id3_chunk;
        int            id3_chunk_size;
        uint8_t          * id3_ptr  = handle->footer + handle->footer_size;
        id3_chunk                  = (chunk_header_t *) id3_ptr;
        id3_chunk->chunk_id        = MAKE_MARKER('I', 'D', '3', ' ');
        id3_chunk_size             = scarletbook_id3_tag_render(sb_handle, id3_ptr + CHUNK_HEADER_SIZE, ft->area, ft->track);
        id3_chunk->chunk_data_size = CALC_CHUNK_SIZE(id3_chunk_size);

        id3_ptr += CEIL_ODD_NUMBER(CHUNK_HEADER_SIZE + id3_chunk_size);

        handle->footer_size += CEIL_ODD_NUMBER(id3_ptr - handle->footer - handle->footer_size);
    }

    handle->header_size = CEIL_ODD_NUMBER(write_ptr - handle->header);
    form_dsd_chunk->chunk_data_size = CALC_CHUNK_SIZE(handle->header_size + handle->footer_size + handle->audio_data_size - CHUNK_HEADER_SIZE);

    return 0;
}
static void	GetConfig(ALAC_ENCODER *p, ALACSpecificConfig * config );

static int32_t	EncodeStereo(ALAC_ENCODER *p, struct BitBuffer * bitstream, int32_t * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
static int32_t	EncodeStereoFast(ALAC_ENCODER *p, struct BitBuffer * bitstream, int32_t * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
static int32_t	EncodeStereoEscape(ALAC_ENCODER *p, struct BitBuffer * bitstream, int32_t * input, uint32_t stride, uint32_t numSamples );
static int32_t	EncodeMono(ALAC_ENCODER *p, struct BitBuffer * bitstream, int32_t * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );



// Note: in C you can't typecast to a 2-dimensional array pointer but that's what we need when
// picking which coefs to use so we declare this typedef b/c we *can* typecast to this type
typedef int16_t (*SearchCoefs)[kALACMaxCoefs];

// defines/constants
const uint32_t kALACEncoderMagic	= MAKE_MARKER ('d', 'p', 'g', 'e');
const uint32_t kMaxSampleSize		= 32;			// max allowed bit width is 32
const uint32_t kDefaultMixBits		= 2;
const uint32_t kDefaultMixRes		= 0;
const uint32_t kMaxRes				= 4;
const uint32_t kDefaultNumUV		= 8;
const uint32_t kMinUV				= 4;
const uint32_t kMaxUV				= 8;

// static functions
#if VERBOSE_DEBUG
static void AddFiller( BitBuffer * bits, int32_t numBytes );
#endif


/*
//#ifdef WIN32
//#include "stdafx.h"
#include <string.h>
//#endif
#include <stdlib.h>
#include "Wav.h"

//BE:#define	MAKE_MARKER(a, b, c, d)    (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
#define	MAKE_MARKER(a, b, c, d)    ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))

static const uint32 MARKER_FMT  = MAKE_MARKER ('f', 'm', 't', ' ');
static const uint32 MARKER_DATA = MAKE_MARKER ('d', 'a', 't', 'a');



WavReader::WavReader()
	: _fd(NULL)
	, _rawDataLen(0)
	, _rawDataPos(0)
{
	memset(&_format, 0, WAVE_FORMAT_SIZE);
}

WavReader::~WavReader()
{
	close();
}


Result WavReader::open(const char *path)
{
Exemple #4
0
static void
wav_subchunk_test (size_t chunk_size)
{	SNDFILE 		* file ;
	SF_INFO			sfinfo ;
	SF_CHUNK_INFO	chunk_info ;
	char filename [256] ;
	char chunk_data [10240] ;
	short audio [16] ;
	int	err, value ;

	snprintf (filename, sizeof (filename), "subchunk_%04d.wav", (int) chunk_size) ;
	print_test_name (__func__, filename) ;

	exit_if_true (sizeof (chunk_data) < chunk_size, "\n\nLine %d : sizeof (data) < chunk_size\n\n", __LINE__) ;

	memset (chunk_data, 53, sizeof (chunk_data)) ;
	chunk_data [chunk_size] = 0 ;

	/* Fill in the chunk data. */
	value = MAKE_MARKER ('a', 'd', 't', 'l') ;
	memcpy (chunk_data, &value, sizeof (value)) ;
	value = MAKE_MARKER ('n', 'o', 't', 'e') ;
	memcpy (chunk_data + 4, &value, sizeof (value)) ;
	value = H2LE_32 (chunk_size - 12) ;
	memcpy (chunk_data + 8, &value, sizeof (value)) ;

	sfinfo.samplerate	= 44100 ;
	sfinfo.channels		= 1 ;
	sfinfo.frames		= 0 ;
	sfinfo.format		= SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;

	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;

	/* Set up the chunk to write. */
	memset (&chunk_info, 0, sizeof (chunk_info)) ;
	snprintf (chunk_info.id, sizeof (chunk_info.id), "LIST") ;
	chunk_info.id_size = 4 ;
	chunk_info.data = chunk_data ;
	chunk_info.datalen = chunk_size ;

	err = sf_set_chunk (file, &chunk_info) ;
	exit_if_true (
		err != SF_ERR_NO_ERROR,
		"\n\nLine %d : sf_set_chunk returned for testdata : %s\n\n", __LINE__, sf_error_number (err)
		) ;

	memset (chunk_info.data, 0, chunk_info.datalen) ;

	/* Add some audio data. */
	memset (audio, 0, sizeof (audio)) ;
	sf_write_short (file, audio, ARRAY_LEN (audio)) ;

	sf_close (file) ;

	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;

	exit_if_true (
		sfinfo.frames != ARRAY_LEN (audio),
		"\n\nLine %d : Incorrect sample count (%d should be %d)\n", __LINE__, (int) sfinfo.frames, (int) ARRAY_LEN (audio)
		) ;

	if (chunk_size < 512)
		check_log_buffer_or_die (file, __LINE__) ;

	sf_close (file) ;

	unlink (filename) ;
	puts ("ok") ;
} /* wav_subchunk_test */