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 */
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 */
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 */
/* 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; } }
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, ¤t_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(¤t_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 */