tags:

views:

162

answers:

4

I am reading a raw audio file (CD track rip) in, doing byte swapping, and then writing back out to a wav file.

The routine I have processes the bytes properly, but only does about half the file. I am a VB.NET Developer, not really a C# developer, and this code does not convert to VB.NET properly (It gets an overflow error).

It's not really a "swap" so much as a calc/prune. (short)((buffer[i + 1] * 256) + buffer[i])

I believe it is writing only half of the samples, but I've no idea how to fix!

        public static short[] SwapBytesArray(string fileName)
    {
        byte[] buffer = System.IO.File.ReadAllBytes(fileName);
        long fileLength = buffer.LongLength;
        if ((fileLength & 1) == 1)
        {
            throw new ArgumentException("File length must be an even number of bytes");
        }
        System.Collections.Generic.List<short> sList = new System.Collections.Generic.List<short>();


        for (long i = 0; i < fileLength - 1; i += 2)
        {
            byte tmp = buffer[i];
            sList.Add((short)((buffer[i + 1] * 256) + buffer[i]));
            //buffer[i + 1] = tmp;
        }
        return sList.ToArray();
    }
+1  A: 

If the size of the file is greater than maximum integer, then you'll overflow the index variable (index should be a long since num is a long). Presumably you use buffer.LongLength instead of buffer.Length because your data is known to be larger, so a likely issue regardless.

brlcad
+1  A: 

Why do you want to return an array of short?

If you are writing back out to a file wouldn't a byte[] array be a better choice?

i.e

public static byte[] SwapBytes(string fileName)
{ 
    byte[] buffer = System.IO.File.ReadAllBytes(fileName);

    long fileLength = buffer.LongLength;

    if ((fileLength & 1) == 1)
    {
        throw new ArgumentException("File length must be an even number of bytes");
    }

    for (long i = 0; i < fileLength  - 1 ; i +=2 )
    {
        byte tmp = buffer[i];
        buffer[i] = buffer[i + 1];
        buffer[i + 1] = tmp;
    }

    return buffer;
}
Mitch Wheat
It can be Byte[] or Short[]
Rick Ratayczak
I added your code, and changed the code above, but it still only processes half of the file.
Rick Ratayczak
+1  A: 

This seems incredibly wasteful of memory. You read in the entire file as a sequence of bytes, then duplicate it in a short[] array. You may even duplicate it again when you return that array.

Your actual problem may lie in the way you are writing out the shorts when this function returns (rather than bytes). I think we need to see that code.

paxdiablo
+1  A: 

I would think a streaming approach would be more efficient and less prone to errors. .NET has very good support for streams, so something like the following should work:

public void SwapBytesStreamed(Stream inputStream, Stream outputStream)
{
    byte[] bytePair = new byte[2];
    long offset = 0;
    while (offset < inputStream.Length)
    {
        int bytesRead = inputStream.Read(bytePair, 0, 2);
        if (bytesRead == 0) break;

        if (bytesRead == 2)
        {
            outputStream.WriteByte(bytePair[1]);
        }
        outputStream.WriteByte(bytePair[0]);

        offset += bytesRead;
    }
}

Then use it like the following:

public Stream SwapBytesInFile(string filename)
{
    Stream inputStream = File.Open(filename, FileMode.Open);
    MemoryStream outputStream = new MemoryStream();

    SwapBytesStreamed(inputStream, outputStream);
}
jrista