lamejs icon indicating copy to clipboard operation
lamejs copied to clipboard

Voice are not clear. Audio having distortion

Open durgadp opened this issue 4 years ago • 16 comments

I am using your lamejs for recording voice and convert into mp3. Below is audio link what i am exactly facing the problem after recording Distorted Audio : https://www.ptemocktest.com/pte/uploaddata/answer-audio/d3cd0a153620a3ddb12e09c31c3f7bbd.mp3

This is configuration i am using to record

var mp3Encoder, maxSamples = 1152, samplesMono, config, dataBuffer; var clearBuffer = function () { dataBuffer = []; };

var appendToBuffer = function (mp3Buf) { dataBuffer.push(new Int8Array(mp3Buf)); };

var init = function (prefConfig) { config = prefConfig || {debug: true}; mp3Encoder = new lamejs.Mp3Encoder(1, config.sampleRate || 48000, config.bitRate || 128); clearBuffer(); };

Please help where i am doing wrong with configuration.

durgadp avatar Jul 27 '19 08:07 durgadp

i cant tell from looking at the code but it looks like you are not feeding the encoder properly

zhuker avatar Jul 30 '19 15:07 zhuker

Please let me help what i need to be code for encoder properly

durgadp avatar Jul 30 '19 16:07 durgadp

sounds like you are calling flush() too often, try calling it only at the end of encode

zhuker avatar Jul 30 '19 16:07 zhuker

Can I share the code file with you? You want me to call flush after sending to the server or before.

durgadp avatar Jul 31 '19 07:07 durgadp

Can I share the code file with you? You want me to call flush after sending to the server or before.

Post the most relevant snippet here, i'll take a look

zhuker avatar Jul 31 '19 13:07 zhuker

/**

  • Created by intelWorx on 27/10/2015. */ (function () { 'use strict';

console.log('MP3 conversion worker started.'); importScripts('https://www.ptemocktest.com/pte/public/customjs/js/lame.min.js');

var mp3Encoder, maxSamples = 1152, samplesMono, config, dataBuffer; var clearBuffer = function () { dataBuffer = []; };

var appendToBuffer = function (mp3Buf) { dataBuffer.push(new Int8Array(mp3Buf)); };

var init = function (prefConfig) { config = prefConfig || {debug: true}; mp3Encoder = new lamejs.Mp3Encoder(1, config.sampleRate || 48000, config.bitRate || 128); clearBuffer(); };

var floatTo16BitPCM = function floatTo16BitPCM(input, output) { //var offset = 0; for (var i = 0; i < input.length; i++) { var s = Math.max(-1, Math.min(1, input[i])); output[i] = (s < 0 ? s * 0x8000 : s * 0x7FFF); } };

var convertBuffer = function(arrayBuffer){ var data = new Float32Array(arrayBuffer); var out = new Int16Array(arrayBuffer.length); floatTo16BitPCM(data, out) return out; };

var encode = function (arrayBuffer) { samplesMono = convertBuffer(arrayBuffer); var remaining = samplesMono.length; for (var i = 0; remaining >= 0; i += maxSamples) { var left = samplesMono.subarray(i, i + maxSamples); var mp3buf = mp3Encoder.encodeBuffer(left); appendToBuffer(mp3buf); remaining -= maxSamples; }

};

var finish = function () { appendToBuffer(mp3Encoder.flush()); self.postMessage({ cmd: 'end', buf: dataBuffer }); if (config.debug) { console.log('Sending finished command'); } clearBuffer(); //free up memory };

self.onmessage = function (e) { switch (e.data.cmd) { case 'init': init(e.data.config); break;

  case 'encode':
    encode(e.data.buf);
    break;

  case 'finish':
    finish();
    break;
}

};

})();

durgadp avatar Jul 31 '19 14:07 durgadp

    var data = new Float32Array(arrayBuffer);
    var out = new Int16Array(arrayBuffer.length);

change to

    var data = new Float32Array(arrayBuffer);
    var out = new Int16Array(data.length);

zhuker avatar Jul 31 '19 14:07 zhuker

I have tried by replace this code but still facing same issue. Please let me know where i am doing wrong with code.

durgadp avatar Sep 16 '19 14:09 durgadp

can you create an end-to-end example i can reproduce here? i mean no worker code, no messages

zhuker avatar Sep 16 '19 14:09 zhuker

Above is my file please let me know which code i need to remove from it.

durgadp avatar Sep 16 '19 15:09 durgadp

I can’t reproduce the problem using the code you posted.

Sent from my iPhone

On Sep 16, 2019, at 6:05 PM, Durga Parshad [email protected] wrote:

Above is my file please let me know which code i need to remove from it.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

zhuker avatar Sep 16 '19 15:09 zhuker

arrayBuffer passed to your var encode = function (arrayBuffer) { must be of size divisible by 1152 * 4 if size is different encoder will produce the clicks you are hearing

zhuker avatar Sep 17 '19 10:09 zhuker

What i need to do for 1152 * 4 into my encode function so it will ignore

durgadp avatar Sep 19 '19 14:09 durgadp

@durgadp I'm testing lamejs as fallback for vmsgjs right now. Here is my handling of this limitation (mono sound example).

// assumes that t - is some sort of object, in my case it's vmsgjs Recorder instance
t.len = 0;
// List of valid buffSize values can be found here:
// https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createScriptProcessor
// To use buffSize = 256 change t.samplesInFrame to 18. In other cases you don't change it
t.buffSize = 1024;
t.samplesInFrame = 9;
t.sampleFrameSize = t.buffSize * t.samplesInFrame;
t.unsentSamples = [];

function startRecording(){
  // assumes that
  //  t.encNode = (t.audioCtx.createScriptProcessor || t.audioCtx.createJavaScriptNode)
  //              .call(t.audioCtx, t.buffSize, inputChannelsNumber, outputChannelsNumber)
  t.encNode.onaudioprocess = function(e){
   // create new array so data won't be corrupted, references suck sometimes
   t.unsentSamples[t.len++]	=	new Float32Array(e.inputBuffer.getChannelData(0));
    if (!(t.len % t.samplesInFrame)){
      t.worker.postMessage({
         cmd: 'encode',
         data: { buf: concatSamples(t.unsentSamples, t.sampleFrameSize) }
      });
      t.len = 0;
      t.unsentSamples = [];
    }
  }
  t.encNode.connect(t.audioCtx.destination);
}

function stopRecording(){
  t.len = 0;
  t.unsentSamples = [];
  t.encNode.onaudioprocess = null;
  t.unsentSamples && t.unsentSamples.length && t.worker.postMessage({
    cmd: 'encode',
    data: {
       buf: concatSamples(t.unsentSamples, t.sampleFrameSize)
    }
 });
 t.worker.postMessage({ cmd: 'finish' });
 // disconnect Nodes, destroy stuff
}

// concatenate audio samples
// if not enough samples passed we will still return valid Float32Array
// when totalLength passed divisible by 4608 = 1152*4
// samples - array of Float32Arrays
// totalLength - combined length of Float32Arrays in samples
function concatSamples(samples, totalLength){
  var l = samples.length,
  len = 0,
  res = new Float32Array(totalLength);		
  for (var i = 0; i < l; i++){
    res.set(samples[i], len);
    len += samples[i].length;
  }
  return res;
}

Hope this helps others to work around this limitation.

lostrepo avatar Oct 06 '19 10:10 lostrepo

sounds like you are calling flush() too often, try calling it only at the end of encode

What do you mean by calling flush() too often?

durgadp avatar Feb 14 '20 17:02 durgadp

t.sampleFrameSize

var remaining = samplesMono.length; I am getting 2048 length here which is divisible by 4. Help me if i am doing any thing wrong.

durgadp avatar Feb 14 '20 18:02 durgadp