Ejemplo n.º 1
0
Uint32 Sound_Decode(Sound_Sample *sample)
{
    Sound_SampleInternal *internal = NULL;
    Uint32 retval = 0;
SNDDBG(("Sound_Decode(%p), buffer_size=%d\n", sample, sample->buffer_size));
        /* a boatload of sanity checks... */
    BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
    BAIL_IF_MACRO(sample == NULL, ERR_INVALID_ARGUMENT, 0);
    BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_ERROR, ERR_PREV_ERROR, 0);
    BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_EOF, ERR_PREV_EOF, 0);

    internal = (Sound_SampleInternal *) sample->opaque;

    assert(sample->buffer != NULL);
    assert(sample->buffer_size > 0);
    assert(internal->buffer != NULL);
    assert(internal->buffer_size > 0);

        /* reset EAGAIN. Decoder can flip it back on if it needs to. */
    sample->flags &= ~SOUND_SAMPLEFLAG_EAGAIN;
    retval = internal->funcs->read(sample);

    if (retval > 0 && internal->sdlcvt.needed)
    {
        internal->sdlcvt.len = retval;
        Sound_ConvertAudio(&internal->sdlcvt);
        retval = internal->sdlcvt.len_cvt;
    } /* if */
SNDDBG(("Sound_Decode return %d, cvt=%d, flags=%x\n", retval, internal->sdlcvt.needed, sample->flags));
    return(retval);
} /* Sound_Decode */
Ejemplo n.º 2
0
static int MIDI_open(Sound_Sample *sample, const char *ext)
{
    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
    SDL_RWops *rw = internal->rw;
    SDL_AudioSpec spec;
    MidiSong *song;

    spec.channels = 2;
    spec.format = AUDIO_S16SYS;
    spec.freq = 44100;
    spec.samples = 4096;
    
    song = Timidity_LoadSong(rw, &spec);
    BAIL_IF_MACRO(song == NULL, "MIDI: Not a MIDI file.", 0);
    Timidity_SetVolume(song, 100);
    Timidity_Start(song);

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

    internal->decoder_private = (void *) song;

    sample->actual.channels = 2;
    sample->actual.rate = 44100;
    sample->actual.format = AUDIO_S16SYS;
    
    sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
    return(1); /* we'll handle this data. */
} /* MIDI_open */
Ejemplo n.º 3
0
/*
 * This is declared in the internal header.
 */
void __Sound_SetError(const char *str)
{
    ErrMsg *err;

    if (str == NULL)
        return;

    SNDDBG(("__Sound_SetError(\"%s\");%s\n", str,
              (initialized) ? "" : " [NOT INITIALIZED!]"));

    if (!initialized)
        return;

    err = findErrorForCurrentThread();
    if (err == NULL)
    {
        err = (ErrMsg *) malloc(sizeof (ErrMsg));
        if (err == NULL)
            return;   /* uhh...? */

        memset((void *) err, '\0', sizeof (ErrMsg));
        err->tid = SDL_ThreadID();

        SDL_LockMutex(errorlist_mutex);
        err->next = error_msgs;
        error_msgs = err;
        SDL_UnlockMutex(errorlist_mutex);
    } /* if */

    err->error_available = 1;
    strncpy(err->error_string, str, sizeof (err->error_string));
    err->error_string[sizeof (err->error_string) - 1] = '\0';
} /* __Sound_SetError */
Ejemplo n.º 4
0
static __inline__ void output_ogg_comments(OggVorbis_File *vf)
{
#if (defined DEBUG_CHATTER)
    int i;
    vorbis_comment *vc = ov_comment(vf, -1);

    if (vc == NULL)
        return;

    SNDDBG(("OGG: vendor == [%s].\n", vc->vendor));
    for (i = 0; i < vc->comments; i++)
    {
        SNDDBG(("OGG: user comment [%s].\n", vc->user_comments[i]));
    } /* for */
#endif
} /* output_ogg_comments */
Ejemplo n.º 5
0
/* This is meant to find and open files for reading */
SDL_RWops *open_file(char *name)
{
  SDL_RWops *rw;

  if (!name || !(*name))
    {
      SNDDBG(("Attempted to open nameless file.\n"));
      return 0;
    }

  /* First try the given name */

  SNDDBG(("Trying to open %s\n", name));
  if ((rw = SDL_RWFromFile(name, "rb")))
    return rw;

  if (name[0] != PATH_SEP)
  {
    char current_filename[1024];
    PathList *plp = pathlist;
    int l;

    while (plp)  /* Try along the path then */
      {
	*current_filename = 0;
	l = strlen(plp->path);
	if(l)
	  {
	    strcpy(current_filename, plp->path);
	    if(current_filename[l - 1] != PATH_SEP)
	    {
	      current_filename[l] = PATH_SEP;
	      current_filename[l + 1] = '\0';
	    }
	  }
	strcat(current_filename, name);
	SNDDBG(("Trying to open %s\n", current_filename));
	if ((rw = SDL_RWFromFile(current_filename, "rb")))
	  return rw;
	plp = plp->next;
      }
  }
  
  /* Nothing could be opened. */
  SNDDBG(("Could not open %s\n", name));
  return 0;
}
Ejemplo n.º 6
0
/* This'll allocate memory or die. */
void *safe_malloc(size_t count)
{
  void *p;

  p = malloc(count);
  if (p == NULL)
    SNDDBG(("Sorry. Couldn't malloc %d bytes.\n", count));

  return p;
}
Ejemplo n.º 7
0
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 */
Ejemplo n.º 8
0
/*
 * The bulk of the Sound_NewSample() work is done here...
 *  Ask the specified decoder to handle the data in (rw), and if
 *  so, construct the Sound_Sample. Otherwise, try to wind (rw)'s stream
 *  back to where it was, and return false.
 */
static int init_sample(const Sound_DecoderFunctions *funcs,
                        Sound_Sample *sample, const char *ext,
                        Sound_AudioInfo *_desired)
{
    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
    Sound_AudioInfo desired;
    int pos = SDL_RWtell(internal->rw);

        /* fill in the funcs for this decoder... */
    sample->decoder = &funcs->info;
    internal->funcs = funcs;
    if (!funcs->open(sample, ext))
    {
        SDL_RWseek(internal->rw, pos, SEEK_SET);  /* set for next try... */
        return(0);
    } /* if */

    /* success; we've got a decoder! */

    /* Now we need to set up the conversion buffer... */

    memcpy(&desired, (_desired != NULL) ? _desired : &sample->actual,
            sizeof (Sound_AudioInfo));

    if (desired.format == 0)
        desired.format = sample->actual.format;
    if (desired.channels == 0)
        desired.channels = sample->actual.channels;
    if (desired.rate == 0)
        desired.rate = sample->actual.rate;

    if (Sound_BuildAudioCVT(&internal->sdlcvt,
                            sample->actual.format,
                            sample->actual.channels,
                            sample->actual.rate,
                            desired.format,
                            desired.channels,
                            desired.rate,
                            sample->buffer_size) == -1)
    {
        __Sound_SetError(SDL_GetError());
        funcs->close(sample);
        SDL_RWseek(internal->rw, pos, SEEK_SET);  /* set for next try... */
        return(0);
    } /* if */

    if (internal->sdlcvt.len_mult > 1)
    {
        void *rc = realloc(sample->buffer,
                           sample->buffer_size * internal->sdlcvt.len_mult);
        if (rc == NULL)
        {
            funcs->close(sample);
            SDL_RWseek(internal->rw, pos, SEEK_SET);  /* set for next try... */
            return(0);
        } /* if */

        sample->buffer = rc;
    } /* if */

        /* these pointers are all one and the same. */
    memcpy(&sample->desired, &desired, sizeof (Sound_AudioInfo));
    internal->sdlcvt.buf = internal->buffer = sample->buffer;
    internal->buffer_size = sample->buffer_size / internal->sdlcvt.len_mult;
    internal->sdlcvt.len = internal->buffer_size;

    /* Prepend our new Sound_Sample to the sample_list... */
    SDL_LockMutex(samplelist_mutex);
    internal->next = sample_list;
    if (sample_list != NULL)
        ((Sound_SampleInternal *) sample_list->opaque)->prev = sample;
    sample_list = sample;
    SDL_UnlockMutex(samplelist_mutex);

    SNDDBG(("New sample DESIRED format: %s format, %d rate, %d channels.\n",
            fmt_to_str(sample->desired.format),
            sample->desired.rate,
            sample->desired.channels));

    SNDDBG(("New sample ACTUAL format: %s format, %d rate, %d channels.\n",
            fmt_to_str(sample->actual.format),
            sample->actual.rate,
            sample->actual.channels));

    SNDDBG(("On-the-fly conversion: %s.\n",
            internal->sdlcvt.needed ? "ENABLED" : "DISABLED"));

    return(1);
} /* init_sample */
Ejemplo n.º 9
0
static Uint32 CoreAudio_read(Sound_Sample *sample)
{
	OSStatus error_result = noErr;	
	/* Documentation/example shows SInt64, but is problematic for big endian
	 * on 32-bit cast for ExtAudioFileRead() because it takes the upper
	 * bits which turn to 0.
	 */
	UInt32 buffer_size_in_frames = 0;
	UInt32 buffer_size_in_frames_remaining = 0;
	UInt32 total_frames_read = 0;
	UInt32 data_buffer_size = 0;
	UInt32 bytes_remaining = 0;
	size_t total_bytes_read = 0;
	Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
	CoreAudioFileContainer* core_audio_file_container = (CoreAudioFileContainer *) internal->decoder_private;
	UInt32 max_buffer_size = internal->buffer_size;

//	printf("internal->buffer_size=%d, internal->buffer=0x%x, sample->buffer_size=%d\n", internal->buffer_size, internal->buffer, sample->buffer_size); 
//	printf("internal->max_buffer_size=%d\n", max_buffer_size); 

	/* Compute how many frames will fit into our max buffer size */
	/* Warning: If this is not evenly divisible, the buffer will not be completely filled which violates the SDL_sound assumption. */
	buffer_size_in_frames = max_buffer_size / core_audio_file_container->outputFormat->mBytesPerFrame;
//	printf("buffer_size_in_frames=%ld, internal->buffer_size=%d, internal->buffer=0x%x outputFormat->mBytesPerFrame=%d, sample->buffer_size=%d\n", buffer_size_in_frames, internal->buffer_size, internal->buffer, core_audio_file_container->outputFormat->mBytesPerFrame, sample->buffer_size); 


//	void* temp_buffer = malloc(max_buffer_size);
	
	AudioBufferList audio_buffer_list;
	audio_buffer_list.mNumberBuffers = 1;
	audio_buffer_list.mBuffers[0].mDataByteSize = max_buffer_size;
	audio_buffer_list.mBuffers[0].mNumberChannels = core_audio_file_container->outputFormat->mChannelsPerFrame;
	audio_buffer_list.mBuffers[0].mData = internal->buffer;


	bytes_remaining = max_buffer_size;
	buffer_size_in_frames_remaining = buffer_size_in_frames;
	
	// oops. Due to the kAudioFormatFlagIsPacked bug, 
	// I was misled to believe that Core Audio
	// was not always filling my entire requested buffer. 
	// So this while-loop might be unnecessary.
	// However, I have not exhaustively tested all formats, 
	// so maybe it is possible this loop is useful.
	// It might also handle the not-evenly disvisible case above.
	while(buffer_size_in_frames_remaining > 0 && !(sample->flags & SOUND_SAMPLEFLAG_EOF))
	{
		
		data_buffer_size = (UInt32)(buffer_size_in_frames * core_audio_file_container->outputFormat->mBytesPerFrame);
//		printf("data_buffer_size=%d\n", data_buffer_size); 

		buffer_size_in_frames = buffer_size_in_frames_remaining;
		
//		printf("reading buffer_size_in_frames=%"PRId64"\n", buffer_size_in_frames); 


		audio_buffer_list.mBuffers[0].mDataByteSize = bytes_remaining;
		audio_buffer_list.mBuffers[0].mData = &(((UInt8*)internal->buffer)[total_bytes_read]);

		
		/* Read the data into an AudioBufferList */
		error_result = ExtAudioFileRead(core_audio_file_container->extAudioFileRef, &buffer_size_in_frames, &audio_buffer_list);
		if(error_result == noErr)
		{
		
		
			/* Success */
			
			total_frames_read += buffer_size_in_frames;
			buffer_size_in_frames_remaining = buffer_size_in_frames_remaining - buffer_size_in_frames;
			
//			printf("read buffer_size_in_frames=%"PRId64", buffer_size_in_frames_remaining=%"PRId64"\n", buffer_size_in_frames, buffer_size_in_frames_remaining); 

			/* ExtAudioFileRead returns the number of frames actually read. Need to convert back to bytes. */
			data_buffer_size = (UInt32)(buffer_size_in_frames * core_audio_file_container->outputFormat->mBytesPerFrame);
//			printf("data_buffer_size=%d\n", data_buffer_size); 

			total_bytes_read += data_buffer_size;
			bytes_remaining = bytes_remaining - data_buffer_size;

			/* Note: 0 == buffer_size_in_frames is a legitimate value meaning we are EOF. */
			if(0 == buffer_size_in_frames)
			{
				sample->flags |= SOUND_SAMPLEFLAG_EOF;			
			}

		}
		else 
		{
			SNDDBG(("Core Audio: ExtAudioFileReadfailed, reason: [%s].\n", CoreAudio_FourCCToString(error_result)));

			sample->flags |= SOUND_SAMPLEFLAG_ERROR;
			break;
			
		}
	}
	
	if( (!(sample->flags & SOUND_SAMPLEFLAG_EOF)) && (total_bytes_read < max_buffer_size))
	{
		SNDDBG(("Core Audio: ExtAudioFileReadfailed SOUND_SAMPLEFLAG_EAGAIN, reason: [total_bytes_read < max_buffer_size], %d, %d.\n", total_bytes_read , max_buffer_size));
		
		/* Don't know what to do here. */
		sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
	}
	return total_bytes_read;
} /* CoreAudio_read */
Ejemplo n.º 10
0
static int CoreAudio_open(Sound_Sample *sample, const char *ext)
{
	CoreAudioFileContainer* core_audio_file_container;
	AudioFileID* audio_file_id;
	OSStatus error_result;
	Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
	AudioStreamBasicDescription	actual_format;
	AudioStreamBasicDescription	output_format;
	Float64 estimated_duration;
	UInt32 format_size;
	

	core_audio_file_container = (CoreAudioFileContainer*)malloc(sizeof(CoreAudioFileContainer));
	BAIL_IF_MACRO(core_audio_file_container == NULL, ERR_OUT_OF_MEMORY, 0);


	audio_file_id = (AudioFileID*)malloc(sizeof(AudioFileID));
	BAIL_IF_MACRO(audio_file_id == NULL, ERR_OUT_OF_MEMORY, 0);

	error_result = AudioFileOpenWithCallbacks(
		internal->rw,
		CoreAudio_ReadCallback,
		NULL,
		CoreAudio_SizeCallback,
		NULL,
		CoreAudio_GetAudioTypeForExtension(ext),
		audio_file_id
	);
	if (error_result != noErr)
	{
		AudioFileClose(*audio_file_id);
		free(audio_file_id);
		free(core_audio_file_container);
		SNDDBG(("Core Audio: can't grok data. reason: [%s].\n", CoreAudio_FourCCToString(error_result)));
		BAIL_MACRO("Core Audio: Not valid audio data.", 0);
	} /* if */
	
    format_size = sizeof(actual_format);
    error_result = AudioFileGetProperty(
		*audio_file_id,
		kAudioFilePropertyDataFormat,
		&format_size,
		&actual_format
	);
    if (error_result != noErr)
	{
		AudioFileClose(*audio_file_id);
		free(audio_file_id);
		free(core_audio_file_container);
		SNDDBG(("Core Audio: AudioFileGetProperty failed. reason: [%s]", CoreAudio_FourCCToString(error_result)));
		BAIL_MACRO("Core Audio: Not valid audio data.", 0);
	} /* if */

    format_size = sizeof(estimated_duration);
    error_result = AudioFileGetProperty(
		*audio_file_id,
		kAudioFilePropertyEstimatedDuration,
		&format_size,
		&estimated_duration
	);
    if (error_result != noErr)
	{
		AudioFileClose(*audio_file_id);
		free(audio_file_id);
		free(core_audio_file_container);
		SNDDBG(("Core Audio: AudioFileGetProperty failed. reason: [%s].\n", CoreAudio_FourCCToString(error_result)));
		BAIL_MACRO("Core Audio: Not valid audio data.", 0);
	} /* if */


	core_audio_file_container->audioFileID = audio_file_id;
	
	internal->decoder_private = core_audio_file_container;
	
	sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
	sample->actual.rate = (UInt32) actual_format.mSampleRate;
	sample->actual.channels = (UInt8)actual_format.mChannelsPerFrame;
	internal->total_time = (SInt32)(estimated_duration * 1000.0 + 0.5);

#if 0
	/* FIXME: Both Core Audio and SDL 1.3 support float and 32-bit formats */
	if(actual_format.mFormatFlags & kAudioFormatFlagIsBigEndian)
	{
		if(16 == actual_format.mBitsPerChannel)
		{
			if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags)
			{
				sample->actual.format = AUDIO_S16MSB;
			}
			else
			{
				sample->actual.format = AUDIO_U16MSB;				
			}
		}
		else if(8 == actual_format.mBitsPerChannel)
		{
			if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags)
			{
				sample->actual.format = AUDIO_S8;
			}
			else
			{
				sample->actual.format = AUDIO_U8;				
			}
		}
		else // might be 0 for undefined? 
		{
			// This case seems to come up a lot for me. Maybe for file types like .m4a?
			sample->actual.format = AUDIO_S16SYS;
			SNDDBG(("Core Audio: Unsupported actual_format.mBitsPerChannel: [%d].\n", actual_format.mBitsPerChannel));
			
		}
	}
	else // little endian
	{
		if(16 == actual_format.mBitsPerChannel)
		{
			if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags)
			{
				sample->actual.format = AUDIO_S16LSB;
			}
			else
			{
				sample->actual.format = AUDIO_U16LSB;				
			}
		}
		else if(8 == actual_format.mBitsPerChannel)
		{
			if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags)
			{
				sample->actual.format = AUDIO_S8;
			}
			else
			{
				sample->actual.format = AUDIO_U8;				
			}
		}
		else // might be 0 for undefined? 
		{
			sample->actual.format = AUDIO_S16SYS;
			
			SNDDBG(("Core Audio: Unsupported actual_format.mBitsPerChannel: [%d].\n", actual_format.mBitsPerChannel));
		}

	}
#else
	
	
	
    /*
     * I want to use Core Audio to do conversion and decoding for performance reasons.
	 * This is particularly important on mobile devices like iOS.
	 * Taking from the Ogg Vorbis decode, I pretend the "actual" format is the same 
	 * as the desired format. 
     */
    sample->actual.format = (sample->desired.format == 0) ?
	AUDIO_S16SYS : sample->desired.format;
#endif	


	SNDDBG(("CoreAudio: channels == (%d).\n", sample->actual.channels));
	SNDDBG(("CoreAudio: sampling rate == (%d).\n",sample->actual.rate));
	SNDDBG(("CoreAudio: total seconds of sample == (%d).\n", internal->total_time));
	SNDDBG(("CoreAudio: sample->actual.format == (%d).\n", sample->actual.format));


	
	error_result = ExtAudioFileWrapAudioFileID(*audio_file_id,
		false, // set to false for read-only
		&core_audio_file_container->extAudioFileRef
	);
	if(error_result != noErr)
	{
		AudioFileClose(*audio_file_id);
		free(audio_file_id);
		free(core_audio_file_container);
		SNDDBG(("Core Audio: can't wrap data. reason: [%s].\n", CoreAudio_FourCCToString(error_result)));
		BAIL_MACRO("Core Audio: Failed to wrap data.", 0);
	} /* if */


	/* The output format must be linear PCM because that's the only type OpenAL knows how to deal with.
	 * Set the client format to 16 bit signed integer (native-endian) data because that is the most
	 * optimal format on iPhone/iPod Touch hardware.
	 * Maintain the channel count and sample rate of the original source format.
	 */
	output_format.mSampleRate = actual_format.mSampleRate; // preserve the original sample rate
	output_format.mChannelsPerFrame = actual_format.mChannelsPerFrame; // preserve the number of channels
	output_format.mFormatID = kAudioFormatLinearPCM; // We want linear PCM data
	output_format.mFramesPerPacket = 1; // We know for linear PCM, the definition is 1 frame per packet

	if(sample->desired.format == 0)
	{
		// do AUDIO_S16SYS
		output_format.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; // I seem to read failures problems without kAudioFormatFlagIsPacked. From a mailing list post, this seems to be a Core Audio bug.
		output_format.mBitsPerChannel = 16; // We know we want 16-bit
	}
	else
	{
		output_format.mFormatFlags = 0; // clear flags
		output_format.mFormatFlags |= kAudioFormatFlagIsPacked; // I seem to read failures problems without kAudioFormatFlagIsPacked. From a mailing list post, this seems to be a Core Audio bug.
		// Mask against bitsize
		if(0xFF & sample->desired.format)
		{
			output_format.mBitsPerChannel = 16; /* 16-bit */
		}
		else
		{
			output_format.mBitsPerChannel = 8; /* 8-bit */
		}

		// Mask for signed/unsigned
		if((1<<15) & sample->desired.format)
		{
			output_format.mFormatFlags = output_format.mFormatFlags | kAudioFormatFlagIsSignedInteger;

		}
		else
		{
			// no flag set for unsigned
		}
		// Mask for big/little endian
		if((1<<12) & sample->desired.format)
		{
			output_format.mFormatFlags = output_format.mFormatFlags | kAudioFormatFlagIsBigEndian;
		}
		else
		{
			// no flag set for little endian 
		}
	}

	output_format.mBytesPerPacket = output_format.mBitsPerChannel/8 * output_format.mChannelsPerFrame; // e.g. 16-bits/8 * channels => so 2-bytes per channel per frame
	output_format.mBytesPerFrame = output_format.mBitsPerChannel/8 * output_format.mChannelsPerFrame; // For PCM, since 1 frame is 1 packet, it is the same as mBytesPerPacket

	
/*
	output_format.mSampleRate = actual_format.mSampleRate; // preserve the original sample rate
	output_format.mChannelsPerFrame = actual_format.mChannelsPerFrame; // preserve the number of channels
	output_format.mFormatID = kAudioFormatLinearPCM; // We want linear PCM data
//	output_format.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
	output_format.mFormatFlags = kAudioFormatFlagsNativeEndian |  kAudioFormatFlagIsSignedInteger;
	output_format.mFramesPerPacket = 1; // We know for linear PCM, the definition is 1 frame per packet
	output_format.mBitsPerChannel = 16; // We know we want 16-bit
	output_format.mBytesPerPacket = 2 * output_format.mChannelsPerFrame; // We know we are using 16-bit, so 2-bytes per channel per frame
	output_format.mBytesPerFrame = 2 * output_format.mChannelsPerFrame; // For PCM, since 1 frame is 1 packet, it is the same as mBytesPerPacket
*/
	SNDDBG(("output_format: mSampleRate: %lf\n", output_format.mSampleRate)); 
	SNDDBG(("output_format: mChannelsPerFrame: %d\n", output_format.mChannelsPerFrame)); 
	SNDDBG(("output_format: mFormatID: %d\n", output_format.mFormatID)); 
	SNDDBG(("output_format: mFormatFlags: %d\n", output_format.mFormatFlags)); 
	SNDDBG(("output_format: mFramesPerPacket: %d\n", output_format.mFramesPerPacket)); 
	SNDDBG(("output_format: mBitsPerChannel: %d\n", output_format.mBitsPerChannel)); 
	SNDDBG(("output_format: mBytesPerPacket: %d\n", output_format.mBytesPerPacket)); 
	SNDDBG(("output_format: mBytesPerFrame: %d\n", output_format.mBytesPerFrame)); 
	
	
	/* Set the desired client (output) data format */
	error_result = ExtAudioFileSetProperty(core_audio_file_container->extAudioFileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(output_format), &output_format);
	if(noErr != error_result)
	{
		ExtAudioFileDispose(core_audio_file_container->extAudioFileRef);
		AudioFileClose(*audio_file_id);
		free(audio_file_id);
		free(core_audio_file_container);
		SNDDBG(("Core Audio: ExtAudioFileSetProperty(kExtAudioFileProperty_ClientDataFormat) failed, reason: [%s].\n", CoreAudio_FourCCToString(error_result)));
		BAIL_MACRO("Core Audio: Not valid audio data.", 0);
	}	


	core_audio_file_container->outputFormat = (AudioStreamBasicDescription*)malloc(sizeof(AudioStreamBasicDescription));
	BAIL_IF_MACRO(core_audio_file_container->outputFormat == NULL, ERR_OUT_OF_MEMORY, 0);


	
	/* Copy the output format to the audio_description that was passed in so the 
	 * info will be returned to the user.
	 */
	memcpy(core_audio_file_container->outputFormat, &output_format, sizeof(AudioStreamBasicDescription));

	

	return(1);
} /* CoreAudio_open */
Ejemplo n.º 11
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 */
Ejemplo n.º 12
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 */
Ejemplo n.º 13
0
static int OGG_open(Sound_Sample *sample, const char *ext)
{
    int rc;
    double total_time;
    OggVorbis_File *vf;
    vorbis_info *info;
    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;

    vf = (OggVorbis_File *) malloc(sizeof (OggVorbis_File));
    BAIL_IF_MACRO(vf == NULL, ERR_OUT_OF_MEMORY, 0);

    rc = ov_open_callbacks(internal->rw, vf, NULL, 0, RWops_ogg_callbacks);
    if (rc != 0)
    {
#if (defined DEBUG_CHATTER)		
        SNDDBG(("OGG: can't grok data. reason: [%s].\n", ogg_error(rc)));
#endif
        free(vf);
        BAIL_MACRO("OGG: Not valid Ogg Vorbis data.", 0);
    } /* if */

    info = ov_info(vf, -1);
    if (info == NULL)
    {
        ov_clear(vf);
        free(vf);
        BAIL_MACRO("OGG: failed to retrieve bitstream info", 0);
    } /* if */

    output_ogg_comments(vf);
	
    SNDDBG(("OGG: bitstream version == (%d).\n", info->version));
    SNDDBG(("OGG: bitstream channels == (%d).\n", info->channels));
    SNDDBG(("OGG: bitstream sampling rate == (%ld).\n", info->rate));
    SNDDBG(("OGG: seekable == {%s}.\n", ov_seekable(vf) ? "TRUE" : "FALSE"));
    SNDDBG(("OGG: number of logical bitstreams == (%ld).\n", ov_streams(vf)));
    SNDDBG(("OGG: serial number == (%ld).\n", ov_serialnumber(vf, -1)));
    SNDDBG(("OGG: total seconds of sample == (%f).\n", ov_time_total(vf, -1)));

    internal->decoder_private = vf;
    sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
    sample->actual.rate = (uint32_t) info->rate;
    sample->actual.channels = (uint8_t) info->channels;
    total_time = ov_time_total(vf, -1);
    if (OV_EINVAL == total_time)
      internal->total_time = -1;
    else
      internal->total_time = (int32_t)(total_time);


    /*
     * Since we might have more than one logical bitstream in the OGG file,
     *  and these bitstreams may be in different formats, we might be
     *  converting two or three times: once in vorbisfile, once again in
     *  SDL_sound, and perhaps a third time to get it to the sound device's
     *  format. That's wickedly inefficient.
     *
     * To combat this a little, if the user specified a desired format, we
     *  claim that to be the "actual" format of the collection of logical
     *  bitstreams. This means that VorbisFile will do a conversion as
     *  necessary, and SDL_sound will not. If the user didn't specify a
     *  desired format, then we pretend the "actual" format is something that
     *  OGG files are apparently commonly encoded in.
     */
    sample->actual.format = (sample->desired.format == 0) ?
                             AUDIO_S16SYS : sample->desired.format;
    return(1);
} /* OGG_open */