Skip to content

Commit b9322cb

Browse files
committed
Added getWaveformData() method and $soxCommand configuration
1 parent 11e14ed commit b9322cb

File tree

2 files changed

+73
-45
lines changed

2 files changed

+73
-45
lines changed

Waveform.php

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*
44
*
55
* @author MaximAL
6+
* @since 2018-10-22 Added `getWaveformData()` method and `$soxCommand` configuration
67
* @since 2016-11-21
78
* @date 2016-11-21
89
* @time 19:08
@@ -31,6 +32,9 @@ class Waveform
3132
public static $backgroundColor = [245, 245, 245, 1];
3233
public static $axisColor = [0, 0, 0, 0.1];
3334

35+
// SoX command: 'sox', '/usr/local/bin/sox' etc
36+
public static $soxCommand = 'sox';
37+
3438

3539
public function __construct($filename)
3640
{
@@ -41,7 +45,7 @@ public function getInfo()
4145
{
4246
$out = null;
4347
$ret = null;
44-
exec('sox --i ' . escapeshellarg($this->filename) . ' 2>&1', $out, $ret);
48+
exec(self::$soxCommand . ' --i ' . escapeshellarg($this->filename) . ' 2>&1', $out, $ret);
4549
$str = implode('|', $out);
4650

4751
$match = null;
@@ -100,8 +104,58 @@ public function getDuration()
100104
return $this->duration;
101105
}
102106

103-
104107
public function getWaveform($filename, $width, $height)
108+
{
109+
// Calculating parameters
110+
$needChannels = $this->getChannels() > 1 ? 2 : 1;
111+
$data = $this->getWaveformData($width);
112+
$lines1 = $data['lines1'];
113+
$lines2 = $data['lines2'];
114+
115+
// Creating image
116+
$img = imagecreatetruecolor($width, $height);
117+
imagesavealpha($img, true);
118+
//if (function_exists('imageantialias')) {
119+
// imageantialias($img, true);
120+
//}
121+
122+
// Colors
123+
$back = self::rgbaToColor($img, self::$backgroundColor);
124+
$color = self::rgbaToColor($img, self::$color);
125+
$axis = self::rgbaToColor($img, self::$axisColor);
126+
imagefill($img, 0, 0, $back);
127+
128+
// Center Ys
129+
$center1 = $needChannels === 2 ? ($height / 2 - 1) / 2 : $height / 2;
130+
$center2 = $needChannels === 2 ? $height - $center1 : null;
131+
132+
// Drawing channel 1
133+
for ($i = 0; $i < count($lines1); $i += 2) {
134+
$min = $lines1[$i];
135+
$max = $lines1[$i+1];
136+
$x = $i / 2 / self::$linesPerPixel;
137+
138+
imageline($img, $x, $center1 - $min * $center1, $x, $center1 - $max * $center1, $color);
139+
}
140+
// Drawing channel 2
141+
for ($i = 0; $i < count($lines2); $i += 2) {
142+
$min = $lines2[$i];
143+
$max = $lines2[$i + 1];
144+
$x = $i / 2 / self::$linesPerPixel;
145+
146+
imageline($img, $x, $center2 - $min * $center1, $x, $center2 - $max * $center1, $color);
147+
}
148+
149+
// Axis
150+
imageline($img, 0, $center1, $width - 1, $center1, $axis);
151+
if ($center2 !== null) {
152+
imageline($img, 0, $center2, $width - 1, $center2, $axis);
153+
}
154+
155+
return imagepng($img, $filename);
156+
}
157+
158+
public function getWaveformData($width)
105159
{
106160
// Calculating parameters
107161
$needChannels = $this->getChannels() > 1 ? 2 : 1;
@@ -113,7 +167,7 @@ public function getWaveform($filename, $width, $height)
113167
//}
114168

115169
// Command text
116-
$command = 'sox ' . escapeshellarg($this->filename) .
170+
$command = self::$soxCommand . ' ' . escapeshellarg($this->filename) .
117171
' -c ' . $needChannels .
118172
' -r ' . $needRate . ' -e floating-point -t raw -';
119173

@@ -126,7 +180,7 @@ public function getWaveform($filename, $width, $height)
126180
$pipes = null;
127181
$proc = proc_open($command, $outputs, $pipes);
128182
if (!$proc) {
129-
throw new \Exception('Failed to run sox command');
183+
throw new \Exception('Failed to run `sox` command');
130184
}
131185

132186
$lines1 = [];
@@ -157,47 +211,7 @@ public function getWaveform($filename, $width, $height)
157211
throw new \Exception('Failed to run `sox` command. Error:' . PHP_EOL . $err);
158212
}
159213

160-
// Creating image
161-
$img = imagecreatetruecolor($width, $height);
162-
imagesavealpha($img, true);
163-
//if (function_exists('imageantialias')) {
164-
// imageantialias($img, true);
165-
//}
166-
167-
// Colors
168-
$back = self::rgbaToColor($img, self::$backgroundColor);
169-
$color = self::rgbaToColor($img, self::$color);
170-
$axis = self::rgbaToColor($img, self::$axisColor);
171-
imagefill($img, 0, 0, $back);
172-
173-
// Center Ys
174-
$center1 = $needChannels === 2 ? ($height / 2 - 1) / 2 : $height / 2;
175-
$center2 = $needChannels === 2 ? $height - $center1 : null;
176-
177-
// Drawing channel 1
178-
for ($i = 0; $i < count($lines1); $i += 2) {
179-
$min = $lines1[$i];
180-
$max = $lines1[$i+1];
181-
$x = $i / 2 / self::$linesPerPixel;
182-
183-
imageline($img, $x, $center1 - $min * $center1, $x, $center1 - $max * $center1, $color);
184-
}
185-
// Drawing channel 2
186-
for ($i = 0; $i < count($lines2); $i += 2) {
187-
$min = $lines2[$i];
188-
$max = $lines2[$i + 1];
189-
$x = $i / 2 / self::$linesPerPixel;
190-
191-
imageline($img, $x, $center2 - $min * $center1, $x, $center2 - $max * $center1, $color);
192-
}
193-
194-
// Axis
195-
imageline($img, 0, $center1, $width - 1, $center1, $axis);
196-
if ($center2 !== null) {
197-
imageline($img, 0, $center2, $width - 1, $center2, $axis);
198-
}
199-
200-
return imagepng($img, $filename);
214+
return ['lines1' => $lines1, 'lines2' => $lines2];
201215
}
202216

203217
public static function rgbaToColor($img, $rgba)

readme.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,20 @@ $success = $waveform->getWaveform('thumbnail.png', 1024, 512);
103103
By default they are WAV, MP3 and OGG files.
104104

105105

106+
## Integration with other libraries (e.g. wavesurfer.js)
107+
108+
`Waveform` class has `getWaveformData()` method for retrieving the waveform data without generating the image.
109+
You can use it to integrate with different libraries, for instance, with the great
110+
[wavesurfer.js](https://wavesurfer-js.org/).
111+
112+
```php
113+
$waveform = new Waveform('track.mp3');
114+
$width = 1024;
115+
$data = $waveform->getWaveformData($width);
116+
// $data['lines1'] and $data['lines2'] now have the waveform data for channels 1 and 2
117+
```
118+
119+
106120
## Contact the author
107121

108122
* Website: https://maximals.ru (Russian)

0 commit comments

Comments
 (0)