├── .gitignore ├── LICENSE ├── README.md ├── example.html ├── example.js ├── gulpfile.js ├── index.js ├── package.json └── waveform.png /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | dist/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2015-present Christian Nilsson 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-waveform 2 | 3 | > Generates waveform using Web Audio API. 4 | 5 |

6 | 7 |

8 | 9 | 10 | ## Install 11 | 12 | ```sh 13 | npm install react-waveform 14 | ``` 15 | 16 | 17 | ## Props 18 | 19 | * **buffer** AudioBuffer 20 | * **width** Number 21 | * **height** Number 22 | * **zoom** Number 23 | * **color** String 24 | * **onDone** Function 25 | 26 | 27 | ## Example 28 | 29 | ```javascript 30 | var React = require('react'); 31 | var Waveform = require('react-waveform'); 32 | 33 | var request = new XMLHttpRequest(); 34 | request.open('GET', 'HardaTider-Har&nu.mp3', true); 35 | request.responseType = 'arraybuffer'; 36 | 37 | request.addEventListener('load', function () { 38 | var context = new (window.AudioContext || window.webkitAudioContext)(); 39 | 40 | context.decodeAudioData(request.response, function (buffer) { 41 | React.render( 42 | , 43 | document.getElementById('waveform') 44 | ); 45 | }); 46 | }); 47 | 48 | request.send(); 49 | ``` 50 | 51 | 52 | ## License 53 | 54 | MIT 55 | -------------------------------------------------------------------------------- /example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Example 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var Waveform = require('./index'); 3 | 4 | var request = new XMLHttpRequest(); 5 | request.open('GET', 'HardaTider-Har&nu.mp3', true); 6 | request.responseType = 'arraybuffer'; 7 | 8 | request.addEventListener('load', function () { 9 | var context = new (window.AudioContext || window.webkitAudioContext)(); 10 | 11 | context.decodeAudioData(request.response, function (buffer) { 12 | React.render( 13 | , 14 | document.getElementById('waveform') 15 | ); 16 | }); 17 | }); 18 | 19 | request.send(); 20 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var browserify = require('gulp-browserify'); 3 | var concat = require('gulp-concat'); 4 | 5 | var paths = { 6 | example: 'example.html', 7 | main: 'example.js', 8 | js: ['index.js', 'example.js'], 9 | dist: 'dist/' 10 | }; 11 | 12 | gulp.task('copyexample', function () { 13 | return gulp.src(paths.example) 14 | .pipe(gulp.dest(paths.dist)); 15 | }); 16 | 17 | gulp.task('browserify', function () { 18 | return gulp.src(paths.main) 19 | .pipe(browserify({ transform: 'reactify', debug: true })) 20 | .pipe(concat('main.js')) 21 | .pipe(gulp.dest(paths.dist)); 22 | }); 23 | 24 | gulp.task('watch', function () { 25 | gulp.watch(paths.example, ['copyexample']); 26 | gulp.watch(paths.js, ['browserify']); 27 | }); 28 | 29 | gulp.task('default', ['browserify', 'copyexample']); 30 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | 3 | module.exports = React.createClass({ 4 | displayName: 'Waveform', 5 | 6 | getDefaultProps: function () { 7 | return { 8 | buffer: null, 9 | width: 500, 10 | height: 100, 11 | zoom: 1, 12 | color: 'black', 13 | onDone: null 14 | }; 15 | }, 16 | 17 | propTypes: { 18 | buffer: React.PropTypes.object.isRequired, 19 | width: React.PropTypes.number, 20 | height: React.PropTypes.number, 21 | zoom: React.PropTypes.number, 22 | color: React.PropTypes.string, 23 | onDone: React.PropTypes.func 24 | }, 25 | 26 | componentDidMount: function () { 27 | var width = this.props.width * this.props.zoom; 28 | var middle = this.props.height / 2; 29 | 30 | var channelData = this.props.buffer.getChannelData(0); 31 | var step = Math.ceil(channelData.length / width); 32 | 33 | var ctx = this.refs.canvas.getDOMNode().getContext('2d'); 34 | ctx.fillStyle = this.props.color; 35 | this.draw(width, step, middle, channelData, ctx); 36 | 37 | if (this.props.onDone) { this.props.onDone(); } 38 | }, 39 | 40 | draw: function (width, step, middle, data, ctx) { 41 | for (var i = 0; i < width; i += 1) { 42 | var min = 1.0; 43 | var max = -1.0; 44 | 45 | for (var j = 0; j < step; j += 1) { 46 | var datum = data[(i * step) + j]; 47 | 48 | if (datum < min) { 49 | min = datum; 50 | } else if (datum > max) { 51 | max = datum; 52 | } 53 | 54 | ctx.fillRect(i, (1 + min) * middle, 1, Math.max(1, (max - min) * middle)); 55 | } 56 | } 57 | }, 58 | 59 | render: function () { 60 | return ( 61 | 65 | ); 66 | } 67 | }); 68 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-waveform", 3 | "version": "0.1.1", 4 | "description": "Generates waveform using Web Audio API.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/klambycom/react-waveform.git" 12 | }, 13 | "keywords": [ 14 | "react", 15 | "waveform", 16 | "audio" 17 | ], 18 | "author": "Christian Nilsson (http://klamby.com/)", 19 | "license": "MIT", 20 | "devDependencies": { 21 | "gulp": "^3.8.11", 22 | "gulp-browserify": "^0.5.1", 23 | "gulp-concat": "^2.4.3", 24 | "reactify": "^1.0.0" 25 | }, 26 | "dependencies": { 27 | "react": "^0.12.2" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /waveform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klambycom/react-waveform/5168350976b0806096a279f6e2d5db8fe167ce93/waveform.png --------------------------------------------------------------------------------