/// <summary>
/// Adds silence to wav files alter volume
/// </summary>
/// <param name="silenceInsertLength">Milliseconds to insert at start of wav</param>
/// <param name="volume">0=silent, 1=100%</param>
/// <param name="maxLength">If the wav is longer than this then crop (includes silence), if 0 then don't crop</param>
/// <param name="srcFilenames">Filenames to pad</param>
public static void SetLengthSilenceAndVolume(float silenceInsertLength, float maxLength, float volume, string fileName)
{
FileStream inS;
FileStream outS;
WavSingleChunkHeader h;
uint silenceLen;
string tmpName;
//uint origChunkLen;
int copied;
byte[] buff = new byte[10000];
for (int i = 0; i < buff.Length; i++)
buff[i] = 0;
tmpName = string.Format("{0}_{1}", fileName, Guid.NewGuid().ToString("N"));
using (inS = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
using (outS = new FileStream(tmpName, FileMode.CreateNew, FileAccess.ReadWrite))
{
h = ParseWavSingleChunkHeader(inS);
//origChunkLen = h.ChunkLength;
silenceLen = (uint)((float)h.AvgBytesPerSec * (silenceInsertLength / 1000F));
silenceLen -= silenceLen % h.BlockAlign;
uint newLenBytes = maxLength != 0 ? (uint)((float)h.AvgBytesPerSec * (maxLength / 1000F)) : h.ChunkLength + silenceLen;
newLenBytes -= newLenBytes % h.BlockAlign;
h.ChunkLength = (uint)((uint)inS.Length - h.DataOffset) + silenceLen;
if (h.ChunkLength > newLenBytes)
h.ChunkLength = newLenBytes;
h.ChunkLength -= h.ChunkLength % h.BlockAlign;
h.FileLength = (h.ChunkLength + (uint)h.DataOffset) - 8;
WriteSingleChunkHeader(h, outS);
copied = 0;
int len = 0;
while (copied < silenceLen)
{
len = buff.Length;
if (copied + buff.Length > silenceLen)
len = (int)silenceLen - copied;
outS.Write(buff, 0, len);
copied += len;
}
//origChunkLen = h.ChunkLength; //we need to copy this much
//copy audio and set volume
BinaryEndianWriter bw = new BinaryEndianWriter(outS);
BinaryEndianReader br = new BinaryEndianReader(inS);
int b32;
while (copied != h.ChunkLength) //length is block aligned so don't worry about channel count
{
b32 = (int)br.ReadInt16(EndianType.Little);
b32 = (int)((float)b32 * volume);
b32 = Math.Max((int)short.MinValue, Math.Min((int)short.MaxValue, b32));
bw.Write((short)b32, EndianType.Little);
copied += 2;
}
//copied = (int)origChunkLen; //we've copied this much (silence included)
//while (copied < h.ChunkLength) //pad to the length we said it was in the header
//{
// inS.Read(buff, 0, buff.Length);
// if (copied + buff.Length < h.ChunkLength)
// outS.Write(buff, 0, buff.Length);
// else
// outS.Write(buff, 0, (int)h.ChunkLength % - copied);
// copied += buff.Length;
//}
outS.Flush();
}
}
if (File.Exists(fileName))
{
if (File.Exists(tmpName))
FileHelper.Move(tmpName, fileName);
}
}