Phonegap混合audio文件

我使用Phonegap为Ios构build了一个卡拉OK应用程序。

我可以使用media.play()函数播放www / assets文件夹中的audio文件

这允许用户收听背景音轨。 而媒体正在播放另一媒体实例正在录制。

一旦录音结束,我需要把录音文件放在背景音轨上,我不知道如何去做这件事。

我认为可能的一种方法是使用WEb Audio API – 我从HTML5 Rocks获取了以下代码,将两个文件加载到AudioContext中,并允许我同时播放这两个文件。 但是,我想要做的是将两个缓冲区写入一个.wav文件。 有什么办法可以将source1和source2合并成一个新的文件?

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

这个解决scheme中可能有些东西我如何将一个audio数据数组转换成一个wav文件? 据我所知,他们交错两个缓冲区和编码为.wav,但我不知道他们在哪里写入文件(保存新的wav文件)的任何想法?

下面的答案 – 并没有真正的帮助,因为我使用Web Audio Api(javascript)而不是IOS

解决scheme是使用offlineAudioContext

步骤如下:1.使用BufferLoader将两个文件作为缓冲区加载2.创buildOfflineAudioContext 3.将两个缓冲区连接到OfflineAudioContext 4.启动两个缓冲区5.使用offline startRendering函数6.设置offfline.oncomplete函数获取renderedBuffer的句柄。

代码如下:

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

我build议直接混合PCM。 如果初始化与两个轨道的时间框架重叠的缓冲区,则该公式是可加的:

混合(a,b)= a + b-a * b / 65535。

这个公式取决于无符号的16位整数。 这是一个例子:

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

这可以是一个非常有效的方式来处理签名的16位audio。 去这里的来源 。