---------------------------------------------------------------------------------- |-- Module : Sound.OpenAL.AL.Buffer-- Copyright : (c) Sven Panne 2003-2005-- License : BSD-style (see the file libraries/OpenAL/LICENSE)-- -- Maintainer : sven.panne@aedion.de-- Stability : provisional-- Portability : portable---- This module corresponds to chapter 6 (Buffers) of the OpenAL Specification-- and Reference (version 1.1).---- A buffer encapsulates OpenAL state related to storing sample data. The-- application can request and release buffer objects, and fill them with-- data. Data can be supplied compressed and encoded as long as the format is-- supported. Buffers can, internally, contain waveform data as uncompressed or-- compressed samples.-- -- Unlike source (see "Sound.OpenAL.AL.Source") and listener (see-- "Sound.OpenAL.AL.Listener") objects, buffer objects can be shared among AL-- contexts. Buffers are referenced by sources. A single buffer can be referred-- to by multiple sources. This separation allows drivers and hardware to-- optimize storage and processing where applicable.-- -- The simplest supported format for buffer data is PCM. PCM data is assumed to-- use the processor\'s native byte order. Other formats use the byte order-- native to that format.-- -- At this time, buffer states are defined for purposes of discussion. The-- states described in this section are not exposed through the API (can not be-- queried, or be set directly), and the state description used in the-- implementation might differ from this.---- A buffer is considered to be in one of the following states, with respect to-- all sources:---- [/unused/] The buffer is not included in any queue for any source. In-- particular, the buffer is neither pending nor current for any source. The-- buffer name can be deleted at this time.---- [/processed/] The buffer is listed in the queue of at least one source, but-- is neither pending nor current for any source. The buffer can be deleted as-- soon as it has been unqueued for all sources it is queued with.---- [/pending/] There is at least one source for which the buffer has been queued,-- for which the buffer data has not yet been dereferenced. The buffer can only-- be unqueued for those sources that have dereferenced the data in the buffer-- in its entirety, and cannot be deleted or changed.---- The buffer state is dependent on the state of all sources that is has been-- queued for. A single queue occurrence of a buffer propagates the buffer state-- (over all sources) from /unused/ to /processed/ or higher. Sources that are-- in the 'Stopped' or 'Initial' states still have queue entries that cause-- buffers to be /processed/.-- -- A single queue entry with a single source for which the buffer is not yet-- /processed/ propagates the buffer\'s queuing state to /pending/.-- -- Buffers that are /processed/ for a given source can be unqueued from that-- source\'s queue. Buffers that have been unqueued from all sources are-- /unused/. Buffers that are /unused/ can be deleted, or changed by writing-- 'bufferData'.----------------------------------------------------------------------------------moduleSound.OpenAL.AL.Buffer(Buffer,MemoryRegion(..),Format(..),BufferData(..),bufferData)whereimportForeign.Marshal.Alloc(alloca)importForeign.Ptr(Ptr,nullPtr)importGraphics.Rendering.OpenGL.GL.StateVar(StateVar,makeStateVar)importSound.OpenAL.AL.BufferInternal(Buffer)importSound.OpenAL.AL.BasicTypes(ALint,ALsizei,ALenum)importSound.OpenAL.AL.Format(Format(..),marshalFormat)importSound.OpenAL.AL.PeekPoke(peek1)importSound.OpenAL.ALC.Context(Frequency)importSound.OpenAL.Constants(al_FREQUENCY,al_SIZE,al_BITS,al_CHANNELS)#ifdef __HADDOCK__importSound.OpenAL.AL.SourceState(SourceState(..))importSound.OpenAL.AL.Errors(ALErrorCategory(..))#endif--------------------------------------------------------------------------------dataMemoryRegiona=MemoryRegion(Ptra)ALsizei#ifdef __HADDOCK__-- Help Haddock a bit, because it doesn't do any instance inference.instanceEq(MemoryRegiona)instanceOrd(MemoryRegiona)instanceShow(MemoryRegiona)#elsederiving(Eq,Ord,Show)#endifdataBufferDataa=BufferData(MemoryRegiona)FormatFrequency#ifdef __HADDOCK__-- Help Haddock a bit, because it doesn't do any instance inference.instanceEq(BufferDataa)instanceOrd(BufferDataa)instanceShow(BufferDataa)#elsederiving(Eq,Ord,Show)#endif---------------------------------------------------------------------------------- | A special case of buffer state is the actual sound sample data stored in-- association with the buffer. Applications can specify sample data using-- 'bufferData'.---- The data specified is copied to an internal software, or if possible,-- hardware buffer. The implementation is free to apply decompression,-- conversion, resampling, and filtering as needed. The internal format of the-- buffer is not exposed to the application, and not accessible.---- Buffers containing audio data with more than one channel will be played-- without 3D spatialization features, these formats are normally used for-- background music. Applications should always check for an error condition-- after attempting to specify buffer data in case an implementation has to-- generate an 'ALOutOfMemory' or a conversion related 'ALInvalidValue' error.-- The application is free to reuse the memory specified by the data pointer-- once 'bufferData' is set. The implementation has to dereference, e.g. copy,-- the data while accessing 'bufferData' execution.bufferData::Buffer->StateVar(BufferDataa)bufferDatabuffer=makeStateVar(getBufferDatabuffer)(setBufferDatabuffer)getBufferData::Buffer->IO(BufferDataa)getBufferDatabuffer=dochannels<-getBufferibufferChannelsbits<-getBufferibufferBitsraw<-returnnullPtr-- ToDo: AL_DATA query missing!!!size<-getBufferibufferSizefrequency<-getBufferibufferFrequencyreturn$BufferData(MemoryRegionrawsize)(makeFormatchannelsbits)frequencysetBufferData::Buffer->BufferDataa->IO()setBufferDatabuffer(BufferData(MemoryRegionrawsize)formatfrequency)=alBufferDatabuffer(marshalFormatformat)rawsize(roundfrequency)foreignimportCALLCONVunsafe"alBufferData"alBufferData::Buffer->ALenum->Ptra->ALsizei->ALsizei->IO()---------------------------------------------------------------------------------- ToDo: What about IMAADPCMMono16, IMAADPCMStereo16, Vorbis...?makeFormat::ALint->ALint->FormatmakeFormat18=Mono8makeFormat28=Stereo8makeFormat116=Mono16makeFormat216=Stereo16makeFormatchannelsbits=error("makeFormat: illegal values "++show(channels,bits))--------------------------------------------------------------------------------dataBufferQuery=Frequency|Size|Bits|ChannelsmarshalBufferQuery::BufferQuery->ALenummarshalBufferQueryx=casexofFrequency->al_FREQUENCYSize->al_SIZEBits->al_BITSChannels->al_CHANNELS--------------------------------------------------------------------------------getBufferi::Numa=>Buffer->BufferQuery->IOagetBufferibufferquery=alloca$\buf->doalGetBufferibuffer(marshalBufferQueryquery)bufpeek1fromIntegralbufforeignimportCALLCONVunsafe"alGetBufferi"alGetBufferi::Buffer->ALenum->PtrALint->IO()