1
votes

What I have done is converted a wave file to amplitude values in a short[] array as found here Mean amplitude of a .wav in C#

I modified the values and now want to convert back to .wav format or a byte[] array which when can be written to a byte file.

1
@SS 'Kain' I don't know how I can reverse this var x = 0; var length = fa.Length; for (int s = startByte; s < length; s = s + 2) { sLeft[x] = (short)(fa[s + 1] * 0x100 + fa[s]); x++; } So it converts the amplitude data back to a byte array, And is readable.coffeesaga

1 Answers

1
votes
void SetShortToBuffer(short val,byte[] outArray,int Offset)
{
    outArray[Offset] = (byte)(val & 0x00FF);
    Offset++;
    outArray[Offset] = (byte)((val >> 8) & 0x00FF);
}

byte[] ConvertShortArray(short[] Data,int Offset,int Count)
{
    byte[] helper = new byte[Count * sizeof(short)];

    int end = Offset+Count;
    int io=0;
    for (int i = Offset; i < end; i++)
    {
        SetShortToBuffer(Data[i], helper, io);
        io+=sizeof(short);
    }

    return helper; 
}

In C this would not be an issue, you could simply tell the compiler that your previously declared short array should now be treated as a byte array (simple cast) but after failing to do so in C# outside of unsafe context I came up with this code :)

You can use ConvertShortArray function to get chunks of data in case your wave is large

EDIT:

Quick and dirty wave header creator, not tested

byte[] CreateWaveFileHeader(int SizeOfData, short ChannelCount, uint SamplesPerSecond, short BitsPerSample)
{

    short BlockAlign = (short)(ChannelCount * (BitsPerSample / 8));
    uint AverageBytesPerSecond = SamplesPerSecond * BlockAlign;

    List<byte> pom = new List<byte>();
    pom.AddRange(ASCIIEncoding.ASCII.GetBytes("RIFF"));
    pom.AddRange(BitConverter.GetBytes(SizeOfData + 36)); //Size + up to data
    pom.AddRange(ASCIIEncoding.ASCII.GetBytes("WAVEfmt "));
    pom.AddRange(BitConverter.GetBytes(((uint)16))); //16 For PCM
    pom.AddRange(BitConverter.GetBytes(((short)1))); //PCM FMT
    pom.AddRange(BitConverter.GetBytes(((short)ChannelCount)));
    pom.AddRange(BitConverter.GetBytes((uint)SamplesPerSecond));
    pom.AddRange(BitConverter.GetBytes((uint)AverageBytesPerSecond));
    pom.AddRange(BitConverter.GetBytes((short)BlockAlign));
    pom.AddRange(BitConverter.GetBytes((short)BitsPerSample));
    pom.AddRange(ASCIIEncoding.ASCII.GetBytes("data"));
    pom.AddRange(BitConverter.GetBytes(SizeOfData));

    return pom.ToArray();
}