Вопрос

Я создаю приложение караоке с помощью Phonegap для iOS.

У меня есть аудиофайлы в папке www / atacets, которые я могу играть с помощью функции media.play ()

Это позволяет пользователю прослушивать подложку. Хотя носитель играет другой медиа-экземпляр, является записью.

Как только запись закончила, мне нужно заложить файл записи голоса на подложку, и я понятия не имею о том, как я могу сделать это.

Один подход, который я подумал, что может работать - это использовать веб-аудио API - у меня есть следующий код, который я взял из HTML5 Rocks , которые загружают два файла в аудиоконструкцию и позволяет мне играть как одновременно. Однако то, что я хотел бы сделать, это напишите два буфера в один файл .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);
}
.

Там может быть что-то в этом решении Как я могу преобразовать массив аудиоданных в файл wav? насколько я могу разглядеть, они чередуются два буфера и кодируют их как .wav, но я не могу выяснить, где Они пишут их в файл (сохраняя новый файл WAV) любые идеи?

Ответ ниже - на самом деле не помогает, как я использую Web Audio API (JavaScript), а не IOS

Это было полезно?

Решение

решение было использовать OfflineAudioContext

Шаги были: 1. Загрузите два файла в качестве буферов с помощью буферного загрузчика 2. Создайте OfflineAudioContext 3. Подсоедините два буфера до OfflineAudioContext 4. Начните два буфера 5. Используйте функцию вне форума StarTrendering 6. Установите функцию OFFFLINE.ONCOMPLETE, чтобы получить ручку на рендереме.

Вот код:

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

Другие советы

Я бы предложил смешивать 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-битный аудио. Перейти сюда для источника .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top