1

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.

Community
  • 1
  • 1
ZeunO8
  • 422
  • 6
  • 25
  • @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. – ZeunO8 Aug 22 '11 at 19:53

1 Answers1

1
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();
}
Djole
  • 1,145
  • 5
  • 10
  • This looks good and all. Though some things I don't get is... What is the point of SetShortToBuffer, if it doesn't return anything? And what is the Offset and Count parameters? – ZeunO8 Aug 23 '11 at 10:28
  • Oh and this wont add the .wav header so it appears as an invalid wave file. – ZeunO8 Aug 23 '11 at 10:35
  • `SetShortToBuffer` is a function that sets the values in the `byte[] outArray` parameter, it is more efficient than using the `BitConverter` class to allocate you a new buffer each time you need to covert a `short` into a 2-byte-array. The `Offset` parameter in `SetShortToBuffer` is the one telling the function where to assign the given `val`. `ConvertShortArray`'s param Offset is there to enable you to start converting shorts to bytes from the middle of the short array, the Count parameter is there to give you the possibility of not converting the whole array at once – Djole Aug 23 '11 at 10:42
  • Edited my post to include means to create .wav file header – Djole Aug 23 '11 at 11:17