Skip to content

Commit

Permalink
[feature] Add combined dual channel via channelLayout property (#38).
Browse files Browse the repository at this point in the history
  • Loading branch information
hvianna committed Feb 12, 2023
2 parents a0b683f + dfba75c commit 623dc72
Show file tree
Hide file tree
Showing 9 changed files with 344 additions and 145 deletions.
72 changes: 43 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,15 @@ options = {<br>
&emsp;&emsp;[audioCtx](#audioctx-audiocontext-object): *undefined*, // constructor only<br>
&emsp;&emsp;[barSpace](#barspace-number): **0.1**,<br>
&emsp;&emsp;[bgAlpha](#bgalpha-number): **0.7**,<br>
&emsp;&emsp;[channelLayout](#channellayout-string): **'single'**,<br>
&emsp;&emsp;[connectSpeakers](#connectspeakers-boolean): **true**, // constructor only<br>
&emsp;&emsp;[fftSize](#fftsize-number): **8192**,<br>
&emsp;&emsp;[fillAlpha](#fillalpha-number): **1**,<br>
&emsp;&emsp;[frequencyScale](#frequencyscale-string): **'log'**,<br>
&emsp;&emsp;[fsElement](#fselement-htmlelement-object): *undefined*, // constructor only<br>
&emsp;&emsp;[gradient](#gradient-string): **'classic'**,<br>
&emsp;&emsp;[gradientLeft](#gradientleft-string): *undefined*,<br>
&emsp;&emsp;[gradientRight](#gradientright-string): *undefined*,<br>
&emsp;&emsp;[height](#height-number): *undefined*,<br>
&emsp;&emsp;[ledBars](#ledbars-boolean): **false**,<br>
&emsp;&emsp;[linearAmplitude](#linearamplitude-boolean): **false**,<br>
Expand Down Expand Up @@ -158,7 +161,7 @@ options = {<br>
&emsp;&emsp;[spinSpeed](#spinspeed-number): **0**,<br>
&emsp;&emsp;[splitGradient](#splitgradient-boolean): **false**,<br>
&emsp;&emsp;[start](#start-boolean): **true**,<br>
&emsp;&emsp;[stereo](#stereo-boolean): **false**,<br>
&emsp;&emsp;[stereo](#stereo-deprecated-boolean): **false**, // DEPRECATED - use channelLayout instead<br>
&emsp;&emsp;[useCanvas](#usecanvas-boolean): **true**,<br>
&emsp;&emsp;[volume](#volume-number): **1**,<br>
&emsp;&emsp;[weightingFilter](#weightingFilter-string): **''**<br>
Expand Down Expand Up @@ -315,6 +318,23 @@ Defaults to **0.7**.

[2D rendering context](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D) used for drawing in audioMotion's *Canvas*.

### `channelLayout` *string*

*Available since v4.0.0*

Defines the number and layout of analyzer channels.

channelLayout | description
-------------- |------------
'single' | Single channel analyzer, representing the combined output of both left and right channels.
'dualVertical' | Dual channel analyzer, with left channel shown at the top and right channel at the bottom.
'dualCombined' | Left and right channel graphs are shown overlaid. Works best with semi-transparent **Graph** [`mode`](#mode-number) or [`outlineBars`](#outlinebars-boolean).

!> When a *dual* layout is selected, any mono (single channel) audio source connected to the analyzer will output sound only from the left speaker,
unless a stereo source is simultaneously connected to the analyzer, which will force the mono input to be upmixed to stereo.

See also [`gradientLeft`](#gradientleft-string), [`gradientRight`](#gradientright-string) and [`splitGradient`](#splitgradient-boolean).

### `connectedSources` *array* *(Read only)*

*Available since v3.0.0*
Expand Down Expand Up @@ -398,8 +418,21 @@ Name of the color gradient used for analyzer graphs.

It must be a built-in or [registered](#registergradient-name-options-) gradient name. Built-in gradients are *'classic'*, *'prism'* and *'rainbow'*.

See also [`gradientLeft`](#gradientleft-string) and [`gradientRight`](#gradientright-string).

Defaults to **'classic'**.

### `gradientLeft` *string*
### `gradientRight` *string*

*Available since v4.0.0*

When using a dual [`channelLayout`](#channellayout-string), different gradients can be selected for the left and right channels.

When [`channelLayout`](#channellayout-string) is set to *'single'*, the gradient selected by `gradientLeft` is used.

The [`gradient`](#gradient-string) property can be used as a shorthand to set the same gradient for both channels. Its read value returns only the left (or single) channel gradient though.

### `height` *number*
### `width` *number*

Expand Down Expand Up @@ -655,7 +688,7 @@ When *true*, the spectrum analyzer is rendered in a circular shape, with radial
In radial visualization, [`ledBars`](#ledbars-boolean) and [`lumiBars`](#lumibars-boolean) effects are disabled, and
[`showPeaks`](#showpeaks-boolean) has no effect for [**Graph** mode](#mode-number).

When [`stereo`](#stereo-boolean) is *true*, a larger diameter is used and the right channel bars are rendered towards the center of the analyzer.
When [`channelLayout`](#channellayout-string) is set to *'dualVertical'*, a larger diameter is used and the right channel bars are rendered towards the center of the analyzer.

See also [`spinSpeed`](#spinspeed-number).

Expand Down Expand Up @@ -782,24 +815,13 @@ When *true*, the gradient will be split between both channels, so each channel w
|:--:|:--:|
| ![split-on](img/splitGradient_on.png) | ![split-off](img/splitGradient_off.png) |

This option has no effect on horizontal gradients, or when [`stereo`](#stereo-boolean) is set to *false*.
This option has no effect on horizontal gradients, or when [`channelLayout`](#channellayout-string) is set to *'single'* or *'dualCombined'*.

Defaults to **false**.

### `stereo` *boolean*

*Available since v3.0.0*

When *true*, the spectrum analyzer will display separate graphs for the left and right audio channels.
### `stereo` **(DEPRECATED)** *boolean*

Notes:
- Stereo tracks will always output stereo audio, even if `stereo` is set to *false* (in such case the analyzer graph will represent both channels combined);
- Mono (single channel) tracks will output audio only on the left channel when `stereo` is *true*, unless you have another stereo source simultaneously
connected to the analyzer, which will force the mono source to be upmixed to stereo.

See also [`splitGradient`](#splitgradient-boolean).

Defaults to **false**.
**This property will be removed in version 5** - Use [`channelLayout`](#channellayout-string) instead.

### `useCanvas` *boolean*

Expand Down Expand Up @@ -1010,7 +1032,7 @@ Returns an array with current data for each analyzer bar. Each array element is

`hold` values are integers and indicate the hold time (in frames) for the current peak. The maximum value is 30 and means the peak has just been set, while negative values mean the peak is currently falling down.

Please note that `hold` and `value` will have only one element when [`stereo`](#stereo-boolean) is *false*, but `peak` is always a two-element array.
Please note that `hold` and `value` will have only one element when [`channelLayout`](#channellayout-string) is set to *'single'*, but `peak` is always a two-element array.

You can use this method to create your own visualizations using the analyzer data. See [this pen](https://codepen.io/hvianna/pen/ZEKWWJb) for usage example.

Expand Down Expand Up @@ -1043,32 +1065,24 @@ Use this method inside your callback function to create additional visual effect

Registers a custom color gradient.

`name` must be a non-empty *string* that will be used to select this gradient, via the [`gradient`](#gradient-string) property.
`name` must be a non-empty string that will be used to select this gradient, via the [`gradient`](#gradient-string) property.

`options` must be an object as shown below:

```js
const options = {
bgColor: '#011a35', // background color (optional) - defaults to '#111'
dir: 'h', // add this property to create a horizontal gradient (optional)
colorStops: [ // list your gradient colors in this array (at least 2 entries are required)
colorStops: [ // list your gradient colors in this array (at least one color is required)
'red', // colors may be defined in any valid CSS format
{ pos: .6, color: '#ff0' }, // use an object to adjust the offset (0 to 1) of a colorStop
'hsl( 120, 100%, 50% )' // colors may be defined in any valid CSS format
'hsl( 120, 100%, 50% )'
]
}

audioMotion.registerGradient( 'myGradient', options );
```

!> In TypeScript projects make sure to import the `GradientOptions` definition and use it as the type of your object, like so:

```js
import AudioMotionAnalyzer, { GradientOptions } from 'audiomotion-analyzer'

const options: GradientOptions = {
```
Additional information about [gradient color-stops](https://developer.mozilla.org/en-US/docs/Web/API/CanvasGradient/addColorStop).

### `setCanvasSize( width, height )`
Expand Down
35 changes: 32 additions & 3 deletions demo/fluid.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,36 @@ <h1><a href="https://audiomotion.dev" class="logo">audioMotion-analyzer</a> | fl
<option value="classic">classic</option>
<option value="prism">prism</option>
<option value="rainbow">rainbow</option>
<option value="SteelBlue">SteelBlue</option>
<option value="OrangeRed">OrangeRed</option>
</select>
</label>

<label class="label">gradientLeft
<select data-setting="gradientLeft">
<option value="classic">classic</option>
<option value="prism">prism</option>
<option value="rainbow">rainbow</option>
<option value="SteelBlue">SteelBlue</option>
<option value="OrangeRed">OrangeRed</option>
</select>
</label>

<label class="label">gradientRight
<select data-setting="gradientRight">
<option value="classic">classic</option>
<option value="prism">prism</option>
<option value="rainbow">rainbow</option>
<option value="SteelBlue">SteelBlue</option>
<option value="OrangeRed">OrangeRed</option>
</select>
</label>

<label class="label">channelLayout
<select data-setting="channelLayout">
<option value="single">single</option>
<option value="dualCombined">dualCombined</option>
<option value="dualVertical">dualVertical</option>
</select>
</label>

Expand Down Expand Up @@ -185,7 +215,7 @@ <h1><a href="https://audiomotion.dev" class="logo">audioMotion-analyzer</a> | fl
<fieldset>
<legend>mode 10 / outlineBars</legend>
<label class="label">lineWidth
<input type="range" min="0" max="5" step="1" data-setting="lineWidth">
<input type="range" min="0" max="4" step=".5" data-setting="lineWidth">
<div class="value"></div>
</label>

Expand Down Expand Up @@ -250,8 +280,7 @@ <h1><a href="https://audiomotion.dev" class="logo">audioMotion-analyzer</a> | fl
<button data-prop="lumiBars">lumiBars</button>
<button data-prop="noteLabels">noteLabels</button>
<button data-prop="outlineBars">outlineBars</button>
<button data-prop="splitGradient">splitGradient</button>
<button data-prop="stereo">stereo</button><br>
<button data-prop="splitGradient">splitGradient</button><br>
<button data-prop="showBgColor">showBgColor</button>
<button data-prop="showFPS">showFPS</button>
<button data-prop="showPeaks">showPeaks</button>
Expand Down
24 changes: 24 additions & 0 deletions demo/fluid.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,26 @@ const presets = [
weightingFilter: 'D'
}
},
{
name: 'Combined stereo + custom gradients',
options: {
mode: 10,
channelLayout: 'dualCombined',
fillAlpha: .25,
frequencyScale: 'bark',
gradientLeft: 'SteelBlue',
gradientRight: 'OrangeRed',
linearAmplitude: true,
linearBoost: 1.8,
lineWidth: 1.5,
mirror: 0,
overlay: false,
radial: false,
reflexRatio: 0,
showPeaks: false,
weightingFilter: 'D'
}
},
{
name: 'Testing config 1',
options: {
Expand Down Expand Up @@ -125,6 +145,10 @@ catch( err ) {
document.getElementById('container').innerHTML = `<p>audioMotion-analyzer failed with error: ${ err.code ? '<strong>' + err.code + '</strong>' : '' } <em>${ err.code ? err.message : err }</em></p>`;
}

// register custom gradients
audioMotion.registerGradient( 'OrangeRed', { colorStops: [ 'OrangeRed' ] } );
audioMotion.registerGradient( 'SteelBlue', { colorStops: [ 'SteelBlue' ] } );

// Display package version at the footer
document.getElementById('version').innerText = AudioMotionAnalyzer.version;

Expand Down
31 changes: 30 additions & 1 deletion demo/multi.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,36 @@ <h1><a href="https://audiomotion.dev" class="logo">audioMotion-analyzer</a> | mu
<option value="classic">classic</option>
<option value="prism">prism</option>
<option value="rainbow">rainbow</option>
<option value="SteelBlue">SteelBlue</option>
<option value="OrangeRed">OrangeRed</option>
</select>
</label>

<label class="label">gradientLeft
<select data-setting="gradientLeft">
<option value="classic">classic</option>
<option value="prism">prism</option>
<option value="rainbow">rainbow</option>
<option value="SteelBlue">SteelBlue</option>
<option value="OrangeRed">OrangeRed</option>
</select>
</label>

<label class="label">gradientRight
<select data-setting="gradientRight">
<option value="classic">classic</option>
<option value="prism">prism</option>
<option value="rainbow">rainbow</option>
<option value="SteelBlue">SteelBlue</option>
<option value="OrangeRed">OrangeRed</option>
</select>
</label>

<label class="label">channelLayout
<select data-setting="channelLayout">
<option value="single">single</option>
<option value="dualCombined">dualCombined</option>
<option value="dualVertical">dualVertical</option>
</select>
</label>

Expand Down Expand Up @@ -246,7 +276,6 @@ <h1><a href="https://audiomotion.dev" class="logo">audioMotion-analyzer</a> | mu
<button data-prop="outlineBars">outlineBars</button>
<button data-prop="loRes">loRes</button>
<button data-prop="splitGradient">splitGradient</button>
<button data-prop="stereo">stereo</button>
<br>
<button data-prop="showBgColor">showBgColor</button>
<button data-prop="showFPS">showFPS</button>
Expand Down
8 changes: 7 additions & 1 deletion demo/multi.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ try {
updateUI();
}
});

// register custom gradients
audioMotion[ i ].registerGradient( 'OrangeRed', { colorStops: [ 'OrangeRed' ] } );
audioMotion[ i ].registerGradient( 'SteelBlue', { colorStops: [ 'SteelBlue' ] } );
}
}
catch( err ) {
Expand Down Expand Up @@ -64,8 +68,10 @@ audioMotion[0].setOptions({
// top right
audioMotion[1].setOptions({
mode: 10,
channelLayout: 'dualCombined',
fillAlpha: .3,
gradient: 'rainbow',
gradientLeft: 'SteelBlue',
gradientRight: 'OrangeRed',
linearAmplitude: true,
linearBoost: 1.2,
lineWidth: 1.5,
Expand Down
30 changes: 30 additions & 0 deletions demo/overlay.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,36 @@ <h1><a href="https://audiomotion.dev" class="logo">audioMotion-analyzer</a> | ov
<option value="classic">classic</option>
<option value="prism">prism</option>
<option value="rainbow">rainbow</option>
<option value="SteelBlue">SteelBlue</option>
<option value="OrangeRed">OrangeRed</option>
</select>
</label>

<label class="label">gradientLeft
<select data-setting="gradientLeft">
<option value="classic">classic</option>
<option value="prism">prism</option>
<option value="rainbow">rainbow</option>
<option value="SteelBlue">SteelBlue</option>
<option value="OrangeRed">OrangeRed</option>
</select>
</label>

<label class="label">gradientRight
<select data-setting="gradientRight">
<option value="classic">classic</option>
<option value="prism">prism</option>
<option value="rainbow">rainbow</option>
<option value="SteelBlue">SteelBlue</option>
<option value="OrangeRed">OrangeRed</option>
</select>
</label>

<label class="label">channelLayout
<select data-setting="channelLayout">
<option value="single">single</option>
<option value="dualCombined">dualCombined</option>
<option value="dualVertical">dualVertical</option>
</select>
</label>

Expand Down
4 changes: 4 additions & 0 deletions demo/overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ catch( err ) {
// Display package version at the footer
document.getElementById('version').innerText = AudioMotionAnalyzer.version;

// register custom gradients
audioMotion.registerGradient( 'OrangeRed', { colorStops: [ 'OrangeRed' ] } );
audioMotion.registerGradient( 'SteelBlue', { colorStops: [ 'SteelBlue' ] } );

// Event listeners for UI controls

document.querySelectorAll('button[data-prop]').forEach( el => {
Expand Down
Loading

0 comments on commit 623dc72

Please sign in to comment.