Skip to content

Commit cf06c1d

Browse files
committed
1 parent e8795f5 commit cf06c1d

File tree

6 files changed

+688
-692
lines changed

6 files changed

+688
-692
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
node_modules
2-
dist
1+
node_modules
2+
dist
33
package-lock.json

README.md

Lines changed: 114 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,93 @@
1-
# JavaScript Heatmap Spectrogram Chart
2-
3-
![JavaScript Heatmap Spectrogram Chart](spectrogram.png)
4-
5-
This demo application belongs to the set of examples for LightningChart JS, data visualization library for JavaScript.
6-
7-
LightningChart JS is entirely GPU accelerated and performance optimized charting library for presenting massive amounts of data. It offers an easy way of creating sophisticated and interactive charts and adding them to your website or web application.
8-
9-
The demo can be used as an example or a seed project. Local execution requires the following steps:
10-
11-
- Make sure that relevant version of [Node.js](https://nodejs.org/en/download/) is installed
12-
- Open the project folder in a terminal:
13-
14-
npm install # fetches dependencies
15-
npm start # builds an application and starts the development server
16-
17-
- The application is available at *http://localhost:8080* in your browser, webpack-dev-server provides hot reload functionality.
18-
19-
20-
## Description
21-
22-
This example shows a simple use case for Heatmaps as a spectrogram.
23-
24-
Spectrogram is a visual representation of the spectrum of frequencies. Spectrograms can be used to visualize any wave form. Most often spectrograms are used to display audio signals.
25-
26-
This example loads a audio file and shows spectrograms for each channel on the audio file.
27-
28-
The spectrogram shows frequency on one axis (Y Axis) and time on the other (X Axis). The color of a the heatmap at any point is the amplitude of the frequency at the specified time.
29-
30-
## Getting the data
31-
32-
First the audio file that will be shown is loaded with [fetch][fetch] and converted into an ArrayBuffer.
33-
34-
```js
35-
const response = await fetch('url')
36-
const buffer = await response.arrayBuffer()
37-
```
38-
39-
This example uses the [Web Audio APIs][web-audio-api] to retrieve the frequency data to display in the heatmap. These APIs make it easy to work with audio files and manipulate the files. For spectrogram use the [AnalyzerNode][analyzer-node] is the most useful part of the API as it provides [getByteFrequencyData][getByteFrequencyData] method which is a implementation of [Fast Fourier Transform][fft].
40-
The AudioContext contains method to convert an ArrayBuffer into an [AudioBuffer][AudioBuffer].
41-
42-
```js
43-
const audioBuffer = await audioContext.decodeAudioData(buffer)
44-
```
45-
46-
Now that the audio file is converted into a AudioBuffer it's possible to start extracting data from it.
47-
48-
To process the full audio buffer as fast as possible, a [OfflineAudioContext][OfflineAudioContext] is used. The OfflineAudioContext doesn't output the data to a audio device, instead it will go through the audio as fast as possible and outputs an AudioBuffer with the processed data. In this example the processed audio buffer is not used, but the processing is used to calculate the FFT data we need to display the intensities for each frequency in the spectrogram. The audio buffer we have created is used as a [buffer source][createBufferSource] for the OfflineAudioContext.
49-
50-
The buffer source only has a single output but we want to be able to process each channel separately, to do this a [ChannelSplitter][createChannelSplitter] is used with the output count matching the source channel count.
51-
52-
```js
53-
const splitter = offlineCtx.createChannelSplitter(source.channelCount)
54-
```
55-
56-
This makes it possible to process each channel separately by making it possible to create AnalyzerNodes for each channel and only piping a single channel to each analyzer.
57-
58-
A [ScriptProcessorNode][createScriptProcessor] is used to go through the audio buffer in chuncks. For each chunk, the FFT data is calculated for each channel and stored in large enough buffers to fit the full data.
59-
60-
Last [startRendering()][start-rendering] method is called to render out the audio buffer. This is when all of the FFT calculation is done.
61-
62-
## Showing the data
63-
64-
Each channel of the audio file is shown in it's own chart inside a single dashboard. When the data is calculated, a dashboard is made. This dashboard is then passed to functions that setup the charts inside the dashboard and create the heatmap series based on the script processor buffer size and fft resolution.
65-
66-
The data from the audio APIs is in wrong format to display in the heatmap without editing it. The heatmap data has to be mapped from the one dimensional array it was generated in to a two dimensional array. This mapping in this example is done with `remapDataToTwoDimensionalMatrix` function, this function maps the data in columns. If the heatmap was displayed vertically, then the mapping would be easier as each stride of data could just be placed as a row.
67-
68-
```js
69-
// Datamapping for vertical spectrogram
70-
const output = Array.from(Array(tickCount)).map(()=> Array.from(Array(strideSize)))
71-
for(let row = 0; row < strideSize; row += 1){
72-
output[row] = arr.slice(row*strideSize, row*strideSize + strideSize)
73-
}
74-
```
75-
76-
[web-audio-api]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API
77-
[analyzer-node]: https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode
78-
[getByteFrequencyData]: https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getByteFrequencyData
79-
[fft]: https://en.wikipedia.org/wiki/Fast_Fourier_transform
80-
[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
81-
[AudioBuffer]: https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer
82-
[OfflineAudioContext]: https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext
83-
[createBufferSource]: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createBufferSource
84-
[createChannelSplitter]: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createChannelSplitter
85-
[createSciptProcessor]: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createScriptProcessor
86-
[start-rendering]: https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext/startRendering
87-
88-
89-
## API Links
90-
1+
# JavaScript Heatmap Spectrogram Chart
2+
3+
![JavaScript Heatmap Spectrogram Chart](spectrogram.png)
4+
5+
This demo application belongs to the set of examples for LightningChart JS, data visualization library for JavaScript.
6+
7+
LightningChart JS is entirely GPU accelerated and performance optimized charting library for presenting massive amounts of data. It offers an easy way of creating sophisticated and interactive charts and adding them to your website or web application.
8+
9+
The demo can be used as an example or a seed project. Local execution requires the following steps:
10+
11+
- Make sure that relevant version of [Node.js](https://nodejs.org/en/download/) is installed
12+
- Open the project folder in a terminal:
13+
14+
npm install # fetches dependencies
15+
npm start # builds an application and starts the development server
16+
17+
- The application is available at *http://localhost:8080* in your browser, webpack-dev-server provides hot reload functionality.
18+
19+
20+
## Description
21+
22+
This example shows a simple use case for Heatmaps as a spectrogram.
23+
24+
Spectrogram is a visual representation of the spectrum of frequencies. Spectrograms can be used to visualize any wave form. Most often spectrograms are used to display audio signals.
25+
26+
This example loads a audio file and shows spectrograms for each channel on the audio file.
27+
28+
The spectrogram shows frequency on one axis (Y Axis) and time on the other (X Axis). The color of a the heatmap at any point is the amplitude of the frequency at the specified time.
29+
30+
## Getting the data
31+
32+
First the audio file that will be shown is loaded with [fetch][fetch] and converted into an ArrayBuffer.
33+
34+
```js
35+
const response = await fetch('url')
36+
const buffer = await response.arrayBuffer()
37+
```
38+
39+
This example uses the [Web Audio APIs][web-audio-api] to retrieve the frequency data to display in the heatmap. These APIs make it easy to work with audio files and manipulate the files. For spectrogram use the [AnalyzerNode][analyzer-node] is the most useful part of the API as it provides [getByteFrequencyData][getByteFrequencyData] method which is a implementation of [Fast Fourier Transform][fft].
40+
The AudioContext contains method to convert an ArrayBuffer into an [AudioBuffer][AudioBuffer].
41+
42+
```js
43+
const audioBuffer = await audioContext.decodeAudioData(buffer)
44+
```
45+
46+
Now that the audio file is converted into a AudioBuffer it's possible to start extracting data from it.
47+
48+
To process the full audio buffer as fast as possible, a [OfflineAudioContext][OfflineAudioContext] is used. The OfflineAudioContext doesn't output the data to a audio device, instead it will go through the audio as fast as possible and outputs an AudioBuffer with the processed data. In this example the processed audio buffer is not used, but the processing is used to calculate the FFT data we need to display the intensities for each frequency in the spectrogram. The audio buffer we have created is used as a [buffer source][createBufferSource] for the OfflineAudioContext.
49+
50+
The buffer source only has a single output but we want to be able to process each channel separately, to do this a [ChannelSplitter][createChannelSplitter] is used with the output count matching the source channel count.
51+
52+
```js
53+
const splitter = offlineCtx.createChannelSplitter(source.channelCount)
54+
```
55+
56+
This makes it possible to process each channel separately by making it possible to create AnalyzerNodes for each channel and only piping a single channel to each analyzer.
57+
58+
A [ScriptProcessorNode][createScriptProcessor] is used to go through the audio buffer in chuncks. For each chunk, the FFT data is calculated for each channel and stored in large enough buffers to fit the full data.
59+
60+
Last [startRendering()][start-rendering] method is called to render out the audio buffer. This is when all of the FFT calculation is done.
61+
62+
## Showing the data
63+
64+
Each channel of the audio file is shown in it's own chart inside a single dashboard. When the data is calculated, a dashboard is made. This dashboard is then passed to functions that setup the charts inside the dashboard and create the heatmap series based on the script processor buffer size and fft resolution.
65+
66+
The data from the audio APIs is in wrong format to display in the heatmap without editing it. The heatmap data has to be mapped from the one dimensional array it was generated in to a two dimensional array. This mapping in this example is done with `remapDataToTwoDimensionalMatrix` function, this function maps the data in columns. If the heatmap was displayed vertically, then the mapping would be easier as each stride of data could just be placed as a row.
67+
68+
```js
69+
// Datamapping for vertical spectrogram
70+
const output = Array.from(Array(tickCount)).map(()=> Array.from(Array(strideSize)))
71+
for(let row = 0; row < strideSize; row += 1){
72+
output[row] = arr.slice(row*strideSize, row*strideSize + strideSize)
73+
}
74+
```
75+
76+
[web-audio-api]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API
77+
[analyzer-node]: https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode
78+
[getByteFrequencyData]: https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getByteFrequencyData
79+
[fft]: https://en.wikipedia.org/wiki/Fast_Fourier_transform
80+
[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
81+
[AudioBuffer]: https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer
82+
[OfflineAudioContext]: https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext
83+
[createBufferSource]: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createBufferSource
84+
[createChannelSplitter]: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createChannelSplitter
85+
[createSciptProcessor]: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createScriptProcessor
86+
[start-rendering]: https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext/startRendering
87+
88+
89+
## API Links
90+
9191
* [Heatmap Grid Series Intensity]
9292
* [Paletted Fill Style]
9393
* [LUT]
@@ -97,29 +97,29 @@ for(let row = 0; row < strideSize; row += 1){
9797
* [Color factory HSV]
9898
* [Empty fill style]
9999
* [Empty line style]
100-
101-
102-
## Support
103-
104-
If you notice an error in the example code, please open an issue on [GitHub][0] repository of the entire example.
105-
106-
Official [API documentation][1] can be found on [Arction][2] website.
107-
108-
If the docs and other materials do not solve your problem as well as implementation help is needed, ask on [StackOverflow][3] (tagged lightningchart).
109-
110-
If you think you found a bug in the LightningChart JavaScript library, please contact support@arction.com.
111-
112-
Direct developer email support can be purchased through a [Support Plan][4] or by contacting sales@arction.com.
113-
114-
[0]: https://github.com/Arction/
115-
[1]: https://www.arction.com/lightningchart-js-api-documentation/
116-
[2]: https://www.arction.com
117-
[3]: https://stackoverflow.com/questions/tagged/lightningchart
118-
[4]: https://www.arction.com/support-services/
119-
120-
© Arction Ltd 2009-2020. All rights reserved.
121-
122-
100+
101+
102+
## Support
103+
104+
If you notice an error in the example code, please open an issue on [GitHub][0] repository of the entire example.
105+
106+
Official [API documentation][1] can be found on [Arction][2] website.
107+
108+
If the docs and other materials do not solve your problem as well as implementation help is needed, ask on [StackOverflow][3] (tagged lightningchart).
109+
110+
If you think you found a bug in the LightningChart JavaScript library, please contact support@arction.com.
111+
112+
Direct developer email support can be purchased through a [Support Plan][4] or by contacting sales@arction.com.
113+
114+
[0]: https://github.com/Arction/
115+
[1]: https://www.arction.com/lightningchart-js-api-documentation/
116+
[2]: https://www.arction.com
117+
[3]: https://stackoverflow.com/questions/tagged/lightningchart
118+
[4]: https://www.arction.com/support-services/
119+
120+
© Arction Ltd 2009-2020. All rights reserved.
121+
122+
123123
[Heatmap Grid Series Intensity]: https://www.arction.com/lightningchart-js-api-documentation/v3.1.0/classes/heatmapgridseriesintensityvalues.html
124124
[Paletted Fill Style]: https://www.arction.com/lightningchart-js-api-documentation/v3.1.0/classes/palettedfill.html
125125
[LUT]: https://www.arction.com/lightningchart-js-api-documentation/v3.1.0/classes/lut.html
@@ -129,4 +129,4 @@ Direct developer email support can be purchased through a [Support Plan][4] or b
129129
[Color factory HSV]: https://www.arction.com/lightningchart-js-api-documentation/v3.1.0/globals.html#colorhsv
130130
[Empty fill style]: https://www.arction.com/lightningchart-js-api-documentation/v3.1.0/globals.html#emptyfill
131131
[Empty line style]: https://www.arction.com/lightningchart-js-api-documentation/v3.1.0/globals.html#emptyline
132-
132+

assets/play_circle_outline-24px.svg

Lines changed: 1 addition & 1 deletion
Loading

package.json

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
{
2-
"version": "1.0.1",
3-
"scripts": {
4-
"build": "webpack --mode production",
5-
"start": "webpack-dev-server"
6-
},
7-
"license": "Custom",
8-
"private": true,
9-
"main": "./src/index.js",
10-
"devDependencies": {
11-
"copy-webpack-plugin": "^6.0.2",
12-
"html-webpack-plugin": "^3.2.0",
13-
"webpack-cli": "^3.3.10",
14-
"webpack-dev-server": "^3.9.0"
15-
},
16-
"dependencies": {
17-
"@arction/lcjs": "^3.2.0",
18-
"@arction/xydata": "^1.4.0",
19-
"clean-webpack-plugin": "^3.0.0",
20-
"webpack": "^4.41.2",
21-
"webpack-stream": "^5.2.1"
22-
}
23-
}
1+
{
2+
"version": "1.0.1",
3+
"scripts": {
4+
"build": "webpack --mode production",
5+
"start": "webpack-dev-server"
6+
},
7+
"license": "Custom",
8+
"private": true,
9+
"main": "./src/index.js",
10+
"devDependencies": {
11+
"copy-webpack-plugin": "^6.0.2",
12+
"html-webpack-plugin": "^3.2.0",
13+
"webpack-cli": "^3.3.10",
14+
"webpack-dev-server": "^3.9.0"
15+
},
16+
"dependencies": {
17+
"@arction/lcjs": "^3.2.0",
18+
"@arction/xydata": "^1.4.0",
19+
"clean-webpack-plugin": "^3.0.0",
20+
"webpack": "^4.41.2",
21+
"webpack-stream": "^5.2.1"
22+
}
23+
}

0 commit comments

Comments
 (0)