-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Work with WAVE and RF64 files -- -- Work with WAVE and RF64 files. @package wave @version 0.1.3 -- | This module provides a safe interface that allows to manipulate WAVE -- files in their “classic” form as well as files in the RF64 format -- https://tech.ebu.ch/docs/tech/tech3306-2009.pdf. RF64 adds the -- ability to store files larger than 4 Gb. -- -- The main feature of the API is that it does not allow the user to -- duplicate information and introduce errors in that way. For example, -- block align may be calculated from other parameters of audio stream, -- thus we do not store it in the Wave record and do not allow -- user to specify it. We provide, however, a way to calculate it given -- Wave record, see waveBlockAlign. The same is done for -- channels. Channel mask is a more general means of providing -- information about number of channels and corresponding speaker -- positions, thus we only store channel mask in user-friendly form, but -- number of channels can be derived from that information. -- -- Another feature of the library is that it does not dictate how to -- read/write audio data. What we give is the information about audio -- data and offset in file where it begins. To write data user may use a -- callback that receives a Handle as argument. Size of data block -- is deduced automatically for you. Exclusion of audio data from -- consideration makes the library pretty fast and open to different ways -- to handle audio data itself, including using foreign code (such as C). -- -- The library provides control over all parts of WAVE file that may be -- of interest. In particular, it even allows to write arbitrary chunks -- between fmt and data chunks, although it's rarely -- useful (and may actually confuse buggy applications that don't know -- how to skip unknown chunks). module Codec.Audio.Wave -- | Representation of “essential” information about a WAVE file. Every -- field in this record provides orthogonal piece of information, so no -- field can be calculated from other fields. The fields are complemented -- by the following functions that calculate some derivative parameters: -- waveByteRate, waveBitRate, waveBitsPerSample, -- waveBlockAlign, and waveChannels. data Wave Wave :: !WaveFormat -> !Word32 -> !SampleFormat -> !(Set SpeakerPosition) -> !Word32 -> !Word64 -> !Word64 -> [(ByteString, ByteString)] -> Wave -- | This specifies format of file this Wave record was extracted/to -- be written to, WaveFormat. Default value is: -- WaveVanilla. [waveFileFormat] :: Wave -> !WaveFormat -- | Sample rate in Hz, default is: 44100. [waveSampleRate] :: Wave -> !Word32 -- | Sample format. The library supports signed/unsigned integers and -- floats. Default value: SampleFormatPcmInt 16. [waveSampleFormat] :: Wave -> !SampleFormat -- | The channel mask as a Set of SpeakerPositions. Default -- value is speakerStereo. [waveChannelMask] :: Wave -> !(Set SpeakerPosition) -- | Offset in bytes from the beginning of file where actual sample data -- begins. Default value: 0. [waveDataOffset] :: Wave -> !Word32 -- | Size of audio data in bytes. Default value: 0. [waveDataSize] :: Wave -> !Word64 -- | Total number of samples in the audio stream. “Samples” here mean -- multi-channel samples, so one second of 44.1 kHz audio will have 44100 -- samples regardless of the number of channels. For PCM format it's -- deduced from size of data-block, for other formats it's read -- from/written to the “fact” chunk. Default value: 0. [waveSamplesTotal] :: Wave -> !Word64 -- | Other chunks as (tag, body) pairs. Only first four bytes of -- tag are significant (and it must be four bytes long, if it's -- too short it will be padded by null bytes). Default value: -- []. [waveOtherChunks] :: Wave -> [(ByteString, ByteString)] -- | WaveFormat as flavor of WAVE file. data WaveFormat -- | Classic WAVE file, 4 Gb size limitation WaveVanilla :: WaveFormat -- | WAVE file with RF64 extension WaveRF64 :: WaveFormat -- | Sample formats with associated bit depth (when variable). data SampleFormat -- | Unsigned/signed integers, the argument is the number of bits per -- sample (8 bit and less are encoded as unsigned integers). SampleFormatPcmInt :: Word16 -> SampleFormat -- | Samples are 32 bit floating point numbers. SampleFormatIeeeFloat32Bit :: SampleFormat -- | Samples are 64 bit floating point numbers. SampleFormatIeeeFloat64Bit :: SampleFormat -- | Speaker positions clarifying which exactly channels are packed in the -- WAVE file. data SpeakerPosition -- | Front left SpeakerFrontLeft :: SpeakerPosition -- | Front right SpeakerFrontRight :: SpeakerPosition -- | Front center SpeakerFrontCenter :: SpeakerPosition -- | Sub-woofer SpeakerLowFrequency :: SpeakerPosition -- | Back left SpeakerBackLeft :: SpeakerPosition -- | Back right SpeakerBackRight :: SpeakerPosition -- | Front left of center SpeakerFrontLeftOfCenter :: SpeakerPosition -- | Front right of center SpeakerFrontRightOfCenter :: SpeakerPosition -- | Back center SpeakerBackCenter :: SpeakerPosition -- | Side left SpeakerSideLeft :: SpeakerPosition -- | Side right SpeakerSideRight :: SpeakerPosition -- | Top center SpeakerTopCenter :: SpeakerPosition -- | Top front left SpeakerTopFrontLeft :: SpeakerPosition -- | Top front center SpeakerTopFrontCenter :: SpeakerPosition -- | Top front right SpeakerTopFrontRight :: SpeakerPosition -- | Top back left SpeakerTopBackLeft :: SpeakerPosition -- | Top back center SpeakerTopBackCenter :: SpeakerPosition -- | Top back right SpeakerTopBackRight :: SpeakerPosition -- | Exceptions the library can throw. data WaveException -- | Format of given file doesn't look like anything familiar. The first -- argument is a message explaining what's wrong and the second argument -- is the file name. BadFileFormat :: String -> FilePath -> WaveException -- | The library found a chunk which is not a data chunk but is -- way too long. The first argument is the tag of the chunk and the -- second argument is the file name. NonDataChunkIsTooLong :: ByteString -> FilePath -> WaveException -- | The specified format is non-PCM, it's vanilla WAVE, but “fact” chunk -- is missing. NonPcmFormatButMissingFact :: FilePath -> WaveException -- | Byte rate of a given Wave file. Byte rate is the number of -- bytes it takes to encode one second of audio. waveByteRate :: Wave -> Word32 -- | Bit rate in kilobits per second. waveBitRate :: Wave -> Double -- | Number of significant bits in every sample. waveBitsPerSample :: Wave -> Word16 -- | Block alignment of samples as number of bits per sample (rounded -- towards next multiplier of 8 if necessary) multiplied by number of -- channels. This is how many bytes it takes to encode a single -- multi-channel sample. waveBlockAlign :: Wave -> Word16 -- | Total number of channels present in the audio stream. waveChannels :: Wave -> Word16 -- | Duration in seconds. waveDuration :: Wave -> Double -- | Front center (C). speakerMono :: Set SpeakerPosition -- | Front left (L), front right (R). speakerStereo :: Set SpeakerPosition -- | L, R, back left (Lb), back right (Rb). speakerQuad :: Set SpeakerPosition -- | Surround: L, R, front center (C), back center (Cb). speakerSurround :: Set SpeakerPosition -- | L, R, C, Lb, Rb, low frequency (LFE). speaker5_1 :: Set SpeakerPosition -- | L, R, C, Lb, Rb, front left-of-center, front right-of-center, LFE. speaker7_1 :: Set SpeakerPosition -- | L, R, C, side left (Ls), side right (Rs), LFE. speaker5_1Surround :: Set SpeakerPosition -- | L, R, C, Lb, Rb, Ls, Rs, LFE. speaker7_1Surround :: Set SpeakerPosition -- | Read Wave record from a WAVE file found at given path. This -- action throws WaveException if the file is malformed and cannot -- be read. -- -- You can feed vanilla WAVE and RF64 files. The actual format is -- detected automatically from contents of the file, not by extension. -- -- PCM with samples in form of integers and floats only are supported, -- see SampleFormat. Addition of other formats will be performed -- on request, please feel free to contact me at -- https://github.com/mrkkrp/wave/issues. -- -- Finally, if “fmt” chunk is not extensible, we try to guess channel -- mask from number of channels alone, here is how: -- --