'------------------------------------------------------------------------------------------------------------ ' ' This is an OGG player plugin for the OPENAL context. It uses the STB libraries. PvE - MIT License 2016. ' ' Web address: https://github.com/nothings/stb ' '------------------------------------------------------------------------------------------------------------ ' ' OGG_OPEN(file$) ' => Load the OGG file, song ID is returned ' ' OGG_PLAY(songID) ' => Start playing the OGG file ' ' OGG_PAUSE(songID) ' => Pause playing the OGG file ' ' OGG_STOP(songID) ' => Stop playing the OGG file ' ' OGG_UPDATE(songID) ' => Keep the OpenAL buffers filled, to be used in callback function. ' ' OGG_BUSY(songID) ' => Check if we're still playing (TRUE) or not e.g. song is finished (FALSE) ' ' OGG_VOLUME(songID, volume) ' => Set the volume of the source in range 0.0 - 1.0 ' ' OGG_CLOSE(songID) ' => Free resources for the current file ' ' OGG_FREE ' => Free all memory resources for the complete OGG context ' '------------------------------------------------------------------------------------------------------------ PRAGMA INCLUDE stb-master/stb_vorbis.c : ' Include the stb_vorbis header file PROTO stb_vorbis_get_samples_short_interleaved stb_vorbis_close RECORD OGG LOCAL chunk : ' This is the chunk size we will be parsing LOCAL data TYPE short* LOCAL buffer[2] TYPE int LOCAL stream TYPE stb_vorbis* LOCAL channels, rate TYPE int END RECORD '------------------------------------------------------------------------------------------------------------ OPTION MEMTYPE short OGG.chunk = 262144 : ' Default chunk size OGG.data = MEMORY(OGG.chunk) : ' STB working area '------------------------------------------------------------------------------------------------------------ FUNCTION OGG_OPEN(filename$) LOCAL info TYPE stb_vorbis_info LOCAL source, samples TYPE int IF NOT(FILEEXISTS(filename$)) THEN PRINT "ERROR: cannot find file '", filename$, "'! Exiting..." END 1 END IF OGG.stream = stb_vorbis_open_filename(filename$, NULL, NULL) info = stb_vorbis_get_info(OGG.stream) OGG.channels = info.channels OGG.rate = info.sample_rate samples = stb_vorbis_stream_length_in_samples(OGG.stream) * OGG.channels ' Error cleanup alGetError() alGenBuffers(2, OGG.buffer) stb_vorbis_get_samples_short_interleaved(OGG.stream, OGG.channels, OGG.data, OGG.chunk) alBufferData(OGG.buffer[0], AL_FORMAT_STEREO16, OGG.data, OGG.chunk*sizeof(short), OGG.rate) stb_vorbis_get_samples_short_interleaved(OGG.stream, OGG.channels, OGG.data, OGG.chunk) alBufferData(OGG.buffer[1], AL_FORMAT_STEREO16, OGG.data, OGG.chunk*sizeof(short), OGG.rate) alGenSources(1, &source) alSourceQueueBuffers(source, 2, OGG.buffer) ' Returned source is used as song ID RETURN source END FUNCTION SUB OGG_SHOW_INFO PRINT "Channels: ", OGG.channels PRINT "Rate: ", OGG.rate PRINT "Duration: ", stb_vorbis_stream_length_in_seconds(OGG.stream), " seconds." END SUB SUB OGG_PLAY(int Source) alSourcePlay(Source) END SUB SUB OGG_PAUSE(int Source) alSourcePause(Source) END SUB SUB OGG_STOP(int Source) alSourceStop(Source) END SUB SUB OGG_UPDATE(int Source) LOCAL processed, which, samples TYPE int alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed) IF processed THEN alSourceUnqueueBuffers(Source, 1, &which) samples = stb_vorbis_get_samples_short_interleaved(OGG.stream, OGG.channels, OGG.data, OGG.chunk) alBufferData(which, AL_FORMAT_STEREO16, OGG.data, samples*2*sizeof(short), OGG.rate) alSourceQueueBuffers(Source, 1, &which) ENDIF END SUB FUNCTION OGG_BUSY(int Source) LOCAL state TYPE int alGetSourcei(Source, AL_SOURCE_STATE, &state) IF state = AL_PLAYING THEN RETURN TRUE RETURN FALSE END FUNCTION SUB OGG_VOLUME(int Source, volume#) alSourcef(Source, AL_GAIN, volume#) END SUB SUB OGG_CLOSE(int Source) stb_vorbis_close(OGG.stream) alDeleteSources(1, &Source) END SUB SUB OGG_FREE FREE OGG.data alDeleteBuffers(2, OGG.buffer) END SUB