Phonegap mezclando files de audio

Estoy construyendo una aplicación de karaoke con Phonegap para iOS.

Tengo files de audio en la carpeta www / assets que puedo reproducir usando la function media.play ()

Esto permite al usuario escuchar la pista de acompañamiento. Mientras el medio está reproduciendo, otra instancia de Media está grabando.

Una vez que la grabación ha finalizado, necesito colocar el file de grabación de voz en la pista de respaldo y no tengo idea de cómo podría hacer esto.

Un enfoque que pensé que podría funcionar es usar WEb Audio API: tengo el siguiente código que tomé de HTML5 Rocks, que carga los dos files en un AudioContext y me permite reproducirlos simultáneamente. Sin embargo, lo que me gustaría hacer es escribir los dos búferes en un solo file .wav. ¿Hay alguna forma en que pueda combinar source1 y source2 en un único file nuevo?

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); } 

Puede haber algo en esta solución ¿Cómo convierto una matriz de datos de audio en un file WAV? Por lo que puedo deducir, están entrelazando los dos búferes y codificándolos como .wav pero no puedo descifrar dónde están escribiéndolos en un file (guardando el nuevo file wav) ¿Alguna idea?

La respuesta a continuación – realmente no ayuda, ya que estoy usando Audio Web Api (javascript) no IOS

La solución era utilizar offlineAudioContext

Los pasos fueron: 1. Cargue los dos files como búferes con el BufferLoader 2. Cree un OfflineAudioContext 3. conecte los dos búferes a OfflineAudioContext 4. inicie los dos búferes 5. use la function startRendering sin connection 6. Establezca la function offfline.oncomplete para get un identificador en el rendenetworkingBuffer.

Aquí está el código:

 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.rendenetworkingBuffer); sendWaveToPost(ev); } offline.startRendering(); 

Sugiero mezclar el PCM directamente. Si inicializa un búfer que se solapa con los frameworks de time de ambas pistas, entonces la fórmula es aditiva:

mezclar (a, b) = a + b – a * b / 65535.

Esta fórmula depende de los integers sin signo de 16 bits. He aquí un ejemplo:

 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]; } } 

Esta puede ser una forma muy efectiva de manejar audio de 16 bits firmado. Ve aquí para la fuente .