/// <summary> /// Add invalid data (since we need to check garbage for a mp3 resync we may need to combine multiple invalid chunks). /// </summary> /// <param name="buffer">The buffer to add to invalid data frame.</param> void InvalidData(byte[] buffer) { if (buffer.Length == 0) { return; } if (m_InvalidFrame == null) { m_InvalidFrame = new MP3InvalidFrame(); } m_InvalidFrame.Add(buffer); }
/// <summary> /// Gets the next frame. /// </summary> /// <returns>Returns the next frame or null (at end of stream).</returns> public AudioFrame GetNextFrame() { while (true) { #region return buffered frames first (if any) // got a decoded frame at the cache ? if (m_BufferedFrame != null) { AudioFrame result; if (m_InvalidFrame != null) { result = m_InvalidFrame; m_InvalidFrame = null; } else { result = m_BufferedFrame; m_BufferedFrame = null; } return(result); } #endregion #region search next frame start // search the next interesting position var searchResult = FindFrame(); if (searchResult == null) { #region end of stream cleanup // invalid data at end of stream ? if (m_Reader.Available > 0) { // yes buffer InvalidData(m_Reader.GetBuffer()); } // got an invalid frame ? if (m_InvalidFrame != null) { // return invalid frame AudioFrame result = m_InvalidFrame; m_InvalidFrame = null; return(result); } // got an id3v1 ? if (m_ID3v1 != null) { // return id3v1 AudioFrame result = m_ID3v1; m_ID3v1 = null; return(result); } // everything done, return null return(null); #endregion } #endregion #region check search result // got garbage at the beginning? if (searchResult.Index > 0) { // yes, invalid data InvalidData(m_Reader.GetBuffer(searchResult.Index)); continue; } #endregion #region decode frame // try to decode frame try { var valid = false; AudioFrame frame = null; switch (searchResult.Match) { #region decode mp3 frame case MatchType.MP3Frame: var audioFrame = new MP3AudioFrame(); valid = audioFrame.Parse(m_Reader); frame = audioFrame; break; #endregion #region decode id3 frame case MatchType.ID3Frame: frame = new ID3v2(); valid = frame.Parse(m_Reader); break; #endregion default: throw new NotImplementedException(string.Format("Unknown frame type {0}", searchResult.Match)); } // parsed successfully? if (valid) { // yes, cache frame m_BufferedFrame = frame; } else { // no invalidate InvalidData(m_Reader.GetBuffer(1)); } } catch (Exception ex) { Trace.TraceError(string.Format("Error while decoding {0} in stream {1}", searchResult.Match, m_Reader)); Trace.TraceError(ex.ToString()); // invalid frame or decoder error, move ahead var count = (searchResult.Index < 0) ? 1 : searchResult.Index + 1; InvalidData(m_Reader.GetBuffer(count)); } #endregion } }