Phonegap Mixing Audio Files
-
21-12-2019 - |
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
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 .