PHPackages                             remithefox/wave - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. remithefox/wave

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

remithefox/wave
===============

Library to generating wave files

1.0.0(2y ago)0161MITPHPPHP &gt;=8.0

Since Nov 24Pushed 2y ago1 watchersCompare

[ Source](https://github.com/remithefox/wave)[ Packagist](https://packagist.org/packages/remithefox/wave)[ RSS](/packages/remithefox-wave/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (1)Versions (2)Used By (1)

remithefox/wave
===============

[](#remithefoxwave)

A PHP library that helps you create WAVE files

Installation
------------

[](#installation)

### Composer

[](#composer)

```
$ composer require remithefox/wave
```

Usage
-----

[](#usage)

### Creating new wave file

[](#creating-new-wave-file)

You can create wave file by static method `Wave::createNew()`. e.g.:

```
use RemiTheFox\Wave\AbstractFloatWave;
use RemiTheFox\Wave\Wave;

$wave = Wave::createNew(
    __DIR__ . '/sound.wav', // filename
    2,                      // number of channels
    44100,                  // sample rate
    16                      // bits per sample
);

// Wave object can be also decorated with FloatDecorator
$floatWave = AbstractFloatWave::decorate($wave);
```

More comfortable way to create new wave file is using builder. e.g.:

```
use RemiTheFox\Wave\Wave;

$builder = Wave::builder()
    ->setNumberOfChannels(2)
    ->setSampleRate(44100)
    ->setBitsPerSample(16)
    ->setFloatDecorator(true);

$wave = $builder->create(__DIR__ . '/sound.wav');
```

builder setters:

settersdefaultsignificance`setNumberOfChannels()``2`number of channels`setSampleRate()``44100`number of samples per seconds1`setBitsPerSample()``16`bits per sample (highly recommend to use 8 or 16)`setFloatDecorator()``false`use float decorator (wave object will be packed in decorator that calculate sample values to float in range -1..1)1. Sample rate must be at least 2 times grater than the highest frequency to avoid aliasing (Nyquist frequency). Most often sampling frequency is 44.1kHz (44 100Hz) and this sample rate is recommended for music. For human speech sampling frequency must be at least 8kHz (8 000Hz).

### Opening existing files

[](#opening-existing-files)

To open exiting file use method `Wave::createFromFile()`

```
use RemiTheFox\Wave\AbstractFloatWave;
use RemiTheFox\Wave\Wave;

$wave = Wave::createFromFile(__DIR__ . 'existing-file.wav');

// Wave object can be also decorated with FloatDecorator
$floatWave = AbstractFloatWave::decorate($wave);
```

### Float decorator

[](#float-decorator)

Whether you use the float decorator or not, you will get an object that implements the interface `RemiTheFox\Wave\WaveInterface`. If you use decorator you can read and write float values from -1 to 1, otherwise you can read and write integer values from 0 to 255 for 8-bit files or from 0 to 65535 for 16-bit files.

### Getters

[](#getters)

gettertypesignificance`isWritable()``bool`returns true if file is writable`getNumberOfChannels()``int`returns number of channels`getSampleRate()``int`returns number of sample per second`getBytesPerSecond()``int`returns number of data bytes per second`getBytesPerSampleAllChannels()``int`returns number of bytes per sample for all channels`getBitsPerSample()``int`returns number of bits of sample value for single channel`getBytesPerSample()``int`returns number of bytes per sample for single channel`getNumberOfSamples()``int`returns number of samples`getPosition()``int`returns number of current sample### Navigation in file

[](#navigation-in-file)

#### Seeking

[](#seeking)

To seek use method `WaveInterface::seek()`

```
// ...
/** @var \RemiTheFox\Wave\WaveInterface $wave */
$wave->seek(2137); // goes to sample number 2137
```

NOTICE: first sample has number 0.

#### Getting current position

[](#getting-current-position)

to get current position use method `WaveInterface::getPosition()`

```
// ...
/** @var \RemiTheFox\Wave\WaveInterface $wave */
$position = $wave->getPosition(); // returns current position
```

NOTICE: first sample has number 0.

#### Human friendly time

[](#human-friendly-time)

Position of some specified time depends on file sample rate, so if you want to go to sample on 1:30 you need to go to sample number Fs\*90. It isn't comfortable, so you can use method `WaveInterface::time()` e.g.:

```
// ...
/** @var \RemiTheFox\Wave\WaveInterface $wave */
$wave->seek($wave->time(1, 30)); // goes to 1:30 regardless of sampling frequency
```

method takes 2 or 3 arguments:

argumenttyperequiredsignificanceminutesfloatYESnumber of minutessecondsfloatYESnumber of secondssamplesintNOoffset in samples### Reading

[](#reading)

To read use method `WaveInterface::read()` e.g.:

```
// ...
/** @var \RemiTheFox\Wave\WaveInterface $wave */
$sample = $wave->read();
```

Method returns array of values of all channels in single sample and goes one sample forward.

### Writing

[](#writing)

To write use method `WaveInterface::write()` e.g.:

```
// ...
/** @var \RemiTheFox\Wave\WaveInterface $wave */
$sample = $wave->write([0,1]); // write one sample and go one sample forward
```

Method write values of all channels in single sample and goes one sample forward. Values should be supplied as array.

### Array access and iterating

[](#array-access-and-iterating)

`\RemiTheFox\Wave\WaveInterface` extends `\ArrayAccess` and `\Iterator` so you can use it as array.

#### Array access

[](#array-access)

```
// ...
/** @var \RemiTheFox\Wave\WaveInterface $wave */
$sample = $wave[420]; // reads sample number 420
$wave[420] = [0, 0];  // replaces sample number 420
$wave[] = [0, 0];     // adds sample at the end of file
```

#### Iterating

[](#iterating)

```
// ...
/** @var \RemiTheFox\Wave\WaveInterface $wave */
foreach ($wave as $sampleNumber => $sampleValues) {
    // ...
}
```

### Generators

[](#generators)

You can use method `WaveInterface::toGenerator()` to create generator which yields samples. Method can be called with start sample number in argument or without arguments (starts from file begin). e.g.:

```
// ...
/** @var \RemiTheFox\Wave\WaveInterface $wave */

$generator = $wave->toGenerator(21);
foreach ($generator as $sampleNumber => $sampleValues){
    // ...
}
```

You can also use some other generator (or any other iterable type) to write samples using method `WaveInterface::toGenerator()`. e.g.:

```
// ...
function tone(int $sampleRate, float $frequency, int $length, float $volume = 1): \Generator
{
    for ($i = 0; $i < $length; $i++) {
        $sample = $volume * sin(2 * pi() * $frequency * $i / $sampleRate);
        yield [$sample];
    }
}

/** @var \RemiTheFox\Wave\WaveInterface $wave */

$sampleRate = $wave->getSampleRate();
$frequency = 1000; // 1kHz
$length = $wave->time(0, 5);

$generator = tone($sampleRate, $frequency, $length);
$wave->fromGenerator($generator);
```

### Exceptions

[](#exceptions)

All exceptions are in namespace `\RemiTheFox\Wave\Exception` implements `\RemiTheFox\Wave\Exception\WaveExceptionInterface`.

exceptionsignificanceCannotCreateFileExceptionCannot create file. It can be caused for example by permissions or lack of disk space.CannotOpenFileExceptionError during opening file.FileIsNotReadableExceptionCannot open file. File is not readable.FileIsNotWritableExceptionCannot write to file. File is not writable.FileNotFoundExceptionFile not exists.FloatDecoratorNotFoundCannot decorate file other than 8-bit and 16-bit.FormatNotSupportedExceptionWave file format is other than PCM.HeaderCorruptedExceptionWave file header is corrupted. Header markers not found.HeaderDataInconsistentExceptionWave file header data is inconsistent.NotApplicableBitPerSampleExceptionTried to decorate Wave object using wrong decorator.long text? ASCII-fox:

```
 /\-/\
(=^w^=)
 )   (

```

###  Health Score

22

—

LowBetter than 22% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

906d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/0193368da52007e2a803d8827dd0b584ce1dd93fab2a3805cdc21db817882a6e?d=identicon)[remithefox](/maintainers/remithefox)

---

Top Contributors

[![remithefox](https://avatars.githubusercontent.com/u/46873705?v=4)](https://github.com/remithefox "remithefox (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/remithefox-wave/health.svg)

```
[![Health](https://phpackages.com/badges/remithefox-wave/health.svg)](https://phpackages.com/packages/remithefox-wave)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
