none
Converting byte[] array to short[]

    Question

  • Hey knowledgeable people!

    I am trying to convert an array of byte to an array of short, every other item is the item I need.

    I have currently solved it with this method
           
    1        public static short[] ToShortArray(byte[] Data, int items) 
    2        { 
    3            int Ctr = 0; 
    4            short[] Arr = new short[items]; 
    5            for (int i = 0; i < items*2; i++) 
    6            { 
    7                if (i == 0 || i % 2 == 0) 
    8                { 
    9                    Arr[Ctr] = (short)Data[i]; 
    10                    Ctr++; 
    11                } 
    12            } 
    13            return Arr; 
    14        } 

    But the force tells me there must be a better way!

    Would love to hear a more elegant solution, perhaps with lambdas ???

    Kind Regards,

    Tim
    Tuesday, December 23, 2008 9:40 PM

Answers

  •         public static short[] ToShortArray(byte[] data, int items)     
            {     
                short[] retVal = new short[items];     
                for (int i = 0; i < retVal.Length; i++)     
                    retVal[i] = (short)(data[i * 2] | data[i * 2 + 1] << 8); ;     
                return retVal;     
            }    
    hello there! the bit convertor works but i think this might perform better~ i dont have much time to do too much testing on it.. hope its wad you needed.. good luck
    • Marked as answer by Tim Kock Wednesday, December 24, 2008 10:38 AM
    Wednesday, December 24, 2008 7:59 AM
  • It's slightly faster to use Buffer.BlockCopy() to convert the data, like so:
    (It was about 1.5 times faster in release build on my PC)

    using System; 
    using System.Diagnostics; 
     
    namespace Demo 
        public class Program 
        { 
            [STAThread] 
            public static void Main() 
            { 
                byte[] testData = new byte[1000000]; 
     
                Random rng = new Random(10000); 
                rng.NextBytes(testData);      // Start with some random bytes. 
     
                short[] test1 = ToShortArray(testData); 
                short[] test2 = ToShortArrayFast(testData); 
     
                Debug.Assert(test1.Length == test2.Length); 
     
                for (int i = 0; i < test1.Length; ++i) 
                { 
                    Debug.Assert(test1[i] == test2[i]); 
                } 
     
                int count = 1000
     
                Stopwatch sw = new Stopwatch(); 
                sw.Start(); 
     
                for (int i = 0; i < count; ++i) 
                { 
                    ToShortArray(testData); 
                } 
     
                sw.Stop(); 
                double t1 = sw.Elapsed.TotalSeconds; 
                Console.WriteLine("ToShortArray() took " + sw.Elapsed); 
                sw.Reset(); 
                sw.Start(); 
     
                for (int i = 0; i < count; ++i) 
                { 
                    ToShortArrayFast(testData); 
                } 
     
                sw.Stop(); 
                double t2 = sw.Elapsed.TotalSeconds; 
                Console.WriteLine("ToShortArrayFast() took " + sw.Elapsed); 
                Console.WriteLine("The fast version was " + (t1/t2) + " times faster."); 
            } 
     
            public static short[] ToShortArray(byte[] data) 
            { 
                short[] retVal = new short[data.Length/sizeof(short)]; 
                for (int i = 0; i < retVal.Length; i++) 
                    retVal[i] = (short)(data[i * 2] | data[i * 2 + 1] <8); ; 
                return retVal; 
            } 
     
            public static short[] ToShortArrayFast(byte[] data) 
            { 
                short[] retVal = new short[data.Length/sizeof(short)]; 
                Buffer.BlockCopy(data, 0, retVal, 0, retVal.Length*sizeof(short)); 
                return retVal; 
            } 
        } 

    • Marked as answer by Tim Kock Wednesday, December 24, 2008 1:11 PM
    Wednesday, December 24, 2008 11:14 AM

All replies

  • Right... thank you for your reply, but I know how to type cast, you can see that from the statement above, but what I am referring to is:

    Through Marshal.PtrToStructure I am getting a structure which has a field of byte[], and this needs to be converted to short[], i.e:

    I am getting this

    0, 0, 1, 0, 2, 0, 3

    and need to get this

    0, 1, 2


    Tuesday, December 23, 2008 9:54 PM
  •  
                byte[ ] bts = new byte[ 10 ];  
                bts.Cast<short> ( ); 



    AlexB
    Tuesday, December 23, 2008 9:59 PM
  •  I am sorry, Tim, I deleted those posts in a hurry. I usually read stuff superficially and frequently get in trouble with it.
    AlexB
    Tuesday, December 23, 2008 10:00 PM
  • Don't worry dude, just hope you understand what I am on about, its marshalled from a c structure in memory. Thats not the problem but the byte[] needs conversion to short[] which means the managed structure will have the short value I wan't every other items, since short is 2 bytes in length.

    What I wrote works fine, but I was wondering if there was perhaps a better way. usually there are nifty methods in BitConverter or the text namespaces.

    Anyway, if you have anything please share!

    Thank you
    Tuesday, December 23, 2008 10:02 PM
  • AlexBB said:

     

                byte[ ] bts = new byte[ 10 ];  
                bts.Cast<short> ( ); 



    AlexB


    that doesn't work,

    return Data.Cast<short>().ToArray(); 

    doesn't work either.

    ;)

    Thank you very much though for taking the time


    Tuesday, December 23, 2008 10:06 PM
  •  What do you mean does not work? What is the exception? It's been understood that you will fill your array with some meaningful bytes. My array is empty. I put it there for type casting.
    AlexB
    Tuesday, December 23, 2008 11:56 PM
  • You mentioned BitConverter already; have you tried:

    public static short[] ToShortArray(byte[] Data, int items)    
    {    
      short[] Arr = new short[items];  
      for (int i = 0; i != items; ++i)  
        Arr[i] = BitConverter.ToInt16(Data, i * 2);  
      return Arr;  

           -Steve
    Wednesday, December 24, 2008 1:43 AM
  •         public static short[] ToShortArray(byte[] data, int items)     
            {     
                short[] retVal = new short[items];     
                for (int i = 0; i < retVal.Length; i++)     
                    retVal[i] = (short)(data[i * 2] | data[i * 2 + 1] << 8); ;     
                return retVal;     
            }    
    hello there! the bit convertor works but i think this might perform better~ i dont have much time to do too much testing on it.. hope its wad you needed.. good luck
    • Marked as answer by Tim Kock Wednesday, December 24, 2008 10:38 AM
    Wednesday, December 24, 2008 7:59 AM
  • Rejinderi, that looks like exactly what I am looking for, It works great, but could you explain it so that I understand if fully as I need to adapt it to convert from byte array to int array too.

    Thank you very much for all your efforts guys!
    Wednesday, December 24, 2008 10:28 AM
  • Stephen, your solution works very well too, it is also a bit easier to adapt as I am not fully understanding of bit shifting etc. It is a tiny bit slower though, but I will see what I can do.

    Thank you very much!
    Wednesday, December 24, 2008 10:53 AM
  • It's slightly faster to use Buffer.BlockCopy() to convert the data, like so:
    (It was about 1.5 times faster in release build on my PC)

    using System; 
    using System.Diagnostics; 
     
    namespace Demo 
        public class Program 
        { 
            [STAThread] 
            public static void Main() 
            { 
                byte[] testData = new byte[1000000]; 
     
                Random rng = new Random(10000); 
                rng.NextBytes(testData);      // Start with some random bytes. 
     
                short[] test1 = ToShortArray(testData); 
                short[] test2 = ToShortArrayFast(testData); 
     
                Debug.Assert(test1.Length == test2.Length); 
     
                for (int i = 0; i < test1.Length; ++i) 
                { 
                    Debug.Assert(test1[i] == test2[i]); 
                } 
     
                int count = 1000
     
                Stopwatch sw = new Stopwatch(); 
                sw.Start(); 
     
                for (int i = 0; i < count; ++i) 
                { 
                    ToShortArray(testData); 
                } 
     
                sw.Stop(); 
                double t1 = sw.Elapsed.TotalSeconds; 
                Console.WriteLine("ToShortArray() took " + sw.Elapsed); 
                sw.Reset(); 
                sw.Start(); 
     
                for (int i = 0; i < count; ++i) 
                { 
                    ToShortArrayFast(testData); 
                } 
     
                sw.Stop(); 
                double t2 = sw.Elapsed.TotalSeconds; 
                Console.WriteLine("ToShortArrayFast() took " + sw.Elapsed); 
                Console.WriteLine("The fast version was " + (t1/t2) + " times faster."); 
            } 
     
            public static short[] ToShortArray(byte[] data) 
            { 
                short[] retVal = new short[data.Length/sizeof(short)]; 
                for (int i = 0; i < retVal.Length; i++) 
                    retVal[i] = (short)(data[i * 2] | data[i * 2 + 1] <8); ; 
                return retVal; 
            } 
     
            public static short[] ToShortArrayFast(byte[] data) 
            { 
                short[] retVal = new short[data.Length/sizeof(short)]; 
                Buffer.BlockCopy(data, 0, retVal, 0, retVal.Length*sizeof(short)); 
                return retVal; 
            } 
        } 

    • Marked as answer by Tim Kock Wednesday, December 24, 2008 1:11 PM
    Wednesday, December 24, 2008 11:14 AM
  • Niiaaaooooooceeeeee!!!!!!

    Where do you guys get this stuff from, I have been programming for years and doing fine, but always felt like things could go faster. How do you discover this sort of stuff!?

    Thank you very much, you are all geniuses
    Wednesday, December 24, 2008 1:11 PM
  • About three times as fast on my machine, thats very smooth Matthew!
    Wednesday, December 24, 2008 1:14 PM