Domanda

Sto costruendo un'applicazione Karaoke utilizzando Phonegap per iOS.

Ho file audio nella cartella www / asset che sono in grado di riprodurre utilizzando la funzione Media.Play ()

Ciò consente all'utente di ascoltare la pista di supporto. Mentre il supporto riproduce un'altra istanza media è la registrazione.

Una volta terminata la registrazione, ho bisogno di posare il file di registrazione vocale sulla traccia di supporto e non ho idea di come potrei andare a fare questo.

Un approccio Ho pensato che potrebbe funzionare è utilizzare l'API dell'audio Web - Ho il seguente codice che ho preso da HTML5 Rocks che carica i due file in un audioContext e mi consente di riprodurre contemporaneamente. Tuttavia, ciò che vorrei fare è scrivere i due buffer in un singolo file .wav. C'è un modo in cui posso combinare Source1 e Source2 in un unico nuovo file?

var context;
var bufferLoader;

function init() {
    // Fix up prefixing
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    context = new AudioContext();

    bufferLoader = new BufferLoader(
        context,
        [
            'backingTrack.wav',
            'voice.wav',
        ],
        finishedLoading
    );

    bufferLoader.load();
}

function finishedLoading(bufferList) {
    // Create two sources and play them both together.
    var source1 = context.createBufferSource();
    var source2 = context.createBufferSource();
    source1.buffer = bufferList[0];
    source2.buffer = bufferList[1];

    source1.connect(context.destination);
    source2.connect(context.destination);
    source1.start(0);
    source2.start(0);
}


function BufferLoader(context, urlList, callback) {
    this.context = context;
    this.urlList = urlList;
    this.onload = callback;
    this.bufferList = new Array();
    this.loadCount = 0;
}

BufferLoader.prototype.loadBuffer = function(url, index) {
    // Load buffer asynchronously
    var request = new XMLHttpRequest();
    request.open("GET", url, true);
    request.responseType = "arraybuffer";

    var loader = this;

    request.onload = function() {
        // Asynchronously decode the audio file data in request.response
        loader.context.decodeAudioData(
            request.response,
            function(buffer) {
                if (!buffer) {
                    alert('error decoding file data: ' + url);
                    return;
                }
                loader.bufferList[index] = buffer;
                if (++loader.loadCount == loader.urlList.length)
                    loader.onload(loader.bufferList);
            },
            function(error) {
                console.error('decodeAudioData error', error);
            }
        );
    }

    request.onerror = function() {
        alert('BufferLoader: XHR error');
    }

    request.send();
}

BufferLoader.prototype.load = function() {
    for (var i = 0; i < this.urlList.length; ++i)
        this.loadBuffer(this.urlList[i], i);
}
.

Potrebbe esserci qualcosa in questa soluzione Come convertire una serie di dati audio in un file wav? per quanto posso capire che stanno interlacciando i due buffer e li codificano come un .wav ma non riesco a capire Li stanno scrivendo in un file (salvando il nuovo file WAV) qualsiasi idea?

La risposta qui sotto - non aiuta davvero come sto usando Web AUDIO API (JavaScript) non iOS

È stato utile?

Soluzione

La soluzione era usare il OfflineAudiocontext

I passaggi erano: 1. Carica i due file come buffer utilizzando il bufferloader 2. Creare un offlineaudiocontext 3. Collega i due buffer all'offlineAudiocontext 4. Avvia i due buffer 5. Utilizzare la funzione Startrendering offline 6. Impostare la funzione offfline.oncomplete per ottenere una maniglia sul renderingbuffer.

Ecco il codice:

offline = new webkitOfflineAudioContext(2, voice.buffer.length, 44100);
vocalSource = offline.createBufferSource();
vocalSource.buffer = bufferList[0];
vocalSource.connect(offline.destination);

backing = offline.createBufferSource();
backing.buffer = bufferList[1];
backing.connect(offline.destination);

vocalSource.start(0);
backing.start(0);

offline.oncomplete = function(ev){
    alert(bufferList);
    playBackMix(ev);
    console.log(ev.renderedBuffer);
    sendWaveToPost(ev);
}
offline.startRendering();
.

Altri suggerimenti

Suggerirei di mescolare direttamente il PCM.Se si inizializza un buffer che si sovrappone ai fotogrammi di tempo di entrambe le tracce, la formula è additiva:

.

Mix (A, B)= A + B - A * B / 65535.

Questa formula dipende da numeri interi a 16 bit non firmati.Ecco un esempio:

SInt16 *bufferA, SInt16 *bufferB;
NSInteger bufferLength;
SInt16 *outputBuffer;

for ( NSInteger i=0; i<bufferLength; i++ ) {
  if ( bufferA[i] < 0 && bufferB[i] < 0 ) {
    // If both samples are negative, mixed signal must have an amplitude between 
    // the lesser of A and B, and the minimum permissible negative amplitude
    outputBuffer[i] = (bufferA[i] + bufferB[i]) - ((bufferA[i] * bufferB[i])/INT16_MIN);
  } else if ( bufferA[i] > 0 && bufferB[i] > 0 ) {
    // If both samples are positive, mixed signal must have an amplitude between the greater of
    // A and B, and the maximum permissible positive amplitude
    outputBuffer[i] = (bufferA[i] + bufferB[i]) - ((bufferA[i] * bufferB[i])/INT16_MAX);
  } else {
    // If samples are on opposite sides of the 0-crossing, mixed signal should reflect 
    // that samples cancel each other out somewhat
    outputBuffer[i] = bufferA[i] + bufferB[i];
  }
}
.

Questo può essere un modo molto efficace per gestire l'audio firmato a 16 bit. Vai qui per la fonte .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top