mirror of
https://github.com/samirkumardas/pcm-player.git
synced 2025-04-12 05:11:24 +02:00
example added
This commit is contained in:
parent
42d56c4a1a
commit
14254cc819
11 changed files with 39 additions and 253 deletions
13
.babelrc
13
.babelrc
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"es2015",
|
|
||||||
{
|
|
||||||
"modules": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"external-helpers"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -7,32 +7,25 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="container" style="width: 400px; margin: 0 auto;">
|
<div id="container" style="width: 400px; margin: 0 auto;">
|
||||||
<h2>It should play audio if everying went well!</h2>
|
<h2>It should play audio if everying went well!</h2>
|
||||||
<p>Yea! recoreded audio is not in good qualtity though! </p>
|
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
var channels = 1,
|
var socketURL = 'ws://localhost:8080';
|
||||||
socketURL = 'ws://localhost:8080';
|
var player = new PCMPlayer({
|
||||||
|
encoding: '16bitInt',
|
||||||
var decoder = new Decoder.OpusToPCM({
|
channels: 2,
|
||||||
channels: channels
|
sampleRate: 8000,
|
||||||
|
flushingTime: 1000
|
||||||
});
|
});
|
||||||
|
|
||||||
decoder.on('decode', function(pcmData) {
|
|
||||||
player.feed(pcmData);
|
|
||||||
});
|
|
||||||
|
|
||||||
var player = new PCMPlayer(channels, decoder.getSampleRate());
|
|
||||||
|
|
||||||
var ws = new WebSocket(socketURL);
|
var ws = new WebSocket(socketURL);
|
||||||
ws.binaryType = 'arraybuffer';
|
ws.binaryType = 'arraybuffer';
|
||||||
ws.addEventListener('message',function(event) {
|
ws.addEventListener('message',function(event) {
|
||||||
var data = new Uint8Array(event.data);
|
var data = new Uint8Array(event.data);
|
||||||
decoder.decode(data);
|
player.feed(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="../dist/opus_to_pcm.js"></script>
|
<script type="text/javascript" src="../pcm-player.js"></script>
|
||||||
<script type="text/javascript" src="player/pcm_player.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
BIN
example/server/16bit-8000.raw
Normal file
BIN
example/server/16bit-8000.raw
Normal file
Binary file not shown.
BIN
example/server/32bit (float)-8000.raw
Normal file
BIN
example/server/32bit (float)-8000.raw
Normal file
Binary file not shown.
|
@ -1,25 +1,19 @@
|
||||||
const WebSocket = require('ws');
|
const WebSocket = require('ws');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const opusPackets = './raw_opus/';
|
const pcm_file = './16bit-8000.raw';
|
||||||
let packets = [],
|
let interval = 0,
|
||||||
source = [],
|
sampleRate = 8000,
|
||||||
interval = 0,
|
channels = 2,
|
||||||
count = 0,
|
bytesChunk = (sampleRate * channels),
|
||||||
|
offset = 0,
|
||||||
|
pcmData,
|
||||||
wss;
|
wss;
|
||||||
|
|
||||||
fs.readdir(opusPackets, (err, files) => {
|
fs.readFile(pcm_file, (err, data) => {
|
||||||
files.forEach(function(file) {
|
if (err) throw err;
|
||||||
fs.readFile(opusPackets+file, (err, data) => {
|
pcmData = data;
|
||||||
if (err) throw err;
|
openSocket();
|
||||||
source.push(data);
|
|
||||||
count++;
|
|
||||||
if (files.length == count) {
|
|
||||||
packets = source.slice();
|
|
||||||
openSocket();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,26 +26,24 @@ function openSocket() {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
}
|
}
|
||||||
interval = setInterval(function() {
|
interval = setInterval(function() {
|
||||||
sendPacket();
|
sendData();
|
||||||
}, 10);
|
}, 500);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendPacket() {
|
function sendData() {
|
||||||
let packet;
|
let payload;
|
||||||
if (packets.length == 0 && interval){
|
if (offset >= pcmData.length) {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
packets = source.slice();
|
offset = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet = packets.shift();
|
payload = pcmData.subarray(offset, (offset + bytesChunk));
|
||||||
|
offset += bytesChunk;
|
||||||
wss.clients.forEach(function each(client) {
|
wss.clients.forEach(function each(client) {
|
||||||
if (client.readyState === WebSocket.OPEN) {
|
if (client.readyState === WebSocket.OPEN) {
|
||||||
client.send(packet);
|
client.send(payload);
|
||||||
if (packets.length % 100 == 0){
|
|
||||||
console.log(`Remainging packets ${packets.length}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -1,77 +0,0 @@
|
||||||
// Karma configuration
|
|
||||||
// Generated on Fri Nov 03 2017 16:10:03 GMT+0600 (+06)
|
|
||||||
|
|
||||||
module.exports = function(config) {
|
|
||||||
config.set({
|
|
||||||
|
|
||||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
|
||||||
basePath: '',
|
|
||||||
|
|
||||||
|
|
||||||
// frameworks to use
|
|
||||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
|
||||||
frameworks: ['mocha'],
|
|
||||||
|
|
||||||
// list of files / patterns to load in the browser
|
|
||||||
files: [
|
|
||||||
'test/*.js'
|
|
||||||
],
|
|
||||||
|
|
||||||
// list of files to exclude
|
|
||||||
exclude: [
|
|
||||||
],
|
|
||||||
|
|
||||||
// preprocess matching files before serving them to the browser
|
|
||||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
|
||||||
preprocessors: {
|
|
||||||
'test/*.js': ['rollup']
|
|
||||||
},
|
|
||||||
|
|
||||||
rollupPreprocessor: {
|
|
||||||
plugins: [
|
|
||||||
require('rollup-plugin-node-globals')(),
|
|
||||||
require('rollup-plugin-node-builtins')(),
|
|
||||||
require('rollup-plugin-babel')()
|
|
||||||
],
|
|
||||||
format: 'iife', // Helps prevent naming collisions.
|
|
||||||
name: 'Decoder', // Required for 'iife' format.
|
|
||||||
sourcemap: 'inline' // Sensible for testing.
|
|
||||||
},
|
|
||||||
|
|
||||||
// test results reporter to use
|
|
||||||
// possible values: 'dots', 'progress'
|
|
||||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
|
||||||
reporters: ['progress'],
|
|
||||||
|
|
||||||
|
|
||||||
// web server port
|
|
||||||
port: 9876,
|
|
||||||
|
|
||||||
|
|
||||||
// enable / disable colors in the output (reporters and logs)
|
|
||||||
colors: true,
|
|
||||||
|
|
||||||
|
|
||||||
// level of logging
|
|
||||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
|
||||||
logLevel: config.LOG_INFO,
|
|
||||||
|
|
||||||
|
|
||||||
// enable / disable watching file and executing tests whenever any file changes
|
|
||||||
autoWatch: false,
|
|
||||||
|
|
||||||
|
|
||||||
// start these browsers
|
|
||||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
|
||||||
browsers: ['Chrome'],
|
|
||||||
|
|
||||||
|
|
||||||
// Continuous Integration mode
|
|
||||||
// if true, Karma captures browsers, runs the tests and exits
|
|
||||||
singleRun: true,
|
|
||||||
|
|
||||||
// Concurrency level
|
|
||||||
// how many browser should be started simultaneous
|
|
||||||
concurrency: Infinity
|
|
||||||
})
|
|
||||||
}
|
|
19
package.json
19
package.json
|
@ -14,24 +14,7 @@
|
||||||
},
|
},
|
||||||
"author": "Samir Das",
|
"author": "Samir Das",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-plugin-external-helpers": "^6.22.0",
|
"ws": "^3.3.0"
|
||||||
"babel-preset-es2015": "^6.24.1",
|
|
||||||
"babel-register": "^6.26.0",
|
|
||||||
"karma": "^1.7.1",
|
|
||||||
"karma-chrome-launcher": "^2.2.0",
|
|
||||||
"karma-mocha": "^1.3.0",
|
|
||||||
"karma-rollup-preprocessor": "^5.0.1",
|
|
||||||
"mocha": "^4.0.1",
|
|
||||||
"path": "^0.12.7",
|
|
||||||
"rollup": "^0.50.0",
|
|
||||||
"rollup-plugin-babel": "^2.7.1",
|
|
||||||
"rollup-plugin-buble": "^0.16.0",
|
|
||||||
"rollup-plugin-eslint": "^3.0.0",
|
|
||||||
"rollup-plugin-node-builtins": "^2.1.2",
|
|
||||||
"rollup-plugin-node-globals": "^1.1.0",
|
|
||||||
"rollup-plugin-node-resolve": "^3.0.0",
|
|
||||||
"rollup-plugin-replace": "^1.1.1",
|
|
||||||
"rollup-plugin-uglify": "^1.0.1"
|
|
||||||
},
|
},
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,16 @@ function PCMPlayer(option) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PCMPlayer.prototype.init = function(option) {
|
PCMPlayer.prototype.init = function(option) {
|
||||||
var default = {
|
var defaults = {
|
||||||
encoding: '16bitInt',
|
encoding: '16bitInt',
|
||||||
channels: 1,
|
channels: 1,
|
||||||
sampleRate: 8000,
|
sampleRate: 8000,
|
||||||
flushingTime: 200
|
flushingTime: 1000
|
||||||
};
|
};
|
||||||
this.option = Object.assign({}, default, option);
|
this.option = Object.assign({}, defaults, option);
|
||||||
this.samples = new Float32Array();
|
this.samples = new Float32Array();
|
||||||
this.flush = this.flush.bind(this);
|
this.flush = this.flush.bind(this);
|
||||||
this.interval = setInterval(this.flush, this.flushingTime);
|
this.interval = setInterval(this.flush, this.option.flushingTime);
|
||||||
this.maxValue = this.getMaxValue();
|
this.maxValue = this.getMaxValue();
|
||||||
this.typedArray = this.getTypedArray();
|
this.typedArray = this.getTypedArray();
|
||||||
this.createContext();
|
this.createContext();
|
||||||
|
@ -31,10 +31,10 @@ PCMPlayer.prototype.getMaxValue = function () {
|
||||||
|
|
||||||
PCMPlayer.prototype.getTypedArray = function () {
|
PCMPlayer.prototype.getTypedArray = function () {
|
||||||
var typedArrays = {
|
var typedArrays = {
|
||||||
'8bitInt': 'Int8Array',
|
'8bitInt': Int8Array,
|
||||||
'16bitInt': 'Int16Array',
|
'16bitInt': Int16Array,
|
||||||
'32bitInt': 'Int32Array',
|
'32bitInt': Int32Array,
|
||||||
'32bitFloat': 'Float32Array'
|
'32bitFloat': Float32Array
|
||||||
}
|
}
|
||||||
|
|
||||||
return typedArrays[this.option.encoding] ? typedArrays[this.option.encoding] : typedArrays['16bitInt'];
|
return typedArrays[this.option.encoding] ? typedArrays[this.option.encoding] : typedArrays['16bitInt'];
|
||||||
|
@ -53,7 +53,7 @@ PCMPlayer.prototype.isTypedArray = function(data) {
|
||||||
};
|
};
|
||||||
|
|
||||||
PCMPlayer.prototype.feed = function(data) {
|
PCMPlayer.prototype.feed = function(data) {
|
||||||
if (!this.isTypedArray(isTypedArray)) return;
|
if (!this.isTypedArray(data)) return;
|
||||||
data = this.getFormatedValue(data);
|
data = this.getFormatedValue(data);
|
||||||
var tmp = new Float32Array(this.samples.length + data.length);
|
var tmp = new Float32Array(this.samples.length + data.length);
|
||||||
tmp.set(this.samples, 0);
|
tmp.set(this.samples, 0);
|
||||||
|
@ -114,6 +114,7 @@ PCMPlayer.prototype.flush = function() {
|
||||||
if (this.startTime < this.audioCtx.currentTime) {
|
if (this.startTime < this.audioCtx.currentTime) {
|
||||||
this.startTime = this.audioCtx.currentTime;
|
this.startTime = this.audioCtx.currentTime;
|
||||||
}
|
}
|
||||||
|
console.log('start vs current '+this.startTime+' vs '+this.audioCtx.currentTime);
|
||||||
bufferSource.buffer = audioBuffer;
|
bufferSource.buffer = audioBuffer;
|
||||||
bufferSource.connect(this.gainNode);
|
bufferSource.connect(this.gainNode);
|
||||||
bufferSource.start(this.startTime);
|
bufferSource.start(this.startTime);
|
|
@ -1,28 +0,0 @@
|
||||||
/* global process */
|
|
||||||
|
|
||||||
// Rollup plugins
|
|
||||||
import babel from 'rollup-plugin-babel';
|
|
||||||
import eslint from 'rollup-plugin-eslint';
|
|
||||||
import replace from 'rollup-plugin-replace';
|
|
||||||
import uglify from 'rollup-plugin-uglify';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
input: 'src/opus-to-pcm.js',
|
|
||||||
output: {
|
|
||||||
file: 'dist/opus_to_pcm.js',
|
|
||||||
format: 'iife',
|
|
||||||
name: 'Decoder',
|
|
||||||
sourcemap: false, //inline
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
eslint(),
|
|
||||||
babel({
|
|
||||||
exclude: 'node_modules/**',
|
|
||||||
}),
|
|
||||||
replace({
|
|
||||||
exclude: 'node_modules/**',
|
|
||||||
ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
|
|
||||||
}),
|
|
||||||
(process.env.NODE_ENV === 'production' && uglify()),
|
|
||||||
],
|
|
||||||
};
|
|
|
@ -1,31 +0,0 @@
|
||||||
import {equal, deepEqual} from 'assert';
|
|
||||||
import Event from '../src/utils/event.js';
|
|
||||||
|
|
||||||
var event = new Event('XYZ');
|
|
||||||
|
|
||||||
var callback = function() {
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('event tests --', function() {
|
|
||||||
|
|
||||||
beforeEach(function(){
|
|
||||||
event.offAll();
|
|
||||||
event.on('topic1',callback);
|
|
||||||
event.on('topic1',callback);
|
|
||||||
event.on('topic2',callback);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('listener should be 2 for the topic1', function() {
|
|
||||||
equal(event.listener.topic1.length, 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('event dispatcher should be return true for a successful dispatcher', function() {
|
|
||||||
equal(event.dispatch('topic1', true), true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('listener should be zero after removing all listeners', function() {
|
|
||||||
event.offAll();
|
|
||||||
deepEqual(event.listener, {});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
34
test/ogg.js
34
test/ogg.js
|
@ -1,34 +0,0 @@
|
||||||
import {equal} from 'assert';
|
|
||||||
import Ogg from '../src/utils/ogg.js';
|
|
||||||
var channel = 1,
|
|
||||||
decoder = new Ogg(channel),
|
|
||||||
audioCtx = new (window.AudioContext || window.webkitAudioContext)(),
|
|
||||||
sampleRate = audioCtx.sampleRate;
|
|
||||||
|
|
||||||
|
|
||||||
describe('Ogg tests -- ', function() {
|
|
||||||
it('sample rate should be same system sample rate', function() {
|
|
||||||
equal(decoder.getSampleRate(), sampleRate);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('magic Signature of ID header should be Opus Head', function() {
|
|
||||||
var idHeader = decoder.getIDHeader();
|
|
||||||
var dv = new DataView(idHeader.buffer);
|
|
||||||
equal(dv.getUint32(0, true), 1937076303);
|
|
||||||
equal(dv.getUint32(4, true), 1684104520);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('magic Signature of comment header should be Opus Tags', function() {
|
|
||||||
var commonHeader = decoder.getCommentHeader();
|
|
||||||
var dv = new DataView(commonHeader.buffer);
|
|
||||||
equal(dv.getUint32(0, true), 1937076303);
|
|
||||||
equal(dv.getUint32(4, true), 1936154964);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('page header should be started with OggS', function() {
|
|
||||||
var segmentData = new Uint8Array(20);
|
|
||||||
var page = decoder.getPage(segmentData, 4);
|
|
||||||
var dv = new DataView(page.buffer);
|
|
||||||
equal(dv.getUint32(0, true), 1399285583);
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Add table
Reference in a new issue