'------------------------------------------------------------------------------------------------------------ ' ' This is a WAV player plugin for the OPENAL context. PvE - MIT License 2016. ' '------------------------------------------------------------------------------------------------------------ ' ' WAV_OPEN(file$) ' => Load the WAV file, song ID is returned ' ' WAV_PLAY(songID) ' => Start playing the WAV file ' ' WAV_PAUSE(songID) ' => Pause playing the WAV file ' ' WAV_STOP(songID) ' => Stop playing the WAV file ' ' WAV_UPDATE(songID) ' => Keep the OpenAL buffers filled, to be used in callback function. ' ' WAV_BUSY(songID) ' => Check if we're still playing (TRUE) or not e.g. song is finished (FALSE) ' ' WAV_VOLUME(songID, volume) ' => Set the volume of the source in range 0.0 - 1.0 ' ' WAV_CLOSE(songID) ' => Free resources for the current file ' ' WAV_FREE ' => Free all memory resources for the complete WAV context ' '------------------------------------------------------------------------------------------------------------ RECORD WAV LOCAL filename$ LOCAL chunk : ' This is the chunk size we will be parsing LOCAL data TYPE unsigned char* LOCAL buffer[2] TYPE int LOCAL channels, rate, position, format, bits, stereo TYPE int END RECORD '------------------------------------------------------------------------------------------------------------ OPTION MEMTYPE char WAV.chunk = 262144 : ' Default chunk size WAV.data = MEMORY(WAV.chunk) : ' WAV working area WAV.position = 44 '------------------------------------------------------------------------------------------------------------ FUNCTION WAV_OPEN(file$) LOCAL wav TYPE FILE* LOCAL bin TYPE void* LOCAL format, source, amount TYPE int IF NOT(FILEEXISTS(file$)) THEN PRINT "ERROR: cannot find file '", file$, "'! Exiting..." END 1 END IF OPTION MEMTYPE char ' Check on WAV format OPEN file$ FOR READING AS wav bin = MEMORY(44) GETBYTE bin FROM wav SIZE 44 CLOSE FILE wav ' Check on RIFF format IF PEEK(bin) <> ASC("R") OR PEEK(bin+1) <> ASC("I") OR PEEK(bin+2) <> ASC("F") OR PEEK(bin+3) <> ASC("F") THEN PRINT "ERROR: No RIFF formatted file '", file$, "'! Exiting..." END 1 ENDIF ' Check on WAVE file IF PEEK(bin+8) <> ASC("W") OR PEEK(bin+9) <> ASC("A") OR PEEK(bin+10) <> ASC("V") OR PEEK(bin+11) <> ASC("E") THEN PRINT "ERROR: No WAVE information in file '", file$, "'! Exiting..." END 1 ENDIF WAV.filename$ = file$ ' Get the channels OPTION MEMTYPE short WAV.channels = PEEK(bin+22) WAV.bits = PEEK(bin+34) OPTION MEMTYPE int WAV.rate = PEEK(bin+24) WAV.format = 0 IF WAV.channels = 1 THEN WAV.stereo = 0 IF WAV.bits = 8 THEN WAV.format = AL_FORMAT_MONO8 ELIF WAV.bits = 16 THEN WAV.format = AL_FORMAT_MONO16 ENDIF ELIF WAV.channels = 2 THEN WAV.stereo = 1 IF WAV.bits = 8 THEN WAV.format = AL_FORMAT_STEREO8 ELIF WAV.bits = 16 THEN WAV.format = AL_FORMAT_STEREO16 ENDIF ELSE PRINT "ERROR: OpenAL does not support ", WAV.channels, " channels! Exiting..." END 1 END IF ' Check bitrate IF WAV.format = 0 THEN PRINT "ERROR: OpenAL does not support bitrate ", WAV.bits, " ! Exiting..." END 1 ENDIF ' Error cleanup alGetError() alGenBuffers(2, WAV.buffer) ' Fetch the WAV data OPTION MEMTYPE char OPEN WAV.filename$ FOR READING AS wav SEEK wav OFFSET WAV.position GETBYTE WAV.data FROM wav CHUNK WAV.chunk SIZE amount alBufferData(WAV.buffer[0], WAV.format, WAV.data, amount, WAV.rate) IF amount < WAV.chunk THEN WAV.position = -1 ELSE INCR WAV.position, amount GETBYTE WAV.data FROM wav CHUNK WAV.chunk SIZE amount alBufferData(WAV.buffer[1], WAV.format, WAV.data, amount, WAV.rate) IF amount < WAV.chunk THEN WAV.position = -1 ELSE INCR WAV.position, amount ENDIF FI CLOSE FILE wav alGenSources(1, &source) alSourceQueueBuffers(source, 2, WAV.buffer) ' Returned source is used as song ID RETURN source END FUNCTION SUB WAV_SHOW_INFO PRINT "Channels: ", WAV.channels PRINT "Rate: ", WAV.rate PRINT "Bits: ", WAV.bits PRINT IIF$(WAV.stereo, "Stereo", "Mono") END SUB SUB WAV_PLAY(int Source) alSourcePlay(Source) END SUB SUB WAV_PAUSE(int Source) alSourcePause(Source) END SUB SUB WAV_STOP(int Source) alSourceStop(Source) END SUB SUB WAV_UPDATE(int Source) LOCAL wav TYPE FILE* LOCAL processed, which, amount TYPE int alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed) IF processed AND WAV.position > 0 THEN alSourceUnqueueBuffers(Source, 1, &which) OPEN WAV.filename$ FOR READING AS wav SEEK wav OFFSET WAV.position GETBYTE WAV.data FROM wav CHUNK WAV.chunk SIZE amount CLOSE FILE wav IF amount < WAV.chunk THEN WAV.position = -1 ELSE INCR WAV.position, amount FI alBufferData(which, WAV.format, WAV.data, amount, WAV.rate) alSourceQueueBuffers(Source, 1, &which) ENDIF END SUB FUNCTION WAV_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 WAV_VOLUME(int Source, volume#) alSourcef(Source, AL_GAIN, volume#) END SUB SUB WAV_CLOSE(int Source) alDeleteSources(1, &Source) END SUB SUB WAV_FREE FREE WAV.data alDeleteBuffers(2, WAV.buffer) END SUB