private void ParseDefineSound(DefineSoundTag tag) { if (tag.SoundFormat == SoundCompressionType.Nellymoser) { Debug.WriteLine("Nellymoser Sound not supported"); Log.AppendLine( "Nellymoser Sound not supported" + " at frame " + this.curFrame + " in clip " + this.curTimeline.Name); soundPaths[tag.SoundId] = null; return; } else if (tag.SoundFormat == SoundCompressionType.ADPMC) { Debug.WriteLine("ADPMC Sound not supported"); Log.AppendLine( "ADPMC Sound not supported" + " at frame " + this.curFrame + " in clip " + this.curTimeline.Name); soundPaths[tag.SoundId] = null; return; } string ext = SoundStreamHeadTag.SoundExtentions[(int)tag.SoundFormat]; string path = v.ResourceFolder + @"/" + VexObject.SoundPrefix + tag.SoundId + ext; soundPaths[tag.SoundId] = path; WriteSoundToDisk(path, tag); }
private void WriteSoundToDisk(string path, DefineSoundTag tag) { byte[] bytes = tag.SoundData; IOUtils.EnsurePath(path); FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write); if (tag.SoundFormat == SoundCompressionType.MP3) { int skipHeader = 2; fs.Write(bytes, skipHeader, bytes.Length - skipHeader); } else if (tag.SoundFormat == SoundCompressionType.Uncompressed || tag.SoundFormat == SoundCompressionType.UncompressedLE) { byte[] header = GetWavHeader(tag); fs.Write(header, 0, header.Length); fs.Write(bytes, 0, bytes.Length); } else if(tag.SoundFormat == SoundCompressionType.ADPMC) { // not supported Log.AppendLine( "ADPMC Sound not supported" + " at frame " + this.curFrame + " in clip " + this.curTimeline.Name); } fs.Close(); }
private byte[] GetWavHeader(DefineSoundTag tag) { /* 52 49 46 46 // 'RIFF' XX D0 3B 01 00 // Chunk Data Size (file size) - 8 57 41 56 45 // 'WAVE' 66 6D 74 20 // 'fmt ' XX 10 00 00 00 // size -- 16 + extra format bytes 01 00 // Compression code XX 02 00 // Number of channels 22 56 00 00 // Sample rate 88 58 01 00 // Average bytes per second 04 00 // Block align 10 00 // Significant bits per sample // Extra format bytes (may be 2 bytes that specify additonal fmt byte count) 64 61 74 61 // 'data' XX 7C 3B 01 00 // chunkSize F8 FF // ?? ?? */ // Compression Code // 0 (0x0000) Unknown // 1 (0x0001) PCM/uncompressed ** // 2 (0x0002) Microsoft ADPCM ** // 6 (0x0006) ITU G.711 a-law // 7 (0x0007) ITU G.711 µ-law // 17 (0x0011) IMA ADPCM // 20 (0x0016) ITU G.723 ADPCM (Yamaha) // 49 (0x0031) GSM 6.10 // 64 (0x0040) ITU G.721 ADPCM // 80 (0x0050) MPEG // 65,536 (0xFFFF) Experimental byte[] header = new byte[] { 0x52, 0x49, 0x46, 0x46, 0xD0, 0x3B, 0x01, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x22, 0x56, 0x00, 0x00, 0x88, 0x58, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x7C, 0x3B, 0x01, 0x00, 0x00, 0x00}; uint dataLen = (uint)tag.SoundData.Length; uint riffChunkSize = dataLen + 38; uint compression = 1; // uncompressed and uncompressedLE if (tag.SoundFormat == SoundCompressionType.ADPMC) { compression = 2; // more work needs to be done here to support the 'extra byte' info. } uint channelCount = tag.IsStereo ? 2U : 1U; uint sampleRate = tag.SoundRate; uint blockAlign = (tag.SoundSize / 8) * channelCount; uint avgBytesPS = sampleRate * blockAlign; uint sigBitsPerSample = tag.SoundSize; uint dataChunkSize = dataLen + 2; // swf misses 2 first bytes? header[4] = (byte)(riffChunkSize & 0xFF); header[5] = (byte)((riffChunkSize >> 8) & 0xFF); header[6] = (byte)((riffChunkSize >> 16) & 0xFF); header[7] = (byte)((riffChunkSize >> 24) & 0xFF); header[20] = (byte)compression; header[22] = (byte)channelCount; header[24] = (byte)(sampleRate & 0xFF); header[25] = (byte)((sampleRate >> 8) & 0xFF); header[26] = (byte)((sampleRate >> 16) & 0xFF); header[27] = (byte)((sampleRate >> 24) & 0xFF); header[28] = (byte)(avgBytesPS & 0xFF); header[29] = (byte)((avgBytesPS >> 8) & 0xFF); header[30] = (byte)((avgBytesPS >> 16) & 0xFF); header[31] = (byte)((avgBytesPS >> 24) & 0xFF); header[32] = (byte)blockAlign; header[34] = (byte)sigBitsPerSample; header[40] = (byte)(dataChunkSize & 0xFF); header[41] = (byte)((dataChunkSize >> 8) & 0xFF); header[42] = (byte)((dataChunkSize >> 16) & 0xFF); header[43] = (byte)((dataChunkSize >> 24) & 0xFF); return header; }