Beispiel #1
0
	Status fillBuffer(AL::Buffer::ID alBuffer)
	{
		uint32_t decoded = Sound_Decode(sample);

		if (sample->flags & SOUND_SAMPLEFLAG_EAGAIN)
		{
			/* Try to decode one more time on EAGAIN */
			decoded = Sound_Decode(sample);

			/* Give up */
			if (sample->flags & SOUND_SAMPLEFLAG_EAGAIN)
				return ALDataSource::Error;
		}

		if (sample->flags & SOUND_SAMPLEFLAG_ERROR)
			return ALDataSource::Error;

		AL::Buffer::uploadData(alBuffer, alFormat, sample->buffer, decoded, alFreq);

		if (sample->flags & SOUND_SAMPLEFLAG_EOF)
		{
			if (looped)
			{
				Sound_Rewind(sample);
				return ALDataSource::WrapAround;
			}
			else
			{
				return ALDataSource::EndOfStream;
			}
		}

		return ALDataSource::NoError;
	}
Beispiel #2
0
/* Notify the sound channel completion */
static void sound_completion_callback(int chan)
{
    channel_t *sound_channel = sound_channels[chan];
    if (!sound_channel || Mix_Playing(chan))
    {
        gli_strict_warning("sound callback failed");
        return;
    }
    if (!sound_channel->buffered || !sound_channel->decode)
    {
        if (sound_channel->notify)
        {
            gli_event_store(evtype_SoundNotify, 0,
                            sound_channel->resid, sound_channel->notify);
        }
        cleanup_channel(sound_channel);
        sound_channels[chan] = 0;
        return;
    }
    Uint32 soundbytes = Sound_Decode(sound_channel->decode);
    if (!soundbytes)
    {
        sound_channel->loop--;
        if (!sound_channel->loop)
        {
            if (sound_channel->notify)
            {
                gli_event_store(evtype_SoundNotify, 0,
                                sound_channel->resid, sound_channel->notify);
            }
            cleanup_channel(sound_channel);
            sound_channels[chan] = 0;
            return;
        }
        else
        {
            Sound_Rewind(sound_channel->decode);
            soundbytes = Sound_Decode(sound_channel->decode);
        }
    }
    Sound_Sample *sample = sound_channel->decode;
    sound_channel->sample = Mix_QuickLoad_RAW(sample->buffer, soundbytes);
    Mix_ChannelFinished(&sound_completion_callback);
    if (Mix_PlayChannel(sound_channel->sdl_channel,
                        sound_channel->sample,
                        FALSE) >= 0)
    {
        return;
    }
    gli_strict_warning("buffer sound failed");
    gli_strict_warning(Mix_GetError());
    cleanup_channel(sound_channel);
    return;
}
Beispiel #3
0
/** Start a compressed sound channel */
static glui32 play_compressed(schanid_t chan, char *ext)
{
    SDL_LockAudio();
    chan->status = CHANNEL_SOUND;
    chan->buffered = 1;
    chan->sdl_channel = Mix_GroupAvailable(FREE);
    Mix_GroupChannel(chan->sdl_channel, BUSY);
    SDL_UnlockAudio();
    chan->decode = Sound_NewSample(chan->sdl_rwops, ext, output, 65536);
    Uint32 soundbytes = Sound_Decode(chan->decode);
    Sound_Sample *sample = chan->decode;
    chan->sample = Mix_QuickLoad_RAW(sample->buffer, soundbytes);
    if (chan->sdl_channel < 0)
        gli_strict_warning("No available sound channels");
    if (chan->sdl_channel >= 0 && chan->sample)
    {
        SDL_LockAudio();
        sound_channels[chan->sdl_channel] = chan;
        SDL_UnlockAudio();
        Mix_Volume(chan->sdl_channel, chan->volume);
        Mix_ChannelFinished(&sound_completion_callback);
        if (Mix_PlayChannel(chan->sdl_channel, chan->sample, 0) >= 0)
            return 1;
    }
    gli_strict_warning("play sound failed");
    gli_strict_warning(Mix_GetError());
    SDL_LockAudio();
    cleanup_channel(chan);
    SDL_UnlockAudio();
    return 0;
}
Beispiel #4
0
void updateAudio_platform(AudioInstance* instance)
{
    uint64_t now = getTime();
    if(now < instance->mAudio.mNextRead)
        return;

    instance->mAudio.mNextRead+= instance->mAudio.mReadFreq;

    uint32_t numBytes = Sound_Decode(instance->mAudio.mSample);
    if(numBytes)
    {
        if(numBytes < SDL_BUFFER_SIZE)
        {
            instance->mPlaysRemain--;
            if(instance->mPlaysRemain)
            {
                resetAudio_platform(instance);
            }

//            dprintf("%d", instance->mAudio.mSample->flags);
//            dprintf("EOF");
        }
        AudioBuffer* b = gAudioLibrary->getAudioBuffer();
        if(!b)
        {
            dprintf("Out of audio buffers!");
            return;
        }
        alBufferData(b->mBuffer, instance->mFormat, instance->mAudio.mSample->buffer, numBytes, instance->mSampleRate);
        //dprintf("Q %u on %u", b->mBuffer, instance->mSource);
        alSourceQueueBuffers(instance->mSource, 1, &b->mBuffer);
        if(instance->mState == AudioInstance::ReadyToPlay)
        {
            instance->mState = AudioInstance::Playing;
            alSourcePlay(instance->mSource);
        }

        if(!instance->mBuffersHead)
        {
 //           dprintf("head insert");
            instance->mBuffersHead = b;
            instance->mBuffersTail = b;
        }

        instance->mBuffersTail->mNext = b;
        b->mNext = NULL;
        instance->mBuffersTail = b;
    }

    ALint state;
    alGetSourcei(instance->mSource, AL_SOURCE_STATE, &state);
    
    // Stopped but still buffers.
    if(state == AL_STOPPED && instance->mBuffersHead)
    {
        dprintf("Buffer underrun. Restarting stream.");
        alSourcePlay(instance->mSource);
    }
}
	void SourceMusic::Idle(void) {
		if(_sample == NULL)
			return;
		
		// printf("idling\n");
		while( _isPlaying && 
					 (_read == _decoded || 
					 (_read - _decoded + _buffersize) % _buffersize >
					 _sample_buffersize ) )	{
			// if(_read == _decoded)	printf("_read == _decoded == %d\n", _read);
			// fill the buffer
			int count = Sound_Decode(_sample);
			// printf("adding %d bytes to buffer\n", count);
			if(count <= _buffersize - _decoded) {
				memcpy(_buffer + _decoded, _sample->buffer, count);
			} else {
				// wrapping around end of buffer (usually doesn't happen when 
				// _buffersize is a multiple of _sample_buffersize)
				// printf("wrapping around end of buffer\n");
				memcpy(_buffer + _decoded, _sample->buffer, _buffersize - _decoded);
				memcpy(_buffer, (Uint8*) _sample->buffer + _buffersize - _decoded,
							 count - (_buffersize - _decoded));
			}
			_decoded = (_decoded + count) % _buffersize;

			// check for end of sample, loop
			if((_sample->flags & SOUND_SAMPLEFLAG_ERROR) || 
			   (_sample->flags & SOUND_SAMPLEFLAG_EOF)) {
				// some error has occured, maybe end of sample reached
#ifndef macintosh
				SDL_SemWait(_sem);
#else
                SDL_LockAudio();
#endif
				// todo: let playback finish, because there's still data
				// in the buffer that has to be mixed
				CleanUp();
				// fprintf(stderr, "end of sample reached!\n");
				if(_loop) {
					// fprintf(stderr, "looping music\n");
					if(_loop != 255) 
						_loop--;
					CreateSample();
				} else {
					_isPlaying = 0;
					// todo: notify sound system (maybe load another song?)
				}
#ifndef macintosh
				SDL_SemPost(_sem);
#else
                SDL_UnlockAudio();
#endif
			}
		} // buffer has been filled
	}
Beispiel #6
0
static void audio_callback(void *userdata, Uint8 *stream, int len)
{
	sstate *data = userdata;
	Sound_Sample *sample = data->sample;
	int bw = 0;

	while (bw < len)
	{
		int cpysize;

		if (data->decoded_bytes == 0) /* need more data! */
		{
			/* if there wasn't previously an error or EOF, read more. */
			if ( ((sample->flags & SOUND_SAMPLEFLAG_ERROR) == 0) &&
				 ((sample->flags & SOUND_SAMPLEFLAG_EOF) == 0) )
			{
				data->decoded_bytes = Sound_Decode(sample);
				data->decoded_ptr = sample->buffer;
			} /* if */

			if (data->decoded_bytes == 0)
			{
				/* ...there isn't any more data to read! */
				memset(stream + bw, '\0', len - bw);  /* write silence. */
				data->done_flag = 1;
				return;  /* we're done playback, one way or another. */
			} /* if */
		}

		/* we have data decoded and ready to write to the device... */
		cpysize = len - bw;  /* len - bw == amount device still wants. */
		if (cpysize > data->decoded_bytes)
			cpysize = data->decoded_bytes;  /* clamp to what we have left. */

		/* if it's 0, next iteration will decode more or decide we're done. */
		if (cpysize > 0)
		{
			/* write this iteration's data to the device. */
			memcpy(stream + bw, (Uint8 *) data->decoded_ptr, cpysize);

			/* update state for next iteration or callback */
			bw += cpysize;
			data->decoded_ptr += cpysize;
			data->decoded_bytes -= cpysize;
		}
	}
}
Beispiel #7
0
void myMusicPlayer(void *udata, Uint8 *stream, int len)
{
	int i,act=0;
	Sint16 *ptr2;

	if (stream!=0) {
		ptr2=(Sint16 *)stream;
		if (playing_music) {
			while(act<len) {
				if (music_loaded[music_position]) {
					/* Play a music file: */ 

					if ((music_sound[music_position]->flags&SOUND_SAMPLEFLAG_EOF)) {
						/* End of file: */ 
						if (music_loaded[music_position+1]) {
							music_position++;
						} /* if */ 
						Sound_Rewind(music_sound[music_position]);
					} else {
						/* In the middle of the file: */ 
						int decoded=0;
						Sint16 *ptr;

						Sound_SetBufferSize(music_sound[music_position], len-act);
						
						decoded=Sound_Decode(music_sound[music_position]);
						ptr=(Sint16 *)music_sound[music_position]->buffer;
						for(i=0;i<decoded;i+=2,ptr++,ptr2++) {
							*ptr2=((Sint32(*ptr)*Sint32(music_volume))/127);
						} /* for */ 
						act+=decoded;
					} /* if */ 
				} else {
					/* No music file loaded: */ 
					for(i=act;i<len;i++) stream[i]=0;
					act=len;
				} /* if */ 
			} /* while */ 
		} else {
			/* No music to play: */ 
			for(i=0;i<len;i++) stream[i]=0;
		} /* if */ 
	} else {
		fprintf(stderr,"ERROR in myMusicPlayer(): null music stream!!\n");
	} /* if */ 
} /* myMusicPlayer */ 
Beispiel #8
0
Uint32 Sound_DecodeAll(Sound_Sample *sample)
{
    Sound_SampleInternal *internal = NULL;
    void *buf = NULL;
    Uint32 newBufSize = 0;

    BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
    BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_EOF, ERR_PREV_EOF, 0);
    BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_ERROR, ERR_PREV_ERROR, 0);

    internal = (Sound_SampleInternal *) sample->opaque;

    while ( ((sample->flags & SOUND_SAMPLEFLAG_EOF) == 0) &&
            ((sample->flags & SOUND_SAMPLEFLAG_ERROR) == 0) )
    {
        Uint32 br = Sound_Decode(sample);
        void *ptr = realloc(buf, newBufSize + br);
        if (ptr == NULL)
        {
            sample->flags |= SOUND_SAMPLEFLAG_ERROR;
            __Sound_SetError(ERR_OUT_OF_MEMORY);
        } /* if */
        else
        {
            buf = ptr;
            memcpy( ((char *) buf) + newBufSize, sample->buffer, br );
            newBufSize += br;
        } /* else */
    } /* while */

    if (buf == NULL)  /* ...in case first call to realloc() fails... */
        return(sample->buffer_size);

    if (internal->buffer != sample->buffer)
        free(internal->buffer);

    free(sample->buffer);

    internal->sdlcvt.buf = internal->buffer = sample->buffer = buf;
    sample->buffer_size = newBufSize;
    internal->buffer_size = newBufSize / internal->sdlcvt.len_mult;
    internal->sdlcvt.len = internal->buffer_size;

    return(newBufSize);
} /* Sound_DecodeAll */
Beispiel #9
0
/*
** Audio stream callback.
**
** Called by the SDL background thread each time the audio buffer is ready
** to receive more data.  The function decodes PCM samples from the sound
** stream and copies them to the buffer for playback. When an end-of-stream
** is reached, closes the audio stream and exits cleanly.
*/
static void
stream_callback (void *userdata, Uint8 *buffer, int length)
{
  Sound_Sample *stream = (Sound_Sample *) userdata;

  Uint32 bytes_decoded;

  /* Decode a chunk of PCM samples from the sound stream. */
  Sound_SetBufferSize (stream, length);
  bytes_decoded = Sound_Decode (stream);

  if (bytes_decoded == 0) {
    /* End-of-stream reached; exit cleanly. */
    Sound_FreeSample (stream);
    Sound_Quit ();
    SDL_Quit ();
    exit (0);
  }

  /* Copy the decoded samples to the audio buffer. */
  memcpy (buffer, stream->buffer, length);
}