/// <summary> /// Create a wave from a stream. /// </summary> /// <param name="s">The stream.</param> /// <param name="version">Version of the file.</param> /// <returns></returns> public static b_wav CreateWave(b_stm s, byte vMajor, byte vMinor, byte vRevision) { b_wav b = new b_wav(); b.fileHeader = new FileHeader("FWAV", ByteOrder.BigEndian, vMajor, vMinor, vRevision, 0, new List <SizedReference>()); b.data = s.data; b.info = new b_wav.InfoBlock(); b.info.sampleRate = s.info.streamSoundInfo.sampleRate; b.info.originalLoopStart = s.info.streamSoundInfo.originalLoopStart; b.info.loopStart = s.info.streamSoundInfo.loopStart; b.info.loopEnd = s.info.streamSoundInfo.sampleCount; b.info.isLoop = s.info.streamSoundInfo.isLoop; b.info.encoding = s.info.streamSoundInfo.encoding; b.info.channelInfo = new List <b_wav.InfoBlock.ChannelInfo>(); foreach (b_stm.ChannelInfo c in s.info.channels) { b_wav.InfoBlock.ChannelInfo i = new b_wav.InfoBlock.ChannelInfo(); i.dspAdpcmInfo = c.dspAdpcmInfo; b.info.channelInfo.Add(i); } b.Update(ByteOrder.BigEndian); return(b); }
/// <summary> /// Create a wave from a binary wave. /// </summary> /// <param name="w">The binary wave.</param> /// <param name="version">Version of the file.</param> /// <returns></returns> public static b_wav CreateWave(BinaryWave w, byte vMajor, byte vMinor, byte vRevision) { b_wav b = new b_wav(); b.fileHeader = new FileHeader("FWAV", ByteOrder.BigEndian, vMajor, vMinor, vRevision, 0, new List <SizedReference>()); b.data = w.Data; b.info = new b_wav.InfoBlock(); b.info.sampleRate = w.SampleRate; b.info.originalLoopStart = w.LoopStartSample; b.info.loopStart = w.LoopStartSample; b.info.loopEnd = w.LoopEndSample == 0xFFFFFFFF ? w.NumSamples : w.LoopEndSample; b.info.isLoop = w.Loops && w.LoopEndSample != 0xFFFFFFFF; b.info.encoding = 2; b.info.channelInfo = new List <b_wav.InfoBlock.ChannelInfo>(); foreach (DspAdpcmInfo d in w.DspAdpcmInfo) { b_wav.InfoBlock.ChannelInfo i = new b_wav.InfoBlock.ChannelInfo(); i.dspAdpcmInfo = d; b.info.channelInfo.Add(i); } b.Update(ByteOrder.BigEndian); return(b); }
/// <summary> /// Create a looping b_wav. /// </summary> /// <param name="sampleRate">The sample rate.</param> /// <param name="numSamples">Number of samples.</param> /// <param name="samples">Pcm8[][] or Pcm16[][] audio samples.</param> /// <param name="encoding">If samples is Pcm8[][] always 0. Must be 1 or 2 for if samples is Pcm16[][].</param> /// <param name="version">The version of the file.</param> /// <param name="loopStart">Loop starting point.</param> /// <returns></returns> public static b_wav CreateWave(UInt32 sampleRate, UInt32 numSamples, object samples, byte encoding, byte vMajor, byte vMinor, byte vRevision, UInt32 loopStart) { b_wav b = CreateWave(sampleRate, numSamples, samples, encoding, vMajor, vMinor, vRevision); b.info.loopStart = loopStart; b.info.isLoop = true; return(b); }
/// <summary> /// Pcm16 to dsp adpcm for wav, and update the b_wav channel info. /// </summary> /// <param name="pcm16">The pcm16 audio data.</param> /// <param name="b">The b_wav.</param> /// <returns></returns> public static byte[][] Pcm16ToDspApdcmWAV(Int16[][] pcm16, ref b_wav b) { byte[][] data = new byte[pcm16.Length][]; b.info.channelInfo = new List <b_wav.InfoBlock.ChannelInfo>(); for (int i = 0; i < data.Length; i++) { b.info.channelInfo.Add(new b_wav.InfoBlock.ChannelInfo()); data[i] = DspAdpcmEncoder.EncodeSamples(pcm16[i], out b.info.channelInfo[i].dspAdpcmInfo, b.info.loopStart); } return(data); }
/// <summary> /// Create a standard b_wav. /// </summary> /// <param name="sampleRate">The sample rate.</param> /// <param name="numSamples">Number of samples.</param> /// <param name="samples">Pcm8[][] or Pcm16[][] audio samples.</param> /// <param name="encoding">If samples is Pcm8[][] always 0. Must be 1 or 2 for if samples is Pcm16[][].</param> /// <param name="version">The version of the file.</param> /// <returns></returns> public static b_wav CreateWave(UInt32 sampleRate, UInt32 numSamples, object samples, byte encoding, byte vMajor, byte vMinor, byte vRevision) { //Create wav. b_wav b = new b_wav(); b.fileHeader = new FileHeader("FWAV", ByteOrder.BigEndian, vMajor, vMinor, vRevision, 0, new List <SizedReference>()); b.info = new b_wav.InfoBlock(); b.info.magic = "INFO".ToCharArray(); b.info.encoding = encoding; b.info.isLoop = false; b.info.loopStart = b_wav.InfoBlock.NULL_LOOP; b.info.loopEnd = numSamples; b.info.originalLoopStart = b_wav.InfoBlock.NULL_LOOP; b.info.padding = 0; b.info.sampleRate = sampleRate; b.info.channelInfo = new List <b_wav.InfoBlock.ChannelInfo>(); //Encoding. switch (encoding) { case EncodingTypes.PCM8: b.data = new SoundNStreamDataBlock(EncoderFactory.Pcm8ToSignedPcm8(samples as byte[][]), encoding); for (int i = 0; i < (samples as byte[][]).Length; i++) { b.info.channelInfo.Add(new b_wav.InfoBlock.ChannelInfo() { reserved = 0, dspAdpcmInfo = null }); } break; case EncodingTypes.PCM16: b.data = new SoundNStreamDataBlock(samples, encoding); for (int i = 0; i < (samples as Int16[][]).Length; i++) { b.info.channelInfo.Add(new b_wav.InfoBlock.ChannelInfo() { reserved = 0, dspAdpcmInfo = null }); } break; case EncodingTypes.DSP_ADPCM: b.data = new SoundNStreamDataBlock(EncoderFactory.Pcm16ToDspApdcmWAV(samples as Int16[][], ref b), encoding); break; } b.Update(ByteOrder.BigEndian); //Return wav. return(b); }
/// <summary> /// New binary wave. /// </summary> /// <param name="wave">Wave to create this from.</param> public BinaryWave(b_wav wave) { //Set data. ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian; Major = 0; Minor = 1; SampleRate = wave.info.sampleRate; NumSamples = wave.info.loopEnd; switch (wave.info.encoding) { case 0: wave.data.dspAdpcm = EncoderFactory.Pcm16ToDspApdcmWAV(EncoderFactory.SignedPcm8ToPcm16(wave.data.pcm8), ref wave); break; case 1: wave.data.dspAdpcm = EncoderFactory.Pcm16ToDspApdcmWAV(wave.data.pcm16, ref wave); break; } DspAdpcmInfo = new DspAdpcmInfo[wave.info.channelInfo.Count]; for (int i = 0; i < DspAdpcmInfo.Length; i++) { DspAdpcmInfo[i] = wave.info.channelInfo[i].dspAdpcmInfo; } Loops = wave.info.isLoop; LoopStartSample = wave.info.loopStart; LoopEndSample = wave.info.loopEnd; Data = wave.data; //Do channel pans. ChannelPans = new ChannelPan[wave.info.channelInfo.Count()]; for (int i = 0; i < wave.info.channelInfo.Count(); i++) { if (i == wave.info.channelInfo.Count() - 1) { ChannelPans[i] = ChannelPan.Middle; } else if (i % 2 == 0) { ChannelPans[i] = ChannelPan.Left; ChannelPans[i] = ChannelPan.Right; } } }
/// <summary> /// Create a wave from a FISP. /// </summary> /// <param name="f"></param> /// <returns></returns> public static b_wav CreateWave(FISP f, byte vMajor, byte vMinor, byte vRevision) { //New wave. b_wav b = new b_wav(); //Trim the fat from each loop. object channels = new short[f.data.data.Count()][]; for (int i = 0; i < (channels as short[][]).Length; i++) { List <short> l = new List <short>(); for (int j = 0; j < f.stream.loopEnd; j++) { l.Add(f.data.data[i][j]); } (channels as short[][])[i] = l.ToArray(); } //PCM8 conversion. if (f.stream.encoding == EncodingTypes.PCM8) { channels = EncoderFactory.Pcm16ToPcm8(channels as short[][]); } //If looped. if (f.stream.isLoop) { b = WaveFactory.CreateWave(f.stream.sampleRate, f.stream.loopEnd, channels, f.stream.encoding, vMajor, vMinor, vRevision, f.stream.loopStart); } //Not looped. else { b = WaveFactory.CreateWave(f.stream.sampleRate, f.stream.loopEnd, channels, f.stream.encoding, vMajor, vMinor, vRevision); } //Info. b.info.originalLoopStart = f.stream.originalLoopStart; return(b); }
/// <summary> /// Make a RIFF Wave from a b_wav. /// </summary> /// <param name="b">The b_wav.</param> /// <returns></returns> public static RiffWave CreateRiffWave(b_wav b) { RiffWave r = new RiffWave(); UInt16 bytesPerSample = 2; if (b.info.encoding == EncodingTypes.PCM8) { bytesPerSample = 1; } //Non-looping. if (!b.info.isLoop) { r = CreateRiffWave(b.info.sampleRate, bytesPerSample, b.data.GetDataWAV(b.info)); } //Looping. else { r = CreateRiffWave(b.info.sampleRate, bytesPerSample, b.data.GetDataWAV(b.info), b.info.loopStart, b.info.loopEnd); } return(r); }
/// <summary> /// Load bars from bytes. /// </summary> /// <param name="src"></param> public void Load(byte[] b) { MemoryStream src = new MemoryStream(b); BinaryDataReader br = new BinaryDataReader(src); fileHeader = new Header(ref br); numTracks = br.ReadUInt32(); trackInfo = new List <UInt32>(); for (int i = 0; i < numTracks; i++) { trackInfo.Add(br.ReadUInt32()); } fileReferences = new FileReference[numTracks]; for (int i = 0; i < numTracks; i++) { fileReferences[i] = new FileReference() { AMTAOffset = br.ReadUInt32(), WAVOffset = br.ReadUInt32() }; } amtas = new List <AMTA>(); wavs = new List <b_wav>(); for (int i = 0; i < numTracks; i++) { long basePos = br.Position; Syroot.BinaryData.ByteOrder b2 = br.ByteOrder; br.Position = fileReferences[i].AMTAOffset; AMTA a = new AMTA(); a.magic = new string(br.ReadChars(4)); a.byteOrder = br.ReadUInt16(); if (a.byteOrder == ByteOrder.BigEndian) { br.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian; } else { br.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian; } a.byteOrder = ByteOrder.BigEndian; a.version = br.ReadUInt16(); a.chunkSize = br.ReadUInt32(); a.dataOffset = br.ReadUInt32(); a.markOffset = br.ReadUInt32(); a.extOffset = br.ReadUInt32(); a.strgOffset = br.ReadUInt32(); a.data = new AMTA.Data(); a.mark = new AMTA.Mark(); a.ext = new AMTA.Ext(); a.strg = new AMTA.Strg(); br.Position = basePos + a.dataOffset; a.data.magic = new string(br.ReadChars(4)); a.data.restOfSize = br.ReadUInt32(); a.data.unknown = br.ReadBytes((int)a.data.restOfSize); br.Position = basePos + a.markOffset; a.mark.magic = new string(br.ReadChars(4)); a.mark.restOfSize = br.ReadUInt32(); a.mark.unknown = br.ReadBytes((int)a.mark.restOfSize); br.Position = basePos + a.extOffset; a.ext.magic = new string(br.ReadChars(4)); a.ext.restOfSize = br.ReadUInt32(); a.ext.unknown = br.ReadBytes((int)a.ext.restOfSize); br.Position = basePos + a.strgOffset; a.strg.magic = new string(br.ReadChars(4)); a.strg.restOfSize = br.ReadUInt32(); a.strg.trackName = new string(br.ReadChars((int)a.strg.restOfSize - 1)); br.ByteOrder = b2; } for (int i = 0; i < numTracks; i++) { br.Position = fileReferences[i].WAVOffset; br.ReadUInt32s(3); b_wav w = new b_wav(); int length = (int)br.ReadUInt32(); br.Position -= 12; w.Load(br.ReadBytes(length)); wavs.Add(w); } }
/// <summary> /// Create a stream from wave. /// </summary> /// <param name="b">The b_wav.</param> /// <param name="version">Version of the output stream.</param> /// <returns></returns> public static b_stm CreateStream(b_wav b, byte vMajor, byte vMinor, byte vRevision) { //Simple hack, but doesn't hurt optimization since SEEK must be recreated anyway. return(CreateStream(RiffWaveFactory.CreateRiffWave(b), b.info.encoding >= EncodingTypes.DSP_ADPCM, vMajor, vMinor, vRevision)); }
/// <summary> /// Create a new b_wav from a RIFF Wave. /// </summary> /// <param name="r">The RIFF Wave.</param> /// <param name="encode">Whether or not to encode PCM16 data.</param> /// <param name="version">Version of the file.</param> /// <returns></returns> public static b_wav CreateWave(RiffWave r, bool encode, byte vMajor, byte vMinor, byte vRevision) { b_wav b = new b_wav(); bool loops = false; if (r.smpl != null) { loops = true; if (r.smpl.numLoops < 1) { loops = false; } } if (r.fmt.bitsPerSample == RiffWave.FmtChunk.BitsPerSample.PCM8) { List <byte[]> pcm8 = new List <byte[]>(); int count = 0; UInt32 endSample = (UInt32)r.data.channels[0].pcm8.Count(); if (loops) { endSample = r.smpl.loops[0].endSample; } foreach (RiffWave.DataChunk.DataSamples d in r.data.channels) { if (count <= endSample) { pcm8.Add(d.pcm8.ToArray()); } count += 1; } if (!loops) { b = CreateWave(r.fmt.sampleRate, endSample, pcm8.ToArray(), EncodingTypes.PCM8, vMajor, vMinor, vRevision); } else { b = CreateWave(r.fmt.sampleRate, endSample, pcm8.ToArray(), EncodingTypes.PCM8, vMajor, vMinor, vRevision, r.smpl.loops[0].startSample); } } else { List <Int16[]> pcm16 = new List <Int16[]>(); int count2 = 0; UInt32 endSample2 = (UInt32)r.data.channels[0].pcm16.Count(); if (loops) { endSample2 = r.smpl.loops[0].endSample; } foreach (RiffWave.DataChunk.DataSamples d in r.data.channels) { if (count2 <= endSample2) { pcm16.Add(d.pcm16.ToArray()); } count2 += 1; } byte encoding = EncodingTypes.PCM16;; if (encode) { encoding = EncodingTypes.DSP_ADPCM; } if (!loops) { b = CreateWave(r.fmt.sampleRate, (UInt32)r.data.channels[0].pcm16.Count(), pcm16.ToArray(), encoding, vMajor, vMinor, vRevision); } else { b = CreateWave(r.fmt.sampleRate, (UInt32)r.data.channels[0].pcm16.Count(), pcm16.ToArray(), encoding, vMajor, vMinor, vRevision, r.smpl.loops[0].startSample); } } return(b); }