2014-12-22 1 views
0

Задача
Javascript-созданный WAV-файл некорректной длины и беззвучный.Веб-аудио API - созданный JAVA файл неверной длины и беззвучный

Детали
Я использую JavaScript Web Audio API для создания веб-приложение, которое может принимать несколько звуковых файлов, захватить случайный кусок каждого из них, а затем «смешивать» их вместе в пробоотборник (серийно , т. е. file1 + file2 + ... + fileN), вроде рода mashup. Звуки могут быть успешно загружены в мой пользовательский объект SoundPlayer, и они могут быть воспроизведены. Однако, когда вы идете, чтобы их смешивать вместе, полученный WAV-файл имеет неправильную длину и полностью отключается.

Интерфейс позволяет до 10 звуков загружаться и воспроизводиться на их собственном томе. Вы нажимаете кнопку, чтобы сделать сэмплером WAV их вместе, и он динамически создает ссылку для ее загрузки. У меня также есть способ увидеть шестнадцатеричный дамп результирующего файла, и он показывает кучу 00s и даже некоторые NaN в нижней части, поэтому, очевидно, мой алгоритм испорчен, но я просто не могу понять, как это сделать.

Когда вы нажимаете «Сделать пробник!» Кнопка, она выполняет следующую функцию (с массивом пользовательских объектов SoundPlayer, которые содержат аудио буферов, в качестве аргумента):

function createSampler(sndArr) { 
    var numberOfChannels = _getSoundChannelsMin(sndArr); 
    var sndLengthSum = (function() { 
    var lng = 0; 
    for (var i = 0; i < sndArr.length; i++) { 
     lng += sndArr[i].audioBuffer.length; 
    } 
    return lng; 
    })(); 

    var samplerBuffer = getAudioContext().createBuffer(
    numberOfChannels, 
    sndLengthSum, 
    sndArr[0].audioBuffer.sampleRate 
); 

    for (var i = 0; i < numberOfChannels; i++) { 
    var channel = samplerBuffer.getChannelData(i); 
    channel.set(sndArr[0].audioBuffer.getChannelData(i), 0); 
    for (var j = 1; j < sndArr.length; j++) { 
     channel.set(sndArr[j].audioBuffer.getChannelData(i), sndArr[j-1].audioBuffer.length); 
    } 
    } 

    // encode our newly made audio blob into a wav file 
    var dataView = _encodeWavFile(samplerBuffer, samplerBuffer.sampleRate); 
    var audioBlob = new Blob([dataView], { type : 'audio/wav' }); 

// post new wav file to download link 
_enableDownload(audioBlob); 
} 

Количество каналов (. моно/стерео/и т.д.) приобретается с помощью этой функции :

function _getSoundChannelsMin(sndArr) { 
    var sndChannelsArr = []; 
    sndArr.forEach(function(snd) { 
    sndChannelsArr.push(snd.audioBuffer.numberOfChannels); 
    }); 
    return Math.min.apply(Math, sndChannelsArr); 
} 

WAV кодируется с помощью этой функции:

function _encodeWavFile(samples, sampleRate) { 
    var buffer = new ArrayBuffer(44 + samples.length * 2); 
    var view = new DataView(buffer); 

    // RIFF identifier 
    _writeString(view, 0, 'RIFF'); 
    // file length 
    view.setUint32(4, 36 + samples.length * 2, true); 
    // RIFF type 
    _writeString(view, 8, 'WAVE'); 
    // format chunk identifier 
    _writeString(view, 12, 'fmt '); 
    // format chunk length 
    view.setUint32(16, 16, true); 
    // sample format (raw) 
    view.setUint16(20, 1, true); 
    // stereo (2 channels) 
    view.setUint16(22, 2, true); 
    // sample rate 
    view.setUint32(24, sampleRate, true); 
    // byte rate (sample rate * block align) 
    view.setUint32(28, sampleRate * 4, true); 
    // block align (channels * bytes/sample) 
    view.setUint16(32, 4, true); 
    // bits/sample 
    view.setUint16(34, 16, true); 
    // data chunk identifier 
    _writeString(view, 36, 'data'); 
    // data chunk length 
    view.setUint32(40, samples.length * 2, true); 
    // write the PCM samples 
    _writePCMSamples(view, 44, samples); 

    return view; 
} 

Строки в файле WAV обрабатываются с этим:

function _writeString(view, offset, string) { 
    for (var i = 0; i < string.length; i++){ 
    view.setUint8(offset + i, string.charCodeAt(i)); 
    } 
} 

образцы PCM передаются с этим:

function _writePCMSamples(output, offset, input) { 
    for (var i = 0; i < input.length; i++, offset+=2){ 
    var s = Math.max(-1, Math.min(1, input[i])); 
    output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true); 
    } 
} 

Наконец, файл WAV превращается в связь с этим:

function _enableDownload(blob, givenFilename) { 
    var url = (window.URL || window.webkitURL).createObjectURL(blob); 
    var link = document.getElementById("linkDownloadSampler"); 
    var d = new Date(); 
    var defaultFilename = "sampler" + d.curDateTime() + ".wav"; 
    link.style.display = "inline"; 
    link.href = url; 
    link.download = givenFilename || defaultFilename; 
} 

Вот отрывок из шестнадцатеричного дампа я получаю:

52 49 46 46 FFFD FFFD 02 00 57 41 56 45 66 6D 74 20 RIFF....WAVEfmt 
10 00 00 00 01 00 02 00 FFFD FFFD 00 00 00 FFFD 02 00 ................ 
04 00 10 00 64 61 74 61 FFFD FFFD 02 00 00 00 00 00 ....data........ 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 

Если кто-нибудь может помочь мне увидеть ошибку в моих путях, я был бы признателен. Извините за длинный пост, но я хотел опубликовать все соответствующие данные и код вперед.

Спасибо!

ответ

1

Вы пренебрегаете приращением смещения при выписывании волновых данных.

Попробуйте это:

output.setInt16(offset + i, s < 0 ? s * 0x8000 : s * 0x7FFF, true); 
         ^^^^ 

Не двигая место записи вы будете просто держать перезаписывать тот же компенсировали в файле, пока, наконец, он будет перезаписан значением последнего образца.

Кроме того, я вижу, что вы отправили код _writePCMSamples, но вызывающий закомментирован, и вы, по-видимому, просто пытаетесь сделать то же самое в строке. Встроенный код имеет ту же ошибку.

+0

Я обновил свой код и удалил прокомментированные '_writePCMSamples', поскольку я забыл, что добавил это позже. Кроме того, я уже обновляю 'offset' в функции' _writePCMSamples': это после 'i ​​++'. Несмотря на это, я попытался удалить это и добавить вашу идею, но я получаю тот же результат. – mjchadwick