コード例 #1
0
ファイル: music_timidity.c プロジェクト: davidsiaw/SDL2_mixer
static int TIMIDITY_GetSome(void *context, void *data, int bytes, SDL_bool *done)
{
    TIMIDITY_Music *music = (TIMIDITY_Music *)context;
    int filled, amount, expected;

    if (music->stream) {
        filled = SDL_AudioStreamGet(music->stream, data, bytes);
        if (filled != 0) {
            return filled;
        }
    }

    if (!music->play_count) {
        /* All done */
        *done = SDL_TRUE;
        return 0;
    }

    if (music->stream) {
        expected = music->buffer_size;
        amount = Timidity_PlaySome(music->song, music->buffer, music->buffer_size);
        if (SDL_AudioStreamPut(music->stream, music->buffer, amount) < 0) {
            return -1;
        }
    } else {
        expected = bytes;
        amount = Timidity_PlaySome(music->song, data, bytes);
    }
        
    if (amount < expected) {
        if (music->play_count == 1) {
            /* We didn't consume anything and we're done */
            music->play_count = 0;
        } else {
            int play_count = -1;
            if (music->play_count > 0) {
                play_count = (music->play_count - 1);
            }
            if (TIMIDITY_Play(music, play_count) < 0) {
                return -1;
            }
        }
    }
    if (music->stream) {
        /* We'll pick it up from the stream next time around */
        return 0;
    } else {
        /* We wrote output data */
        return amount;
    }
}
コード例 #2
0
ファイル: sound.c プロジェクト: JesseRahikainen/Xturos
// stereo LRLRLR order
void mixerCallback( void* userdata, Uint8* streamData, int len )
{
	memset( streamData, len, workingSilence );
	memset( workingBuffer, 0, workingBufferSize );
	if( workingBuffer == NULL ) {
		return;
	}

	int numSamples = ( len / WORKING_CHANNELS ) / ( ( SDL_AUDIO_MASK_BITSIZE & WORKING_FORMAT ) / 8 );

#if 0
	int soundFreq = 440; // wave length
	float step = 1.0f / WORKING_RATE;
	// for testing audio output
	for( int s = 0; s < numSamples; ++s ) {
		int streamIdx = ( s * WORKING_CHANNELS );
		testTimePassed += 1.0f / WORKING_RATE;
		float v = sinf( testTimePassed * soundFreq * M_TWO_PI_F );
		workingBuffer[streamIdx] = v * 0.1f;
		workingBuffer[streamIdx+1] = v * 0.1f;
	}
#else
	// advance each playing sound
	for( EntityID id = idSet_GetFirstValidID( &playingIDSet ); id != INVALID_ENTITY_ID; id = idSet_GetNextValidID( &playingIDSet, id ) ) {
		int i = idSet_GetIndex( id );
		Sound* snd = &( playingSounds[i] );
		Sample* sample = &( samples[snd->sample] );
		
		// for right now lets assume the pitch will stay the same, when we get it working it'll just involve
		//  changing the speed at which we move through the array
		bool soundDone = false;
		float volume = snd->volume * sbSoundGroups[snd->group].volume * masterVolume;
		for( int s = 0; ( s < numSamples ) && !soundDone; ++s ) {

			int streamIdx = ( s * WORKING_CHANNELS );

			// we're assuming stereo output here
			if( sample->numChannels == 1 ) {
				float data = sample->data[(int)snd->pos] * volume;
/* left */		workingBuffer[streamIdx] += data * inverseLerp( 1.0f, 0.0f, snd->pan );
/* right */		workingBuffer[streamIdx+1] += data * inverseLerp( -1.0f, 0.0f, snd->pan );
				snd->pos += snd->pitch;
			} else {
				// if the sample is stereo then we ignore panning
				//  NOTE: Pitch change doesn't work with stereo samples yet
				workingBuffer[streamIdx] += sample->data[(int)snd->pos] * volume;
				workingBuffer[streamIdx+1] += sample->data[(int)snd->pos+1] * volume;
				snd->pos += 2.0f;
			}

			if( snd->pos >= sample->numSamples ) {
				if( sample->loops ) {
					snd->pos -= (float)sample->numSamples;
				} else {
					soundDone = true;
				}
			}
		}

		if( soundDone ) {
			idSet_ReleaseID( &playingIDSet, id ); // this doesn't invalidate the id for the loop
		}
	}

	for( int i = 0; i < MAX_STREAMING_SOUNDS; ++i ) {
		if( !streamingSounds[i].playing ) continue;

		StreamingSound* stream = &( streamingSounds[i] );
		bool soundDone = false;
		float volume = stream->volume * sbSoundGroups[stream->group].volume * masterVolume;

		// if the next buffer fill would be past what we have loaded then load some more
		//  note: the SDL_AudioStreamAvailable return value is in bytes
		while( ( SDL_AudioStreamAvailable( stream->sdlStream ) < len ) && !( stream->readDone ) ) {
			int read = 0;
			int request = STREAM_READ_BUFFER_SIZE / sizeof( short );
			size_t test = ARRAY_SIZE( streamReadBuffer );
			// returns the number of samples stored per channel
			int samplesPerChannel = stb_vorbis_get_samples_short_interleaved(
				stream->access, stream->access->channels, streamReadBuffer, request );
			read = samplesPerChannel * sizeof( short );

			SDL_AudioStreamPut( stream->sdlStream, streamReadBuffer, samplesPerChannel * stream->channels * sizeof( short ) );

			// reached the end of the file, are we looping?
			if( read != request ) {
				if( stream->loops ) {
					stb_vorbis_seek_start( stream->access );
				} else {
					stream->readDone = true;
					SDL_AudioStreamFlush( stream->sdlStream );
				}
			}
		}

		// read data from the audio stream until there is no more left or the end of the buffer to fill
		int bytesToStream = numSamples * stream->channels * sizeof( sbStreamWorkingBuffer[0] );
		sb_Reserve( sbStreamWorkingBuffer, (size_t)bytesToStream );
		int gotten = SDL_AudioStreamGet( stream->sdlStream, sbStreamWorkingBuffer, bytesToStream );
		if( gotten < 0 ) {
			llog( LOG_ERROR, "Error reading from sdlStream: %s", SDL_GetError( ) );
			stream->playing = false;
			continue;
		} else if( gotten == 0 ) {
			// end of stream
			stream->playing = false;
		}

		int samplesGotten = gotten / ( stream->channels * sizeof( sbStreamWorkingBuffer[0] ) );
		for( int s = 0; s < samplesGotten; ++s ) {
			// then just mix those samples
			int streamIdx = ( s * WORKING_CHANNELS );
			int workingIdx = ( s * stream->channels );
			
			// we're assuming stereo output here
			if( stream->access->channels == 1 ) {
				float data = sbStreamWorkingBuffer[workingIdx] * volume;
				workingBuffer[streamIdx] += data * inverseLerp( 1.0f, 0.0f, stream->pan );		// left
				workingBuffer[streamIdx+1] += data * inverseLerp( -1.0f, 0.0f, stream->pan );   // right
			} else {
				// if the sample is stereo then we ignore panning
				workingBuffer[streamIdx] += sbStreamWorkingBuffer[workingIdx] * volume;
				workingBuffer[streamIdx+1] += sbStreamWorkingBuffer[workingIdx + 1] * volume;
			}
		}
	}
#endif

	memcpy( streamData, workingBuffer, len );
}