diff --git a/README.md b/README.md
index 23f9e37a..4040f79d 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@ The Opus encoder will not work if the value is not 8000, 12000, 16000, 24000 or
rec.addEventListener( type, listener[, useCapture] )
-**addEventListener** will add an event listener to the event target. Custom events are "recordingProgress", "recordingError", "dataAvailable", "start", "pause", "resume" and "stop".
+**addEventListener** will add an event listener to the event target. Available events are "recordingProgress", "streamError", "streamReady", dataAvailable", "start", "pause", "resume" and "stop".
rec.setMonitorGain( gain )
diff --git a/example.html b/example.html
index 8514a4af..826f6477 100644
--- a/example.html
+++ b/example.html
@@ -77,9 +77,6 @@
Log
init.addEventListener( "click", function(){
- init.disabled = pause.disabled = resume.disabled = stopButton.disabled = true;
- start.disabled = false;
-
recorder = new Recorder({
monitorGain: monitorGain.value,
numberOfChannels: numberOfChannels.value,
@@ -117,10 +114,16 @@ Log
screenLogger('Recorded ' + e.detail + ' seconds');
});
- recorder.addEventListener( "recordingError", function(e){
+ recorder.addEventListener( "streamError", function(e){
screenLogger('Error encountered: ' + e.error.name );
});
+ recorder.addEventListener( "streamReady", function(e){
+ screenLogger('Audio stream is ready. Recording can begin.');
+ init.disabled = pause.disabled = resume.disabled = stopButton.disabled = true;
+ start.disabled = false;
+ });
+
recorder.addEventListener( "dataAvailable", function(e){
var fileName = new Date().toISOString() + "." + e.detail.type.split("/")[1];
var url = URL.createObjectURL( e.detail );
diff --git a/oggopus.js b/oggopus.js
index 6c0504e2..88574349 100644
--- a/oggopus.js
+++ b/oggopus.js
@@ -29,11 +29,10 @@ var OggOpus = function( config ){
OggOpus.prototype.encode = function( samples ) {
var sampleIndex = 0;
- var lengthToCopy;
while ( sampleIndex < samples.length ) {
- lengthToCopy = Math.min( this.encoderBufferLength - this.encoderBufferIndex, samples.length - sampleIndex );
+ var lengthToCopy = Math.min( this.encoderBufferLength - this.encoderBufferIndex, samples.length - sampleIndex );
this.encoderBuffer.set( samples.subarray( sampleIndex, sampleIndex+lengthToCopy ), this.encoderBufferIndex );
sampleIndex += lengthToCopy;
this.encoderBufferIndex += lengthToCopy;
@@ -199,18 +198,23 @@ OggOpus.prototype.segmentPacket = function( packetLength ) {
var packetIndex = 0;
while ( packetLength >= 0 ) {
+
+ if ( this.segmentTableIndex === 255 ) {
+ this.generatePage();
+ this.headerType = 1;
+ }
+
var segmentLength = Math.min( packetLength, 255 );
this.segmentTable[ this.segmentTableIndex++ ] = segmentLength;
this.segmentData.set( this.encoderOutputBuffer.subarray( packetIndex, packetIndex + segmentLength ), this.segmentDataIndex );
this.segmentDataIndex += segmentLength;
packetIndex += segmentLength;
packetLength -= 255;
-
- if ( this.segmentTableIndex === 255 ) {
- this.generatePage();
- this.headerType = ( packetLength >= 0 ) ? 1 : 0;
- }
}
this.granulePosition += ( 48 * this.encoderFrameSize );
+ if ( this.segmentTableIndex === 255 ) {
+ this.generatePage();
+ this.headerType = 0;
+ }
};
diff --git a/recorder.js b/recorder.js
index 05f11820..5f0fc8aa 100755
--- a/recorder.js
+++ b/recorder.js
@@ -49,25 +49,28 @@ Recorder.prototype.createAudioNodes = function(){
this.monitorNode = this.audioContext.createGain();
this.setMonitorGain( this.config.monitorGain );
- // 6th order butterworth
if ( this.config.sampleRate < this.audioContext.sampleRate ) {
- this.filterNode = this.audioContext.createBiquadFilter();
- this.filterNode2 = this.audioContext.createBiquadFilter();
- this.filterNode3 = this.audioContext.createBiquadFilter();
- this.filterNode.type = this.filterNode2.type = this.filterNode3.type = "lowpass";
-
- var nyquistFreq = this.config.sampleRate / 2;
- this.filterNode.frequency.value = this.filterNode2.frequency.value = this.filterNode3.frequency.value = nyquistFreq - ( nyquistFreq / 3.5355 );
- this.filterNode.Q.value = 0.51764;
- this.filterNode2.Q.value = 0.70711;
- this.filterNode3.Q.value = 1.93184;
-
- this.filterNode.connect( this.filterNode2 );
- this.filterNode2.connect( this.filterNode3 );
- this.filterNode3.connect( this.scriptProcessorNode );
+ this.createButterworthFilter();
}
};
+Recorder.prototype.createButterworthFilter = function(){
+ this.filterNode = this.audioContext.createBiquadFilter();
+ this.filterNode2 = this.audioContext.createBiquadFilter();
+ this.filterNode3 = this.audioContext.createBiquadFilter();
+ this.filterNode.type = this.filterNode2.type = this.filterNode3.type = "lowpass";
+
+ var nyquistFreq = this.config.sampleRate / 2;
+ this.filterNode.frequency.value = this.filterNode2.frequency.value = this.filterNode3.frequency.value = nyquistFreq - ( nyquistFreq / 3.5355 );
+ this.filterNode.Q.value = 0.51764;
+ this.filterNode2.Q.value = 0.70711;
+ this.filterNode3.Q.value = 1.93184;
+
+ this.filterNode.connect( this.filterNode2 );
+ this.filterNode2.connect( this.filterNode3 );
+ this.filterNode3.connect( this.scriptProcessorNode );
+};
+
Recorder.prototype.initStream = function(){
var that = this;
navigator.getUserMedia(
@@ -77,9 +80,10 @@ Recorder.prototype.initStream = function(){
that.sourceNode = that.audioContext.createMediaStreamSource( stream );
that.sourceNode.connect( that.filterNode || that.scriptProcessorNode );
that.sourceNode.connect( that.monitorNode );
+ that.eventTarget.dispatchEvent( new Event( "streamReady" ) );
},
function ( e ) {
- that.eventTarget.dispatchEvent( new ErrorEvent( "recordingError", { error: e } ) );
+ that.eventTarget.dispatchEvent( new ErrorEvent( "streamError", { error: e } ) );
}
);
};
@@ -129,9 +133,6 @@ Recorder.prototype.setMonitorGain = function( gain ){
Recorder.prototype.start = function(){
if ( this.state === "inactive" && this.sourceNode ) {
- this.monitorNode.connect( this.audioContext.destination );
- this.scriptProcessorNode.connect( this.audioContext.destination );
-
var that = this;
this.worker = new Worker( this.config.workerPath );
this.worker.addEventListener( "message", function( e ) {
@@ -153,7 +154,9 @@ Recorder.prototype.start = function(){
this.state = "recording";
this.recordingTime = 0;
- this.recordBuffers = function(){ delete this.recordBuffers };
+ this.monitorNode.connect( this.audioContext.destination );
+ this.scriptProcessorNode.connect( this.audioContext.destination );
+ this.recordBuffers = function(){ delete this.recordBuffers }; // First buffer can contain old data
this.eventTarget.dispatchEvent( new Event( 'start' ) );
this.eventTarget.dispatchEvent( new CustomEvent( 'recordingProgress', { "detail": this.recordingTime } ) );
}