/// <summary>
		/// Decompress a single frame of MP3
		/// </summary>
		public int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset)
		{
			// 1. copy into our DMO's input buffer
			inputMediaBuffer.LoadData(frame.RawData, frame.FrameLength);

			// 2. Give the input buffer to the DMO to process
			mp3Decoder.MediaObject.ProcessInput(0, inputMediaBuffer, DmoInputDataBufferFlags.None, 0, 0);

			outputBuffer.MediaBuffer.SetLength(0);
			outputBuffer.StatusFlags = DmoOutputDataBufferFlags.None;

			// 3. Now ask the DMO for some output data
			mp3Decoder.MediaObject.ProcessOutput(DmoProcessOutputFlags.None, 1, new[] {outputBuffer});

			if (outputBuffer.Length == 0)
			{
				Debug.WriteLine("ResamplerDmoStream.Read: No output data available");
				return 0;
			}

			// 5. Now get the data out of the output buffer
			outputBuffer.RetrieveData(dest, destOffset);
			Debug.Assert(!outputBuffer.MoreDataAvailable, "have not implemented more data available yet");

			return outputBuffer.Length;
		}
		public int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset)
		{
			Array.Copy(frame.RawData, conversionStream.SourceBuffer, frame.FrameLength);
			int sourceBytesConverted = 0;
			int converted = conversionStream.Convert(frame.FrameLength, out sourceBytesConverted);
			if (sourceBytesConverted != frame.FrameLength)
			{
				throw new InvalidOperationException("Couldn't convert the whole MP3 frame");
			}
			Array.Copy(conversionStream.DestBuffer, 0, dest, destOffset, converted);
			return converted;
		}
示例#3
0
		/// <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;
			var mp3Frame = new Mp3Frame(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;

			mp3DataLength = mp3Stream.Length - dataStartPosition;

			// try for an ID3v1 tag as well
			mp3Stream.Position = mp3Stream.Length - 128;
			var tag = new byte[128];
			mp3Stream.Read(tag, 0, 3);
			if (tag[0] == 'T' && tag[1] == 'A' && tag[2] == 'G')
			{
				id3v1Tag = tag;
				mp3DataLength -= 128;
			}

			mp3Stream.Position = dataStartPosition;

			CreateTableOfContents();
			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;

			Mp3WaveFormat = new Mp3WaveFormat(sampleRate, mp3Frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frameLengthInBytes,
			                                  (int) bitRate);
			decompressor = new AcmMp3FrameDecompressor(Mp3WaveFormat); // new DmoMp3FrameDecompressor(this.Mp3WaveFormat); 
			waveFormat = decompressor.OutputFormat;
			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
			decompressBuffer = new byte[1152*bytesPerSample*2];
		}
示例#4
0
		/// <summary>
		/// Reads the next mp3 frame
		/// </summary>
		/// <returns>Next mp3 frame, or null if EOF</returns>
		public Mp3Frame ReadNextFrame(bool readData)
		{
			if (mp3Stream.Position + frameLengthInBytes <= mp3DataLength + dataStartPosition)
			{
				var frame = new Mp3Frame(mp3Stream, readData);
				tocIndex++;
				return frame;
			}
			return null;
		}
示例#5
0
		/// <summary>
		/// Load Xing Header
		/// </summary>
		/// <param name="frame">Frame</param>
		/// <returns>Xing Header</returns>
		public static XingHeader LoadXingHeader(Mp3Frame frame)
		{
			var xingHeader = new XingHeader();
			xingHeader.frame = frame;
			int offset = 0;

			if (frame.MpegVersion == MpegVersion.Version1)
			{
				if (frame.ChannelMode != ChannelMode.Mono)
					offset = 32 + 4;
				else
					offset = 17 + 4;
			}
			else if (frame.MpegVersion == MpegVersion.Version2)
			{
				if (frame.ChannelMode != ChannelMode.Mono)
					offset = 17 + 4;
				else
					offset = 9 + 4;
			}
			else
			{
				return null;
				// throw new FormatException("Unsupported MPEG Version");
			}

			if ((frame.RawData[offset + 0] == 'X') &&
			    (frame.RawData[offset + 1] == 'i') &&
			    (frame.RawData[offset + 2] == 'n') &&
			    (frame.RawData[offset + 3] == 'g'))
			{
				xingHeader.startOffset = offset;
				offset += 4;
			}
			else
			{
				return null;
			}

			var flags = (XingHeaderOptions) ReadBigEndian(frame.RawData, offset);
			offset += 4;

			if ((flags & XingHeaderOptions.Frames) != 0)
			{
				xingHeader.framesOffset = offset;
				offset += 4;
			}
			if ((flags & XingHeaderOptions.Bytes) != 0)
			{
				xingHeader.bytesOffset = offset;
				offset += 4;
			}
			if ((flags & XingHeaderOptions.Toc) != 0)
			{
				xingHeader.tocOffset = offset;
				offset += 100;
			}
			if ((flags & XingHeaderOptions.VbrScale) != 0)
			{
				xingHeader.vbrScale = ReadBigEndian(frame.RawData, offset);
				offset += 4;
			}
			xingHeader.endOffset = offset;
			return xingHeader;
		}