2017-04-21 2 views
2

J'ai eu quelques problèmes avec PCM Audio sur le navigateur. L'audio PCM provient d'un périphérique Android avec protocole udp et est sauvegardé sur le serveur en tant que * .rawLecture PCM avec javascript

J'ai essayé sans succès de lire ce fichier enregistré avec l'aide de webaudioapi. En utilisant le code suivant, me joue un son effrayant avec le bruit blanc:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); 
audioCtx.sampleRate = 16000; 


// Stereo 
var channels = 1; 
// Create an empty two second stereo buffer at the 
// sample rate of the AudioContext 
var frameCount = audioCtx.sampleRate * 10.0; 

var myAudioBuffer = audioCtx.createBuffer(channels, frameCount, audioCtx.sampleRate); 


var req = new XMLHttpRequest(); 
req.open('GET', "example.raw", false); 
req.overrideMimeType('text\/plain; charset=x-user-defined'); 
req.send(null); 

function play(){ 
    for (var channel = 0; channel < channels; channel++) { 

     var nowBuffering = myAudioBuffer.getChannelData(channel,16,16000); 
     for (var i = 0; i < frameCount; i++) { 
      // audio needs to be in [-1.0; 1.0] 
      // for this reason I also tried to divide it by 32767 
      // as my pcm sample is in 16-Bit. It plays still the 
      // same creepy sound less noisy. 
      nowBuffering[i] = (req.responseText.charCodeAt(i) & 0xff; 

     } 
    } 
    // Get an AudioBufferSourceNode. 
    // This is the AudioNode to use when we want to play an AudioBuffer 
    var source = audioCtx.createBufferSource(); 
    // set the buffer in the AudioBufferSourceNode 
    source.buffer = myAudioBuffer; 
    // connect the AudioBufferSourceNode to the 
    // destination so we can hear the sound 
    source.connect(audioCtx.destination); 
    // start the source playing 
    source.start(); 
} 

Il joue un tel son que je suis non identifiable ne sais pas si elle joue le fichier pcm que je supposé qu'il a à faire. Je suppose qu'il doit faire quelque chose avec le fichier pcm. Le fichier PCM a un taux d'échantillonnage de 16 kHz, 16 bits par échantillon et un seul canal ou plutôt mono-canal.

Quelqu'un a-t-il le même problème ou a-t-il des suggestions pour résoudre mon problème?

Je cherche depuis quelques jours une solution et apprécie toute aide.

Répondre

5

Tout d'abord:

audioCtx.sampleRate = 16000; ne fonctionne pas. Vous ne pouvez pas modifier audioCtx.sampleRate. Au lieu de cela, vous avez besoin de faire ce qui suit:

var frameCount = req.responseText.length/2; 
var myAudioBuffer = audioCtx.createBuffer(channels, frameCount, 16000); 

Parce que votre fichier est de 16 bits, sa longueur en octets est deux fois le nombre d'images dont vous avez besoin.

(req.responseText.charCodeAt(i) & 0xff) donnera une valeur comprise entre 0 et 255, représentant un seul octet de 8 bits. Vous avez besoin de 16 bits.

Vous devez connaître l'ordre des octets de votre échantillon, et traiter deux octets chaque fois

Pour little endian (LSB):

var word = (req.responseText.charCodeAt(i * 2) & 0xff) + ((req.responseText.charCodeAt(i * 2 + 1) & 0xff) << 8); 

Pour big endian (MSB en premier):

var unsignedWord = ((req.responseText.charCodeAt(i * 2) & 0xff) << 8) + (req.responseText.charCodeAt(i * 2 + 1) & 0xff); 

Cela donnera un nombre compris entre 0 et 65535, représentant un entier non signé de 16 bits. Afin de convertir en entier signé, vous devez effectuer les opérations suivantes (remplacez X par le code ci-dessus)

var signedWord = (unsignedWord + 32768) % 65536 - 32768; 

Cela donnera un nombre entre -32768 et 32767, que vous pouvez ensuite diviser par 32768,0 pour obtenir le résultat souhaité.

nowBuffering[i] = signedWord/32768.0; 

Edit: Exemple de travail https://o.lgm.cl/example.html (16 bits poids faible)

0

@Locolois

J'ai essayé votre suggestion/solution et obtenir des sons clairs, qui malheureusement encore ne semblait pas être l'original . Il y a aussi du bruit blanc toutes les secondes, ce qui était moins effrayant que ma solution: D mais je n'ai toujours pas entendu ma voix que j'ai enregistrée. Je ne suis pas sûr si le pcm, qui exportations android.audiorecord a grand ou petit endian, alors j'ai essayé les deux façons. Mais le son que j'ai entendu en utilisant la suggestion que vous avez faite pour big endian, sonnait plus correct pour moi que la petite version endian. La petite version d'endian était également entièrement avec le bruit blanc.

Est-il la mise en œuvre droite, de votre explication ?:

for (var i = 0; i < frameCount; i+=2) { 

      var msbFirst = (req.responseText.charCodeAt(i) & 0xff) + (req.responseText.charCodeAt(i + 1) & 0xff) << 8; 
      var msbSigned = (msbFirst + 32768) % 65536 - 32768; 
      nowBuffering[i] = msbSigned/65536.0; 
     } 
+0

Il y avait une erreur dans ma solution. J'ai soumis un correctif et ajouté un exemple. – Locoluis

+0

Je l'essaie avec votre exemple. Il ne fonctionne toujours pas ...:/ Pouvez-vous essayer de jouer ce cru avec votre exemple? http://taxameter.esy.es/example.raw –

+0

Ok, j'ai tout faux, en fournissant tous les autres cadres. Mes exemples ont fonctionné parce qu'ils avaient des données sans heurts. J'ai mis à jour la réponse et l'exemple de travail. De plus, inutile d'utiliser ou de jouer avec 'audioCtx.sampleRate'. – Locoluis