void RestartVorbisPlayer(VorbisPlayer *self) { stb_vorbis_seek_start(self->vorbis); self->currentframe=NULL; self->framepos=0; self->framelength=0; }
bool AEAudioStreamUpdate(AEAudioStream* self){ ALint processed=0; alGetSourcei(self->source, AL_BUFFERS_PROCESSED, &processed); while(processed--){ ALuint buffer=0; alSourceUnqueueBuffers(self->source, 1, &buffer); if(not AEAudioStreamStream(self, buffer)){ bool shouldExit=true; if(self->shouldLoop){ stb_vorbis_seek_start(self->stream); self->totalSamplesLeft=stb_vorbis_stream_length_in_samples(self->stream) * self->info.channels; shouldExit=not AEAudioStreamStream(self, buffer); } if(shouldExit) return false; } alSourceQueueBuffers(self->source, 1, &buffer); } return true; }
void snd_PlayStreaming( int streamID, float volume, float pan ) // todo: fade in? { assert( ( streamID >= 0 ) && ( streamID < MAX_STREAMING_SOUNDS ) ); SDL_LockAudioDevice( devID ); { if( ( streamingSounds[streamID].access != NULL ) && !streamingSounds[streamID].playing ) { streamingSounds[streamID].sdlStream = SDL_NewAudioStream( AUDIO_S16, (Uint8)( streamingSounds[streamID].access->channels ), streamingSounds[streamID].access->sample_rate, WORKING_FORMAT, streamingSounds[streamID].channels, WORKING_RATE ); if( streamingSounds[streamID].sdlStream == NULL ) { llog( LOG_ERROR, "Unable to create SDL_AudioStream for streaming sound." ); return; } streamingSounds[streamID].playing = true; streamingSounds[streamID].volume = volume; streamingSounds[streamID].pan = pan; stb_vorbis_seek_start( streamingSounds[streamID].access ); streamingSounds[streamID].readDone = false; } } SDL_UnlockAudioDevice( devID ); }
virtual void pull(AudioChunk &chunk) { if (!chunk.length()) return; if (!valid || finished) {chunk.silence(); return;} int samples, have = 0, need = chunk.length(); //Create pointers to 16-bit data short *d16[PG_MAX_CHANNELS]; for (Uint32 i = 0; i < chunk.format().channels; ++i) d16[i] = (short*) chunk.start(i); while (true) { samples = stb_vorbis_get_samples_short(ogg, chunk.format().channels, d16, (need-have)); if (samples < 0) { finished = true; //cout << " VORBIS ERROR" << endl; break; } if (samples == 0) { //File's end if (loop) { stb_vorbis_seek_start(ogg); continue; } else { finished = true; break; } } for (Uint32 i=0; i < chunk.format().channels; ++i) d16[i] += samples; have += samples; //if (have > need) cout << "VORBIS OVERDRAW" << endl; //std::cout << "OGG pull: " << have << "/" << need << std::endl; if (have >= need) break; } //Cutoff marker if necessary if (have < need) chunk.cutoff(have); //Upsample data to 24-bit Sint32s for (Uint32 i=0; i < chunk.format().channels; ++i) { Sint32 *start = chunk.start(i), *op = start + have; short *ip = d16[i]; while (op!=start) {*(--op) = 256 * Sint32(*(--ip));} } }
void Sound::RewindDecoder(void* decoder) { if (!decoder) return; stb_vorbis* vorbis = static_cast<stb_vorbis*>(decoder); stb_vorbis_seek_start(vorbis); }
static inline void LoadNextFrameIfNeeded(VorbisPlayer *self) { if(self->framepos>=self->framelength) { self->framepos=0; self->framelength=stb_vorbis_get_frame_float(self->vorbis,NULL,&self->currentframe); if(!self->framelength) { stb_vorbis_seek_start(self->vorbis); self->framelength=stb_vorbis_get_frame_float(self->vorbis,NULL,&self->currentframe); } } }
result WavStreamInstance::rewind() { if (mOgg) { stb_vorbis_seek_start(mOgg); } else if (mFile) { mFile->seek(mParent->mDataOffset); } mOffset = 0; mStreamTime = 0; return 0; }
int WavStreamInstance::rewind() { if (mOgg) { stb_vorbis_seek_start(mOgg); } else if (mFile) { fseek(mFile, mParent->mDataOffset, SEEK_SET); } mOffset = 0; mStreamTime = 0; return 1; }
// Update (re-fill) music buffers if data already processed extern void UpdateMusicStream() { ALuint buffer = 0; ALint processed = 0; bool active = true; if (musicEnabled) { // Get the number of already processed buffers (if any) alGetSourcei(currentMusic.source, AL_BUFFERS_PROCESSED, &processed); while (processed > 0) { // Recover processed buffer for refill alSourceUnqueueBuffers(currentMusic.source, 1, &buffer); // Refill buffer active = BufferMusicStream(buffer); // If no more data to stream, restart music (if loop) if ((!active) && (currentMusic.loop)) { if (currentMusic.loop) { stb_vorbis_seek_start(currentMusic.stream); currentMusic.totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic.stream) * currentMusic.channels; active = BufferMusicStream(buffer); } } // Add refilled buffer to queue again... don't let the music stop! alSourceQueueBuffers(currentMusic.source, 1, &buffer); if(alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Ogg playing, error buffering data..."); processed--; } ALenum state; alGetSourcei(currentMusic.source, AL_SOURCE_STATE, &state); if ((state != AL_PLAYING) && active) alSourcePlay(currentMusic.source); if (!active) StopMusicStream(); } }
void AudioStream::Update() { //Hacer con variable auxiliar ALint buffersProcessed; alGetSourcei(source->GetID(), AL_BUFFERS_PROCESSED, &buffersProcessed); while (buffersProcessed--) { uint32 buffer; alSourceUnqueueBuffers(source->GetID(), 1, &buffer); if (Stream(buffer)) { alSourceQueueBuffers(source->GetID(), 1, &buffer); } else if (shouldLoop) { stb_vorbis_seek_start(stream); samplesLeft = stb_vorbis_stream_length_in_samples(stream) * info.channels; if (Stream(buffer)) alSourceQueueBuffers(source->GetID(), 1, &buffer); } } }
unsigned OggVorbisSoundStream::GetData(signed char* dest, unsigned numBytes) { if (!decoder_) return 0; stb_vorbis* vorbis = static_cast<stb_vorbis*>(decoder_); unsigned channels = stereo_ ? 2 : 1; unsigned outSamples = stb_vorbis_get_samples_short_interleaved(vorbis, channels, (short*)dest, numBytes >> 1); unsigned outBytes = (outSamples * channels) << 1; // Rewind and retry if is looping and produced less output than should have if (outBytes < numBytes && !stopAtEnd_) { numBytes -= outBytes; stb_vorbis_seek_start(vorbis); outSamples = stb_vorbis_get_samples_short_interleaved(vorbis, channels, (short*)(dest + outBytes), numBytes >> 1); outBytes += (outSamples * channels) << 1; }
void MusicOGG::run() { while (m_isPlaying) { if (m_bufferCount < MUSIC_BUFFER_COUNT) { m_mutex.lock(); auto pBuffer = m_buffers.back(); m_buffers.pop_back(); m_mutex.unlock(); pBuffer->count = stb_vorbis_get_samples_float_interleaved(m_pStream, m_engineChannelCount, pBuffer->data.data(), m_bufferMax) * m_engineChannelCount; pBuffer->offset = 0; if (pBuffer->count) { m_mutex.lock(); m_buffers.insert(m_buffers.begin() + m_bufferCount, pBuffer); ++m_bufferCount; m_mutex.unlock(); } else { if (m_loop) { stb_vorbis_seek_start(m_pStream); m_mutex.lock(); m_buffers.push_back(pBuffer); m_mutex.unlock(); continue; } else { // Done playing! stb_vorbis_close(m_pStream); m_pStream = nullptr; m_done = true; break; } } } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } }
int MusicPlayer::pullAudio(AUDIO_SAMPLE_TYPE *target, int sampleCount) { memset(target, 0, sampleCount * sizeof(AUDIO_SAMPLE_TYPE)); #ifdef USE_OGG if(v && error==0) { int samples = stb_vorbis_get_samples_short_interleaved(v, channels, target, sampleCount); if(samples==0) { stb_vorbis_seek_start(v); stb_vorbis_get_samples_short_interleaved(v, channels, target, sampleCount); // error=-1; } } #endif #ifdef USE_MP3 if (!error) { size_t done; error = mpg123_read(mh, (unsigned char *) target, sampleCount * sizeof(AUDIO_SAMPLE_TYPE), &done); // read will return MPG123_DONE eventually... if (error == MPG123_DONE) { mpg123_seek(mh, 0, SEEK_SET); error = mpg123_read(mh, (unsigned char *) target, sampleCount * sizeof(AUDIO_SAMPLE_TYPE), &done); } // ignore format change if (error == MPG123_NEW_FORMAT) error = MPG123_OK; } #endif return sampleCount; }
const i32 audio_updateAndPlay(MemoryArena_ *arena, AudioManager *audioManager, AudioRenderer *audioRenderer) { AudioVorbis *audio = audioRenderer->audio; if (!audio) return 0; u32 alSourceId = getSourceId(audioManager, audioRenderer); if (alIsSource(alSourceId) == AL_FALSE) { DEBUG_LOG("audio_updateAndPlay(): Update failed on invalid source id"); return -1; } ALint audioState; alGetSourcei(alSourceId, AL_SOURCE_STATE, &audioState); AL_CHECK_ERROR(); if (audioState == AL_STOPPED || audioState == AL_INITIAL) { if (audioState == AL_STOPPED) { if (audioRenderer->numPlays != AUDIO_REPEAT_INFINITE) audioRenderer->numPlays--; if (audioRenderer->numPlays == AUDIO_REPEAT_INFINITE || audioRenderer->numPlays > 0) { // TODO(doyle): Delete and recreate fixes clicking when reusing // buffers alDeleteBuffers(ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId); AL_CHECK_ERROR(); alGenBuffers(ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId); AL_CHECK_ERROR(); } else { i32 result = rendererRelease(arena, audioManager, audioRenderer); return result; } } if (audioRenderer->isStreaming) { stb_vorbis_seek_start(audio->file); for (i32 i = 0; i < ARRAY_COUNT(audioRenderer->bufferId); i++) { i16 audioChunk[AUDIO_CHUNK_SIZE_] = {0}; stb_vorbis_get_samples_short_interleaved( audio->file, audio->info.channels, audioChunk, AUDIO_CHUNK_SIZE_); alBufferData(audioRenderer->bufferId[i], audioRenderer->format, audioChunk, AUDIO_CHUNK_SIZE_ * sizeof(i16), audio->info.sample_rate); AL_CHECK_ERROR(); } alSourceQueueBuffers(alSourceId, ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId); } else { alSourceQueueBuffers(alSourceId, 1, audioRenderer->bufferId); } AL_CHECK_ERROR(); alSourcePlay(alSourceId); AL_CHECK_ERROR(); } else if (audioState == AL_PLAYING) { ALint numProcessedBuffers; alGetSourcei(alSourceId, AL_BUFFERS_PROCESSED, &numProcessedBuffers); AL_CHECK_ERROR(); if (numProcessedBuffers > 0) { // TODO(doyle): Possibly wrong, we should pass in all processed buffers? ALint numBuffersToUnqueue = 1; ALuint emptyBufferId; alSourceUnqueueBuffers(alSourceId, numBuffersToUnqueue, &emptyBufferId); AL_CHECK_ERROR(); i16 audioChunk[AUDIO_CHUNK_SIZE_] = {0}; i32 sampleCount = stb_vorbis_get_samples_short_interleaved( audio->file, audio->info.channels, audioChunk, AUDIO_CHUNK_SIZE_); /* There are still samples to play */ if (sampleCount > 0) { alBufferData(emptyBufferId, audioRenderer->format, audioChunk, sampleCount * audio->info.channels * sizeof(i16), audio->info.sample_rate); AL_CHECK_ERROR(); alSourceQueueBuffers(alSourceId, 1, &emptyBufferId); AL_CHECK_ERROR(); } } } return 0; }
void WavStreamInstance::getAudio(float *aBuffer, unsigned int aSamples) { unsigned int channels = mChannels; if (mFile == NULL) return; if (mOgg) { unsigned int offset = 0; if (mOggFrameOffset < mOggFrameSize) { int b = getOggData(mOggOutputs, aBuffer, aSamples, aSamples, mOggFrameSize, mOggFrameOffset, channels); mOffset += b; offset += b; mOggFrameOffset += b; } while (offset < aSamples) { mOggFrameSize = stb_vorbis_get_frame_float(mOgg, NULL, &mOggOutputs); mOggFrameOffset = 0; int b; b = getOggData(mOggOutputs, aBuffer + offset, aSamples - offset, aSamples, mOggFrameSize, mOggFrameOffset, channels); mOffset += b; offset += b; mOggFrameOffset += b; if (mOffset >= mParent->mSampleCount) { if (mFlags & AudioSourceInstance::LOOPING) { stb_vorbis_seek_start(mOgg); mOffset = aSamples - offset; mLoopCount++; } else { unsigned int i; for (i = 0; i < channels; i++) memset(aBuffer + offset + i * aSamples, 0, sizeof(float) * (aSamples - offset)); mOffset += aSamples - offset; offset = aSamples; } } } } else { unsigned int copysize = aSamples; if (copysize + mOffset > mParent->mSampleCount) { copysize = mParent->mSampleCount - mOffset; } getWavData(mFile, aBuffer, copysize, aSamples, channels, mParent->mChannels, mParent->mBits); if (copysize != aSamples) { if (mFlags & AudioSourceInstance::LOOPING) { mFile->seek(mParent->mDataOffset); getWavData(mFile, aBuffer + copysize, aSamples - copysize, aSamples, channels, mParent->mChannels, mParent->mBits); mOffset = aSamples - copysize; mLoopCount++; } else { unsigned int i; for (i = 0; i < channels; i++) memset(aBuffer + copysize + i * aSamples, 0, sizeof(float) * (aSamples - copysize)); mOffset += aSamples; } } else { mOffset += aSamples; } } }
// 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 ); }
void nVorbisStream::rewind() { stb_vorbis_seek_start(_vorbis); }