Question

Je construis une application de karaoké à l'aide de téléphonesGap pour iOS.

J'ai des fichiers audio dans le dossier www / actifs que je suis capable de jouer à l'aide de la fonction media.play ()

Cela permet à l'utilisateur d'écouter la piste de support. Pendant que le support joue une autre instance de média est enregistré.

Une fois que l'enregistrement a terminé, j'ai besoin de poser le fichier d'enregistrement vocal sur la piste de support et je n'ai aucune idée de la façon dont je pourrais faire cela.

Une approche que j'ai pensée pourrait fonctionner est d'utiliser l'API audio Web - j'ai le code suivant que j'ai pris de HTML5 Rocks qui charge les deux fichiers dans un audiocontext et me permet de jouer simultanément. Cependant, ce que je voudrais faire, c'est écrire les deux tampons dans un seul fichier .wav. Est-ce que je peux combiner Source1 et Source2 dans un seul nouveau fichier?

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

Il pourrait y avoir quelque chose dans cette solution Comment convertir une gamme de données audio en fichier WAV? autant que je puisse dire, ils se mêlent aux deux tampons et les codant en tant que .wav mais je ne peux pas comprendre où Ils les écrivent dans un fichier (sauvegarder le nouveau fichier WAV) toutes les idées?

La réponse ci-dessous - ne vous aide pas vraiment car j'utilise l'API audio Web (JavaScript) non IOS

Était-ce utile?

La solution

La solution consistait à utiliser l'OFFLINEAUDIOCONTEXT

Les étapes étaient: 1. Chargez les deux fichiers sous forme de tampons à l'aide du chargeur tampon 2. Créer un offlinAudiOcontext 3. Connectez les deux tampons à l'OFFLINAUDIOCONTEXT 4. Démarrer les deux tampons 5. Utilisez la fonction StarTrendering hors ligne 6. Définissez la fonction Offfline.OnComplet pour obtenir une poignée sur le rendubuffer.

Voici le code:

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

Autres conseils

Je suggérerais de mélanger directement le PCM.Si vous initialisez un tampon qui chevauche les trames de temps des deux pistes, la formule est additive:

Mélange (A, B)= A + B - A * B / 65535.

Cette formule dépend des entiers de 16 bits non signés.Voici un exemple:

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

Cela peut être un moyen très efficace de gérer l'audio 16 bits signé. Allez ici pour la source .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top