Re: DirectX mp3 decoding

311 views
Skip to first unread message

Alessandro Angeli [MVP::DigitalMedia]

unread,
Apr 11, 2005, 1:49:55 PM4/11/05
to
S Matos wrote:

> Hi
> I need to decode large MP3 file to WAV format. At the
> same time I want to break this file into 10sec chunks. I
> was thinking of using DirectShow filters, but it seems I
> can only output in PCM format (8, 11, 22, or 44kHz sample
> rates) and I want to keep the original sample rate
> (16kHz).
> Is there a simple way of doing this?

Neither the MP3 decoder nor the WAV muxer will change the
sample rate in DirectShow. However, since changing output
file while the graph is running is not trivial, decoding the
MP3 yourself using an ACM decoder (like the l3codeca.acm,
which is default used by DirectShow) and writing the WAVs
would be easier and more efficient. Consider that an MP3
file is a raw MP3 stream you can directly feed to the
decoder, ACM codecs are easy to use and documented in the
Platform SDK and WAV files are very simple, practically raw
streams with a prefixed header which is little more than the
WAVEFORMATEX (look on www.wotsit.org for a description of
the WAV header).

--

// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net


Alessandro Angeli [MVP::DigitalMedia]

unread,
Apr 12, 2005, 1:54:06 PM4/12/05
to
S Matos wrote:

> Thanks for the reply
> I would actually prefer to decode the file using an acm
> decoder... but still don't know how to do it. Can you
> refer me to information on how to use a codec for
> decoding (or give me the direct answer...)?
> I need to be able to select the bit of the file that I
> want and convert that to a WAV that I can then read.

- MP3 frame header info:

http://www.google.it/groups?selm=O3T9AVDdBHA.2416%40tkmsftngp05

- my sample MP3 parser (the full tables are listed in the
docs referenced above):

http://www.google.it/groups?selm=eJti8FKxDHA.2448%40TK2MSFTNGP12.phx.gbl

- my ACM instructions:

http://groups-beta.google.com/group/microsoft.public.win32.programmer.mmedia/msg/d0faa0f66850b9ce

Since you need to perform MP3->PCM, you need to reverse the
input and output WAVEFORMATEX structures.

For the input, populate an MPEGLAYER3WAVEFORMAT with info
from the first MP3 frame header.

MPEGLAYER3WAVEFORMAT.wfx.wForm­atTag
= WAVE_FORMAT_MPEGLAYER3;
MPEGLAYER3WAVEFORMAT.wfx.nChan­nels
= mode == 3 ? 1 : 2;
MPEGLAYER3WAVEFORMAT.wfx.nSamp­lesPerSec
= ...; /// from sampling_freq and version
MPEGLAYER3WAVEFORMAT.wfx.nAvgB­ytesPerSec
= ...; /// from bitrate_index, version and layer, then
divide by 8
MPEGLAYER3WAVEFORMAT.wfx.nBloc­kAlign
= 1;
MPEGLAYER3WAVEFORMAT.wfx.wBits­PerSample
= 0;
MPEGLAYER3WAVEFORMAT.wfx.cbSiz­e
= MPEGLAYER3_WFX_EXTRA_BYTES;
MPEGLAYER3WAVEFORMAT.wID
= MPEGLAYER3_ID_MPEG;
MPEGLAYER3WAVEFORMAT.fdwFlags
= MPEGLAYER3_FLAG_PADDING_OFF;
MPEGLAYER3WAVEFORMAT.nBlockSiz­e
= ...; /// the frame size
MPEGLAYER3WAVEFORMAT.nFramesPe­rBlock
= 1;
MPEGLAYER3WAVEFORMAT.nCodecDel­ay
= 1393;

For the output, populate a WAVEFORMATEX that uses the same
nChannels and nSamplesPerSec of the MPEGLAYER3WAVEFORMAT and
16 wBitsPerSample; you can calculate the rest.

WAVEFORMATEX.wForm­atTag
= WAVE_FORMAT_PCM;
WAVEFORMATEX.nChan­nels
= mp3.wfx.nChannels;
WAVEFORMATEX.nSamp­lesPerSec
= mp3.wfx.nSamplesPerSec;
WAVEFORMATEX.nAvgB­ytesPerSec
= nSamp­lesPerSec * nChannels * wBits­PerSample / 8;
WAVEFORMATEX.nBloc­kAlign
=nAvgB­ytesPerSec / nSamp­lesPerSec;
WAVEFORMATEX.wBits­PerSample
= 16;
WAVEFORMATEX.cbSiz­e
= 0;

My ACM instructions use the FhG MP3 codec that ships in
Windows. If you use the LAME codec,
MPEGLAYER3WAVEFORMAT.nCodecDel­ay should be 0. If you use
the LAME codec and the MP3 streams use LAME's ABR mode, I
think you should sum 2 to MPEGLAYER3WAVEFORMAT.fdwFlags; I
don't know about VBR mode.

You need to cut the MP3 on frame boundaries, so you need to
read it using a parser (see my sample parser) and not as a
flat byte stream.

Alessandro Angeli [MVP::DigitalMedia]

unread,
Apr 12, 2005, 1:57:32 PM4/12/05
to
[I forgot something.]

S Matos wrote:

> Thanks for the reply
> I would actually prefer to decode the file using an acm
> decoder... but still don't know how to do it. Can you
> refer me to information on how to use a codec for
> decoding (or give me the direct answer...)?
> I need to be able to select the bit of the file that I
> want and convert that to a WAV that I can then read.

- MP3 frame header info:

http://www.google.it/groups?selm=O3T9AVDdBHA.2416%40tkmsftngp05

- my sample MP3 parser (the full tables are listed in the
docs referenced above):

http://www.google.it/groups?selm=eJti8FKxDHA.2448%40TK2MSFTNGP12.phx.gbl

- my ACM instructions:

http://groups-beta.google.com/group/microsoft.public.win32.programmer.mmedia/msg/d0faa0f66850b9ce

- WAV format info:

http://www.wotsit.org/download.asp?f=wave

(Notice that a WAV is just a raw stream with a prefixed
header and that the format chunk in this header is just a
WAVEFORMATEX structure.)

S Matos

unread,
Apr 13, 2005, 6:44:02 AM4/13/05
to
Grazie Alessandro
This will surely help.

S Matos

unread,
Apr 15, 2005, 1:46:04 PM4/15/05
to
Hello again
I'm able to read (parse) the mp3 stream, and the Wav format is not a problem.
I'm now trying to implement the acm decoding, but I'm stuck rigth in the
beginning.
The last parameter of the function OpenDriver() is defined as:

"lParam - 32-bit driver-specific value. This value is passed as the lParam2
parameter to the DriverProc function of the installable driver. "

But I can't find this information anywhere. Could you point me in the right
direction (again)?

TIA
Sergio

Alessandro Angeli [MVP::DigitalMedia]

unread,
Apr 18, 2005, 12:01:08 AM4/18/05
to
S Matos wrote:

0L should be ok.

Reply all
Reply to author
Forward
0 new messages