WebAudio で再生しようとするとAudioContext.decodeAudioDataに失敗する
どうやら、こちらにあるヘッダーの破損が原因の様子。
https://developer.ibm.com/answers/questions/180732/seems-watson-text-to-speech-service-returns-a-wav.html
node.jsでTextToSpeechのwavファイルを取得して, クライアントにレスポンスする処理の例
実際にwavデータを見てみると...
バイナリファイルの先頭から ArrayBuffer として出力してみる
{
"0": 82, // R
"1": 73, // I
"2": 70, // F
"3": 70, // F
"4": 255, // (totalDataLen & 0xff);
"5": 255, // ((totalDataLen >> 8) & 0xff);
"6": 255, // ((totalDataLen >> 16) & 0xff);
"7": 255, // ((totalDataLen >> 24) & 0xff);
"8": 87, // W
"9": 65, // A
"10": 86, // V
"11": 69, // E
"12": 102, // f
"13": 109, // m
"14": 116, // t
"15": 32, // ' '
"16": 16, // 4 bytes: size of 'fmt ' chunk
"17": 0,
"18": 0,
"19": 0,
"20": 1, // format = 1
"21": 0,
"22": 1, // channels
"23": 0,
"24": 34, // sampleRate & 0xff
"25": 86, // sampleRate >> 8) & 0xff
"26": 0, // sampleRate >> 16) & 0xff
"27": 0, // sampleRate >> 24) & 0xff
"28": 68, // byteRate & 0xff
"29": 172, // byteRate >> 8 ) & 0xff
"30": 0, // byteRate >> 16) & 0xff
"31": 0, // byteRate >> 24) & 0xff
"32": 2, // block align
"33": 0, // 0
"34": 16, // bits per sample
"35": 0,
"36": 76, // L
"37": 73, // I
"38": 83, // S
"39": 84, // T
"40": 26, // totalAudioLen & 0xff = 16x2+6=38byte??
"41": 0, // totalAudioLen >> 8 & 0xff
"42": 0, // totalAudioLen >> 16 & 0xff
"43": 0 // totalAudioLen >> 24 & 0xff
}
長さ部分の表示が、、明らかに違う.. 全部255で埋まっている... (実際にデータは数KB)
36-39 は "data" が入る想定だが,実際には "LIST" と入っている.
結果的に以下のように, ヘッダーを入れ替える関数を用意して、処理する.
var buffer = getBufferWithFixedWavHeader(response);
/**
* get ArrayBuffer by fixed header data
* @param data binaryData
* @return ArrayBuffer
*/
function getBufferWithFixedWavHeader(data){
var headerSize = 44;
var metaDataSize = 48;
var noHeaderLen = data.length - (headerSize + metaDataSize);
var totalAudioLen = noHeaderLen;
var totalDataLen = noHeaderLen + headerSize - 8;
var header = new ArrayBuffer(headerSize);
for(var i = 0; i < headerSize; i++){
header[i] = data[i];
}
// Total Data Length
header[4] = (totalDataLen & 0xff);
header[5] = ((totalDataLen >> 8) & 0xff);
header[6] = ((totalDataLen >> 16) & 0xff);
header[7] = ((totalDataLen >> 24) & 0xff);
// data
header[36] = 100; //'d'
header[37] = 97; //'a'
header[38] = 116; //'t'
header[39] = 97; //'a'
// Total Audio Length
header[40] = (totalAudioLen & 0xff);
header[41] = ((totalAudioLen >> 8) & 0xff);
header[42] = ((totalAudioLen >> 16) & 0xff);
header[43] = ((totalAudioLen >> 24) & 0xff);
// join
var buffer = new ArrayBuffer(headerSize + noHeaderLen);
// header
for(var i = 0; i < headerSize; i++){
buffer[i] = header[i];
}
// data
for(var i = headerSize,j = (headerSize+metaDataSize) ; j < data.length ; i++,j++){
buffer[i] = data[j];
}
return buffer;
}