/// <summary> /// Opens MP3 from a stream rather than a file /// Will not dispose of this stream itself /// </summary> /// <param name="inputStream">The incoming stream containing MP3 data</param> /// <param name="frameDecompressorBuilder">Factory method to build a frame decompressor</param> public Mp3FileReader(Stream inputStream, FrameDecompressorBuilder frameDecompressorBuilder) { // Calculated as a double to minimize rounding errors mp3Stream = inputStream; id3v2Tag = Id3v2Tag.ReadTag(mp3Stream); dataStartPosition = mp3Stream.Position; var mp3Frame = Mp3Frame.LoadFromStream(mp3Stream); sampleRate = mp3Frame.SampleRate; frameLengthInBytes = mp3Frame.FrameLength; double bitRate = mp3Frame.BitRate; xingHeader = XingHeader.LoadXingHeader(mp3Frame); // If the header exists, we can skip over it when decoding the rest of the file if (xingHeader != null) { dataStartPosition = mp3Stream.Position; } this.mp3DataLength = mp3Stream.Length - dataStartPosition; // try for an ID3v1 tag as well mp3Stream.Position = mp3Stream.Length - 128; byte[] tag = new byte[128]; mp3Stream.Read(tag, 0, 3); if (tag[0] == 'T' && tag[1] == 'A' && tag[2] == 'G') { id3v1Tag = tag; this.mp3DataLength -= 128; } mp3Stream.Position = dataStartPosition; // create a temporary MP3 format before we know the real bitrate this.Mp3WaveFormat = new Mp3WaveFormat(sampleRate, mp3Frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frameLengthInBytes, (int)bitRate); CreateTableOfContents(); this.tocIndex = 0; // [Bit rate in Kilobits/sec] = [Length in kbits] / [time in seconds] // = [Length in bits ] / [time in milliseconds] // Note: in audio, 1 kilobit = 1000 bits. bitRate = (mp3DataLength * 8.0 / TotalSeconds()); mp3Stream.Position = dataStartPosition; // now we know the real bitrate we can create an accurate this.Mp3WaveFormat = new Mp3WaveFormat(sampleRate, mp3Frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frameLengthInBytes, (int)bitRate); decompressor = frameDecompressorBuilder(Mp3WaveFormat); this.waveFormat = decompressor.OutputFormat; this.bytesPerSample = (decompressor.OutputFormat.BitsPerSample) / 8 * decompressor.OutputFormat.Channels; // no MP3 frames have more than 1152 samples in them // some MP3s I seem to get double this.decompressBuffer = new byte[1152 * bytesPerSample * 2]; }
public Mp3FileReader(Stream inputStream, Mp3FileReader.FrameDecompressorBuilder frameDecompressorBuilder) { if (inputStream == null) { throw new ArgumentNullException("inputStream"); } try { this.mp3Stream = inputStream; this.id3v2Tag = Id3v2Tag.ReadTag(this.mp3Stream); this.dataStartPosition = this.mp3Stream.Position; Mp3Frame mp3Frame = Mp3Frame.LoadFromStream(this.mp3Stream); if (mp3Frame == null) { throw new InvalidDataException("Invalid MP3 file - no MP3 Frames Detected"); } double num = (double)mp3Frame.BitRate; this.xingHeader = XingHeader.LoadXingHeader(mp3Frame); if (this.xingHeader != null) { this.dataStartPosition = this.mp3Stream.Position; } Mp3Frame mp3Frame2 = Mp3Frame.LoadFromStream(this.mp3Stream); if (mp3Frame2 != null && (mp3Frame2.SampleRate != mp3Frame.SampleRate || mp3Frame2.ChannelMode != mp3Frame.ChannelMode)) { this.dataStartPosition = mp3Frame2.FileOffset; mp3Frame = mp3Frame2; } this.mp3DataLength = this.mp3Stream.Length - this.dataStartPosition; this.mp3Stream.Position = this.mp3Stream.Length - 128L; byte[] array = new byte[128]; this.mp3Stream.Read(array, 0, 128); if (array[0] == 84 && array[1] == 65 && array[2] == 71) { this.id3v1Tag = array; this.mp3DataLength -= 128L; } this.mp3Stream.Position = this.dataStartPosition; this.Mp3WaveFormat = new Mp3WaveFormat(mp3Frame.SampleRate, (mp3Frame.ChannelMode == ChannelMode.Mono) ? 1 : 2, mp3Frame.FrameLength, (int)num); this.CreateTableOfContents(); this.tocIndex = 0; num = (double)this.mp3DataLength * 8.0 / this.TotalSeconds(); this.mp3Stream.Position = this.dataStartPosition; this.Mp3WaveFormat = new Mp3WaveFormat(mp3Frame.SampleRate, (mp3Frame.ChannelMode == ChannelMode.Mono) ? 1 : 2, mp3Frame.FrameLength, (int)num); this.decompressor = frameDecompressorBuilder(this.Mp3WaveFormat); this.waveFormat = this.decompressor.OutputFormat; this.bytesPerSample = this.decompressor.OutputFormat.BitsPerSample / 8 * this.decompressor.OutputFormat.Channels; this.decompressBuffer = new byte[1152 * this.bytesPerSample * 2]; } catch (Exception) { if (this.ownInputStream) { inputStream.Dispose(); } throw; } }
public static IMp3FrameDecompressor CreateFrameDecompressor(Mp3Frame frame) { WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate ); return new AcmMp3FrameDecompressor(waveFormat); }
private WaveInEvent sourceStream = null; //NAudio.Wave.WaveIn sourceStream = null; #endregion Fields #region Methods public Mp3Frame GetNextMp3Frame() { if (mp3Reader == null) { return null; /*string file = @"H:\stuff\MP3's\Anime\Hideyuki Fukasawa - EMIYA (UBW Extended).mp3"; //@"H:\stuff\MP3's\Alestorm\2011 - Back Through Time\13 - You Are A Pirate.mp3"; mp3Reader = new NAudio.Wave.Mp3FileReader(file);*/ } NAudio.Wave.Mp3Frame frame = mp3Reader.ReadNextFrame(); if (waveFormat == null && frame != null) { waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); } return frame; }
private void StreamMP3() { HttpWebRequest request = null; try { var resp = ConnectionFactory.GetResponse(_source,false, out request); var buffer = new byte[16384 * 4]; // needs to be big enough to hold a decompressed frame IMp3FrameDecompressor decompressor = null; using (var responseStream = resp.GetResponseStream()) { var readFullyStream = new ReadFullyStream(responseStream); while (!_stopEvent.WaitOne(10, false) && !MainForm.ShuttingDown) { if (_bufferedWaveProvider != null && _bufferedWaveProvider.BufferLength - _bufferedWaveProvider.BufferedBytes < _bufferedWaveProvider.WaveFormat.AverageBytesPerSecond/4) { //Debug.WriteLine("Buffer getting full, taking a break"); Thread.Sleep(100); } else { var da = DataAvailable; if (da != null) { Mp3Frame frame; try { frame = Mp3Frame.LoadFromStream(readFullyStream); } catch (EndOfStreamException) { // reached the end of the MP3 file / stream break; } catch (WebException) { // probably we have aborted download from the GUI thread break; } if (decompressor == null || _bufferedWaveProvider == null) { // don't think these details matter too much - just help ACM select the right codec // however, the buffered provider doesn't know what sample rate it is working at // until we have a frame WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); RecordingFormat = new WaveFormat(frame.SampleRate, 16, frame.ChannelMode == ChannelMode.Mono ? 1 : 2); decompressor = new AcmMp3FrameDecompressor(waveFormat); _bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat) {BufferDuration = TimeSpan.FromSeconds(5)}; _sampleChannel = new SampleChannel(_bufferedWaveProvider); _sampleChannel.PreVolumeMeter += SampleChannelPreVolumeMeter; } int decompressed = decompressor.DecompressFrame(frame, buffer, 0); _bufferedWaveProvider.AddSamples(buffer, 0, decompressed); var sampleBuffer = new float[buffer.Length]; _sampleChannel.Read(sampleBuffer, 0, buffer.Length); da.Invoke(this, new DataAvailableEventArgs((byte[]) buffer.Clone())); if (WaveOutProvider != null && Listening) { WaveOutProvider.AddSamples(buffer, 0, buffer.Length); } } } if (_stopEvent.WaitOne(0, false)) break; } AudioFinished?.Invoke(this, new PlayingFinishedEventArgs(ReasonToFinishPlaying.StoppedByUser)); // was doing this in a finally block, but for some reason // we are hanging on response stream .Dispose so never get there if (decompressor != null) { decompressor.Dispose(); decompressor = null; } } } catch (Exception ex) { var af = AudioFinished; af?.Invoke(this, new PlayingFinishedEventArgs(ReasonToFinishPlaying.DeviceLost)); MainForm.LogExceptionToFile(ex,"MP3Stream"); } finally { try { request?.Abort(); } catch { } request = null; } }
private void DecompressFrames() { IMp3FrameDecompressor decompressor = null; IWavePlayer waveOut = null; try { BufferedWaveProvider bufferedWaveProvider = null; var buffer = new byte[16384 * 4]; // needs to be big enough to hold a decompressed frame var firstLoop = true; do { //WaveBuffer getting full, taking a break if (bufferedWaveProvider != null && bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes < bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4) { Thread.Sleep(500); } //StreamBuffer empty, taking a break else if (stream.Length < 16384 * 2) { Thread.Sleep(500); } else { Mp3Frame frame; try { frame = Mp3Frame.LoadFromStream(stream); } catch (EndOfStreamException) { break; } if (frame == null) continue; if (decompressor == null) { WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); decompressor = new AcmMp3FrameDecompressor(waveFormat); bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat) { BufferDuration = TimeSpan.FromSeconds(5) }; // allow us to get well ahead of ourselves } var decompressed = decompressor.DecompressFrame(frame, buffer, 0); if (decompressed > 0) bufferedWaveProvider.AddSamples(buffer, 0, decompressed); if (firstLoop) { firstLoop = false; waveOut = CreateWaveOut(); if (onWaveProviderCreated != null) { var provider = onWaveProviderCreated(bufferedWaveProvider); waveOut.Init(provider); } waveOut.Play(); } } } while (IsPlaying); } finally { if (waveOut != null) { waveOut.Stop(); waveOut.Dispose(); } if (decompressor != null) { decompressor.Dispose(); } } }
/// <summary> /// Opens MP3 from a stream rather than a file /// Will not dispose of this stream itself /// </summary> /// <param name="inputStream">The incoming stream containing MP3 data</param> /// <param name="frameDecompressorBuilder">Factory method to build a frame decompressor</param> public Mp3FileReader(Stream inputStream, FrameDecompressorBuilder frameDecompressorBuilder) { // Calculated as a double to minimize rounding errors mp3Stream = inputStream; id3v2Tag = Id3v2Tag.ReadTag(mp3Stream); dataStartPosition = mp3Stream.Position; var firstFrame = Mp3Frame.LoadFromStream(mp3Stream); double bitRate = firstFrame.BitRate; xingHeader = XingHeader.LoadXingHeader(firstFrame); // If the header exists, we can skip over it when decoding the rest of the file if (xingHeader != null) dataStartPosition = mp3Stream.Position; // workaround for a longstanding issue with some files failing to load // because they report a spurious sample rate change var secondFrame = Mp3Frame.LoadFromStream(mp3Stream); if (secondFrame != null && (secondFrame.SampleRate != firstFrame.SampleRate || secondFrame.ChannelMode != firstFrame.ChannelMode)) { // assume that the first frame was some kind of VBR/LAME header that we failed to recognise properly dataStartPosition = secondFrame.FileOffset; // forget about the first frame, the second one is the first one we really care about firstFrame = secondFrame; } this.mp3DataLength = mp3Stream.Length - dataStartPosition; // try for an ID3v1 tag as well mp3Stream.Position = mp3Stream.Length - 128; byte[] tag = new byte[128]; mp3Stream.Read(tag, 0, 128); if (tag[0] == 'T' && tag[1] == 'A' && tag[2] == 'G') { id3v1Tag = tag; this.mp3DataLength -= 128; } mp3Stream.Position = dataStartPosition; // create a temporary MP3 format before we know the real bitrate this.Mp3WaveFormat = new Mp3WaveFormat(firstFrame.SampleRate, firstFrame.ChannelMode == ChannelMode.Mono ? 1 : 2, firstFrame.FrameLength, (int)bitRate); CreateTableOfContents(); this.tocIndex = 0; // [Bit rate in Kilobits/sec] = [Length in kbits] / [time in seconds] // = [Length in bits ] / [time in milliseconds] // Note: in audio, 1 kilobit = 1000 bits. bitRate = (mp3DataLength * 8.0 / TotalSeconds()); mp3Stream.Position = dataStartPosition; // now we know the real bitrate we can create an accurate this.Mp3WaveFormat = new Mp3WaveFormat(firstFrame.SampleRate, firstFrame.ChannelMode == ChannelMode.Mono ? 1 : 2, firstFrame.FrameLength, (int)bitRate); decompressor = frameDecompressorBuilder(Mp3WaveFormat); this.waveFormat = decompressor.OutputFormat; this.bytesPerSample = (decompressor.OutputFormat.BitsPerSample) / 8 * decompressor.OutputFormat.Channels; // no MP3 frames have more than 1152 samples in them // some MP3s I seem to get double this.decompressBuffer = new byte[1152 * bytesPerSample * 2]; }
private void StreamMP3() { var webRequest = (HttpWebRequest)WebRequest.Create(_source); HttpWebResponse resp = null; try { resp = (HttpWebResponse)webRequest.GetResponse(); } catch (WebException e) { if (e.Status != WebExceptionStatus.RequestCanceled) { } return; } byte[] buffer = new byte[16384 * 4]; // needs to be big enough to hold a decompressed frame IMp3FrameDecompressor decompressor = null; try { using (var responseStream = resp.GetResponseStream()) { var readFullyStream = new ReadFullyStream(responseStream); while (!_stopEvent.WaitOne(0, false)) { if (_bufferedWaveProvider != null && _bufferedWaveProvider.BufferLength - _bufferedWaveProvider.BufferedBytes < _bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4) { //Debug.WriteLine("Buffer getting full, taking a break"); Thread.Sleep(100); } else { Mp3Frame frame = null; try { frame = Mp3Frame.LoadFromStream(readFullyStream); } catch (EndOfStreamException) { // reached the end of the MP3 file / stream break; } catch (WebException) { // probably we have aborted download from the GUI thread break; } if (decompressor == null) { // don't think these details matter too much - just help ACM select the right codec // however, the buffered provider doesn't know what sample rate it is working at // until we have a frame WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); decompressor = new AcmMp3FrameDecompressor(waveFormat); this._bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat) {BufferDuration = TimeSpan.FromSeconds(5)}; _waveOut = new DirectSoundOut(1000); _waveOut.Init(_bufferedWaveProvider); _waveOut.Play(); _waveOut.PlaybackStopped += wavePlayer_PlaybackStopped; } int decompressed = decompressor.DecompressFrame(frame, buffer, 0); //Debug.WriteLine(String.Format("Decompressed a frame {0}", decompressed)); _bufferedWaveProvider.AddSamples(buffer, 0, decompressed); } if (_stopEvent.WaitOne(0, false)) break; } Debug.WriteLine("Exiting"); // was doing this in a finally block, but for some reason // we are hanging on response stream .Dispose so never get there if (decompressor != null) { decompressor.Dispose(); decompressor = null; } } } finally { if (decompressor != null) { decompressor.Dispose(); } if (_waveOut!=null) { _waveOut.Stop(); } } }
public void CanCreateDmoMp3FrameDecompressor() { var mp3Format = new Mp3WaveFormat(44100,2,215,32000); var frameDecompressor = new DmoMp3FrameDecompressor(mp3Format); Assert.IsNotNull(frameDecompressor); }
public void WindowsMediaMp3DecoderSupportsStereoMp3() { WaveFormat waveFormat = new Mp3WaveFormat(44100, 2, 0, 32000); Assert.IsTrue(IsInputFormatSupported(waveFormat)); }
/// <summary> /// Opens MP3 from a stream rather than a file /// Will not dispose of this stream itself /// </summary> /// <param name="inputStream">The incoming stream containing MP3 data</param> /// <param name="frameDecompressorBuilder">Factory method to build a frame decompressor</param> public Mp3FileReader(Stream inputStream, FrameDecompressorBuilder frameDecompressorBuilder) { if (inputStream == null) { throw new ArgumentNullException("inputStream"); } try { mp3Stream = inputStream; id3v2Tag = Id3v2Tag.ReadTag(mp3Stream); dataStartPosition = mp3Stream.Position; var firstFrame = Mp3Frame.LoadFromStream(mp3Stream); if (firstFrame == null) { throw new InvalidDataException("Invalid MP3 file - no MP3 Frames Detected"); } double bitRate = firstFrame.BitRate; xingHeader = XingHeader.LoadXingHeader(firstFrame); // If the header exists, we can skip over it when decoding the rest of the file if (xingHeader != null) { dataStartPosition = mp3Stream.Position; } // workaround for a longstanding issue with some files failing to load // because they report a spurious sample rate change var secondFrame = Mp3Frame.LoadFromStream(mp3Stream); if (secondFrame != null && (secondFrame.SampleRate != firstFrame.SampleRate || secondFrame.ChannelMode != firstFrame.ChannelMode)) { // assume that the first frame was some kind of VBR/LAME header that we failed to recognise properly dataStartPosition = secondFrame.FileOffset; // forget about the first frame, the second one is the first one we really care about firstFrame = secondFrame; } this.mp3DataLength = mp3Stream.Length - dataStartPosition; // try for an ID3v1 tag as well mp3Stream.Position = mp3Stream.Length - 128; byte[] tag = new byte[128]; mp3Stream.Read(tag, 0, 128); if (tag[0] == 'T' && tag[1] == 'A' && tag[2] == 'G') { id3v1Tag = tag; this.mp3DataLength -= 128; } mp3Stream.Position = dataStartPosition; // create a temporary MP3 format before we know the real bitrate this.Mp3WaveFormat = new Mp3WaveFormat(firstFrame.SampleRate, firstFrame.ChannelMode == ChannelMode.Mono ? 1 : 2, firstFrame.FrameLength, (int)bitRate); CreateTableOfContents(); this.tocIndex = 0; // [Bit rate in Kilobits/sec] = [Length in kbits] / [time in seconds] // = [Length in bits ] / [time in milliseconds] // Note: in audio, 1 kilobit = 1000 bits. // Calculated as a double to minimize rounding errors bitRate = (mp3DataLength * 8.0 / TotalSeconds()); mp3Stream.Position = dataStartPosition; // now we know the real bitrate we can create an accurate MP3 WaveFormat this.Mp3WaveFormat = new Mp3WaveFormat(firstFrame.SampleRate, firstFrame.ChannelMode == ChannelMode.Mono ? 1 : 2, firstFrame.FrameLength, (int)bitRate); decompressor = frameDecompressorBuilder(Mp3WaveFormat); this.waveFormat = decompressor.OutputFormat; this.bytesPerSample = (decompressor.OutputFormat.BitsPerSample) / 8 * decompressor.OutputFormat.Channels; // no MP3 frames have more than 1152 samples in them this.bytesPerDecodedFrame = 1152 * bytesPerSample; // some MP3s I seem to get double this.decompressBuffer = new byte[this.bytesPerDecodedFrame * 2]; } catch (Exception) { if (ownInputStream) { inputStream.Dispose(); } throw; } }
private int DecompressFrame(Mp3Frame frame, byte[] buffer) { // decode frame if (_decompressor == null) { WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); _decompressor = new AcmMp3FrameDecompressor(waveFormat); _waveProvider = new BufferedWaveProvider(_decompressor.OutputFormat); _waveProvider.BufferDuration = TimeSpan.FromSeconds(5); _channels = _waveProvider.WaveFormat.Channels; _sampleProvider = _waveProvider.ToSampleProvider(); } return _decompressor.DecompressFrame(frame, buffer, 0); }
public void Stream(string url) { webRequest = (HttpWebRequest)WebRequest.Create(url + "/;"); int metaInt = 0; // blocksize of mp3 data webRequest.Headers.Clear(); webRequest.Method = "GET"; // needed to receive metadata informations webRequest.Headers.Add("Icy-MetaData", "1"); webRequest.UserAgent = "WinampMPEG/5.09"; HttpWebResponse resp = null; try { resp = (HttpWebResponse)webRequest.GetResponse(); } catch (WebException e) { if (e.Status != WebExceptionStatus.RequestCanceled) { //ShowError(e.Message); } return; } byte[] buffer = new byte[16384 * 4]; // needs to be big enough to hold a decompressed frame try { // read blocksize to find metadata block metaInt = Convert.ToInt32(resp.GetResponseHeader("icy-metaint")); } catch { } decompressor = null; try { using (var responseStream = resp.GetResponseStream()) { var readFullyStream = new ReadFullyStream(responseStream); readFullyStream.metaInt = metaInt; System.Threading.Tasks.Task.Factory.StartNew(() => Thread.Sleep(10000)).ContinueWith(x => { volumeProvider = new VolumeWaveProvider16(bufferedWaveProvider); waveOut = new WaveOut(); waveOut.Init(volumeProvider); }); do { if (bufferedWaveProvider != null && bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes < bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4) { Debug.WriteLine("Buffer getting full, taking a break"); Thread.Sleep(500); } else { Mp3Frame frame = null; try { frame = Mp3Frame.LoadFromStream(readFullyStream, true); if (metaInt > 0) songCallback(readFullyStream.SongName); else songCallback("No Song Info in Stream..."); } catch (EndOfStreamException) { this.fullyDownloaded = true; // reached the end of the MP3 file / stream break; } catch (WebException) { // probably we have aborted download from the GUI thread break; } if (decompressor == null) { // don't think these details matter too much - just help ACM select the right codec // however, the buffered provider doesn't know what sample rate it is working at // until we have a frame WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); decompressor = new AcmMp3FrameDecompressor(waveFormat); this.bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat); this.bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(20); // allow us to get well ahead of ourselves //this.bufferedWaveProvider.BufferedDuration = 250; } int decompressed = decompressor.DecompressFrame(frame, buffer, 0); //Debug.WriteLine(String.Format("Decompressed a frame {0}", decompressed)); bufferedWaveProvider.AddSamples(buffer, 0, decompressed); } } while (playbackState != StreamingPlaybackState.Stopped); Debug.WriteLine("Exiting"); // was doing this in a finally block, but for some reason // we are hanging on response stream .Dispose so never get there Dispose(); } } finally { Dispose(); } }
public void CanCreateDmoMp3FrameDecompressor() { Mp3WaveFormat mp3Format = new Mp3WaveFormat(44100,2,215,32000); DmoMp3FrameDecompressor frameDecompressor = new DmoMp3FrameDecompressor(mp3Format); }
/// <summary> /// Opens MP3 from a stream rather than a file /// Will not dispose of this stream itself /// </summary> /// <param name="inputStream"></param> public Mp3FileReader(Stream inputStream) { // Calculated as a double to minimize rounding errors double bitRate; mp3Stream = inputStream; id3v2Tag = Id3v2Tag.ReadTag(mp3Stream); dataStartPosition = mp3Stream.Position; Mp3Frame mp3Frame = Mp3Frame.LoadFromStream(mp3Stream); sampleRate = mp3Frame.SampleRate; frameLengthInBytes = mp3Frame.FrameLength; bitRate = mp3Frame.BitRate; xingHeader = XingHeader.LoadXingHeader(mp3Frame); // If the header exists, we can skip over it when decoding the rest of the file if (xingHeader != null) dataStartPosition = mp3Stream.Position; this.mp3DataLength = mp3Stream.Length - dataStartPosition; // try for an ID3v1 tag as well mp3Stream.Position = mp3Stream.Length - 128; byte[] tag = new byte[128]; mp3Stream.Read(tag, 0, 3); if (tag[0] == 'T' && tag[1] == 'A' && tag[2] == 'G') { id3v1Tag = tag; this.mp3DataLength -= 128; } mp3Stream.Position = dataStartPosition; CreateTableOfContents(); this.tocIndex = 0; // [Bit rate in Kilobits/sec] = [Length in kbits] / [time in seconds] // = [Length in bits ] / [time in milliseconds] // Note: in audio, 1 kilobit = 1000 bits. bitRate = (mp3DataLength * 8.0 / TotalSeconds()); mp3Stream.Position = dataStartPosition; this.Mp3WaveFormat = new Mp3WaveFormat(sampleRate, mp3Frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frameLengthInBytes, (int)bitRate); decompressor = new AcmMp3FrameDecompressor(this.Mp3WaveFormat); // new DmoMp3FrameDecompressor(this.Mp3WaveFormat); this.waveFormat = decompressor.OutputFormat; this.bytesPerSample = (decompressor.OutputFormat.BitsPerSample) / 8 * decompressor.OutputFormat.Channels; // no MP3 frames have more than 1152 samples in them // some MP3s I seem to get double this.decompressBuffer = new byte[1152 * bytesPerSample * 2]; }
private void BufferStream(SongData songData) { var stream = songData.Stream.Value.Item1; var bufferDuration = songData.Stream.Value.Item3; var buffer = new byte[16384 * 4]; var waitTime = 0; var wait = new AutoResetEvent(false); using (var throttledStream = new ThrottledStream(stream)) using (var readFullyStream = new ReadFullyStream(throttledStream)) { IMp3FrameDecompressor decompressor = null; _bufferingComplete = false; do { if (songData.Cts.Token.IsCancellationRequested) { songData.Cts.Token.ThrowIfCancellationRequested(); } wait.WaitOne(waitTime); try { var frame = Mp3Frame.LoadFromStream(readFullyStream); var progress = (int)(readFullyStream.Position / (double)songData.Stream.Value.Item2 * 100); if (progress % 5 == 0) { OnBuffering(new ValueProgressEventArgs<int>(progress, 100)); } if (frame == null) { Trace.WriteLine("Mp3Frame is null"); break; } if (decompressor == null) { var waveFormat = new Mp3WaveFormat( 44100, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); double bufferTimeInSeconds = bufferDuration.TotalSeconds; if (bufferTimeInSeconds.LessThan(60)) { bufferTimeInSeconds = TimeSpan.FromMinutes(2).TotalSeconds; } decompressor = new AcmMp3FrameDecompressor(waveFormat); songData.WaveProvider = new BufferedWaveProvider(decompressor.OutputFormat) { BufferDuration = TimeSpan.FromSeconds(bufferTimeInSeconds), DiscardOnBufferOverflow = true }; // Adjust the maximum bytes to stream per second // This is done to avoid being blacklisted by Grooveshark for several hours throttledStream.MaximumBytesPerSecond = songData.WaveProvider.WaveFormat.AverageBytesPerSecond / 4; } if (songData.WaveProvider != null) { try { int decompressed = decompressor.DecompressFrame(frame, buffer, 0); songData.WaveProvider.AddSamples(buffer, 0, decompressed); if (songData.WaveProvider.BufferLength - songData.WaveProvider.BufferedBytes < songData.WaveProvider.WaveFormat.AverageBytesPerSecond / 4) { Trace.WriteLine("Buffer full. Waiting 500 ms"); waitTime = 500; } } catch (InvalidOperationException e) { Trace.WriteLine(e.Message + ". Wait time is 500ms"); waitTime = 500; } } } catch (Exception e) { Trace.WriteLine(e); break; } } while (_playerState != PlayerState.Stopped); if (decompressor != null) { decompressor.Dispose(); } } _bufferingComplete = true; Trace.WriteLine("Buffer-thread exiting"); }
public bool IsWaveformatEqual(Mp3Frame frame) { //TODO : fix function. somehow it doesn't work 100% ... //hence return false so it always re-inits backend return false; Mp3WaveFormat new_mp3Format = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); if (waveFormat.GetType() != new_mp3Format.GetType()) return false; Mp3WaveFormat CurrentFormat = (Mp3WaveFormat)waveFormat; if( CurrentFormat.SampleRate == new_mp3Format.SampleRate && CurrentFormat.Channels == new_mp3Format.Channels && CurrentFormat.BitsPerSample == new_mp3Format.BitsPerSample && CurrentFormat.AverageBytesPerSecond == new_mp3Format.AverageBytesPerSecond && CurrentFormat.blockSize == new_mp3Format.blockSize && CurrentFormat.ExtraSize == new_mp3Format.ExtraSize) { return true; } else { return false; } }
private void StreamMP3(object state) { this.fullyDownloaded = false; string url = (string)state; webRequest = (HttpWebRequest)WebRequest.Create(url); HttpWebResponse resp = null; try { resp = (HttpWebResponse)webRequest.GetResponse(); } catch(WebException e) { if (e.Status != WebExceptionStatus.RequestCanceled) { ShowError(e.Message); } return; } byte[] buffer = new byte[16384 * 4]; // needs to be big enough to hold a decompressed frame IMp3FrameDecompressor decompressor = null; try { using (var responseStream = resp.GetResponseStream()) { var readFullyStream = new ReadFullyStream(responseStream); do { if (bufferedWaveProvider != null && bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes < bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4) { Debug.WriteLine("Buffer getting full, taking a break"); Thread.Sleep(500); } else { Mp3Frame frame = null; try { frame = Mp3Frame.LoadFromStream(readFullyStream); } catch (EndOfStreamException) { this.fullyDownloaded = true; // reached the end of the MP3 file / stream break; } catch (WebException) { // probably we have aborted download from the GUI thread break; } if (decompressor == null) { // don't think these details matter too much - just help ACM select the right codec // however, the buffered provider doesn't know what sample rate it is working at // until we have a frame WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); decompressor = new AcmMp3FrameDecompressor(waveFormat); this.bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat); this.bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(20); // allow us to get well ahead of ourselves //this.bufferedWaveProvider.BufferedDuration = 250; } int decompressed = decompressor.DecompressFrame(frame, buffer, 0); //Debug.WriteLine(String.Format("Decompressed a frame {0}", decompressed)); bufferedWaveProvider.AddSamples(buffer, 0, decompressed); } } while (playbackState != StreamingPlaybackState.Stopped); Debug.WriteLine("Exiting"); // was doing this in a finally block, but for some reason // we are hanging on response stream .Dispose so never get there decompressor.Dispose(); } } finally { if (decompressor != null) { decompressor.Dispose(); } } }
private void StreamMp3(object state) { _isBuffering(true); ThrottledStream responseStream = (ThrottledStream)state; byte[] buffer = new byte[16384 * 4]; // needs to be big enough to hold a decompressed frame IMp3FrameDecompressor decompressor = null; try { using (responseStream) { _playbackState = StreamingPlaybackState.Buffering; using (var readFullyStream = new ReadFullyStream(responseStream)) { do { if (_bufferedWaveProvider != null && _bufferedWaveProvider.BufferLength - _bufferedWaveProvider.BufferedBytes < _bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4) { Thread.Sleep(500); } Mp3Frame frame; try { frame = Mp3Frame.LoadFromStream(readFullyStream); if (frame == null) { _fullyDownloaded = true; break; } } catch (EndOfStreamException e) { _log.Log(e.Message, Category.Warn, Priority.Medium); _fullyDownloaded = true; // reached the end of the MP3 file / stream break; } catch (WebException e) { _log.Log(e.Message, Category.Warn, Priority.Medium); _fullyDownloaded = true; // probably we have aborted download from the GUI thread break; } catch (Exception e) { _log.Log(e.Message, Category.Exception, Priority.High); _fullyDownloaded = true; break; } if (decompressor == null) { WaveFormat waveFormat = new Mp3WaveFormat(44100, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate); decompressor = new AcmMp3FrameDecompressor(waveFormat); _bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat); if (_track.TotalDuration != TimeSpan.Zero) { _bufferedWaveProvider.BufferDuration = _track.TotalDuration; } else { _bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(25); } responseStream.MaximumBytesPerSecond = _bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4; } if (_bufferedWaveProvider != null) { try { int decompressed = decompressor.DecompressFrame(frame, buffer, 0); _bufferedWaveProvider.AddSamples(buffer, 0, decompressed); } catch (Exception e) { _fullyDownloaded = true; _log.Log("Grooveshark: Error decompressing frame: " + e.Message, Category.Exception, Priority.Medium); break; } } } while (_playbackState != StreamingPlaybackState.Stopped); // was doing this in a finally block, but for some reason // we are hanging on response stream .Dispose so never get there if (decompressor != null) { decompressor.Dispose(); decompressor = null; } } } } finally { if (decompressor != null) { decompressor.Dispose(); decompressor = null; } } _log.Log("Grooveshark: Buffer thread exiting", Category.Info, Priority.Medium); }