/// <summary> /// Create a block data from audio data. Default length 512 bytes, 256 samples. /// </summary> /// <param name="channel">Channel audio data</param> /// <returns>Block data</returns> static byte[][] CreateBlocks(byte[] channel, int blockSize, int waveType) { List <Byte[]> blocks = new List <Byte[]>(); if (waveType == 2) { return(Compression_ADPCM.CompressBlock(channel, blockSize)); } int nBlocks = channel.Length / blockSize; int lastBlockLength = channel.Length % blockSize; Byte[] block = new Byte[blockSize]; for (int i = 0; i < nBlocks; i++) { block = new Byte[blockSize]; Array.Copy(channel, i * blockSize, block, 0, blockSize); if (waveType == 0) { block = PCM.PCM16ToPCM8(block); } blocks.Add(block); } block = new Byte[lastBlockLength]; Array.Copy(channel, nBlocks * blockSize, block, 0, lastBlockLength); if (waveType == 0) { block = PCM.PCM16ToPCM8(block); } blocks.Add(block); return(blocks.ToArray()); }
/// <summary> /// Read a wave file and return its structure. /// </summary> /// <param name="filein">File to read</param> /// <returns>Structure of the wave file</returns> public static sWAV Read(string filein) { sWAV wav = new sWAV(); BinaryReader br = new BinaryReader(File.OpenRead(filein)); // RIFF header wav.chunkID = br.ReadChars(4); wav.chunkSize = br.ReadUInt32(); wav.format = br.ReadChars(4); if (new String(wav.chunkID) != "RIFF" || new String(wav.format) != "WAVE") { throw new NotSupportedException(); } // fmt sub-chunk wav.wave.fmt.chunkID = br.ReadChars(4); wav.wave.fmt.chunkSize = br.ReadUInt32(); wav.wave.fmt.audioFormat = (WaveFormat)br.ReadUInt16(); wav.wave.fmt.numChannels = br.ReadUInt16(); wav.wave.fmt.sampleRate = br.ReadUInt32(); wav.wave.fmt.byteRate = br.ReadUInt32(); wav.wave.fmt.blockAlign = br.ReadUInt16(); wav.wave.fmt.bitsPerSample = br.ReadUInt16(); br.BaseStream.Position = 0x14 + wav.wave.fmt.chunkSize; String dataID = new String(br.ReadChars(4)); while (dataID != "data") { br.BaseStream.Position += br.ReadUInt32() + 0x04; dataID = new String(br.ReadChars(4)); } // data sub-chunk br.BaseStream.Position -= 4; wav.wave.data.chunkID = br.ReadChars(4); wav.wave.data.chunkSize = br.ReadUInt32(); wav.wave.data.data = br.ReadBytes((int)wav.wave.data.chunkSize - 0x08); br.Close(); // Convert the data to PCM16 if (wav.wave.fmt.audioFormat != WaveFormat.WAVE_FORMAT_PCM) { throw new NotSupportedException(); } if (wav.wave.fmt.audioFormat == WaveFormat.WAVE_FORMAT_PCM && wav.wave.fmt.bitsPerSample == 0x08) // PCM8 { wav.wave.fmt.bitsPerSample = 0x10; wav.wave.fmt.blockAlign = (ushort)(wav.wave.fmt.numChannels * wav.wave.fmt.bitsPerSample / (ushort)(8)); wav.wave.fmt.byteRate = wav.wave.fmt.sampleRate * wav.wave.fmt.bitsPerSample * wav.wave.fmt.numChannels / 8; wav.wave.data.data = PCM.PCM8UnsignedToPCM16(wav.wave.data.data); } return(wav); }
/// <summary> /// Get the channel data converted to PCM-16 from mono audio data /// </summary> /// <param name="data">Data to convert</param> /// <param name="nBlocks">Number of blocks</param> /// <param name="blockLen">Block length</param> /// <param name="lastBlockLen">Last block length</param> /// <param name="waveType">Wavetype of the audio data (compression)</param> /// <returns>Channel data</returns> static byte[] MonoChannel(byte[] data, uint nBlocks, uint blockLen, uint lastBlockLen, int waveType) { List <byte> resultado = new List <byte>(); List <byte> datos = new List <byte>(); datos.AddRange(data); byte[] blockData; for (int i = 0; i < nBlocks - 1; i++) { blockData = new byte[(int)blockLen]; datos.CopyTo(i * (int)blockLen, blockData, 0, (int)blockLen); if (waveType == 2) { resultado.AddRange(Compression_ADPCM.Decompress(blockData, BitConverter.ToInt16(blockData, 0), BitConverter.ToInt16(blockData, 2))); } else if (waveType == 1) { resultado.AddRange(blockData); } else if (waveType == 0) { resultado.AddRange(PCM.PCM8SignedToPCM16(blockData)); } } blockData = new byte[(int)lastBlockLen]; datos.CopyTo((int)(nBlocks - 1) * (int)blockLen, blockData, 0, (int)lastBlockLen); if (waveType == 2) { if (blockData.Length < 4) // Archivos sin sonido { resultado.AddRange(blockData); return(resultado.ToArray()); } resultado.AddRange(Compression_ADPCM.Decompress(blockData, BitConverter.ToInt16(blockData, 0), BitConverter.ToInt16(blockData, 2))); } else if (waveType == 1) { resultado.AddRange(blockData); } else if (waveType == 0) { resultado.AddRange(PCM.PCM8SignedToPCM16(blockData)); } return(resultado.ToArray()); }
/// <summary> /// Get one channels converted to PCM-16 from the audio data /// </summary> /// <param name="data">Audio data with two channels</param> /// <param name="nBlocks">Numbers of blocks in the audio data</param> /// <param name="blockLen">Block length in the audio data</param> /// <param name="lastBlockLen">Length of the last block</param> /// <param name="leftChannel">If true, return the left channel, else return the right channel</param> /// <param name="waveType">The wavetype of the audio data (compression)</param> /// <returns>Data of the channel</returns> static byte[] DivideChannels(byte[] data, uint nBlocks, uint blockLen, uint lastBlockLen, bool leftChannel, int waveType) { List <byte> resultado = new List <byte>(); List <byte> datos = new List <byte>(); datos.AddRange(data); int j = (leftChannel) ? 0 : (int)blockLen; byte[] blockData; for (int i = 0; i < nBlocks - 1; i++) { blockData = new byte[(int)blockLen]; datos.CopyTo(i * (int)blockLen * 2 + j, blockData, 0, (int)blockLen); if (waveType == 2) { resultado.AddRange(Compression_ADPCM.Decompress(blockData, BitConverter.ToInt16(blockData, 0), BitConverter.ToInt16(blockData, 2))); } else if (waveType == 1) { resultado.AddRange(blockData); } else if (waveType == 0) { resultado.AddRange(PCM.PCM8SignedToPCM16(blockData)); } } blockData = new byte[(int)lastBlockLen]; j = (leftChannel) ? 0 : (int)lastBlockLen; datos.CopyTo((int)(nBlocks - 1) * (int)blockLen * 2 + j, blockData, 0, (int)lastBlockLen); if (waveType == 2) { resultado.AddRange(Compression_ADPCM.Decompress(blockData, BitConverter.ToInt16(blockData, 0), BitConverter.ToInt16(blockData, 2))); } else if (waveType == 1) { resultado.AddRange(blockData); } else if (waveType == 0) { resultado.AddRange(PCM.PCM8SignedToPCM16(blockData)); } return(resultado.ToArray()); }
public static sWAV ConvertToWAV(sSWAV swav, bool loop) { sWAV wav = new sWAV(); if (swav.data.info.nWaveType == 0) // 8 Bits per sample, PCM-8 { swav.data.data = PCM.PCM8SignedToPCM16(swav.data.data); if (loop) { Byte[] data = new Byte[(int)swav.data.info.nNonLoopLen]; Array.Copy(swav.data.data, swav.data.info.nLoopOffset, data, 0, data.Length); swav.data.data = data; } wav = WAV.Create_WAV(1, swav.data.info.nSampleRate, 16, swav.data.data); } else if (swav.data.info.nWaveType == 1) // 16 Bits per sample, PCM-16 { if (loop) // NO TESTED { Byte[] data = new Byte[(int)swav.data.info.nNonLoopLen]; Array.Copy(swav.data.data, swav.data.info.nLoopOffset, data, 0, data.Length); swav.data.data = data; } wav = WAV.Create_WAV(1, swav.data.info.nSampleRate, 16, swav.data.data); } else if (swav.data.info.nWaveType >= 2) // 4 Bits per sample, IMA-ADPCM { swav.data.data = Compression_ADPCM.Decompress( swav.data.data, BitConverter.ToUInt16(swav.data.data, 0), BitConverter.ToUInt16(swav.data.data, 2)); if (loop) { Byte[] data = new Byte[swav.data.data.Length - ((int)swav.data.info.nLoopOffset * 2)]; Array.Copy(swav.data.data, swav.data.info.nLoopOffset * 2, data, 0, data.Length); swav.data.data = data; } wav = WAV.Create_WAV(1, swav.data.info.nSampleRate, 16, swav.data.data); } return(wav); }
public static sSWAV ConvertToSWAV(sWAV wav, int waveType, int volume = 150) { sSWAV swav = new sSWAV(); swav.header.type = "SWAV".ToCharArray(); swav.header.magic = 0x0100FEFF; swav.header.nSize = 0x10; swav.header.nBlock = 0x01; swav.data.type = "DATA".ToCharArray(); swav.data.info.nWaveType = (byte)waveType; swav.data.info.bLoop = 1; swav.data.info.nSampleRate = (ushort)wav.wave.fmt.sampleRate; swav.data.info.nTime = (ushort)(1.6756991e+7 / wav.wave.fmt.sampleRate); swav.data.info.nLoopOffset = 0x01; if (wav.wave.fmt.numChannels > 1) { wav.wave.data.data = WAV.ConvertToMono(wav.wave.data.data, wav.wave.fmt.numChannels, wav.wave.fmt.bitsPerSample); } //wav.wave.data.data = ChangeVolume(wav.wave.data.data, volume, wav.wave.fmt.bitsPerSample); if (waveType == 0) { swav.data.data = PCM.PCM16ToPCM8(wav.wave.data.data); } else if (waveType == 2) { List <byte> temp = new List <byte>(); temp.AddRange(new Byte[] { 0x00, 0x00, 0x00, 0x00 }); temp.AddRange(Compression_ADPCM.Compress(wav.wave.data.data)); swav.data.data = temp.ToArray(); } else { swav.data.data = wav.wave.data.data; } swav.data.nSize = (uint)swav.data.data.Length + 0x0A; swav.data.info.nNonLoopLen = (uint)swav.data.data.Length; swav.header.nFileSize = swav.data.nSize + swav.header.nSize; return(swav); }