private async Task <AudioEncodingProperties> ParseEncodingFromMediaAsync()
        {
            //grab the first frame and strip it for information

            AudioEncodingProperties obtainedProperties = null;
            IBuffer buffer = null;

            if (AudioInfo.AudioFormat == StreamAudioFormat.AAC)
            {
                //obtainedProperties = AudioEncodingProperties.CreateAac(0, 2, 0);
                throw new Exception("Not supported.");
            }

            var provider = AudioProviderFactory.GetAudioProvider(AudioInfo.AudioFormat);

            ServerAudioInfo firstFrame = await provider.GrabFrameInfoAsync(streamProcessor, AudioInfo).ConfigureAwait(false);

            //loop until we receive a few "frames" with identical information.
            while (true)
            {
                cancelTokenSource.Token.ThrowIfCancellationRequested();

                ServerAudioInfo secondFrame = await provider.GrabFrameInfoAsync(streamProcessor, AudioInfo).ConfigureAwait(false);

                if (firstFrame.BitRate == secondFrame.BitRate &&
                    firstFrame.SampleRate == secondFrame.SampleRate)
                {
                    //both frames are identical, use one of them and escape the loop.
                    AudioInfo = firstFrame;
                    break;
                }
                else
                {
                    //frames aren't identical, get rid of the first one using the second frame and loop back.
                    firstFrame = secondFrame;
                    continue;
                }
            }

            cancelTokenSource.Token.ThrowIfCancellationRequested();

            if (AudioInfo.AudioFormat == StreamAudioFormat.MP3)
            {
                //skip the entire first frame/sample to get back on track
                await socket.LoadAsync(MP3Parser.mp3_sampleSize - MP3Parser.HeaderLength);

                buffer = await socket.ReadBufferAsync(MP3Parser.mp3_sampleSize - MP3Parser.HeaderLength);

                //streamProcessor.byteOffset += MP3Parser.mp3_sampleSize - MP3Parser.HeaderLength;


                obtainedProperties = AudioEncodingProperties.CreateMp3((uint)AudioInfo.SampleRate, (uint)AudioInfo.ChannelCount, AudioInfo.BitRate);
            }
            else if (AudioInfo.AudioFormat == StreamAudioFormat.AAC_ADTS)
            {
                //skip the entire first frame/sample to get back on track
                await socket.LoadAsync(AAC_ADTSParser.aac_adts_sampleSize - AAC_ADTSParser.HeaderLength);

                buffer = await socket.ReadBufferAsync(AAC_ADTSParser.aac_adts_sampleSize - AAC_ADTSParser.HeaderLength);

                //streamProcessor.byteOffset += AAC_ADTSParser.aac_adts_sampleSize - AAC_ADTSParser.HeaderLength;

                obtainedProperties = AudioEncodingProperties.CreateAacAdts((uint)AudioInfo.SampleRate, (uint)AudioInfo.ChannelCount, AudioInfo.BitRate);
            }
            else
            {
                throw new Exception("Unsupported format.");
            }

            if (serverSettings.RequestSongMetdata)
            {
                streamProcessor.metadataPos += buffer.Length; //very important or it will throw everything off!
            }
            return(obtainedProperties);
        }
        internal async Task <MediaStreamSample> GetNextSampleAsync(CancellationToken cancelToken)
        {
            if (sampleProvider == null)
            {
                sampleProvider = AudioProviderFactory.GetAudioProvider(shoutcastStream.AudioInfo.AudioFormat);
            }

            //todo check for internet connection and socket connection as well

            cancelToken.ThrowIfCancellationRequested();

            MediaStreamSample sample = null;
            uint sampleLength        = 0;


            //if metadataPos is less than sampleSize away from metadataInt
            if (shoutcastStream.serverSettings.RequestSongMetdata && (shoutcastStream.metadataInt - metadataPos <= sampleProvider.GetSampleSize() &&
                                                                      shoutcastStream.metadataInt - metadataPos > 0))
            {
                //parse part of the frame.
                byte[] partialFrame = new byte[shoutcastStream.metadataInt - metadataPos];
                var    read         = await socket.LoadAsync(shoutcastStream.metadataInt - metadataPos);

                if (read == 0 || read < partialFrame.Length)
                {
                    //disconnected.
                    throw new ShoutcastDisconnectionException();
                }

                await socket.ReadBytesAsync(partialFrame);

                metadataPos += shoutcastStream.metadataInt - metadataPos;
                Tuple <MediaStreamSample, uint> result = await sampleProvider.ParseSampleAsync(this, socket, partial : true, partialBytes : partialFrame).ConfigureAwait(false);

                sample       = result.Item1;
                sampleLength = result.Item2;

                cancelToken.ThrowIfCancellationRequested();
            }
            else
            {
                await HandleMetadataAsync(cancelToken);

                Tuple <MediaStreamSample, uint> result = await sampleProvider.ParseSampleAsync(this, socket).ConfigureAwait(false);

                sample       = result.Item1;
                sampleLength = result.Item2;

                cancelToken.ThrowIfCancellationRequested();

                if (sample == null || sampleLength == 0) //OLD bug: on RELEASE builds, sample.Buffer causes the app to die due to a possible .NET Native bug
                {
                    //MediaStreamSource.NotifyError(MediaStreamSourceErrorStatus.DecodeError);
                    //deferral.Complete();
                    //return;
                    return(null);
                }
                else
                {
                    if (shoutcastStream.serverSettings.RequestSongMetdata)
                    {
                        metadataPos += sampleLength;
                    }
                }
            }

            return(sample);
        }