/// <summary> /// Write a raw file, within a block. /// </summary> /// <param name="bw">The writer.</param> /// <param name="file">File to write.</param> /// <param name="alignBy">After writing the file, align a block to be divisible by a certain number.</param> /// <returns>Size of the file.</returns> public UInt32 WriteFile(BinaryDataWriter bw, ISoundFile file, int alignBy = 1, WriteMode?writeMode = null) { //Old pos. long oldPos = bw.Position; MemoryStream o = new MemoryStream(); BinaryDataWriter bw2 = new BinaryDataWriter(o); if (writeMode == null) { file.Write(bw2); } else { file.Write(writeMode.GetValueOrDefault(), bw2); } bw.Write(o.ToArray()); //New pos. long newPos = bw.Position; //Align. Align(bw, alignBy); //Free memory. bw2.Dispose(); //Return size. return((UInt32)(newPos - oldPos)); }
/// <summary> /// Write the chunk. /// </summary> /// <param name="bw">The writer.</param> public void Write(BinaryDataWriter bw) { //Get the data. MemoryStream o = new MemoryStream(); BinaryDataWriter w = new BinaryDataWriter(o); WriteData(w); Data = o.ToArray(); try { w.Dispose(); } catch { } try { o.Dispose(); } catch { } //Write chunk. bw.Write(Magic.ToCharArray()); bw.Write(Size); bw.Write(Data); }
/// <summary> /// Convert the sequence data to bytes. /// </summary> /// <param name="byteOrder">Byte order.</param> /// <returns>The sequence data.</returns> public byte[] ToBytes(ByteOrder byteOrder) { //New writer. MemoryStream o = new MemoryStream(); BinaryDataWriter bw = new BinaryDataWriter(o); bw.ByteOrder = byteOrder; //Write each command. foreach (var c in Commands) { c.Write(bw, Commands); } //Free. byte[] ret = o.ToArray(); bw.Dispose(); return(ret); }
/// <summary> /// Convert the RIFF to a file. /// </summary> /// <returns>A file.</returns> public byte[] ToFile() { //New writer. MemoryStream o = new MemoryStream(); BinaryDataWriter bw = new BinaryDataWriter(o); //New writer. MemoryStream o2 = new MemoryStream(); BinaryDataWriter w = new BinaryDataWriter(o2); //Write dummy data. foreach (var r in Chunks) { r.Write(w); } //Write data. bw.Write(Magic.ToCharArray()); bw.Write(Size); bw.Write(Type.ToCharArray()); foreach (var r in Chunks) { r.Write(bw); } //To return. byte[] ret = o.ToArray(); //Dispose of data. try { bw.Dispose(); } catch { } try { o.Dispose(); } catch { } try { w.Dispose(); } catch { } try { o2.Dispose(); } catch { } //Return file. return(ret); }
/// <summary> /// Add a new sound file, and return it. /// </summary> /// <param name="type">New file entry type.</param> /// <param name="lastEntry">Last entry.</param> /// <param name="file">File to add.</param> /// <param name="keepReference">Whether or not to keep the reference to the ISoundFile provided.</param> /// <param name="externalPath">Use this if the file is a stream.</param> /// <returns>The new file.</returns> public SoundFile <ISoundFile> AddNewFile(NewFileEntryType type, int lastEntry, ISoundFile file, bool keepReference = false, string externalPath = null) { //Get proper file. ISoundFile f = file; if (f != null && !keepReference) { MemoryStream o = new MemoryStream(); BinaryDataWriter bw = new BinaryDataWriter(o); file.Write(WriteMode, bw); f = SoundArchiveReader.ReadFile(o.ToArray()); try { bw.Dispose(); } catch { } try { o.Dispose(); } catch { } } int index = 0; switch (type) { //Stream. case NewFileEntryType.Stream: while (lastEntry >= 0) { if (Streams[lastEntry].File == null) { lastEntry--; } else { index = Streams[lastEntry].File.FileId + 1; break; } } break; //Wave sound data. case NewFileEntryType.WaveSoundData: while (lastEntry >= 0) { if (WaveSoundDatas[lastEntry].File == null) { lastEntry--; } else { index = WaveSoundDatas[lastEntry].File.FileId + 1; break; } } break; //Sequence. case NewFileEntryType.Sequence: while (lastEntry >= 0) { if (Sequences[lastEntry].File == null) { lastEntry--; } else { index = Sequences[lastEntry].File.FileId + 1; break; } } break; //Bank. case NewFileEntryType.Bank: while (lastEntry >= 0) { if (Banks[lastEntry].File == null) { lastEntry--; } else { index = Banks[lastEntry].File.FileId + 1; break; } } break; //Wave archive. case NewFileEntryType.WaveArchive: while (lastEntry >= 0) { if (WaveArchives[lastEntry].File == null) { lastEntry--; } else { index = WaveArchives[lastEntry].File.FileId + 1; break; } } break; //Group. case NewFileEntryType.Group: while (lastEntry >= 0) { if (Groups[lastEntry].File == null) { lastEntry--; } else { index = Groups[lastEntry].File.FileId + 1; break; } } break; //Prefech. case NewFileEntryType.Prefetch: while (lastEntry >= 0) { if (Streams[lastEntry].PrefetchFile == null) { lastEntry--; } else { index = Streams[lastEntry].PrefetchFile.FileId + 1; break; } } break; } //Insert file at the proper index. var filef = new SoundFile <ISoundFile>() { ExternalFileName = externalPath, File = f, FileType = (externalPath == null ? EFileType.Internal : EFileType.External) }; if (externalPath != null) { filef.BackupExtension = "stm"; } Files.Insert(index, filef); //Recreate file Ids. RecreateFileIds(); //Programmed to fail if it messes up. return(Files[index]); }
/// <summary> /// Convert this to bytes. /// </summary> /// <returns>This as bytes.</returns> public byte[] ToBytes() { //Writer. MemoryStream o = new MemoryStream(); BinaryDataWriter bw = new BinaryDataWriter(o); bw.ByteOrder = ByteOrder; //Header. bw.Write("BWAV".ToCharArray()); bw.Write(ByteOrder == Syroot.BinaryData.ByteOrder.LittleEndian ? CitraFileLoader.ByteOrder.BigEndian : CitraFileLoader.ByteOrder.LittleEndian); ushort version = 0; version += (ushort)(Major << 8); version += Minor; bw.Write(version); bw.Write((uint)0); bw.Write((ushort)0); bw.Write((ushort)DspAdpcmInfo.Length); //Write each channel. uint offset = (uint)(0x4C * DspAdpcmInfo.Length + 0x10); while (offset % 0x40 != 0) { offset++; } for (int i = 0; i < DspAdpcmInfo.Length; i++) { //Info. bw.Write((ushort)1); bw.Write((ushort)ChannelPans[i]); bw.Write(SampleRate); bw.Write(NumSamples); bw.Write(NumSamples); bw.Write(DspAdpcmInfo[i].coefs[0]); bw.Write(DspAdpcmInfo[i].coefs[1]); bw.Write(DspAdpcmInfo[i].coefs[2]); bw.Write(DspAdpcmInfo[i].coefs[3]); bw.Write(DspAdpcmInfo[i].coefs[4]); bw.Write(DspAdpcmInfo[i].coefs[5]); bw.Write(DspAdpcmInfo[i].coefs[6]); bw.Write(DspAdpcmInfo[i].coefs[7]); bw.Write(offset); bw.Write(offset); bw.Write((uint)(Loops ? 1 : 0)); bw.Write(LoopEndSample); bw.Write(LoopStartSample); bw.Write(DspAdpcmInfo[i].pred_scale); bw.Write(DspAdpcmInfo[i].yn1); bw.Write(DspAdpcmInfo[i].yn2); bw.Write((ushort)0); //Offset. offset += (uint)Data.dspAdpcm[i].Length; while (offset % 0x40 != 0) { offset++; } } //Write the data. for (int i = 0; i < DspAdpcmInfo.Length; i++) { //Align. while (bw.Position % 0x40 != 0) { bw.Position++; } //Write data. bw.Write(Data.dspAdpcm[i]); } //Get hash. MemoryStream chanData = new MemoryStream(); BinaryDataWriter chanWriter = new BinaryDataWriter(chanData); foreach (byte[] b in Data.dspAdpcm) { chanWriter.Write(b); } bw.Position = 8; bw.Write(Crc32.Crc32Algorithm.Compute(chanData.ToArray())); //Return and clean. byte[] ret = o.ToArray(); try { bw.Dispose(); } catch { } try { o.Dispose(); } catch { } try { chanWriter.Dispose(); } catch { } try { chanData.Dispose(); } catch { } return(ret); }