2015-01-30 12 views
7

Sto tentando di ridimensionare la frequenza di campionamento che ottengo da audioContext. Credo che stia arrivando a 44100, e voglio che sia 11025. Ho pensato che potevo fare una media ogni 3 campioni e che riproduce alla velocità corretta, ma il tono è troppo alto, come se fossimo tutti a elio .Downsampling di un buffer audio PCM in javascript

Qual è il modo corretto di eseguire il downsampling di un float32Array da 44100 a un int16Array su 11025 campioni.

var context = new Flash.audioContext(); 
var audioInput = context.createMediaStreamSource(stream); 
var recorder = context.createScriptProcessor(null, 1, 1); 
recorder.onaudioprocess = onAudio; 
audioInput.connect(recorder); 
recorder.connect(context.destination); 

var onAudio = function (e) { 
    var left = e.inputBuffer.getChannelData(0); 
    bStream.write(Flash.convertFloat32ToInt16(left)); 
} 

var convertFloat32ToInt16 = function(buffer) { 
    var l = buffer.length; 
    var point = Math.floor(l/3); 
    var buf = new Int16Array(point); 
    for (var x = l; x > 0;) { 
     var average = (buffer[x] + buffer[x-1] + buffer[x-2])/3; 
     buf[point] = average*0x7FFF; 
     point -= 1; 
     x -= 3; 
    } 
    return buf.buffer; 
} 

risposta

10

Per chiunque altro abbia bisogno della risposta.

var downsampleBuffer = function (buffer, sampleRate, outSampleRate) { 
    if (outSampleRate == sampleRate) { 
     return buffer; 
    } 
    if (outSampleRate > sampleRate) { 
     throw "downsampling rate show be smaller than original sample rate"; 
    } 
    var sampleRateRatio = sampleRate/outSampleRate; 
    var newLength = Math.round(buffer.length/sampleRateRatio); 
    var result = new Int16Array(newLength); 
    var offsetResult = 0; 
    var offsetBuffer = 0; 
    while (offsetResult < result.length) { 
     var nextOffsetBuffer = Math.round((offsetResult + 1) * sampleRateRatio); 
     var accum = 0, count = 0; 
     for (var i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) { 
      accum += buffer[i]; 
      count++; 
     } 

     result[offsetResult] = Math.min(1, accum/count)*0x7FFF; 
     offsetResult++; 
     offsetBuffer = nextOffsetBuffer; 
    } 
    return result.buffer; 
} 

Ciò restituirà una frequenza di campionamento più piccola di quella passata ad esso, mentre anche convertirlo in un int16Array invece di un float32.

+0

Grazie a Dio per questo post. Mi hai aiutato così tanto da non averne idea. –

+0

Sono contento che sia stato in grado di aiutare qualcuno :) era un disastro da risolvere. – Neablis

+0

Mi salvi la giornata: 'D – diewland

Problemi correlati