예제 #1
0
파일: au.c 프로젝트: Ancurio/SDL_sound
static int AU_open(Sound_Sample *sample, const char *ext)
{
    Sound_SampleInternal *internal = sample->opaque;
    SDL_RWops *rw = internal->rw;
    int skip, hsize, i, bytes_per_second;
    struct au_file_hdr hdr;
    struct audec *dec;
    char c;

    /* read_au_header() will do byte order swapping. */
    BAIL_IF_MACRO(!read_au_header(rw, &hdr), "AU: bad header", 0);

    dec = malloc(sizeof *dec);
    BAIL_IF_MACRO(dec == NULL, ERR_OUT_OF_MEMORY, 0);
    internal->decoder_private = dec;

    if (hdr.magic == AU_MAGIC)
    {
        /* valid magic */
        dec->encoding = hdr.encoding;
        switch(dec->encoding)
        {
            case AU_ENC_ULAW_8:
                /* Convert 8-bit µ-law to 16-bit linear on the fly. This is
                   slightly wasteful if the audio driver must convert them
                   back, but µ-law only devices are rare (mostly _old_ Suns) */
                sample->actual.format = AUDIO_S16SYS;
                break;

            case AU_ENC_LINEAR_8:
                sample->actual.format = AUDIO_S8;
                break;

            case AU_ENC_LINEAR_16:
                sample->actual.format = AUDIO_S16MSB;
                break;

            default:
                free(dec);
                BAIL_MACRO("AU: Unsupported .au encoding", 0);
        } /* switch */

        sample->actual.rate = hdr.sample_rate;
        sample->actual.channels = hdr.channels;
        dec->remaining = hdr.data_size;
        hsize = hdr.hdr_size;

        /* skip remaining part of header (input may be unseekable) */
        for (i = HDR_SIZE; i < hsize; i++)
        {
            if (SDL_RWread(rw, &c, 1, 1) != 1)
            {
                free(dec);
                BAIL_MACRO(ERR_IO_ERROR, 0);
            } /* if */
        } /* for */
    } /* if */

    else if (__Sound_strcasecmp(ext, "au") == 0)
    {
        /*
         * A number of files in the wild have the .au extension but no valid
         * header; these are traditionally assumed to be 8kHz µ-law. Handle
         * them here only if the extension is recognized.
         */

        SNDDBG(("AU: Invalid header, assuming raw 8kHz µ-law.\n"));
        /* if seeking fails, we lose 24 samples. big deal */
        SDL_RWseek(rw, -HDR_SIZE, SEEK_CUR);
        dec->encoding = AU_ENC_ULAW_8;
        dec->remaining = (Uint32)-1; 		/* no limit */
        sample->actual.format = AUDIO_S16SYS;
        sample->actual.rate = 8000;
        sample->actual.channels = 1;
    } /* else if */

    else
    {
        free(dec);
        BAIL_MACRO("AU: Not an .AU stream.", 0);
    } /* else */    

    bytes_per_second = ( ( dec->encoding == AU_ENC_LINEAR_16 ) ? 2 : 1 )
        * sample->actual.rate * sample->actual.channels ;
    internal->total_time = ((dec->remaining == -1) ? (-1) :
                            ( ( dec->remaining / bytes_per_second ) * 1000 ) +
                            ( ( dec->remaining % bytes_per_second ) * 1000 /
                              bytes_per_second ) );

    sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
    dec->total = dec->remaining;
    dec->start_offset = SDL_RWtell(rw);

    SNDDBG(("AU: Accepting data stream.\n"));
    return(1);
} /* AU_open */
예제 #2
0
Sound_Sample *Sound_NewSample(SDL_RWops *rw, const char *ext,
                              Sound_AudioInfo *desired, Uint32 bSize)
{
    Sound_Sample *retval;
    decoder_element *decoder;

    /* sanity checks. */
    BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, NULL);
    BAIL_IF_MACRO(rw == NULL, ERR_INVALID_ARGUMENT, NULL);

    retval = alloc_sample(rw, desired, bSize);
    if (!retval)
        return(NULL);  /* alloc_sample() sets error message... */

    if (ext != NULL)
    {
        for (decoder = &decoders[0]; decoder->funcs != NULL; decoder++)
        {
            if (decoder->available)
            {
                const char **decoderExt = decoder->funcs->info.extensions;
                while (*decoderExt)
                {
                    if (__Sound_strcasecmp(*decoderExt, ext) == 0)
                    {
                        if (init_sample(decoder->funcs, retval, ext, desired))
                            return(retval);
                        break;  /* done with this decoder either way. */
                    } /* if */
                    decoderExt++;
                } /* while */
            } /* if */
        } /* for */
    } /* if */

    /* no direct extension match? Try everything we've got... */
    for (decoder = &decoders[0]; decoder->funcs != NULL; decoder++)
    {
        if (decoder->available)
        {
            int should_try = 1;
            const char **decoderExt = decoder->funcs->info.extensions;

                /* skip if we would have tried decoder above... */
            while (*decoderExt)
            {
                if (__Sound_strcasecmp(*decoderExt, ext) == 0)
                {
                    should_try = 0;
                    break;
                } /* if */
                decoderExt++;
            } /* while */

            if (should_try)
            {
                if (init_sample(decoder->funcs, retval, ext, desired))
                    return(retval);
            } /* if */
        } /* if */
    } /* for */

    /* nothing could handle the sound data... */
    free(retval->opaque);
    if (retval->buffer != NULL)
        free(retval->buffer);
    free(retval);
    SDL_RWclose(rw);
    __Sound_SetError(ERR_UNSUPPORTED_FORMAT);
    return(NULL);
} /* Sound_NewSample */
예제 #3
0
static int MPGLIB_open(Sound_Sample *sample, const char *ext)
{
    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
    mpglib_t *mpg = NULL;
    int rc;

       /*
        * If I understand things correctly, MP3 files don't really have any
        * magic header we can check for. The MP3 player is expected to just
        * pick the first thing that looks like a valid frame and start
        * playing from there.
        *
        * So here's what we do: If the caller insists that this is really
        * MP3 we'll take his word for it. Otherwise, use the same test as
        * SDL_mixer does and check if the stream starts with something that
        * looks like a frame.
        *
        * A frame begins with 11 bits of frame sync (all bits must be set),
        * followed by a two-bit MPEG Audio version ID:
        *
        *   00 - MPEG Version 2.5 (later extension of MPEG 2)
        *   01 - reserved
        *   10 - MPEG Version 2 (ISO/IEC 13818-3)
        *   11 - MPEG Version 1 (ISO/IEC 11172-3)
        *
        * Apparently we don't handle MPEG Version 2.5.
        */
    if (__Sound_strcasecmp(ext, "MP3") != 0)
    {
        Uint8 mp3_magic[2];

        if (SDL_RWread(internal->rw, mp3_magic, sizeof (mp3_magic), 1) != 1)
            BAIL_MACRO("MPGLIB: Could not read MP3 magic.", 0);

        if (mp3_magic[0] != 0xFF || (mp3_magic[1] & 0xF0) != 0xF0)
            BAIL_MACRO("MPGLIB: Not an MP3 stream.", 0);

            /* If the seek fails, we'll probably miss a frame, but oh well. */
        SDL_RWseek(internal->rw, -sizeof (mp3_magic), SEEK_CUR);
    } /* if */

    mpg = (mpglib_t *) malloc(sizeof (mpglib_t));
    BAIL_IF_MACRO(mpg == NULL, ERR_OUT_OF_MEMORY, 0);
    memset(mpg, '\0', sizeof (mpglib_t));
    InitMP3(&mpg->mp);

    rc = SDL_RWread(internal->rw, mpg->inbuf, 1, sizeof (mpg->inbuf));
    if (rc <= 0)
    {
        free(mpg);
        BAIL_MACRO("MPGLIB: Failed to read any data at all", 0);
    } /* if */

    if (decodeMP3(&mpg->mp, mpg->inbuf, rc,
                    mpg->outbuf, sizeof (mpg->outbuf),
                    &mpg->outleft) == MP3_ERR)
    {
        free(mpg);
        BAIL_MACRO("MPGLIB: Not an MP3 stream?", 0);
    } /* if */

    SNDDBG(("MPGLIB: Accepting data stream.\n"));

    internal->decoder_private = mpg;
    sample->actual.rate = mpglib_freqs[mpg->mp.fr.sampling_frequency];
    sample->actual.channels = mpg->mp.fr.stereo;
    sample->actual.format = AUDIO_S16SYS;
    sample->flags = SOUND_SAMPLEFLAG_NONE;

    return(1); /* we'll handle this data. */
} /* MPGLIB_open */
예제 #4
0
/*
   http://developer.apple.com/library/ios/#documentation/MusicAudio/Reference/AudioFileConvertRef/Reference/reference.html
   kAudioFileAIFFType = 'AIFF',
   kAudioFileAIFCType            = 'AIFC',
   kAudioFileWAVEType            = 'WAVE',
   kAudioFileSoundDesigner2Type  = 'Sd2f',
   kAudioFileNextType            = 'NeXT',
   kAudioFileMP3Type             = 'MPG3',
   kAudioFileMP2Type             = 'MPG2',
   kAudioFileMP1Type             = 'MPG1',
   kAudioFileAC3Type             = 'ac-3',
   kAudioFileAAC_ADTSType        = 'adts',
   kAudioFileMPEG4Type           = 'mp4f',
   kAudioFileM4AType             = 'm4af',
   kAudioFileCAFType             = 'caff',
   kAudioFile3GPType             = '3gpp',
   kAudioFile3GP2Type            = '3gp2',
   kAudioFileAMRType             = 'amrf'
*/
static AudioFileTypeID CoreAudio_GetAudioTypeForExtension(const char* file_extension)
{
	if( (__Sound_strcasecmp(file_extension, "aif") == 0)
		|| (__Sound_strcasecmp(file_extension, "aiff") == 0)
		|| (__Sound_strcasecmp(file_extension, "aifc") == 0)
	)
	{
		return kAudioFileAIFCType;
	}
	else if( (__Sound_strcasecmp(file_extension, "wav") == 0)
		|| (__Sound_strcasecmp(file_extension, "wave") == 0)
	)
	{
		return kAudioFileWAVEType;
	}
	else if( (__Sound_strcasecmp(file_extension, "mp3") == 0)
	)
	{
		return kAudioFileMP3Type;
	}
	else if( (__Sound_strcasecmp(file_extension, "mp4") == 0)
	)
	{
		return kAudioFileMPEG4Type;
	}
	else if( (__Sound_strcasecmp(file_extension, "m4a") == 0)
	)
	{
		return kAudioFileM4AType;
	}
	else if( (__Sound_strcasecmp(file_extension, "aac") == 0)
	)
	{
		return kAudioFileAAC_ADTSType;
	}
	else if( (__Sound_strcasecmp(file_extension, "adts") == 0)
	)
	{
		return kAudioFileAAC_ADTSType;
	}
	else if( (__Sound_strcasecmp(file_extension, "caf") == 0)
		|| (__Sound_strcasecmp(file_extension, "caff") == 0)
	)
	{
		return kAudioFileCAFType;
	}
	else if( (__Sound_strcasecmp(file_extension, "Sd2f") == 0)
		|| (__Sound_strcasecmp(file_extension, "sd2") == 0)
	)
	{
		return kAudioFileSoundDesigner2Type;
	}
	else if( (__Sound_strcasecmp(file_extension, "au") == 0)
		|| (__Sound_strcasecmp(file_extension, "snd") == 0)
		|| (__Sound_strcasecmp(file_extension, "next") == 0)
	)
	{
		return kAudioFileNextType;
	}
	else if( (__Sound_strcasecmp(file_extension, "mp2") == 0)
	)
	{
		return kAudioFileMP2Type;
	}
	else if( (__Sound_strcasecmp(file_extension, "mp1") == 0)
	)
	{
		return kAudioFileMP1Type;
	}
	else if( (__Sound_strcasecmp(file_extension, "ac3") == 0)
	)
	{
		return kAudioFileAC3Type;
	}
	else if( (__Sound_strcasecmp(file_extension, "3gpp") == 0)
			|| (__Sound_strcasecmp(file_extension, "3gp") == 0)		
	)
	{
		return kAudioFile3GPType;
	}
	else if( (__Sound_strcasecmp(file_extension, "3gp2") == 0)
			|| (__Sound_strcasecmp(file_extension, "3g2") == 0)
	)
	{
		return kAudioFile3GP2Type;
	}
	else if( (__Sound_strcasecmp(file_extension, "amrf") == 0)
		|| (__Sound_strcasecmp(file_extension, "amr") == 0)
	)
	{
		return kAudioFileAMRType;
	}
	else if( (__Sound_strcasecmp(file_extension, "ima4") == 0)
		|| (__Sound_strcasecmp(file_extension, "ima") == 0)
	)
	{
		/* not sure about this one */
		return kAudioFileCAFType;
	}
	else
	{
		return 0;
	}

}
예제 #5
0
static int MODPLUG_open(Sound_Sample *sample, const char *ext)
{
    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
    ModPlugFile *module;
    Uint8 *data;
    size_t size;
    Uint32 retval;
    int has_extension = 0;
    int i;

    /*
     * Apparently ModPlug's loaders are too forgiving. They gladly accept
     *  streams that they shouldn't. For now, rely on file extension instead.
     */
    for (i = 0; extensions_modplug[i] != NULL; i++)
    {
        if (__Sound_strcasecmp(ext, extensions_modplug[i]) == 0)
        {
            has_extension = 1;
            break;
        } /* if */
    } /* for */

    if (!has_extension)
    {
        SNDDBG(("MODPLUG: Unrecognized file type: %s\n", ext));
        BAIL_MACRO("MODPLUG: Not a module file.", 0);
    } /* if */
    
        /*
         * ModPlug needs the entire stream in one big chunk. I don't like it,
         *  but I don't think there's any way around it.
         */
    data = (Uint8 *) malloc(CHUNK_SIZE);
    BAIL_IF_MACRO(data == NULL, ERR_OUT_OF_MEMORY, 0);
    size = 0;

    do
    {
        retval = SDL_RWread(internal->rw, &data[size], 1, CHUNK_SIZE);
        size += retval;
        if (retval == CHUNK_SIZE)
        {
            data = (Uint8 *) realloc(data, size + CHUNK_SIZE);
            BAIL_IF_MACRO(data == NULL, ERR_OUT_OF_MEMORY, 0);
        } /* if */
    } while (retval > 0);

        /*
         * It's only safe to change these settings when there're
         *  no other mods being decoded...
         */
    if (modplug_mutex != NULL)
        SDL_LockMutex(modplug_mutex);

    if (total_mods_decoding > 0)
    {
        /* other mods decoding: use the same settings they are. */
        memcpy(&sample->actual, &current_audioinfo, sizeof (Sound_AudioInfo));
    } /* if */
    else
    {
        /* no other mods decoding: define the new ModPlug output settings. */
        memcpy(&sample->actual, &sample->desired, sizeof (Sound_AudioInfo));
        if (sample->actual.rate == 0)
            sample->actual.rate = 44100;
        if (sample->actual.channels == 0)
            sample->actual.channels = 2;
        if (sample->actual.format == 0)
            sample->actual.format = AUDIO_S16SYS;

        memcpy(&current_audioinfo, &sample->actual, sizeof (Sound_AudioInfo));
        settings.mChannels=sample->actual.channels;
        settings.mFrequency=sample->actual.rate;
        settings.mBits = sample->actual.format & 0xFF;
        ModPlug_SetSettings(&settings);
    } /* else */

        /*
         * The buffer may be a bit too large, but that doesn't matter. I think
         *  it's safe to free it as soon as ModPlug_Load() is finished anyway.
         */
    module = ModPlug_Load((void *) data, size);
    free(data);
    if (module == NULL)
    {
        if (modplug_mutex != NULL)
            SDL_UnlockMutex(modplug_mutex);

        BAIL_MACRO("MODPLUG: Not a module file.", 0);
    } /* if */

    total_mods_decoding++;

    if (modplug_mutex != NULL)
        SDL_UnlockMutex(modplug_mutex);

    SNDDBG(("MODPLUG: [%d ms] %s\n",
            ModPlug_GetLength(module), ModPlug_GetName(module)));

    internal->decoder_private = (void *) module;
    sample->flags = SOUND_SAMPLEFLAG_CANSEEK;

    SNDDBG(("MODPLUG: Accepting data stream\n"));
    return(1); /* we'll handle this data. */
} /* MODPLUG_open */