locked
[UWP] IRandomAccessStream to float[] RRS feed

  • Question

  • Hi everyone

    I have a problem turning a RandomAccessStream into a float array. The float array contains values that are NaN. I can't tell if they come from the stream, the byte array or the float array. Performance & quality are important in this so if there is a better way to do this let me know.

    Last count I was getting 122 NaN's.

    thanks

     private async void button_Click(object sender, RoutedEventArgs e)
            {
                string text = "this is text";
    
                SpeechSynthesizer synthesizer = new SpeechSynthesizer();
                SpeechSynthesisStream synthesisStream = await synthesizer.SynthesizeTextToStreamAsync(text);
    
                Stopwatch watch = new Stopwatch();
                watch.Start();
                ProcessStream(synthesisStream.CloneStream());
                watch.Stop();
    
                // Performance is important
                Debug.WriteLine(watch.Elapsed);
            }
    
            private async void ProcessStream(IRandomAccessStream stream)
            {
                // Create a buffer (somewhere to put the stream)
                byte[] bytes = new byte[stream.Size];
    
                // Add stream data to buffer (Following or After that) same result
                // IBuffer x = await stream.ReadAsync(bytes.AsBuffer(), (uint)stream.Size, InputStreamOptions.None);
                using (DataReader reader = new DataReader(stream))
                {
                    await reader.LoadAsync((uint)stream.Size);
                    reader.ReadBytes(bytes);
                }
    
                // Change buffer(in bytes) to a float array
                float[] floatArray = MainPage.ConvertByteToFloat(bytes.ToArray());
    
                int nanCount = 0;
                for (var index = 0; index < floatArray.Length; index++)
                {
                    float value = floatArray[index];
                    if (float.IsNaN(value))
                    {
                        nanCount++;
                    }
                }
    
                Debug.WriteLine("Nan count: " + nanCount);
            }
    
            public static float[] ConvertByteToFloat(byte[] array)
            {
                float[] floatArr = new float[array.Length / 4];
                for (int i = 0; i < floatArr.Length; i++)
                {
                    if (BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(array, i * 4, 4);
                    }
                    floatArr[i] = BitConverter.ToSingle(array, i * 4);
                }
                return floatArr;
            }


    • Edited by hypodyne1 Tuesday, April 4, 2017 9:24 PM
    Tuesday, April 4, 2017 12:53 PM

Answers

  • Debug to narrow down where the problem is. If you're seeing NANs then either you have bad input, a bad conversion, or bad expectations (probably a bad conversion)

    Without having actually tried it, the IsLittleEndian reverse looks suspicious: I'd expect the bytes from the SpeechSynthesisStream to already be in system order, so reversing them again will convert them to BigEndian and break the ToSingle call.

    Rather than converting to a byte[] and then looping over the byte[] you could also just query the floats directly from DataReader.ReadSingle(). I wouldn't expect a significant performance difference between these methods, but if it's noticeable you can profile to confirm.


    Wednesday, April 5, 2017 4:00 AM

All replies

  • Debug to narrow down where the problem is. If you're seeing NANs then either you have bad input, a bad conversion, or bad expectations (probably a bad conversion)

    Without having actually tried it, the IsLittleEndian reverse looks suspicious: I'd expect the bytes from the SpeechSynthesisStream to already be in system order, so reversing them again will convert them to BigEndian and break the ToSingle call.

    Rather than converting to a byte[] and then looping over the byte[] you could also just query the floats directly from DataReader.ReadSingle(). I wouldn't expect a significant performance difference between these methods, but if it's noticeable you can profile to confirm.


    Wednesday, April 5, 2017 4:00 AM
  • Hi Rob

    Turns out I was completely wrong about the data section of wav files. I was reading in 4 bytes and sticking them into a float. A 32 bit float wav file actually reads in 2 bytes (performs some magic on it) and sticks that into a float.

    Found a fast function on Stack Exchange that reads in a wav files header and data sections and returns a float array.

    So now I can read the wav file from the speech synthesis produces, get the data, do a calculation to produce the results I was after.

    Which also confirms you were correct about the other thread of mine you answered.

    Thanks a lot Rob


    • Edited by hypodyne1 Thursday, April 6, 2017 11:40 AM
    Thursday, April 6, 2017 11:36 AM