views:

141

answers:

3

Is there a way, either within the Framework or by using P/Invoke to determine the duration of a wav file that's held in a MemoryStream?

I've already had a look at Managed DirectX and another similar question, but everything seems to work with paths, rather than providing any way to pass in a stream. One of the links in the question I've referenced (A simple C# Wave editor....) makes it fairly clear that I could parse the MemoryStream to determine the duration of the wav file. Ideally I'd like to not re-invent the wheel.

A: 

Try following calculation

streamSize == headerSizeIfAny + playTime * sampling * singleSampleSize ->

playTime = ( streamSize[in bytes] - headerSizeIfAny ) / ( sampling [samples per second] * singleSampleSize[bytes])

piotrfe
@piotrfe, the calculation is utterly useless to me unless I have the file parsed. As I've made fairly clear though, I'd rather `not re-invent the wheel.`. In fact, for my purposes, writing code to parse wav files is a non-starter.
Rob
@Rob: This calculation should work without any parsing, the bitrate of files has to be accessible without reading the wav itself I'm pretty sure as windows explorer can tell me the bitrate. I think you might be able to p/invoke the file properties to dig this up, maybe without p/invoke even... 500k file, no header, has 100k bitrate and that's a rate per second = 5 seconds.
Jimmy Hoffa
@Jimmy, sorry, really not what I'm after. I don't want to do *any* calculation no matter how simplistic. I'm after something I can give a memory stream to and it'll tell me the duration of the wav inside it. Calculating the duration of audio files isn't what my code's about so I'm not about to start =) As it stands, Explorer (Win7 anyway) tells me the duration, as well as the bitrate, making bitrate even more useless to me ;-)
Rob
A: 

try the NAudio library, there is a bunch of api to do what you need

Alex
A: 

Check this out:

http://www.sonicspot.com/guide/wavefiles.html

and this

typedef struct {
  WORD wFormatTag; 
  WORD nChannels; 
  DWORD nSamplesPerSec; 
  DWORD nAvgBytesPerSec; 
  WORD nBlockAlign; 
  WORD wBitsPerSample; 
  WORD cbSize;} WAVEFORMATEX; 

So you have your memorystream... Seek to 0x10 (to skip Riff header) + 0x08 (for format header) = 24

And you are in the structure above.

Use stream.ReadInt16() and stream.ReadInt32() to read wanted structure members.

Then, seek to 54, read one DWORD, and that many bytes is your sample data.

Then figure out your duration from this variables.

NOTE: that will work for ONLY THE SIMPLEST PCM wave files stored in your memorystream. For others, you'll have to honor headers and properly parse them, finding the data chunk and calculating duration according to it's size.

Daniel Mošmondor