/** * Convert sample data to different bits per sample. * * @param int $bitsPerSample (Required) The new number of bits per sample; * * @throws Yop_Poll_WavFileException */ public function convertBitsPerSample($bitsPerSample) { if ($this->getBitsPerSample() == $bitsPerSample) { return $this; } $tempWav = new Yop_Poll_WavFile($this->getNumChannels(), $this->getSampleRate(), $bitsPerSample); $tempWav->filter(array(self::FILTER_MIX => $this), 0, $this->getNumBlocks()); $this->setSamples()->setBitsPerSample($bitsPerSample); // implicit setValidBitsPerSample(), setAudioFormat(), setAudioSubFormat(), setFmtChunkSize(), setFactChunkSize(), setSize(), setActualSize(), setDataOffset(), setByteRate(), setBlockAlign(), setNumBlocks() $this->_samples = $tempWav->_samples; $this->setDataSize(); // implicit setSize(), setActualSize(), setNumBlocks() return $this; }
/** * Generate a wav file given the $letters in the code * @todo Add ability to merge 2 sound files together to have random background sounds * @param array $letters * @return string The binary contents of the wav file */ protected function generateWAV($letters) { $wavCaptcha = new Yop_Poll_WavFile(); $first = true; // reading first wav file foreach ($letters as $letter) { $letter = strtoupper($letter); try { $l = new Yop_Poll_WavFile($this->audio_path . '/' . $letter . '.wav'); if ($first) { // set sample rate, bits/sample, and # of channels for file based on first letter $wavCaptcha->setSampleRate($l->getSampleRate())->setBitsPerSample($l->getBitsPerSample())->setNumChannels($l->getNumChannels()); $first = false; } // append letter to the captcha audio $wavCaptcha->appendWav($l); // random length of silence between $audio_gap_min and $audio_gap_max if ($this->audio_gap_max > 0 && $this->audio_gap_max > $this->audio_gap_min) { $wavCaptcha->insertSilence(mt_rand($this->audio_gap_min, $this->audio_gap_max) / 1000.0); } } catch (Exception $ex) { // failed to open file, or the wav file is broken or not supported // 2 wav files were not compatible, different # channels, bits/sample, or sample rate throw $ex; } } /********* Set up audio filters *****************************/ $filters = array(); if ($this->audio_use_noise == true) { // use background audio - find random file $noiseFile = $this->getRandomNoiseFile(); if ($noiseFile !== false && is_readable($noiseFile)) { try { $wavNoise = new Yop_Poll_WavFile($noiseFile, false); } catch (Exception $ex) { throw $ex; } // start at a random offset from the beginning of the Yop_Poll_WavFile // in order to add more randomness $randOffset = 0; if ($wavNoise->getNumBlocks() > 2 * $wavCaptcha->getNumBlocks()) { $randBlock = rand(0, $wavNoise->getNumBlocks() - $wavCaptcha->getNumBlocks()); $wavNoise->readWavData($randBlock * $wavNoise->getBlockAlign(), $wavCaptcha->getNumBlocks() * $wavNoise->getBlockAlign()); } else { $wavNoise->readWavData(); $randOffset = rand(0, $wavNoise->getNumBlocks() - 1); } $mixOpts = array('wav' => $wavNoise, 'loop' => true, 'blockOffset' => $randOffset); $filters[Yop_Poll_WavFile::FILTER_MIX] = $mixOpts; $filters[Yop_Poll_WavFile::FILTER_NORMALIZE] = $this->audio_mix_normalization; } } if ($this->degrade_audio == true) { // add random noise. // any noise level below 95% is intensely distorted and not pleasant to the ear $filters[Yop_Poll_WavFile::FILTER_DEGRADE] = rand(95, 98) / 100.0; } if (!empty($filters)) { $wavCaptcha->filter($filters); // apply filters to captcha audio } return $wavCaptcha->__toString(); }