ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
WavFile Class Reference
+ Collaboration diagram for WavFile:

Public Member Functions

 __construct ($numChannelsOrFileName=null, $sampleRateOrReadData=null, $bitsPerSample=null)
 WavFile Constructor. More...
 
 __destruct ()
 
 __clone ()
 
 __toString ()
 Output the wav file headers and data. More...
 
 getActualSize ()
 
 getChunkSize ()
 
 getFmtChunkSize ()
 
 getFmtExtendedSize ()
 
 getFactChunkSize ()
 
 getDataSize ()
 
 getDataOffset ()
 
 getAudioFormat ()
 
 getAudioSubFormat ()
 
 getNumChannels ()
 
 setNumChannels ($numChannels)
 
 getChannelMask ()
 
 setChannelMask ($channelMask=self::SPEAKER_DEFAULT)
 
 getSampleRate ()
 
 setSampleRate ($sampleRate)
 
 getBitsPerSample ()
 
 setBitsPerSample ($bitsPerSample)
 
 getValidBitsPerSample ()
 
 getBlockAlign ()
 
 getNumBlocks ()
 
 getByteRate ()
 
 getSamples ()
 
 setSamples (&$samples='')
 
 getMinAmplitude ()
 
 getZeroAmplitude ()
 
 getMaxAmplitude ()
 
 makeHeader ()
 Construct a wav header from this object. More...
 
 getDataSubchunk ()
 Construct wav DATA chunk. More...
 
 save ($filename)
 Save the wav data to a file. More...
 
 openWav ($filename, $readData=true)
 Reads a wav header and data from a file. More...
 
 closeWav ()
 Close a with openWav() previously opened wav file or free the buffer of setWavData(). More...
 
 setWavData (&$data, $free=true)
 Set the wav file data and properties from a wav file in a string. More...
 
 readWavData ($dataOffset=0, $dataSize=null)
 Read the wav data from the file into the buffer. More...
 
 getSampleBlock ($blockNum)
 Return a single sample block from the file. More...
 
 setSampleBlock ($sampleBlock, $blockNum)
 Set a single sample block. More...
 
 getSampleValue ($blockNum, $channelNum)
 Get a float sample value for a specific sample block and channel number. More...
 
 setSampleValue ($sampleFloat, $blockNum, $channelNum)
 Sets a float sample value for a specific sample block number and channel. More...
 
 filter ($filters, $blockOffset=0, $numBlocks=null)
 Run samples through audio processing filters. More...
 
 appendWav (WavFile $wav)
 Append a wav file to the current wav. More...
 
 mergeWav (WavFile $wav, $normalizeThreshold=null)
 Mix 2 wav files together. More...
 
 insertSilence ($duration=1.0)
 Add silence to the wav file. More...
 
 degrade ($quality=1.0)
 Degrade the quality of the wav file by introducing random noise. More...
 
 generateNoise ($duration=1.0, $percent=100)
 Generate noise at the end of the wav for the specified duration and volume. More...
 
 convertBitsPerSample ($bitsPerSample)
 Convert sample data to different bits per sample. More...
 
 displayInfo ()
 Output information about the wav object. More...
 

Static Public Member Functions

static unpackSample ($sampleBinary, $bitDepth=null)
 Unpacks a single binary sample to numeric value. More...
 
static packSample ($sample, $bitDepth)
 Packs a single numeric sample to binary. More...
 
static unpackSampleBlock ($sampleBlock, $bitDepth, $numChannels=null)
 Unpacks a binary sample block to numeric values. More...
 
static packSampleBlock ($samples, $bitDepth)
 Packs an array of numeric channel samples to a binary sample block. More...
 
static normalizeSample ($sampleFloat, $threshold)
 Normalizes a float audio sample. More...
 

Data Fields

const FILTER_MIX = 0x01
 
const FILTER_NORMALIZE = 0x02
 
const FILTER_DEGRADE = 0x04
 
const MAX_CHANNEL = 18
 
const MAX_SAMPLERATE = 192000
 
const SPEAKER_DEFAULT = 0x000000
 Channel Locations for ChannelMask. More...
 
const SPEAKER_FRONT_LEFT = 0x000001
 
const SPEAKER_FRONT_RIGHT = 0x000002
 
const SPEAKER_FRONT_CENTER = 0x000004
 
const SPEAKER_LOW_FREQUENCY = 0x000008
 
const SPEAKER_BACK_LEFT = 0x000010
 
const SPEAKER_BACK_RIGHT = 0x000020
 
const SPEAKER_FRONT_LEFT_OF_CENTER = 0x000040
 
const SPEAKER_FRONT_RIGHT_OF_CENTER = 0x000080
 
const SPEAKER_BACK_CENTER = 0x000100
 
const SPEAKER_SIDE_LEFT = 0x000200
 
const SPEAKER_SIDE_RIGHT = 0x000400
 
const SPEAKER_TOP_CENTER = 0x000800
 
const SPEAKER_TOP_FRONT_LEFT = 0x001000
 
const SPEAKER_TOP_FRONT_CENTER = 0x002000
 
const SPEAKER_TOP_FRONT_RIGHT = 0x004000
 
const SPEAKER_TOP_BACK_LEFT = 0x008000
 
const SPEAKER_TOP_BACK_CENTER = 0x010000
 
const SPEAKER_TOP_BACK_RIGHT = 0x020000
 
const SPEAKER_ALL = 0x03FFFF
 
const WAVE_FORMAT_PCM = 0x0001
 
const WAVE_FORMAT_IEEE_FLOAT = 0x0003
 
const WAVE_FORMAT_EXTENSIBLE = 0xFFFE
 
const WAVE_SUBFORMAT_PCM = "0100000000001000800000aa00389b71"
 
const WAVE_SUBFORMAT_IEEE_FLOAT = "0300000000001000800000aa00389b71"
 

Protected Member Functions

 setActualSize ($actualSize=null)
 
 setChunkSize ($chunkSize=null)
 
 setFmtChunkSize ($fmtChunkSize=null)
 
 setFmtExtendedSize ($fmtExtendedSize=null)
 
 setFactChunkSize ($factChunkSize=null)
 
 setDataSize ($dataSize=null)
 
 setDataOffset ($dataOffset=null)
 
 setAudioFormat ($audioFormat=null)
 
 setAudioSubFormat ($audioSubFormat=null)
 
 setValidBitsPerSample ($validBitsPerSample=null)
 
 setBlockAlign ($blockAlign=null)
 
 setNumBlocks ($numBlocks=null)
 
 setByteRate ($byteRate=null)
 
 readWav ($readData=true)
 Read wav file from a stream. More...
 
 readWavHeader ()
 Parse a wav header. More...
 

Protected Attributes

 $_actualSize
 
 $_chunkSize
 
 $_fmtChunkSize
 
 $_fmtExtendedSize
 
 $_factChunkSize
 
 $_dataSize
 
 $_dataSize_fp
 
 $_dataSize_valid
 
 $_dataOffset
 
 $_audioFormat
 
 $_audioSubFormat
 
 $_numChannels
 
 $_channelMask
 
 $_sampleRate
 
 $_bitsPerSample
 
 $_validBitsPerSample
 
 $_blockAlign
 
 $_numBlocks
 
 $_byteRate
 
 $_samples
 
 $_fp
 

Static Protected Attributes

static $LOOKUP_LOGBASE
 

Detailed Description

Definition at line 69 of file WavFile.php.

Constructor & Destructor Documentation

◆ __construct()

WavFile::__construct (   $numChannelsOrFileName = null,
  $sampleRateOrReadData = null,
  $bitsPerSample = null 
)

WavFile Constructor.

$wav1 = new WavFile(2, 44100, 16); // new wav with 2 channels, at 44100 samples/sec and 16 bits per sample $wav2 = new WavFile('./audio/sound.wav'); // open and read wav file

Parameters
string | int$numChannelsOrFileName(Optional) If string, the filename of the wav file to open. The number of channels otherwise. Defaults to 1.
int | bool$sampleRateOrReadData(Optional) If opening a file and boolean, decides whether to read the data chunk or not. Defaults to true. The sample rate in samples per second otherwise. 8000 = standard telephone, 16000 = wideband telephone, 32000 = FM radio and 44100 = CD quality. Defaults to 8000.
int$bitsPerSample(Optional) The number of bits per sample. Has to be 8, 16 or 24 for PCM audio or 32 for IEEE FLOAT audio. 8 = telephone, 16 = CD and 24 or 32 = studio quality. Defaults to 8.
Exceptions
WavFormatException
WavFileException

Definition at line 221 of file WavFile.php.

222 {
223 $this->_actualSize = 44;
224 $this->_chunkSize = 36;
225 $this->_fmtChunkSize = 16;
226 $this->_fmtExtendedSize = 0;
227 $this->_factChunkSize = 0;
228 $this->_dataSize = 0;
229 $this->_dataSize_fp = 0;
230 $this->_dataSize_valid = true;
231 $this->_dataOffset = 44;
232 $this->_audioFormat = self::WAVE_FORMAT_PCM;
233 $this->_audioSubFormat = null;
234 $this->_numChannels = 1;
235 $this->_channelMask = self::SPEAKER_DEFAULT;
236 $this->_sampleRate = 8000;
237 $this->_bitsPerSample = 8;
238 $this->_validBitsPerSample = 8;
239 $this->_blockAlign = 1;
240 $this->_numBlocks = 0;
241 $this->_byteRate = 8000;
242 $this->_samples = '';
243 $this->_fp = null;
244
245
246 if (is_string($numChannelsOrFileName)) {
247 $this->openWav($numChannelsOrFileName, is_bool($sampleRateOrReadData) ? $sampleRateOrReadData : true);
248
249 } else {
250 $this->setNumChannels(is_null($numChannelsOrFileName) ? 1 : $numChannelsOrFileName)
251 ->setSampleRate(is_null($sampleRateOrReadData) ? 8000 : $sampleRateOrReadData)
252 ->setBitsPerSample(is_null($bitsPerSample) ? 8 : $bitsPerSample);
253 }
254 }
openWav($filename, $readData=true)
Reads a wav header and data from a file.
Definition: WavFile.php:927
const WAVE_FORMAT_PCM
Definition: WavFile.php:112
const SPEAKER_DEFAULT
Channel Locations for ChannelMask.
Definition: WavFile.php:90
setNumChannels($numChannels)
Definition: WavFile.php:634

References openWav(), setNumChannels(), SPEAKER_DEFAULT, and WAVE_FORMAT_PCM.

+ Here is the call graph for this function:

◆ __destruct()

WavFile::__destruct ( )

Definition at line 256 of file WavFile.php.

256 {
257 if (is_resource($this->_fp)) $this->closeWav();
258 }
closeWav()
Close a with openWav() previously opened wav file or free the buffer of setWavData().
Definition: WavFile.php:953

References closeWav().

+ Here is the call graph for this function:

Member Function Documentation

◆ __clone()

WavFile::__clone ( )

Definition at line 260 of file WavFile.php.

260 {
261 $this->_fp = null;
262 }

◆ __toString()

WavFile::__toString ( )

Output the wav file headers and data.

Returns
string The encoded file.

Definition at line 269 of file WavFile.php.

270 {
271 return $this->makeHeader() .
272 $this->getDataSubchunk();
273 }
makeHeader()
Construct a wav header from this object.
Definition: WavFile.php:840
getDataSubchunk()
Construct wav DATA chunk.
Definition: WavFile.php:884

References getDataSubchunk(), and makeHeader().

+ Here is the call graph for this function:

◆ appendWav()

WavFile::appendWav ( WavFile  $wav)

Append a wav file to the current wav.


The wav files must have the same sample rate, number of bits per sample, and number of channels.

Parameters
WavFile$wav(Required) The wav file to append.
Exceptions
WavFileException

Definition at line 1678 of file WavFile.php.

1678 {
1679 // basic checks
1680 if ($wav->getSampleRate() != $this->getSampleRate()) {
1681 throw new WavFileException("Sample rate for wav files do not match.");
1682 } else if ($wav->getBitsPerSample() != $this->getBitsPerSample()) {
1683 throw new WavFileException("Bits per sample for wav files do not match.");
1684 } else if ($wav->getNumChannels() != $this->getNumChannels()) {
1685 throw new WavFileException("Number of channels for wav files do not match.");
1686 }
1687
1688 $this->_samples .= $wav->_samples;
1689 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
1690
1691 return $this;
1692 }
WavFileException indicates an illegal state or argument in this class.
Definition: WavFile.php:1859
setDataSize($dataSize=null)
Definition: WavFile.php:551
getSampleRate()
Definition: WavFile.php:675
getBitsPerSample()
Definition: WavFile.php:693
getNumChannels()
Definition: WavFile.php:630

References getBitsPerSample(), getNumChannels(), getSampleRate(), and setDataSize().

+ Here is the call graph for this function:

◆ closeWav()

WavFile::closeWav ( )

Close a with openWav() previously opened wav file or free the buffer of setWavData().

Not necessary if the data has been read (readData = true) already.

Definition at line 953 of file WavFile.php.

953 {
954 if (is_resource($this->_fp)) fclose($this->_fp);
955
956 return $this;
957 }

Referenced by __destruct(), openWav(), readWav(), readWavData(), and setWavData().

+ Here is the caller graph for this function:

◆ convertBitsPerSample()

WavFile::convertBitsPerSample (   $bitsPerSample)

Convert sample data to different bits per sample.

Parameters
int$bitsPerSample(Required) The new number of bits per sample;
Exceptions
WavFileException

Definition at line 1779 of file WavFile.php.

1779 {
1780 if ($this->getBitsPerSample() == $bitsPerSample) {
1781 return $this;
1782 }
1783
1784 $tempWav = new WavFile($this->getNumChannels(), $this->getSampleRate(), $bitsPerSample);
1785 $tempWav->filter(
1786 array(self::FILTER_MIX => $this),
1787 0,
1788 $this->getNumBlocks()
1789 );
1790
1791 $this->setSamples() // implicit setDataSize(), setSize(), setActualSize(), setNumBlocks()
1792 ->setBitsPerSample($bitsPerSample); // implicit setValidBitsPerSample(), setAudioFormat(), setAudioSubFormat(), setFmtChunkSize(), setFactChunkSize(), setSize(), setActualSize(), setDataOffset(), setByteRate(), setBlockAlign(), setNumBlocks()
1793 $this->_samples = $tempWav->_samples;
1794 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
1795
1796 return $this;
1797 }
getNumBlocks()
Definition: WavFile.php:748
setSamples(&$samples='')
Definition: WavFile.php:781

References getBitsPerSample(), getNumBlocks(), getNumChannels(), getSampleRate(), setDataSize(), and setSamples().

+ Here is the call graph for this function:

◆ degrade()

WavFile::degrade (   $quality = 1.0)

Degrade the quality of the wav file by introducing random noise.

Parameters
floatquality (Optional) The quality relative to the amplitude. 1 = no noise, 0 = max. noise.

Definition at line 1736 of file WavFile.php.

1737 {
1738 return $this->filter(self::FILTER_DEGRADE, array(
1739 WavFile::FILTER_DEGRADE => $quality
1740 ));
1741 }
const FILTER_DEGRADE
Definition: WavFile.php:81
filter($filters, $blockOffset=0, $numBlocks=null)
Run samples through audio processing filters.
Definition: WavFile.php:1571

References filter(), and FILTER_DEGRADE.

+ Here is the call graph for this function:

◆ displayInfo()

WavFile::displayInfo ( )

Output information about the wav object.

Definition at line 1806 of file WavFile.php.

1807 {
1808 $s = "File Size: %u\n"
1809 ."Chunk Size: %u\n"
1810 ."fmt Subchunk Size: %u\n"
1811 ."Extended fmt Size: %u\n"
1812 ."fact Subchunk Size: %u\n"
1813 ."Data Offset: %u\n"
1814 ."Data Size: %u\n"
1815 ."Audio Format: %s\n"
1816 ."Audio SubFormat: %s\n"
1817 ."Channels: %u\n"
1818 ."Channel Mask: 0x%s\n"
1819 ."Sample Rate: %u\n"
1820 ."Bits Per Sample: %u\n"
1821 ."Valid Bits Per Sample: %u\n"
1822 ."Sample Block Size: %u\n"
1823 ."Number of Sample Blocks: %u\n"
1824 ."Byte Rate: %uBps\n";
1825
1826 $s = sprintf($s, $this->getActualSize(),
1827 $this->getChunkSize(),
1828 $this->getFmtChunkSize(),
1829 $this->getFmtExtendedSize(),
1830 $this->getFactChunkSize(),
1831 $this->getDataOffset(),
1832 $this->getDataSize(),
1833 $this->getAudioFormat() == self::WAVE_FORMAT_PCM ? 'PCM' : ($this->getAudioFormat() == self::WAVE_FORMAT_IEEE_FLOAT ? 'IEEE FLOAT' : 'EXTENSIBLE'),
1834 $this->getAudioSubFormat() == self::WAVE_SUBFORMAT_PCM ? 'PCM' : 'IEEE FLOAT',
1835 $this->getNumChannels(),
1836 dechex($this->getChannelMask()),
1837 $this->getSampleRate(),
1838 $this->getBitsPerSample(),
1839 $this->getValidBitsPerSample(),
1840 $this->getBlockAlign(),
1841 $this->getNumBlocks(),
1842 $this->getByteRate());
1843
1844 if (php_sapi_name() == 'cli') {
1845 return $s;
1846 } else {
1847 return nl2br($s);
1848 }
1849 }
getChunkSize()
Definition: WavFile.php:467
getChannelMask()
Definition: WavFile.php:650
getDataSize()
Definition: WavFile.php:547
getAudioSubFormat()
Definition: WavFile.php:612
getFmtExtendedSize()
Definition: WavFile.php:504
getDataOffset()
Definition: WavFile.php:565
getAudioFormat()
Definition: WavFile.php:583
getFmtChunkSize()
Definition: WavFile.php:487
getBlockAlign()
Definition: WavFile.php:732
getFactChunkSize()
Definition: WavFile.php:526
getByteRate()
Definition: WavFile.php:763
getActualSize()
Definition: WavFile.php:453
getValidBitsPerSample()
Definition: WavFile.php:713

References getActualSize(), getAudioFormat(), getAudioSubFormat(), getBitsPerSample(), getBlockAlign(), getByteRate(), getChannelMask(), getChunkSize(), getDataOffset(), getDataSize(), getFactChunkSize(), getFmtChunkSize(), getFmtExtendedSize(), getNumBlocks(), getNumChannels(), getSampleRate(), and getValidBitsPerSample().

+ Here is the call graph for this function:

◆ filter()

WavFile::filter (   $filters,
  $blockOffset = 0,
  $numBlocks = null 
)

Run samples through audio processing filters.

$wav->filter( array( WavFile::FILTER_MIX => array( // Filter for mixing 2 WavFile instances. 'wav' => $wav2, // (Required) The WavFile to mix into this WhavFile. If no optional arguments are given, can be passed without the array. 'loop' => true, // (Optional) Loop the selected portion (with warping to the beginning at the end). 'blockOffset' => 0, // (Optional) Block number to start mixing from. 'numBlocks' => null // (Optional) Number of blocks to mix in or to select for looping. Defaults to the end or all data for looping. ), WavFile::FILTER_NORMALIZE => 0.6, // (Required) Normalization of (mixed) audio samples - see threshold parameter for normalizeSample(). WavFile::FILTER_DEGRADE => 0.9 // (Required) Introduce random noise. The quality relative to the amplitude. 1 = no noise, 0 = max. noise. ), 0, // (Optional) The block number of this WavFile to start with. null // (Optional) The number of blocks to process. );

Parameters
array$filters(Required) An array of 1 or more audio processing filters.
int$blockOffset(Optional) The block number to start precessing from.
int$numBlocks(Optional) The maximum number of blocks to process.
Exceptions
WavFileException

Definition at line 1571 of file WavFile.php.

1572 {
1573 // check preconditions
1574 $totalBlocks = $this->getNumBlocks();
1575 $numChannels = $this->getNumChannels();
1576 if (is_null($numBlocks)) $numBlocks = $totalBlocks - $blockOffset;
1577
1578 if (!is_array($filters) || empty($filters) || $blockOffset < 0 || $blockOffset > $totalBlocks || $numBlocks <= 0) {
1579 // nothing to do
1580 return $this;
1581 }
1582
1583 // check filtes
1584 $filter_mix = false;
1585 if (array_key_exists(self::FILTER_MIX, $filters)) {
1586 if (!is_array($filters[self::FILTER_MIX])) {
1587 // assume the 'wav' parameter
1588 $filters[self::FILTER_MIX] = array('wav' => $filters[self::FILTER_MIX]);
1589 }
1590
1591 $mix_wav = @$filters[self::FILTER_MIX]['wav'];
1592 if (!($mix_wav instanceof WavFile)) {
1593 throw new WavFileException("WavFile to mix is missing or invalid.");
1594 } elseif ($mix_wav->getSampleRate() != $this->getSampleRate()) {
1595 throw new WavFileException("Sample rate of WavFile to mix does not match.");
1596 } else if ($mix_wav->getNumChannels() != $this->getNumChannels()) {
1597 throw new WavFileException("Number of channels of WavFile to mix does not match.");
1598 }
1599
1600 $mix_loop = @$filters[self::FILTER_MIX]['loop'];
1601 if (is_null($mix_loop)) $mix_loop = false;
1602
1603 $mix_blockOffset = @$filters[self::FILTER_MIX]['blockOffset'];
1604 if (is_null($mix_blockOffset)) $mix_blockOffset = 0;
1605
1606 $mix_totalBlocks = $mix_wav->getNumBlocks();
1607 $mix_numBlocks = @$filters[self::FILTER_MIX]['numBlocks'];
1608 if (is_null($mix_numBlocks)) $mix_numBlocks = $mix_loop ? $mix_totalBlocks : $mix_totalBlocks - $mix_blockOffset;
1609 $mix_maxBlock = min($mix_blockOffset + $mix_numBlocks, $mix_totalBlocks);
1610
1611 $filter_mix = true;
1612 }
1613
1614 $filter_normalize = false;
1615 if (array_key_exists(self::FILTER_NORMALIZE, $filters)) {
1616 $normalize_threshold = @$filters[self::FILTER_NORMALIZE];
1617
1618 if (!is_null($normalize_threshold) && abs($normalize_threshold) != 1) $filter_normalize = true;
1619 }
1620
1621 $filter_degrade = false;
1622 if (array_key_exists(self::FILTER_DEGRADE, $filters)) {
1623 $degrade_quality = @$filters[self::FILTER_DEGRADE];
1624 if (is_null($degrade_quality)) $degrade_quality = 1;
1625
1626 if ($degrade_quality >= 0 && $degrade_quality < 1) $filter_degrade = true;
1627 }
1628
1629
1630 // loop through all sample blocks
1631 for ($block = 0; $block < $numBlocks; ++$block) {
1632 // loop through all channels
1633 for ($channel = 1; $channel <= $numChannels; ++$channel) {
1634 // read current sample
1635 $currentBlock = $blockOffset + $block;
1636 $sampleFloat = $this->getSampleValue($currentBlock, $channel);
1637
1638
1639 /************* MIX FILTER ***********************/
1640 if ($filter_mix) {
1641 if ($mix_loop) {
1642 $mixBlock = ($mix_blockOffset + ($block % $mix_numBlocks)) % $mix_totalBlocks;
1643 } else {
1644 $mixBlock = $mix_blockOffset + $block;
1645 }
1646
1647 if ($mixBlock < $mix_maxBlock) {
1648 $sampleFloat += $mix_wav->getSampleValue($mixBlock, $channel);
1649 }
1650 }
1651
1652 /************* NORMALIZE FILTER *******************/
1653 if ($filter_normalize) {
1654 $sampleFloat = $this->normalizeSample($sampleFloat, $normalize_threshold);
1655 }
1656
1657 /************* DEGRADE FILTER *******************/
1658 if ($filter_degrade) {
1659 $sampleFloat += rand(1000000 * ($degrade_quality - 1), 1000000 * (1 - $degrade_quality)) / 1000000;
1660 }
1661
1662
1663 // write current sample
1664 $this->setSampleValue($sampleFloat, $currentBlock, $channel);
1665 }
1666 }
1667
1668 return $this;
1669 }
const FILTER_MIX
Definition: WavFile.php:75
static normalizeSample($sampleFloat, $threshold)
Normalizes a float audio sample.
Definition: WavFile.php:419
getSampleValue($blockNum, $channelNum)
Get a float sample value for a specific sample block and channel number.
Definition: WavFile.php:1389
setSampleValue($sampleFloat, $blockNum, $channelNum)
Sets a float sample value for a specific sample block number and channel.
Definition: WavFile.php:1453
const FILTER_NORMALIZE
Definition: WavFile.php:78

References FILTER_DEGRADE, FILTER_MIX, FILTER_NORMALIZE, getNumBlocks(), getNumChannels(), getSampleValue(), normalizeSample(), and setSampleValue().

Referenced by degrade(), and mergeWav().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateNoise()

WavFile::generateNoise (   $duration = 1.0,
  $percent = 100 
)

Generate noise at the end of the wav for the specified duration and volume.

Parameters
float$duration(Optional) Number of seconds of noise to generate.
float$percent(Optional) The percentage of the maximum amplitude to use. 100 = full amplitude.

Definition at line 1749 of file WavFile.php.

1750 {
1751 $numChannels = $this->getNumChannels();
1752 $numSamples = $this->getSampleRate() * $duration;
1753 $minAmp = $this->getMinAmplitude();
1754 $maxAmp = $this->getMaxAmplitude();
1755 $bitDepth = $this->getBitsPerSample();
1756
1757 for ($s = 0; $s < $numSamples; ++$s) {
1758 if ($bitDepth == 32) {
1759 $val = rand(-$percent * 10000, $percent * 10000) / 1000000;
1760 } else {
1761 $val = rand($minAmp, $maxAmp);
1762 $val = (int)($val * $percent / 100);
1763 }
1764
1765 $this->_samples .= str_repeat(self::packSample($val, $bitDepth), $numChannels);
1766 }
1767
1768 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
1769
1770 return $this;
1771 }
getMinAmplitude()
Definition: WavFile.php:797
getMaxAmplitude()
Definition: WavFile.php:819

References getBitsPerSample(), getMaxAmplitude(), getMinAmplitude(), getNumChannels(), getSampleRate(), and setDataSize().

+ Here is the call graph for this function:

◆ getActualSize()

WavFile::getActualSize ( )

Definition at line 453 of file WavFile.php.

453 {
454 return $this->_actualSize;
455 }
$_actualSize
Definition: WavFile.php:141

References $_actualSize.

Referenced by displayInfo().

+ Here is the caller graph for this function:

◆ getAudioFormat()

WavFile::getAudioFormat ( )

Definition at line 583 of file WavFile.php.

583 {
584 return $this->_audioFormat;
585 }
$_audioFormat
Definition: WavFile.php:168

References $_audioFormat.

Referenced by displayInfo(), and makeHeader().

+ Here is the caller graph for this function:

◆ getAudioSubFormat()

WavFile::getAudioSubFormat ( )

Definition at line 612 of file WavFile.php.

612 {
614 }
$_audioSubFormat
Definition: WavFile.php:171

References $_audioSubFormat.

Referenced by displayInfo(), and makeHeader().

+ Here is the caller graph for this function:

◆ getBitsPerSample()

WavFile::getBitsPerSample ( )

Definition at line 693 of file WavFile.php.

693 {
695 }
$_bitsPerSample
Definition: WavFile.php:183

References $_bitsPerSample.

Referenced by appendWav(), convertBitsPerSample(), displayInfo(), generateNoise(), insertSilence(), and makeHeader().

+ Here is the caller graph for this function:

◆ getBlockAlign()

WavFile::getBlockAlign ( )

Definition at line 732 of file WavFile.php.

732 {
733 return $this->_blockAlign;
734 }
$_blockAlign
Definition: WavFile.php:189

References $_blockAlign.

Referenced by displayInfo(), makeHeader(), and readWavData().

+ Here is the caller graph for this function:

◆ getByteRate()

WavFile::getByteRate ( )

Definition at line 763 of file WavFile.php.

763 {
764 return $this->_byteRate;
765 }
$_byteRate
Definition: WavFile.php:195

References $_byteRate.

Referenced by displayInfo(), and makeHeader().

+ Here is the caller graph for this function:

◆ getChannelMask()

WavFile::getChannelMask ( )

Definition at line 650 of file WavFile.php.

650 {
651 return $this->_channelMask;
652 }
$_channelMask
Definition: WavFile.php:177

References $_channelMask.

Referenced by displayInfo(), and makeHeader().

+ Here is the caller graph for this function:

◆ getChunkSize()

WavFile::getChunkSize ( )

Definition at line 467 of file WavFile.php.

467 {
468 return $this->_chunkSize;
469 }
$_chunkSize
Definition: WavFile.php:144

References $_chunkSize.

Referenced by displayInfo(), and makeHeader().

+ Here is the caller graph for this function:

◆ getDataOffset()

WavFile::getDataOffset ( )

Definition at line 565 of file WavFile.php.

565 {
566 return $this->_dataOffset;
567 }
$_dataOffset
Definition: WavFile.php:165

References $_dataOffset.

Referenced by displayInfo().

+ Here is the caller graph for this function:

◆ getDataSize()

WavFile::getDataSize ( )

Definition at line 547 of file WavFile.php.

547 {
548 return $this->_dataSize;
549 }
$_dataSize
Definition: WavFile.php:156

References $_dataSize.

Referenced by displayInfo(), and getDataSubchunk().

+ Here is the caller graph for this function:

◆ getDataSubchunk()

WavFile::getDataSubchunk ( )

Construct wav DATA chunk.

Returns
string The DATA header and chunk.

Definition at line 884 of file WavFile.php.

885 {
886 // check preconditions
887 if (!$this->_dataSize_valid) {
888 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
889 }
890
891
892 // create subchunk
893 return pack('N', 0x64617461) . // SubchunkID - "data"
894 pack('V', $this->getDataSize()) . // SubchunkSize
895 $this->_samples . // Subchunk data
896 ($this->getDataSize() & 1 ? chr(0) : ''); // padding byte
897 }

References getDataSize(), and setDataSize().

Referenced by __toString(), and save().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getFactChunkSize()

WavFile::getFactChunkSize ( )

Definition at line 526 of file WavFile.php.

526 {
528 }
$_factChunkSize
Definition: WavFile.php:153

References $_factChunkSize.

Referenced by displayInfo(), and makeHeader().

+ Here is the caller graph for this function:

◆ getFmtChunkSize()

WavFile::getFmtChunkSize ( )

Definition at line 487 of file WavFile.php.

487 {
489 }
$_fmtChunkSize
Definition: WavFile.php:147

References $_fmtChunkSize.

Referenced by displayInfo(), and makeHeader().

+ Here is the caller graph for this function:

◆ getFmtExtendedSize()

WavFile::getFmtExtendedSize ( )

Definition at line 504 of file WavFile.php.

504 {
506 }
$_fmtExtendedSize
Definition: WavFile.php:150

References $_fmtExtendedSize.

Referenced by displayInfo(), and makeHeader().

+ Here is the caller graph for this function:

◆ getMaxAmplitude()

WavFile::getMaxAmplitude ( )

Definition at line 819 of file WavFile.php.

820 {
821 if($this->_bitsPerSample == 8) {
822 return 0xFF;
823 } elseif($this->_bitsPerSample == 32) {
824 return 1.0;
825 } else {
826 return (1 << ($this->_bitsPerSample - 1)) - 1;
827 }
828 }

Referenced by generateNoise().

+ Here is the caller graph for this function:

◆ getMinAmplitude()

WavFile::getMinAmplitude ( )

Definition at line 797 of file WavFile.php.

798 {
799 if ($this->_bitsPerSample == 8) {
800 return 0;
801 } elseif ($this->_bitsPerSample == 32) {
802 return -1.0;
803 } else {
804 return -(1 << ($this->_bitsPerSample - 1));
805 }
806 }

Referenced by generateNoise().

+ Here is the caller graph for this function:

◆ getNumBlocks()

WavFile::getNumBlocks ( )

Definition at line 748 of file WavFile.php.

749 {
750 return $this->_numBlocks;
751 }
$_numBlocks
Definition: WavFile.php:192

References $_numBlocks.

Referenced by convertBitsPerSample(), displayInfo(), filter(), and makeHeader().

+ Here is the caller graph for this function:

◆ getNumChannels()

WavFile::getNumChannels ( )

Definition at line 630 of file WavFile.php.

630 {
631 return $this->_numChannels;
632 }
$_numChannels
Definition: WavFile.php:174

References $_numChannels.

Referenced by appendWav(), convertBitsPerSample(), displayInfo(), filter(), generateNoise(), insertSilence(), and makeHeader().

+ Here is the caller graph for this function:

◆ getSampleBlock()

WavFile::getSampleBlock (   $blockNum)

Return a single sample block from the file.

Parameters
int$blockNum(Required) The sample block number. Zero based.
Returns
string The binary sample block (all channels). Returns null if the sample block number was out of range.

Definition at line 1319 of file WavFile.php.

1320 {
1321 // check preconditions
1322 if (!$this->_dataSize_valid) {
1323 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
1324 }
1325
1326 $offset = $blockNum * $this->_blockAlign;
1327 if ($offset + $this->_blockAlign > $this->_dataSize || $offset < 0) {
1328 return null;
1329 }
1330
1331
1332 // read data
1333 return substr($this->_samples, $offset, $this->_blockAlign);
1334 }

References $_blockAlign, and setDataSize().

+ Here is the call graph for this function:

◆ getSampleRate()

WavFile::getSampleRate ( )

Definition at line 675 of file WavFile.php.

675 {
676 return $this->_sampleRate;
677 }
$_sampleRate
Definition: WavFile.php:180

References $_sampleRate.

Referenced by appendWav(), convertBitsPerSample(), displayInfo(), generateNoise(), insertSilence(), and makeHeader().

+ Here is the caller graph for this function:

◆ getSamples()

WavFile::getSamples ( )

Definition at line 777 of file WavFile.php.

777 {
778 return $this->_samples;
779 }

References $_samples.

◆ getSampleValue()

WavFile::getSampleValue (   $blockNum,
  $channelNum 
)

Get a float sample value for a specific sample block and channel number.

Parameters
int$blockNum(Required) The sample block number to fetch. Zero based.
int$channelNum(Required) The channel number within the sample block to fetch. First channel is 1.
Returns
float The float sample value. Returns null if the sample block number was out of range.
Exceptions
WavFileException

Definition at line 1389 of file WavFile.php.

1390 {
1391 // check preconditions
1392 if ($channelNum < 1 || $channelNum > $this->_numChannels) {
1393 throw new WavFileException('Channel number is out of range.');
1394 }
1395
1396 if (!$this->_dataSize_valid) {
1397 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
1398 }
1399
1400 $sampleBytes = $this->_bitsPerSample / 8;
1401 $offset = $blockNum * $this->_blockAlign + ($channelNum - 1) * $sampleBytes;
1402 if ($offset + $sampleBytes > $this->_dataSize || $offset < 0) {
1403 return null;
1404 }
1405
1406 // read binary value
1407 $sampleBinary = substr($this->_samples, $offset, $sampleBytes);
1408
1409 // convert binary to value
1410 switch ($this->_bitsPerSample) {
1411 case 8:
1412 // unsigned char
1413 return (float)((ord($sampleBinary) - 0x80) / 0x80);
1414
1415 case 16:
1416 // signed short, little endian
1417 $data = unpack('v', $sampleBinary);
1418 $sample = $data[1];
1419 if ($sample >= 0x8000) {
1420 $sample -= 0x10000;
1421 }
1422 return (float)($sample / 0x8000);
1423
1424 case 24:
1425 // 3 byte packed signed integer, little endian
1426 $data = unpack('C3', $sampleBinary);
1427 $sample = $data[1] | ($data[2] << 8) | ($data[3] << 16);
1428 if ($sample >= 0x800000) {
1429 $sample -= 0x1000000;
1430 }
1431 return (float)($sample / 0x800000);
1432
1433 case 32:
1434 // 32-bit float
1435 $data = unpack('f', $sampleBinary);
1436 return (float)$data[1];
1437
1438 default:
1439 return null;
1440 }
1441 }
$data

References $data, and setDataSize().

Referenced by filter().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getValidBitsPerSample()

WavFile::getValidBitsPerSample ( )

Definition at line 713 of file WavFile.php.

713 {
715 }
$_validBitsPerSample
Definition: WavFile.php:186

References $_validBitsPerSample.

Referenced by displayInfo(), and makeHeader().

+ Here is the caller graph for this function:

◆ getZeroAmplitude()

WavFile::getZeroAmplitude ( )

Definition at line 808 of file WavFile.php.

809 {
810 if ($this->_bitsPerSample == 8) {
811 return 0x80;
812 } elseif ($this->_bitsPerSample == 32) {
813 return 0.0;
814 } else {
815 return 0;
816 }
817 }

Referenced by insertSilence().

+ Here is the caller graph for this function:

◆ insertSilence()

WavFile::insertSilence (   $duration = 1.0)

Add silence to the wav file.

Parameters
float$duration(Optional) How many seconds of silence. If negative, add to the beginning of the file. Defaults to 1s.

Definition at line 1714 of file WavFile.php.

1715 {
1716 $numSamples = (int)($this->getSampleRate() * abs($duration));
1717 $numChannels = $this->getNumChannels();
1718
1719 $data = str_repeat(self::packSample($this->getZeroAmplitude(), $this->getBitsPerSample()), $numSamples * $numChannels);
1720 if ($duration >= 0) {
1721 $this->_samples .= $data;
1722 } else {
1723 $this->_samples = $data . $this->_samples;
1724 }
1725
1726 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
1727
1728 return $this;
1729 }
getZeroAmplitude()
Definition: WavFile.php:808

References $_samples, $data, getBitsPerSample(), getNumChannels(), getSampleRate(), getZeroAmplitude(), and setDataSize().

+ Here is the call graph for this function:

◆ makeHeader()

WavFile::makeHeader ( )

Construct a wav header from this object.

Includes "fact" chunk in necessary. http://www-mmsp.ece.mcgill.ca/documents/audioformats/wave/wave.html

Returns
string The RIFF header data.

Definition at line 840 of file WavFile.php.

841 {
842 // reset and recalculate
843 $this->setAudioFormat(); // implicit setAudioSubFormat(), setFactChunkSize(), setFmtExtendedSize(), setFmtChunkSize(), setSize(), setActualSize(), setDataOffset()
844 $this->setNumBlocks();
845
846 // RIFF header
847 $header = pack('N', 0x52494646); // ChunkID - "RIFF"
848 $header .= pack('V', $this->getChunkSize()); // ChunkSize
849 $header .= pack('N', 0x57415645); // Format - "WAVE"
850
851 // "fmt " subchunk
852 $header .= pack('N', 0x666d7420); // SubchunkID - "fmt "
853 $header .= pack('V', $this->getFmtChunkSize()); // SubchunkSize
854 $header .= pack('v', $this->getAudioFormat()); // AudioFormat
855 $header .= pack('v', $this->getNumChannels()); // NumChannels
856 $header .= pack('V', $this->getSampleRate()); // SampleRate
857 $header .= pack('V', $this->getByteRate()); // ByteRate
858 $header .= pack('v', $this->getBlockAlign()); // BlockAlign
859 $header .= pack('v', $this->getBitsPerSample()); // BitsPerSample
860 if($this->getFmtExtendedSize() == 24) {
861 $header .= pack('v', 22); // extension size = 24 bytes, cbSize: 24 - 2 = 22 bytes
862 $header .= pack('v', $this->getValidBitsPerSample()); // ValidBitsPerSample
863 $header .= pack('V', $this->getChannelMask()); // ChannelMask
864 $header .= pack('H32', $this->getAudioSubFormat()); // SubFormat
865 } elseif ($this->getFmtExtendedSize() == 2) {
866 $header .= pack('v', 0); // extension size = 2 bytes, cbSize: 2 - 2 = 0 bytes
867 }
868
869 // "fact" subchunk
870 if ($this->getFactChunkSize() == 4) {
871 $header .= pack('N', 0x66616374); // SubchunkID - "fact"
872 $header .= pack('V', 4); // SubchunkSize
873 $header .= pack('V', $this->getNumBlocks()); // SampleLength (per channel)
874 }
875
876 return $header;
877 }
setNumBlocks($numBlocks=null)
Definition: WavFile.php:753
setAudioFormat($audioFormat=null)
Definition: WavFile.php:587
$header

References $header, getAudioFormat(), getAudioSubFormat(), getBitsPerSample(), getBlockAlign(), getByteRate(), getChannelMask(), getChunkSize(), getFactChunkSize(), getFmtChunkSize(), getFmtExtendedSize(), getNumBlocks(), getNumChannels(), getSampleRate(), getValidBitsPerSample(), setAudioFormat(), and setNumBlocks().

Referenced by __toString(), and save().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mergeWav()

WavFile::mergeWav ( WavFile  $wav,
  $normalizeThreshold = null 
)

Mix 2 wav files together.


Both wavs must have the same sample rate and same number of channels.

Parameters
WavFile$wav(Required) The WavFile to mix.
float$normalizeThreshold(Optional) See normalizeSample for an explanation.
Exceptions
WavFileException

Definition at line 1702 of file WavFile.php.

1702 {
1703 return $this->filter(array(
1704 WavFile::FILTER_MIX => $wav,
1705 WavFile::FILTER_NORMALIZE => $normalizeThreshold
1706 ));
1707 }

References filter(), FILTER_MIX, and FILTER_NORMALIZE.

+ Here is the call graph for this function:

◆ normalizeSample()

static WavFile::normalizeSample (   $sampleFloat,
  $threshold 
)
static

Normalizes a float audio sample.

Maximum input range assumed for compression is [-2, 2]. See http://www.voegler.eu/pub/audio/ for more information.

Parameters
float$sampleFloat(Required) The float sample to normalize.
float$threshold(Required) The threshold or gain factor for normalizing the amplitude.
  • >= 1 - Normalize by multiplying by the threshold (boost - positive gain).
    A value of 1 in effect means no normalization (and results in clipping).
  • <= -1 - Normalize by dividing by the the absolute value of threshold (attenuate - negative gain).
    A factor of 2 (-2) is about 6dB reduction in volume.
  • [0, 1) - (open inverval - not including 1) - The threshold above which amplitudes are comressed logarithmically.
    e.g. 0.6 to leave amplitudes up to 60% "as is" and compress above.
  • (-1, 0) - (open inverval - not including -1 and 0) - The threshold above which amplitudes are comressed linearly.
    e.g. -0.6 to leave amplitudes up to 60% "as is" and compress above.
Returns
float The normalized sample.

Definition at line 419 of file WavFile.php.

419 {
420 // apply positive gain
421 if ($threshold >= 1) {
422 return $sampleFloat * $threshold;
423 }
424
425 // apply negative gain
426 if ($threshold <= -1) {
427 return $sampleFloat / -$threshold;
428 }
429
430 $sign = $sampleFloat < 0 ? -1 : 1;
431 $sampleAbs = abs($sampleFloat);
432
433 // logarithmic compression
434 if ($threshold >= 0 && $threshold < 1 && $sampleAbs > $threshold) {
435 $loga = self::$LOOKUP_LOGBASE[(int)($threshold * 20)]; // log base modifier
436 return $sign * ($threshold + (1 - $threshold) * log(1 + $loga * ($sampleAbs - $threshold) / (2 - $threshold)) / log(1 + $loga));
437 }
438
439 // linear compression
440 $thresholdAbs = abs($threshold);
441 if ($threshold > -1 && $threshold < 0 && $sampleAbs > $thresholdAbs) {
442 return $sign * ($thresholdAbs + (1 - $thresholdAbs) / (2 - $thresholdAbs) * ($sampleAbs - $thresholdAbs));
443 }
444
445 // else ?
446 return $sampleFloat;
447 }

Referenced by filter().

+ Here is the caller graph for this function:

◆ openWav()

WavFile::openWav (   $filename,
  $readData = true 
)

Reads a wav header and data from a file.

Parameters
string$filename(Required) The path to the wav file to read.
bool$readData(Optional) If true, also read the data chunk.
Exceptions
WavFormatException
WavFileException

Definition at line 927 of file WavFile.php.

928 {
929 // check preconditions
930 if (!file_exists($filename)) {
931 throw new WavFileException('Failed to open "' . $filename . '". File not found.');
932 } elseif (!is_readable($filename)) {
933 throw new WavFileException('Failed to open "' . $filename . '". File is not readable.');
934 } elseif (is_resource($this->_fp)) {
935 $this->closeWav();
936 }
937
938
939 // open the file
940 $this->_fp = @fopen($filename, 'rb');
941 if (!is_resource($this->_fp)) {
942 throw new WavFileException('Failed to open "' . $filename . '".');
943 }
944
945 // read the file
946 return $this->readWav($readData);
947 }
$filename
Definition: buildRTE.php:89
readWav($readData=true)
Read wav file from a stream.
Definition: WavFile.php:997

References $filename, closeWav(), and readWav().

Referenced by __construct().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ packSample()

static WavFile::packSample (   $sample,
  $bitDepth 
)
static

Packs a single numeric sample to binary.

Parameters
int | float$sample(Required) The sample to encode. Has to be within valid range for $bitDepth. Float values only for 32 bits.
int$bitDepth(Required) The bits per sample to encode with.
Returns
string The encoded binary sample. Returns null for unsupported bit depths.

Definition at line 332 of file WavFile.php.

333 {
334 switch ($bitDepth) {
335 case 8:
336 // unsigned char
337 return chr($sample);
338
339 case 16:
340 // signed short, little endian
341 if ($sample < 0) {
342 $sample += 0x10000;
343 }
344 return pack('v', $sample);
345
346 case 24:
347 // 3 byte packed signed integer, little endian
348 if ($sample < 0) {
349 $sample += 0x1000000;
350 }
351 return pack('C3', $sample & 0xff, ($sample >> 8) & 0xff, ($sample >> 16) & 0xff);
352
353 case 32:
354 // 32-bit float
355 return pack('f', $sample);
356
357 default:
358 return null;
359 }
360 }

Referenced by packSampleBlock().

+ Here is the caller graph for this function:

◆ packSampleBlock()

static WavFile::packSampleBlock (   $samples,
  $bitDepth 
)
static

Packs an array of numeric channel samples to a binary sample block.

Parameters
array$samples(Required) The array of channel sample values. Expects float values for 32 bits and integer otherwise.
int$bitDepth(Required) The bits per sample to encode with.
Returns
string The encoded binary sample block.

Definition at line 392 of file WavFile.php.

392 {
393 $sampleBlock = '';
394 foreach($samples as $sample) {
395 $sampleBlock .= self::packSample($sample, $bitDepth);
396 }
397
398 return $sampleBlock;
399 }
static packSample($sample, $bitDepth)
Packs a single numeric sample to binary.
Definition: WavFile.php:332

References packSample().

+ Here is the call graph for this function:

◆ readWav()

WavFile::readWav (   $readData = true)
protected

Read wav file from a stream.

Parameters
$readData(Optional) If true, also read the data chunk.
Exceptions
WavFormatException
WavFileException

Definition at line 997 of file WavFile.php.

998 {
999 if (!is_resource($this->_fp)) {
1000 throw new WavFileException('No wav file open. Use openWav() first.');
1001 }
1002
1003 try {
1004 $this->readWavHeader();
1005 } catch (WavFileException $ex) {
1006 $this->closeWav();
1007 throw $ex;
1008 }
1009
1010 if ($readData) return $this->readWavData();
1011
1012 return $this;
1013 }
readWavData($dataOffset=0, $dataSize=null)
Read the wav data from the file into the buffer.
Definition: WavFile.php:1278
readWavHeader()
Parse a wav header.
Definition: WavFile.php:1022

References closeWav(), readWavData(), and readWavHeader().

Referenced by openWav(), and setWavData().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readWavData()

WavFile::readWavData (   $dataOffset = 0,
  $dataSize = null 
)

Read the wav data from the file into the buffer.

Parameters
$dataOffset(Optional) The byte offset to skip before starting to read. Must be a multiple of BlockAlign.
$dataSize(Optional) The size of the data to read in bytes. Must be a multiple of BlockAlign. Defaults to all data.
Exceptions
WavFileException

Definition at line 1278 of file WavFile.php.

1279 {
1280 // check preconditions
1281 if (!is_resource($this->_fp)) {
1282 throw new WavFileException('No wav file open. Use openWav() first.');
1283 }
1284
1285 if ($dataOffset < 0 || $dataOffset % $this->getBlockAlign() > 0) {
1286 throw new WavFileException('Invalid data offset. Has to be a multiple of BlockAlign.');
1287 }
1288
1289 if (is_null($dataSize)) {
1290 $dataSize = $this->_dataSize_fp - ($this->_dataSize_fp % $this->getBlockAlign()); // only read complete blocks
1291 } elseif ($dataSize < 0 || $dataSize % $this->getBlockAlign() > 0) {
1292 throw new WavFileException('Invalid data size to read. Has to be a multiple of BlockAlign.');
1293 }
1294
1295
1296 // skip offset
1297 if ($dataOffset > 0 && fseek($this->_fp, $dataOffset, SEEK_CUR) !== 0) {
1298 throw new WavFileException('Seeking to data offset failed.');
1299 }
1300
1301 // read data
1302 $this->_samples .= fread($this->_fp, $dataSize); // allow appending
1303 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
1304
1305 // close file or memory stream
1306 return $this->closeWav();
1307 }

References closeWav(), getBlockAlign(), and setDataSize().

Referenced by readWav().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ readWavHeader()

WavFile::readWavHeader ( )
protected

Parse a wav header.

http://www-mmsp.ece.mcgill.ca/documents/audioformats/wave/wave.html

Exceptions
WavFormatException
WavFileException

Definition at line 1022 of file WavFile.php.

1023 {
1024 if (!is_resource($this->_fp)) {
1025 throw new WavFileException('No wav file open. Use openWav() first.');
1026 }
1027
1028 // get actual file size
1029 $stat = fstat($this->_fp);
1030 $actualSize = $stat['size'];
1031
1032 $this->_actualSize = $actualSize;
1033
1034
1035 // read the common header
1036 $header = fread($this->_fp, 36); // minimum size of the wav header
1037 if (strlen($header) < 36) {
1038 throw new WavFormatException('Not wav format. Header too short.', 1);
1039 }
1040
1041
1042 // check "RIFF" header
1043 $RIFF = unpack('NChunkID/VChunkSize/NFormat', $header);
1044
1045 if ($RIFF['ChunkID'] != 0x52494646) { // "RIFF"
1046 throw new WavFormatException('Not wav format. "RIFF" signature missing.', 2);
1047 }
1048
1049 if ($actualSize - 8 < $RIFF['ChunkSize']) {
1050 trigger_error('"RIFF" chunk size does not match actual file size. Found ' . $RIFF['ChunkSize'] . ', expected ' . ($actualSize - 8) . '.', E_USER_NOTICE);
1051 $RIFF['ChunkSize'] = $actualSize - 8;
1052 //throw new WavFormatException('"RIFF" chunk size does not match actual file size. Found ' . $RIFF['ChunkSize'] . ', expected ' . ($actualSize - 8) . '.', 3);
1053 }
1054
1055 if ($RIFF['Format'] != 0x57415645) { // "WAVE"
1056 throw new WavFormatException('Not wav format. "RIFF" chunk format is not "WAVE".', 4);
1057 }
1058
1059 $this->_chunkSize = $RIFF['ChunkSize'];
1060
1061
1062 // check common "fmt " subchunk
1063 $fmt = unpack('NSubchunkID/VSubchunkSize/vAudioFormat/vNumChannels/'
1064 .'VSampleRate/VByteRate/vBlockAlign/vBitsPerSample',
1065 substr($header, 12));
1066
1067 if ($fmt['SubchunkID'] != 0x666d7420) { // "fmt "
1068 throw new WavFormatException('Bad wav header. Expected "fmt " subchunk.', 11);
1069 }
1070
1071 if ($fmt['SubchunkSize'] < 16) {
1072 throw new WavFormatException('Bad "fmt " subchunk size.', 12);
1073 }
1074
1075 if ( $fmt['AudioFormat'] != self::WAVE_FORMAT_PCM
1076 && $fmt['AudioFormat'] != self::WAVE_FORMAT_IEEE_FLOAT
1077 && $fmt['AudioFormat'] != self::WAVE_FORMAT_EXTENSIBLE)
1078 {
1079 throw new WavFormatException('Unsupported audio format. Only PCM or IEEE FLOAT (EXTENSIBLE) audio is supported.', 13);
1080 }
1081
1082 if ($fmt['NumChannels'] < 1 || $fmt['NumChannels'] > self::MAX_CHANNEL) {
1083 throw new WavFormatException('Invalid number of channels in "fmt " subchunk.', 14);
1084 }
1085
1086 if ($fmt['SampleRate'] < 1 || $fmt['SampleRate'] > self::MAX_SAMPLERATE) {
1087 throw new WavFormatException('Invalid sample rate in "fmt " subchunk.', 15);
1088 }
1089
1090 if ( ($fmt['AudioFormat'] == self::WAVE_FORMAT_PCM && !in_array($fmt['BitsPerSample'], array(8, 16, 24)))
1091 || ($fmt['AudioFormat'] == self::WAVE_FORMAT_IEEE_FLOAT && $fmt['BitsPerSample'] != 32)
1092 || ($fmt['AudioFormat'] == self::WAVE_FORMAT_EXTENSIBLE && !in_array($fmt['BitsPerSample'], array(8, 16, 24, 32))))
1093 {
1094 throw new WavFormatException('Only 8, 16 and 24-bit PCM and 32-bit IEEE FLOAT (EXTENSIBLE) audio is supported.', 16);
1095 }
1096
1097 $blockAlign = $fmt['NumChannels'] * $fmt['BitsPerSample'] / 8;
1098 if ($blockAlign != $fmt['BlockAlign']) {
1099 trigger_error('Invalid block align in "fmt " subchunk. Found ' . $fmt['BlockAlign'] . ', expected ' . $blockAlign . '.', E_USER_NOTICE);
1100 $fmt['BlockAlign'] = $blockAlign;
1101 //throw new WavFormatException('Invalid block align in "fmt " subchunk. Found ' . $fmt['BlockAlign'] . ', expected ' . $blockAlign . '.', 17);
1102 }
1103
1104 $byteRate = $fmt['SampleRate'] * $blockAlign;
1105 if ($byteRate != $fmt['ByteRate']) {
1106 trigger_error('Invalid average byte rate in "fmt " subchunk. Found ' . $fmt['ByteRate'] . ', expected ' . $byteRate . '.', E_USER_NOTICE);
1107 $fmt['ByteRate'] = $byteRate;
1108 //throw new WavFormatException('Invalid average byte rate in "fmt " subchunk. Found ' . $fmt['ByteRate'] . ', expected ' . $byteRate . '.', 18);
1109 }
1110
1111 $this->_fmtChunkSize = $fmt['SubchunkSize'];
1112 $this->_audioFormat = $fmt['AudioFormat'];
1113 $this->_numChannels = $fmt['NumChannels'];
1114 $this->_sampleRate = $fmt['SampleRate'];
1115 $this->_byteRate = $fmt['ByteRate'];
1116 $this->_blockAlign = $fmt['BlockAlign'];
1117 $this->_bitsPerSample = $fmt['BitsPerSample'];
1118
1119
1120 // read extended "fmt " subchunk data
1121 $extendedFmt = '';
1122 if ($fmt['SubchunkSize'] > 16) {
1123 // possibly handle malformed subchunk without a padding byte
1124 $extendedFmt = fread($this->_fp, $fmt['SubchunkSize'] - 16 + ($fmt['SubchunkSize'] & 1)); // also read padding byte
1125 if (strlen($extendedFmt) < $fmt['SubchunkSize'] - 16) {
1126 throw new WavFormatException('Not wav format. Header too short.', 1);
1127 }
1128 }
1129
1130
1131 // check extended "fmt " for EXTENSIBLE Audio Format
1132 if ($fmt['AudioFormat'] == self::WAVE_FORMAT_EXTENSIBLE) {
1133 if (strlen($extendedFmt) < 24) {
1134 throw new WavFormatException('Invalid EXTENSIBLE "fmt " subchunk size. Found ' . $fmt['SubchunkSize'] . ', expected at least 40.', 19);
1135 }
1136
1137 $extensibleFmt = unpack('vSize/vValidBitsPerSample/VChannelMask/H32SubFormat', substr($extendedFmt, 0, 24));
1138
1139 if ( $extensibleFmt['SubFormat'] != self::WAVE_SUBFORMAT_PCM
1140 && $extensibleFmt['SubFormat'] != self::WAVE_SUBFORMAT_IEEE_FLOAT)
1141 {
1142 throw new WavFormatException('Unsupported audio format. Only PCM or IEEE FLOAT (EXTENSIBLE) audio is supported.', 13);
1143 }
1144
1145 if ( ($extensibleFmt['SubFormat'] == self::WAVE_SUBFORMAT_PCM && !in_array($fmt['BitsPerSample'], array(8, 16, 24)))
1146 || ($extensibleFmt['SubFormat'] == self::WAVE_SUBFORMAT_IEEE_FLOAT && $fmt['BitsPerSample'] != 32))
1147 {
1148 throw new WavFormatException('Only 8, 16 and 24-bit PCM and 32-bit IEEE FLOAT (EXTENSIBLE) audio is supported.', 16);
1149 }
1150
1151 if ($extensibleFmt['Size'] != 22) {
1152 trigger_error('Invaid extension size in EXTENSIBLE "fmt " subchunk.', E_USER_NOTICE);
1153 $extensibleFmt['Size'] = 22;
1154 //throw new WavFormatException('Invaid extension size in EXTENSIBLE "fmt " subchunk.', 20);
1155 }
1156
1157 if ($extensibleFmt['ValidBitsPerSample'] != $fmt['BitsPerSample']) {
1158 trigger_error('Invaid or unsupported valid bits per sample in EXTENSIBLE "fmt " subchunk.', E_USER_NOTICE);
1159 $extensibleFmt['ValidBitsPerSample'] = $fmt['BitsPerSample'];
1160 //throw new WavFormatException('Invaid or unsupported valid bits per sample in EXTENSIBLE "fmt " subchunk.', 21);
1161 }
1162
1163 if ($extensibleFmt['ChannelMask'] != 0) {
1164 // count number of set bits - Hamming weight
1165 $c = (int)$extensibleFmt['ChannelMask'];
1166 $n = 0;
1167 while ($c > 0) {
1168 $n += $c & 1;
1169 $c >>= 1;
1170 }
1171 if ($n != $fmt['NumChannels'] || (((int)$extensibleFmt['ChannelMask'] | self::SPEAKER_ALL) != self::SPEAKER_ALL)) {
1172 trigger_error('Invalid channel mask in EXTENSIBLE "fmt " subchunk. The number of channels does not match the number of locations in the mask.', E_USER_NOTICE);
1173 $extensibleFmt['ChannelMask'] = 0;
1174 //throw new WavFormatException('Invalid channel mask in EXTENSIBLE "fmt " subchunk. The number of channels does not match the number of locations in the mask.', 22);
1175 }
1176 }
1177
1178 $this->_fmtExtendedSize = strlen($extendedFmt);
1179 $this->_validBitsPerSample = $extensibleFmt['ValidBitsPerSample'];
1180 $this->_channelMask = $extensibleFmt['ChannelMask'];
1181 $this->_audioSubFormat = $extensibleFmt['SubFormat'];
1182
1183 } else {
1184 $this->_fmtExtendedSize = strlen($extendedFmt);
1185 $this->_validBitsPerSample = $fmt['BitsPerSample'];
1186 $this->_channelMask = 0;
1187 $this->_audioSubFormat = null;
1188 }
1189
1190
1191 // read additional subchunks until "data" subchunk is found
1192 $factSubchunk = array();
1193 $dataSubchunk = array();
1194
1195 while (!feof($this->_fp)) {
1196 $subchunkHeader = fread($this->_fp, 8);
1197 if (strlen($subchunkHeader) < 8) {
1198 throw new WavFormatException('Missing "data" subchunk.', 101);
1199 }
1200
1201 $subchunk = unpack('NSubchunkID/VSubchunkSize', $subchunkHeader);
1202
1203 if ($subchunk['SubchunkID'] == 0x66616374) { // "fact"
1204 // possibly handle malformed subchunk without a padding byte
1205 $subchunkData = fread($this->_fp, $subchunk['SubchunkSize'] + ($subchunk['SubchunkSize'] & 1)); // also read padding byte
1206 if (strlen($subchunkData) < 4) {
1207 throw new WavFormatException('Invalid "fact" subchunk.', 102);
1208 }
1209
1210 $factParams = unpack('VSampleLength', substr($subchunkData, 0, 4));
1211 $factSubchunk = array_merge($subchunk, $factParams);
1212
1213 } elseif ($subchunk['SubchunkID'] == 0x64617461) { // "data"
1214 $dataSubchunk = $subchunk;
1215
1216 break;
1217
1218 } elseif ($subchunk['SubchunkID'] == 0x7761766C) { // "wavl"
1219 throw new WavFormatException('Wave List Chunk ("wavl" subchunk) is not supported.', 106);
1220 } else {
1221 // skip all other (unknown) subchunks
1222 // possibly handle malformed subchunk without a padding byte
1223 if ( $subchunk['SubchunkSize'] < 0
1224 || fseek($this->_fp, $subchunk['SubchunkSize'] + ($subchunk['SubchunkSize'] & 1), SEEK_CUR) !== 0) { // also skip padding byte
1225 throw new WavFormatException('Invalid subchunk (0x' . dechex($subchunk['SubchunkID']) . ') encountered.', 103);
1226 }
1227 }
1228 }
1229
1230 if (empty($dataSubchunk)) {
1231 throw new WavFormatException('Missing "data" subchunk.', 101);
1232 }
1233
1234
1235 // check "data" subchunk
1236 $dataOffset = ftell($this->_fp);
1237 if ($dataSubchunk['SubchunkSize'] < 0 || $actualSize - $dataOffset < $dataSubchunk['SubchunkSize']) {
1238 trigger_error('Invalid "data" subchunk size.', E_USER_NOTICE);
1239 $dataSubchunk['SubchunkSize'] = $actualSize - $dataOffset;
1240 //throw new WavFormatException('Invalid "data" subchunk size.', 104);
1241 }
1242
1243 $this->_dataOffset = $dataOffset;
1244 $this->_dataSize = $dataSubchunk['SubchunkSize'];
1245 $this->_dataSize_fp = $dataSubchunk['SubchunkSize'];
1246 $this->_dataSize_valid = false;
1247 $this->_samples = '';
1248
1249
1250 // check "fact" subchunk
1251 $numBlocks = (int)($dataSubchunk['SubchunkSize'] / $fmt['BlockAlign']);
1252
1253 if (empty($factSubchunk)) { // construct fake "fact" subchunk
1254 $factSubchunk = array('SubchunkSize' => 0, 'SampleLength' => $numBlocks);
1255 }
1256
1257 if ($factSubchunk['SampleLength'] != $numBlocks) {
1258 trigger_error('Invalid sample length in "fact" subchunk.', E_USER_NOTICE);
1259 $factSubchunk['SampleLength'] = $numBlocks;
1260 //throw new WavFormatException('Invalid sample length in "fact" subchunk.', 105);
1261 }
1262
1263 $this->_factChunkSize = $factSubchunk['SubchunkSize'];
1264 $this->_numBlocks = $factSubchunk['SampleLength'];
1265
1266
1267 return $this;
1268
1269 }
$n
Definition: RandomTest.php:80
WavFormatException indicates a malformed or unsupported wav file header.
Definition: WavFile.php:1864

References $header, and $n.

Referenced by readWav().

+ Here is the caller graph for this function:

◆ save()

WavFile::save (   $filename)

Save the wav data to a file.

Parameters
string$filename(Required) The file path to save the wav to.
Exceptions
WavFileException

Definition at line 905 of file WavFile.php.

906 {
907 $fp = @fopen($filename, 'w+b');
908 if (!is_resource($fp)) {
909 throw new WavFileException('Failed to open "' . $filename . '" for writing.');
910 }
911
912 fwrite($fp, $this->makeHeader());
913 fwrite($fp, $this->getDataSubchunk());
914 fclose($fp);
915
916 return $this;
917 }

References $filename, getDataSubchunk(), and makeHeader().

+ Here is the call graph for this function:

◆ setActualSize()

WavFile::setActualSize (   $actualSize = null)
protected

Definition at line 457 of file WavFile.php.

457 {
458 if (is_null($actualSize)) {
459 $this->_actualSize = 8 + $this->_chunkSize; // + "RIFF" header (ID + size)
460 } else {
461 $this->_actualSize = $actualSize;
462 }
463
464 return $this;
465 }

References $_chunkSize.

Referenced by setChunkSize().

+ Here is the caller graph for this function:

◆ setAudioFormat()

WavFile::setAudioFormat (   $audioFormat = null)
protected

Definition at line 587 of file WavFile.php.

587 {
588 if (is_null($audioFormat)) {
589 if (($this->_bitsPerSample <= 16 || $this->_bitsPerSample == 32)
590 && $this->_validBitsPerSample == $this->_bitsPerSample
591 && $this->_channelMask == self::SPEAKER_DEFAULT
592 && $this->_numChannels <= 2) {
593 if ($this->_bitsPerSample <= 16) {
594 $this->_audioFormat = self::WAVE_FORMAT_PCM;
595 } else {
596 $this->_audioFormat = self::WAVE_FORMAT_IEEE_FLOAT;
597 }
598 } else {
599 $this->_audioFormat = self::WAVE_FORMAT_EXTENSIBLE;
600 }
601 } else {
602 $this->_audioFormat = $audioFormat;
603 }
604
605 $this->setAudioSubFormat()
606 ->setFactChunkSize() // implicit setSize(), setActualSize(), setDataOffset()
607 ->setFmtExtendedSize(); // implicit setFmtChunkSize(), setSize(), setActualSize(), setDataOffset()
608
609 return $this;
610 }
setAudioSubFormat($audioSubFormat=null)
Definition: WavFile.php:616
const WAVE_FORMAT_EXTENSIBLE
Definition: WavFile.php:118
const WAVE_FORMAT_IEEE_FLOAT
Definition: WavFile.php:115

References setAudioSubFormat(), WAVE_FORMAT_EXTENSIBLE, WAVE_FORMAT_IEEE_FLOAT, and WAVE_FORMAT_PCM.

Referenced by makeHeader(), setChannelMask(), setNumChannels(), and setValidBitsPerSample().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setAudioSubFormat()

WavFile::setAudioSubFormat (   $audioSubFormat = null)
protected

Definition at line 616 of file WavFile.php.

616 {
617 if (is_null($audioSubFormat)) {
618 if ($this->_bitsPerSample == 32) {
619 $this->_audioSubFormat = self::WAVE_SUBFORMAT_IEEE_FLOAT; // 32 bits are IEEE FLOAT in this class
620 } else {
621 $this->_audioSubFormat = self::WAVE_SUBFORMAT_PCM; // 8, 16 and 24 bits are PCM in this class
622 }
623 } else {
624 $this->_audioSubFormat = $audioSubFormat;
625 }
626
627 return $this;
628 }
const WAVE_SUBFORMAT_PCM
Definition: WavFile.php:121
const WAVE_SUBFORMAT_IEEE_FLOAT
Definition: WavFile.php:124

References WAVE_SUBFORMAT_IEEE_FLOAT, and WAVE_SUBFORMAT_PCM.

Referenced by setAudioFormat().

+ Here is the caller graph for this function:

◆ setBitsPerSample()

WavFile::setBitsPerSample (   $bitsPerSample)

Definition at line 697 of file WavFile.php.

697 {
698 if (!in_array($bitsPerSample, array(8, 16, 24, 32))) {
699 throw new WavFileException('Unsupported bits per sample. Only 8, 16, 24 and 32 bits are supported.');
700 } elseif ($this->_samples !== '') {
701 trigger_error('Wav already has sample data. Changing the bits per sample does not convert and may corrupt the data.', E_USER_NOTICE);
702 }
703
704 $this->_bitsPerSample = (int)$bitsPerSample;
705
706 $this->setValidBitsPerSample() // implicit setAudioFormat(), setAudioSubFormat(), setFmtChunkSize(), setFactChunkSize(), setSize(), setActualSize(), setDataOffset()
707 ->setByteRate()
708 ->setBlockAlign(); // implicit setNumBlocks()
709
710 return $this;
711 }
setValidBitsPerSample($validBitsPerSample=null)
Definition: WavFile.php:717

References setValidBitsPerSample().

+ Here is the call graph for this function:

◆ setBlockAlign()

WavFile::setBlockAlign (   $blockAlign = null)
protected

Definition at line 736 of file WavFile.php.

736 {
737 if (is_null($blockAlign)) {
738 $this->_blockAlign = $this->_numChannels * $this->_bitsPerSample / 8;
739 } else {
740 $this->_blockAlign = $blockAlign;
741 }
742
743 $this->setNumBlocks();
744
745 return $this;
746 }

References setNumBlocks().

+ Here is the call graph for this function:

◆ setByteRate()

WavFile::setByteRate (   $byteRate = null)
protected

Definition at line 767 of file WavFile.php.

767 {
768 if (is_null($byteRate)) {
769 $this->_byteRate = $this->_sampleRate * $this->_numChannels * $this->_bitsPerSample / 8;
770 } else {
771 $this->_byteRate = $byteRate;
772 }
773
774 return $this;
775 }

Referenced by setSampleRate().

+ Here is the caller graph for this function:

◆ setChannelMask()

WavFile::setChannelMask (   $channelMask = self::SPEAKER_DEFAULT)

Definition at line 654 of file WavFile.php.

654 {
655 if ($channelMask != 0) {
656 // count number of set bits - Hamming weight
657 $c = (int)$channelMask;
658 $n = 0;
659 while ($c > 0) {
660 $n += $c & 1;
661 $c >>= 1;
662 }
663 if ($n != $this->_numChannels || (((int)$channelMask | self::SPEAKER_ALL) != self::SPEAKER_ALL)) {
664 throw new WavFileException('Invalid channel mask. The number of channels does not match the number of locations in the mask.');
665 }
666 }
667
668 $this->_channelMask = (int)$channelMask;
669
670 $this->setAudioFormat(); // implicit setAudioSubFormat(), setFactChunkSize(), setFmtExtendedSize(), setFmtChunkSize(), setSize(), setActualSize(), setDataOffset()
671
672 return $this;
673 }

References $n, and setAudioFormat().

+ Here is the call graph for this function:

◆ setChunkSize()

WavFile::setChunkSize (   $chunkSize = null)
protected

Definition at line 471 of file WavFile.php.

471 {
472 if (is_null($chunkSize)) {
473 $this->_chunkSize = 4 + // "WAVE" chunk
474 8 + $this->_fmtChunkSize + // "fmt " subchunk
475 ($this->_factChunkSize > 0 ? 8 + $this->_factChunkSize : 0) + // "fact" subchunk
476 8 + $this->_dataSize + // "data" subchunk
477 ($this->_dataSize & 1); // padding byte
478 } else {
479 $this->_chunkSize = $chunkSize;
480 }
481
482 $this->setActualSize();
483
484 return $this;
485 }
setActualSize($actualSize=null)
Definition: WavFile.php:457

References setActualSize().

Referenced by setDataSize(), setFactChunkSize(), and setFmtChunkSize().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setDataOffset()

WavFile::setDataOffset (   $dataOffset = null)
protected

Definition at line 569 of file WavFile.php.

569 {
570 if (is_null($dataOffset)) {
571 $this->_dataOffset = 8 + // "RIFF" header (ID + size)
572 4 + // "WAVE" chunk
573 8 + $this->_fmtChunkSize + // "fmt " subchunk
574 ($this->_factChunkSize > 0 ? 8 + $this->_factChunkSize : 0) + // "fact" subchunk
575 8; // "data" subchunk
576 } else {
577 $this->_dataOffset = $dataOffset;
578 }
579
580 return $this;
581 }

◆ setDataSize()

WavFile::setDataSize (   $dataSize = null)
protected

Definition at line 551 of file WavFile.php.

551 {
552 if (is_null($dataSize)) {
553 $this->_dataSize = strlen($this->_samples);
554 } else {
555 $this->_dataSize = $dataSize;
556 }
557
558 $this->setChunkSize() // implicit setActualSize()
559 ->setNumBlocks();
560 $this->_dataSize_valid = true;
561
562 return $this;
563 }
setChunkSize($chunkSize=null)
Definition: WavFile.php:471

References setChunkSize().

Referenced by appendWav(), convertBitsPerSample(), generateNoise(), getDataSubchunk(), getSampleBlock(), getSampleValue(), insertSilence(), readWavData(), setSampleBlock(), setSamples(), and setSampleValue().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setFactChunkSize()

WavFile::setFactChunkSize (   $factChunkSize = null)
protected

Definition at line 530 of file WavFile.php.

530 {
531 if (is_null($factChunkSize)) {
532 if ($this->_audioFormat != self::WAVE_FORMAT_PCM) {
533 $this->_factChunkSize = 4;
534 } else {
535 $this->_factChunkSize = 0;
536 }
537 } else {
538 $this->_factChunkSize = $factChunkSize;
539 }
540
541 $this->setChunkSize() // implicit setActualSize()
542 ->setDataOffset();
543
544 return $this;
545 }

References setChunkSize().

+ Here is the call graph for this function:

◆ setFmtChunkSize()

WavFile::setFmtChunkSize (   $fmtChunkSize = null)
protected

Definition at line 491 of file WavFile.php.

491 {
492 if (is_null($fmtChunkSize)) {
493 $this->_fmtChunkSize = 16 + $this->_fmtExtendedSize;
494 } else {
495 $this->_fmtChunkSize = $fmtChunkSize;
496 }
497
498 $this->setChunkSize() // implicit setActualSize()
499 ->setDataOffset();
500
501 return $this;
502 }

References $_fmtExtendedSize, and setChunkSize().

Referenced by setFmtExtendedSize().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setFmtExtendedSize()

WavFile::setFmtExtendedSize (   $fmtExtendedSize = null)
protected

Definition at line 508 of file WavFile.php.

508 {
509 if (is_null($fmtExtendedSize)) {
510 if ($this->_audioFormat == self::WAVE_FORMAT_EXTENSIBLE) {
511 $this->_fmtExtendedSize = 2 + 22; // extension size for WAVE_FORMAT_EXTENSIBLE
512 } elseif ($this->_audioFormat != self::WAVE_FORMAT_PCM) {
513 $this->_fmtExtendedSize = 2 + 0; // empty extension
514 } else {
515 $this->_fmtExtendedSize = 0; // no extension, only for WAVE_FORMAT_PCM
516 }
517 } else {
518 $this->_fmtExtendedSize = $fmtExtendedSize;
519 }
520
521 $this->setFmtChunkSize(); // implicit setSize(), setActualSize(), setDataOffset()
522
523 return $this;
524 }
setFmtChunkSize($fmtChunkSize=null)
Definition: WavFile.php:491

References setFmtChunkSize().

+ Here is the call graph for this function:

◆ setNumBlocks()

WavFile::setNumBlocks (   $numBlocks = null)
protected

Definition at line 753 of file WavFile.php.

753 {
754 if (is_null($numBlocks)) {
755 $this->_numBlocks = (int)($this->_dataSize / $this->_blockAlign); // do not count incomplete sample blocks
756 } else {
757 $this->_numBlocks = $numBlocks;
758 }
759
760 return $this;
761 }

Referenced by makeHeader(), and setBlockAlign().

+ Here is the caller graph for this function:

◆ setNumChannels()

WavFile::setNumChannels (   $numChannels)

Definition at line 634 of file WavFile.php.

634 {
635 if ($numChannels < 1 || $numChannels > self::MAX_CHANNEL) {
636 throw new WavFileException('Unsupported number of channels. Only up to ' . self::MAX_CHANNEL . ' channels are supported.');
637 } elseif ($this->_samples !== '') {
638 trigger_error('Wav already has sample data. Changing the number of channels does not convert and may corrupt the data.', E_USER_NOTICE);
639 }
640
641 $this->_numChannels = (int)$numChannels;
642
643 $this->setAudioFormat() // implicit setAudioSubFormat(), setFactChunkSize(), setFmtExtendedSize(), setFmtChunkSize(), setSize(), setActualSize(), setDataOffset()
644 ->setByteRate()
645 ->setBlockAlign(); // implicit setNumBlocks()
646
647 return $this;
648 }

References setAudioFormat().

Referenced by __construct().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setSampleBlock()

WavFile::setSampleBlock (   $sampleBlock,
  $blockNum 
)

Set a single sample block.


Allows to append a sample block.

Parameters
string$sampleBlock(Required) The binary sample block (all channels).
int$blockNum(Required) The sample block number. Zero based.
Exceptions
WavFileException

Definition at line 1344 of file WavFile.php.

1345 {
1346 // check preconditions
1347 $blockAlign = $this->_blockAlign;
1348 if (!isset($sampleBlock[$blockAlign - 1]) || isset($sampleBlock[$blockAlign])) { // faster than: if (strlen($sampleBlock) != $blockAlign)
1349 throw new WavFileException('Incorrect sample block size. Got ' . strlen($sampleBlock) . ', expected ' . $blockAlign . '.');
1350 }
1351
1352 if (!$this->_dataSize_valid) {
1353 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
1354 }
1355
1356 $numBlocks = (int)($this->_dataSize / $blockAlign);
1357 $offset = $blockNum * $blockAlign;
1358 if ($blockNum > $numBlocks || $blockNum < 0) { // allow appending
1359 throw new WavFileException('Sample block number is out of range.');
1360 }
1361
1362
1363 // replace or append data
1364 if ($blockNum == $numBlocks) {
1365 // append
1366 $this->_samples .= $sampleBlock;
1367 $this->_dataSize += $blockAlign;
1368 $this->_chunkSize += $blockAlign;
1369 $this->_actualSize += $blockAlign;
1370 $this->_numBlocks++;
1371 } else {
1372 // replace
1373 for ($i = 0; $i < $blockAlign; ++$i) {
1374 $this->_samples[$offset + $i] = $sampleBlock[$i];
1375 }
1376 }
1377
1378 return $this;
1379 }

References $_blockAlign, and setDataSize().

+ Here is the call graph for this function:

◆ setSampleRate()

WavFile::setSampleRate (   $sampleRate)

Definition at line 679 of file WavFile.php.

679 {
680 if ($sampleRate < 1 || $sampleRate > self::MAX_SAMPLERATE) {
681 throw new WavFileException('Invalid sample rate.');
682 } elseif ($this->_samples !== '') {
683 trigger_error('Wav already has sample data. Changing the sample rate does not convert the data and may yield undesired results.', E_USER_NOTICE);
684 }
685
686 $this->_sampleRate = (int)$sampleRate;
687
688 $this->setByteRate();
689
690 return $this;
691 }
setByteRate($byteRate=null)
Definition: WavFile.php:767

References setByteRate().

+ Here is the call graph for this function:

◆ setSamples()

WavFile::setSamples ( $samples = '')

Definition at line 781 of file WavFile.php.

781 {
782 if (strlen($samples) % $this->_blockAlign != 0) {
783 throw new WavFileException('Incorrect samples size. Has to be a multiple of BlockAlign.');
784 }
785
786 $this->_samples = $samples;
787
788 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
789
790 return $this;
791 }

References setDataSize().

Referenced by convertBitsPerSample().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setSampleValue()

WavFile::setSampleValue (   $sampleFloat,
  $blockNum,
  $channelNum 
)

Sets a float sample value for a specific sample block number and channel.


Converts float values to appropriate integer values and clips properly.
Allows to append samples (in order).

Parameters
float$sampleFloat(Required) The float sample value to set. Converts float values and clips if necessary.
int$blockNum(Required) The sample block number to set or append. Zero based.
int$channelNum(Required) The channel number within the sample block to set or append. First channel is 1.
Exceptions
WavFileException

Definition at line 1453 of file WavFile.php.

1454 {
1455 // check preconditions
1456 if ($channelNum < 1 || $channelNum > $this->_numChannels) {
1457 throw new WavFileException('Channel number is out of range.');
1458 }
1459
1460 if (!$this->_dataSize_valid) {
1461 $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks()
1462 }
1463
1464 $dataSize = $this->_dataSize;
1465 $bitsPerSample = $this->_bitsPerSample;
1466 $sampleBytes = $bitsPerSample / 8;
1467 $offset = $blockNum * $this->_blockAlign + ($channelNum - 1) * $sampleBytes;
1468 if (($offset + $sampleBytes > $dataSize && $offset != $dataSize) || $offset < 0) { // allow appending
1469 throw new WavFileException('Sample block or channel number is out of range.');
1470 }
1471
1472
1473 // convert to value, quantize and clip
1474 if ($bitsPerSample == 32) {
1475 $sample = $sampleFloat < -1.0 ? -1.0 : ($sampleFloat > 1.0 ? 1.0 : $sampleFloat);
1476 } else {
1477 $p = 1 << ($bitsPerSample - 1); // 2 to the power of _bitsPerSample divided by 2
1478
1479 // project and quantize (round) float to integer values
1480 $sample = $sampleFloat < 0 ? (int)($sampleFloat * $p - 0.5) : (int)($sampleFloat * $p + 0.5);
1481
1482 // clip if necessary to [-$p, $p - 1]
1483 if ($sample < -$p) {
1484 $sample = -$p;
1485 } elseif ($sample > $p - 1) {
1486 $sample = $p - 1;
1487 }
1488 }
1489
1490 // convert to binary
1491 switch ($bitsPerSample) {
1492 case 8:
1493 // unsigned char
1494 $sampleBinary = chr($sample + 0x80);
1495 break;
1496
1497 case 16:
1498 // signed short, little endian
1499 if ($sample < 0) {
1500 $sample += 0x10000;
1501 }
1502 $sampleBinary = pack('v', $sample);
1503 break;
1504
1505 case 24:
1506 // 3 byte packed signed integer, little endian
1507 if ($sample < 0) {
1508 $sample += 0x1000000;
1509 }
1510 $sampleBinary = pack('C3', $sample & 0xff, ($sample >> 8) & 0xff, ($sample >> 16) & 0xff);
1511 break;
1512
1513 case 32:
1514 // 32-bit float
1515 $sampleBinary = pack('f', $sample);
1516 break;
1517
1518 default:
1519 $sampleBinary = null;
1520 $sampleBytes = 0;
1521 break;
1522 }
1523
1524 // replace or append data
1525 if ($offset == $dataSize) {
1526 // append
1527 $this->_samples .= $sampleBinary;
1528 $this->_dataSize += $sampleBytes;
1529 $this->_chunkSize += $sampleBytes;
1530 $this->_actualSize += $sampleBytes;
1531 $this->_numBlocks = (int)($this->_dataSize / $this->_blockAlign);
1532 } else {
1533 // replace
1534 for ($i = 0; $i < $sampleBytes; ++$i) {
1535 $this->_samples{$offset + $i} = $sampleBinary{$i};
1536 }
1537 }
1538
1539 return $this;
1540 }

References $_bitsPerSample, $_dataSize, and setDataSize().

Referenced by filter().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setValidBitsPerSample()

WavFile::setValidBitsPerSample (   $validBitsPerSample = null)
protected

Definition at line 717 of file WavFile.php.

717 {
718 if (is_null($validBitsPerSample)) {
719 $this->_validBitsPerSample = $this->_bitsPerSample;
720 } else {
721 if ($validBitsPerSample < 1 || $validBitsPerSample > $this->_bitsPerSample) {
722 throw new WavFileException('ValidBitsPerSample cannot be greater than BitsPerSample.');
723 }
724 $this->_validBitsPerSample = (int)$validBitsPerSample;
725 }
726
727 $this->setAudioFormat(); // implicit setAudioSubFormat(), setFactChunkSize(), setFmtExtendedSize(), setFmtChunkSize(), setSize(), setActualSize(), setDataOffset()
728
729 return $this;
730 }

References $_bitsPerSample, and setAudioFormat().

Referenced by setBitsPerSample().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setWavData()

WavFile::setWavData ( $data,
  $free = true 
)

Set the wav file data and properties from a wav file in a string.

Parameters
string$data(Required) The wav file data. Passed by reference.
bool$free(Optional) True to free the passed $data after copying.
Exceptions
WavFormatException
WavFileException

Definition at line 967 of file WavFile.php.

968 {
969 // check preconditions
970 if (is_resource($this->_fp)) $this->closeWav();
971
972
973 // open temporary stream in memory
974 $this->_fp = @fopen('php://memory', 'w+b');
975 if (!is_resource($this->_fp)) {
976 throw new WavFileException('Failed to open memory stream to write wav data. Use openWav() instead.');
977 }
978
979 // prepare stream
980 fwrite($this->_fp, $data);
981 rewind($this->_fp);
982
983 // free the passed data
984 if ($free) $data = null;
985
986 // read the stream like a file
987 return $this->readWav(true);
988 }

References $data, closeWav(), and readWav().

+ Here is the call graph for this function:

◆ unpackSample()

static WavFile::unpackSample (   $sampleBinary,
  $bitDepth = null 
)
static

Unpacks a single binary sample to numeric value.

Parameters
string$sampleBinary(Required) The sample to decode.
int$bitDepth(Optional) The bits per sample to decode. If omitted, derives it from the length of $sampleBinary.
Returns
int|float The numeric sample value. Float for 32-bit samples. Returns null for unsupported bit depths.

Definition at line 286 of file WavFile.php.

287 {
288 if ($bitDepth === null) {
289 $bitDepth = strlen($sampleBinary) * 8;
290 }
291
292 switch ($bitDepth) {
293 case 8:
294 // unsigned char
295 return ord($sampleBinary);
296
297 case 16:
298 // signed short, little endian
299 $data = unpack('v', $sampleBinary);
300 $sample = $data[1];
301 if ($sample >= 0x8000) {
302 $sample -= 0x10000;
303 }
304 return $sample;
305
306 case 24:
307 // 3 byte packed signed integer, little endian
308 $data = unpack('C3', $sampleBinary);
309 $sample = $data[1] | ($data[2] << 8) | ($data[3] << 16);
310 if ($sample >= 0x800000) {
311 $sample -= 0x1000000;
312 }
313 return $sample;
314
315 case 32:
316 // 32-bit float
317 $data = unpack('f', $sampleBinary);
318 return $data[1];
319
320 default:
321 return null;
322 }
323 }

References $data.

Referenced by unpackSampleBlock().

+ Here is the caller graph for this function:

◆ unpackSampleBlock()

static WavFile::unpackSampleBlock (   $sampleBlock,
  $bitDepth,
  $numChannels = null 
)
static

Unpacks a binary sample block to numeric values.

Parameters
string$sampleBlock(Required) The binary sample block (all channels).
int$bitDepth(Required) The bits per sample to decode.
int$numChannels(Optional) The number of channels to decode. If omitted, derives it from the length of $sampleBlock and $bitDepth.
Returns
array The sample values as an array of integers of floats for 32 bits. First channel is array index 1.

Definition at line 370 of file WavFile.php.

370 {
371 $sampleBytes = $bitDepth / 8;
372 if ($numChannels === null) {
373 $numChannels = strlen($sampleBlock) / $sampleBytes;
374 }
375
376 $samples = array();
377 for ($i = 0; $i < $numChannels; $i++) {
378 $sampleBinary = substr($sampleBlock, $i * $sampleBytes, $sampleBytes);
379 $samples[$i + 1] = self::unpackSample($sampleBinary, $bitDepth);
380 }
381
382 return $samples;
383 }
static unpackSample($sampleBinary, $bitDepth=null)
Unpacks a single binary sample to numeric value.
Definition: WavFile.php:286

References unpackSample().

+ Here is the call graph for this function:

Field Documentation

◆ $_actualSize

WavFile::$_actualSize
protected

Definition at line 141 of file WavFile.php.

Referenced by getActualSize().

◆ $_audioFormat

WavFile::$_audioFormat
protected

Definition at line 168 of file WavFile.php.

Referenced by getAudioFormat().

◆ $_audioSubFormat

WavFile::$_audioSubFormat
protected

Definition at line 171 of file WavFile.php.

Referenced by getAudioSubFormat().

◆ $_bitsPerSample

WavFile::$_bitsPerSample
protected

Definition at line 183 of file WavFile.php.

Referenced by getBitsPerSample(), setSampleValue(), and setValidBitsPerSample().

◆ $_blockAlign

WavFile::$_blockAlign
protected

Definition at line 189 of file WavFile.php.

Referenced by getBlockAlign(), getSampleBlock(), and setSampleBlock().

◆ $_byteRate

WavFile::$_byteRate
protected

Definition at line 195 of file WavFile.php.

Referenced by getByteRate().

◆ $_channelMask

WavFile::$_channelMask
protected

Definition at line 177 of file WavFile.php.

Referenced by getChannelMask().

◆ $_chunkSize

WavFile::$_chunkSize
protected

Definition at line 144 of file WavFile.php.

Referenced by getChunkSize(), and setActualSize().

◆ $_dataOffset

WavFile::$_dataOffset
protected

Definition at line 165 of file WavFile.php.

Referenced by getDataOffset().

◆ $_dataSize

WavFile::$_dataSize
protected

Definition at line 156 of file WavFile.php.

Referenced by getDataSize(), and setSampleValue().

◆ $_dataSize_fp

WavFile::$_dataSize_fp
protected

Definition at line 159 of file WavFile.php.

◆ $_dataSize_valid

WavFile::$_dataSize_valid
protected

Definition at line 162 of file WavFile.php.

◆ $_factChunkSize

WavFile::$_factChunkSize
protected

Definition at line 153 of file WavFile.php.

Referenced by getFactChunkSize().

◆ $_fmtChunkSize

WavFile::$_fmtChunkSize
protected

Definition at line 147 of file WavFile.php.

Referenced by getFmtChunkSize().

◆ $_fmtExtendedSize

WavFile::$_fmtExtendedSize
protected

Definition at line 150 of file WavFile.php.

Referenced by getFmtExtendedSize(), and setFmtChunkSize().

◆ $_fp

WavFile::$_fp
protected

Definition at line 201 of file WavFile.php.

◆ $_numBlocks

WavFile::$_numBlocks
protected

Definition at line 192 of file WavFile.php.

Referenced by getNumBlocks().

◆ $_numChannels

WavFile::$_numChannels
protected

Definition at line 174 of file WavFile.php.

Referenced by getNumChannels().

◆ $_sampleRate

WavFile::$_sampleRate
protected

Definition at line 180 of file WavFile.php.

Referenced by getSampleRate().

◆ $_samples

WavFile::$_samples
protected

Definition at line 198 of file WavFile.php.

Referenced by getSamples(), and insertSilence().

◆ $_validBitsPerSample

WavFile::$_validBitsPerSample
protected

Definition at line 186 of file WavFile.php.

Referenced by getValidBitsPerSample().

◆ $LOOKUP_LOGBASE

WavFile::$LOOKUP_LOGBASE
staticprotected
Initial value:
= array(
2.513, 2.667, 2.841, 3.038, 3.262,
3.520, 3.819, 4.171, 4.589, 5.093,
5.711, 6.487, 7.483, 8.806, 10.634,
13.302, 17.510, 24.970, 41.155, 96.088
)

Definition at line 133 of file WavFile.php.

◆ FILTER_DEGRADE

const WavFile::FILTER_DEGRADE = 0x04

Definition at line 81 of file WavFile.php.

Referenced by degrade(), filter(), and Securimage\generateWAV().

◆ FILTER_MIX

const WavFile::FILTER_MIX = 0x01

Definition at line 75 of file WavFile.php.

Referenced by filter(), Securimage\generateWAV(), and mergeWav().

◆ FILTER_NORMALIZE

const WavFile::FILTER_NORMALIZE = 0x02

Definition at line 78 of file WavFile.php.

Referenced by filter(), Securimage\generateWAV(), and mergeWav().

◆ MAX_CHANNEL

const WavFile::MAX_CHANNEL = 18

Definition at line 84 of file WavFile.php.

◆ MAX_SAMPLERATE

const WavFile::MAX_SAMPLERATE = 192000

Definition at line 87 of file WavFile.php.

◆ SPEAKER_ALL

const WavFile::SPEAKER_ALL = 0x03FFFF

Definition at line 109 of file WavFile.php.

◆ SPEAKER_BACK_CENTER

const WavFile::SPEAKER_BACK_CENTER = 0x000100

Definition at line 99 of file WavFile.php.

◆ SPEAKER_BACK_LEFT

const WavFile::SPEAKER_BACK_LEFT = 0x000010

Definition at line 95 of file WavFile.php.

◆ SPEAKER_BACK_RIGHT

const WavFile::SPEAKER_BACK_RIGHT = 0x000020

Definition at line 96 of file WavFile.php.

◆ SPEAKER_DEFAULT

const WavFile::SPEAKER_DEFAULT = 0x000000

Channel Locations for ChannelMask.

Definition at line 90 of file WavFile.php.

Referenced by __construct().

◆ SPEAKER_FRONT_CENTER

const WavFile::SPEAKER_FRONT_CENTER = 0x000004

Definition at line 93 of file WavFile.php.

◆ SPEAKER_FRONT_LEFT

const WavFile::SPEAKER_FRONT_LEFT = 0x000001

Definition at line 91 of file WavFile.php.

◆ SPEAKER_FRONT_LEFT_OF_CENTER

const WavFile::SPEAKER_FRONT_LEFT_OF_CENTER = 0x000040

Definition at line 97 of file WavFile.php.

◆ SPEAKER_FRONT_RIGHT

const WavFile::SPEAKER_FRONT_RIGHT = 0x000002

Definition at line 92 of file WavFile.php.

◆ SPEAKER_FRONT_RIGHT_OF_CENTER

const WavFile::SPEAKER_FRONT_RIGHT_OF_CENTER = 0x000080

Definition at line 98 of file WavFile.php.

◆ SPEAKER_LOW_FREQUENCY

const WavFile::SPEAKER_LOW_FREQUENCY = 0x000008

Definition at line 94 of file WavFile.php.

◆ SPEAKER_SIDE_LEFT

const WavFile::SPEAKER_SIDE_LEFT = 0x000200

Definition at line 100 of file WavFile.php.

◆ SPEAKER_SIDE_RIGHT

const WavFile::SPEAKER_SIDE_RIGHT = 0x000400

Definition at line 101 of file WavFile.php.

◆ SPEAKER_TOP_BACK_CENTER

const WavFile::SPEAKER_TOP_BACK_CENTER = 0x010000

Definition at line 107 of file WavFile.php.

◆ SPEAKER_TOP_BACK_LEFT

const WavFile::SPEAKER_TOP_BACK_LEFT = 0x008000

Definition at line 106 of file WavFile.php.

◆ SPEAKER_TOP_BACK_RIGHT

const WavFile::SPEAKER_TOP_BACK_RIGHT = 0x020000

Definition at line 108 of file WavFile.php.

◆ SPEAKER_TOP_CENTER

const WavFile::SPEAKER_TOP_CENTER = 0x000800

Definition at line 102 of file WavFile.php.

◆ SPEAKER_TOP_FRONT_CENTER

const WavFile::SPEAKER_TOP_FRONT_CENTER = 0x002000

Definition at line 104 of file WavFile.php.

◆ SPEAKER_TOP_FRONT_LEFT

const WavFile::SPEAKER_TOP_FRONT_LEFT = 0x001000

Definition at line 103 of file WavFile.php.

◆ SPEAKER_TOP_FRONT_RIGHT

const WavFile::SPEAKER_TOP_FRONT_RIGHT = 0x004000

Definition at line 105 of file WavFile.php.

◆ WAVE_FORMAT_EXTENSIBLE

const WavFile::WAVE_FORMAT_EXTENSIBLE = 0xFFFE

Definition at line 118 of file WavFile.php.

Referenced by setAudioFormat().

◆ WAVE_FORMAT_IEEE_FLOAT

const WavFile::WAVE_FORMAT_IEEE_FLOAT = 0x0003

Definition at line 115 of file WavFile.php.

Referenced by setAudioFormat().

◆ WAVE_FORMAT_PCM

const WavFile::WAVE_FORMAT_PCM = 0x0001

Definition at line 112 of file WavFile.php.

Referenced by __construct(), and setAudioFormat().

◆ WAVE_SUBFORMAT_IEEE_FLOAT

const WavFile::WAVE_SUBFORMAT_IEEE_FLOAT = "0300000000001000800000aa00389b71"

Definition at line 124 of file WavFile.php.

Referenced by setAudioSubFormat().

◆ WAVE_SUBFORMAT_PCM

const WavFile::WAVE_SUBFORMAT_PCM = "0100000000001000800000aa00389b71"

Definition at line 121 of file WavFile.php.

Referenced by setAudioSubFormat().


The documentation for this class was generated from the following file: