acmStreamOpen always fails with MMSYSERR_INVALFLAG Why?

  • Thread starter Thread starter ThunderMusic
  • Start date Start date
T

ThunderMusic

Hi,
I'm trying to use the acm APIs in VB.NET. acmStreamOpen always returns
MMSYSERR_INVALFLAG. Here's how I use it :

declaration is :

Declare Auto Function acmStreamOpen Lib "MsAcm32.dll" (ByRef phas As IntPtr,
ByVal had As Long, ByRef pwfxSrc As MPEGLAYER3WAVEFORMAT, ByRef pm_wfxDst As
WAVEFORMATEX, ByRef pwfltr As Long, ByRef dwCallback As Long, ByRef
dwinstance As Long, ByVal fdwOpen As Int32) As Int32

Used like this :

res = acmStreamOpen(m_has, 0&, m_MP3wfxSrc, m_wfxDst, 0&, 0&, 0&,
ACM_STREAMOPENF_NONREALTIME)

It returns 10, so Invalid Flag... the only specified flag is NonRealtime so
it should work for almost any codec. I'm trying to convert from Mp3 to Wave
(PCM) so I really don't see why it fails. Can someone help me please? I
don't think this is a .NET related error, but I'm posting in .net groups
anyway, in case it does.

Thanks

ThunderMusic
 
ThunderMusic said:
I'm trying to use the acm APIs in VB.NET. acmStreamOpen
always returns MMSYSERR_INVALFLAG. Here's how I use it :

declaration is :

Declare Auto Function acmStreamOpen Lib "MsAcm32.dll"
(ByRef phas As IntPtr, ByVal had As Long, ByRef pwfxSrc
As MPEGLAYER3WAVEFORMAT, ByRef pm_wfxDst As WAVEFORMATEX,
ByRef pwfltr As Long, ByRef dwCallback As Long, ByRef
dwinstance As Long, ByVal fdwOpen As Int32) As Int32
Used like this :

res = acmStreamOpen(m_has, 0&, m_MP3wfxSrc, m_wfxDst, 0&,
0&, 0&, ACM_STREAMOPENF_NONREALTIME)

Try this:

Declare Auto Function acmStreamOpen Lib "MsAcm32.dll"
(ByRef phas As IntPtr,
ByVal had As IntPtr,
ByRef pwfxSrc As MPEGLAYER3WAVEFORMAT,
ByRef pm_wfxDst As WAVEFORMATEX,
ByVal pwfltr As IntPtr,
ByVal dwCallback As IntPtr,
ByVal dwinstance As IntPtr,
ByVal fdwOpen As Int32) As Int32

res = acmStreamOpen(m_has, 0, m_MP3wfxSrc, m_wfxDst,
0, 0, 0, ACM_STREAMOPENF_NONREALTIME)

If it doesn't like 0, use IntPtr.Zero.
 
ThunderMusic said:
I'm trying to use the acm APIs in VB.NET. acmStreamOpen
always returns MMSYSERR_INVALFLAG. Here's how I use it :

declaration is :

Declare Auto Function acmStreamOpen Lib "MsAcm32.dll"
(ByRef phas As IntPtr, ByVal had As Long, ByRef pwfxSrc
As MPEGLAYER3WAVEFORMAT, ByRef pm_wfxDst As WAVEFORMATEX,
ByRef pwfltr As Long, ByRef dwCallback As Long, ByRef
dwinstance As Long, ByVal fdwOpen As Int32) As Int32
Used like this :

res = acmStreamOpen(m_has, 0&, m_MP3wfxSrc, m_wfxDst, 0&,
0&, 0&, ACM_STREAMOPENF_NONREALTIME)

Try this:

Declare Auto Function acmStreamOpen Lib "MsAcm32.dll"
(ByRef phas As IntPtr,
ByVal had As IntPtr,
ByRef pwfxSrc As MPEGLAYER3WAVEFORMAT,
ByRef pm_wfxDst As WAVEFORMATEX,
ByVal pwfltr As IntPtr,
ByVal dwCallback As IntPtr,
ByVal dwinstance As IntPtr,
ByVal fdwOpen As Int32) As Int32

res = acmStreamOpen(m_has, 0, m_MP3wfxSrc, m_wfxDst,
0, 0, 0, ACM_STREAMOPENF_NONREALTIME)

If it doesn't like 0, use IntPtr.Zero.
 
ok, I found the 512 return value means that the conversion is impossible.
The thing is, I'm starting from a mp3 file (96kbps) to a Wave File (44100,
16bits, stereo). Here are the settings I use (I get these with the
acmFormatSuggest Function) :

- m_wfxDst {WAVEFORMATEX} WAVEFORMATEX
cbSize 0 Short
nAvgBytesPerSec 176400 Integer
nBlockAlign 2 Short
nChannels 2 Short
nSamplesPerSec 44100 Integer
wBitsPerSample 16 Short
wFormatTag 1 Short

- m_MP3wfxSrc {MPEGLAYER3WAVEFORMAT} MPEGLAYER3WAVEFORMAT
fdwFlags 0 Integer
nBlockSize 1 Short
nCodecDelay 0 Short
nFramesPerBlock 1 Short
- wfx {WAVEFORMATEX} WAVEFORMATEX
cbSize 12 Short
nAvgBytesPerSec 12000 Integer
nBlockAlign 0 Short
nChannels 2 Short
nSamplesPerSec 44100 Integer
wBitsPerSample 16 Short
wFormatTag 85 Short
wID 1 Short

Everything seems to be right, so I don't understand why I get this error.

Thanks for the help

ThunderMusic
 
"Error 512 - Not Possible" is the random return when you have upset the
Audio Compression Manager genie <g>.

I think that the WAVEFORMAT for the MPeg3 should have some extra bytes
added at the end of its structure. The only information I have for it
is a note in C / Delphi ...

// define MP3 output format
LPMPEGLAYER3WAVEFORMAT mp3format = (LPMPEGLAYER3WAVEFORMAT) LocalAlloc(

LPTR, maxFormatSize );
mp3format->wfx.cbSize = MPEGLAYER3_WFX_EXTRA_BYTES;
mp3format->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3;
mp3format->wfx.nChannels = 2;
mp3format->wfx.nAvgBytesPerSec = 16000;
mp3format->wfx.wBitsPerSample = 0;
mp3format->wfx.nBlockAlign = 1;
mp3format->wfx.nSamplesPerSec = 44100; // 44.1kHz
mp3format->wID = MPEGLAYER3_ID_MPEG; <-thik this is ok
mp3format->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF;
mp3format->nBlockSize = MP3_BLOCK_SIZE; // 417
mp3format->nFramesPerBlock = 1; // MUST BE ONE
mp3format->nCodecDelay = 0; // 0 for LAME or 1393 for fraunh..

// Delphi declaration
TMpegAudioStreamFormat = packed record
wfx:TWavFormat ;
wID:WORD;
fdwFlags:DWORD;
nBlockSize:WORD;
nFramesPerBlock:WORD;
nCodecDelay:WORD;
end;

As you can see the mp3Format includes the WAVEFORMATEX structure and
then adds MPEGLAYER3_WFX_EXTRA_BYTES extra bytes. I don't know what the
value of this constant is, but it looks like 10 4 (DWord) + 6 (Word *
3).

I also think you may also need the Frauenhofer professional codec if
you are doing quality decoding. I had it in a file named I3codecp.exe
(first letter is eye). If you Google for it you may find it. Just run
it and it installs the codec.

To use ACM you must convert at the same sample rate (which you are). If
you want to change sample rate you have to do a three-stage conversion,
firstly to the same sample rate with different formats, then to
different sample rates at the same format. It makes for great fun with
multiple buffers in one line with multiple ACM streams <g>.


Alan Lloyd
 
ok, it works now with the good values in nBlockSize and nBlockAlign.... Now
I have a problem farther in the code (when it comes to allocate the
buffers), but it's strictly a .NET problem, so I will post in .NET groups...

thanks a lot

ThunderMusic
 
LPTR, maxFormatSize );
mp3format->wfx.cbSize = MPEGLAYER3_WFX_EXTRA_BYTES;
mp3format->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3;
mp3format->wfx.nChannels = 2;
mp3format->wfx.nAvgBytesPerSec = 16000;
mp3format->wfx.wBitsPerSample = 0;
mp3format->wfx.nBlockAlign = 1;
mp3format->wfx.nSamplesPerSec = 44100; // 44.1kHz
mp3format->wID = MPEGLAYER3_ID_MPEG; <-thik this is ok
mp3format->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF;
mp3format->nBlockSize = MP3_BLOCK_SIZE; // 417
mp3format->nFramesPerBlock = 1; // MUST BE ONE
mp3format->nCodecDelay = 0; // 0 for LAME or 1393 for
fraunh..

- 1393 as nCodedDelay when using the FhG codec is not
necessary (it works even with 0).

- 417 as nBlockSize is only valid for 44KHz/128Kbps/stereo:
it is the actual MP3 frame size and it depends on the
combination of samplerate/bitrate/channels and
nFramesPerBlock

- nFramesPerBlock should allow other values as long as
nBlockSize is also changed accordingly
As you can see the mp3Format includes the WAVEFORMATEX
structure and then adds MPEGLAYER3_WFX_EXTRA_BYTES extra
bytes. I don't know what the value of this constant is,
but it looks like 10 4 (DWord) + 6 (Word * 3).

From mmreg.h:

#define MPEGLAYER3_WFX_EXTRA_BYTES 12
I also think you may also need the Frauenhofer
professional codec if you are doing quality decoding. I
had it in a file named I3codecp.exe (first letter is
eye). If you Google for it you may find it. Just run it
and it installs the codec.

It is L3CodecP.acm and not I3CodecP.acm (L3 as in Layer3,
that is MP3) and it is also illegal to use without a license
from FhG, which is impossible to get AFAIK. I don't think
there is any difference in quality between the pro codec (P)
and the usual one in Windows (A): the A is simply limited to
a max of 56Kbps/24KHz when encoding, while the P had no
limits.
 
ThunderMusic said:
ok, I found the 512 return value means that the
conversion is impossible. The thing is, I'm starting from
a mp3 file (96kbps) to a Wave File (44100, 16bits,
stereo). Here are the settings I use (I get these with
the acmFormatSuggest Function) :
- m_wfxDst {WAVEFORMATEX} WAVEFORMATEX
cbSize 0 Short
nAvgBytesPerSec 176400 Integer
nBlockAlign 2 Short
nChannels 2 Short
nSamplesPerSec 44100 Integer
wBitsPerSample 16 Short
wFormatTag 1 Short

Are you really sure you got this from acmFormatSuggest()?
With WAVE_FORMAT_PCM audio nBlockAlign must be
nChannels*wBitsPerSample/8, that is 4 and not 2.
- m_MP3wfxSrc {MPEGLAYER3WAVEFORMAT} MPEGLAYER3WAVEFORMAT
fdwFlags 0 Integer
nBlockSize 1 Short
nCodecDelay 0 Short
nFramesPerBlock 1 Short
- wfx {WAVEFORMATEX} WAVEFORMATEX
cbSize 12 Short
nAvgBytesPerSec 12000 Integer
nBlockAlign 0 Short
nChannels 2 Short
nSamplesPerSec 44100 Integer
wBitsPerSample 16 Short
wFormatTag 85 Short
wID 1 Short

Same as before, acmFormatSuggest() filled this in?
nBlockAlign is supposed to be 1 for WAVE_FORMAT_MPEGLAYER3
and nBlockSize is supposed to be the MP3 frame size, which
is always greater than 1 (313 for 44KHz/96Kbps/stereo).
nCodecDelay should be 1393 when using the system's FhG codec
(but it should work with 0 as well).
 
#define MPEGLAYER3_WFX_EXTRA_BYTES 12

OK, but the Delphi structure shows 10, and interrogating
the driver with ACM gives 14 <g>

On another site the extra bytes were commented with "Void as every
frame of an MPEG file has the information which would be contained in
the extra bytes" - is this true ?
It is L3CodecP.acm and not I3CodecP.acm (L3 as in Layer3,
that is MP3)

My file is I3CodecP.acm (I for India) and that is how I downloaded it.
I don't know if it _is_ Frauenhofer's although that is how it is
labelled with an ACM call. When I got it (some years ago associated
with an article) I emailed Frauenhofer because I suspected it _might_
be pirated. They did not even reply so I assumed that they did not
care.

Alan Lloyd
 
OK, but the Delphi structure shows 10, and interrogating
the driver with ACM gives 14 <g>

The Delphi definition is wrong and your ACM codec is not
compliant with the official definition of WAVEFORMATEX for
WAVE_FORMAT_MPEGLAYER3 given in the ACM registry, that is
mmreg.h. The original FhG codec and LAME are compliant and
so are other codecs. Besides, the structure should be DWORD
aligned (even if it is not an absolute requirement) and both
10 and 14 are not.
On another site the extra bytes were commented with "Void
as every frame of an MPEG file has the information which
would be contained in the extra bytes" - is this true ?

More or less.

- wID
not present in the header (and not necessary?)
- fdwFlags
padding; a bit in the header
- nBlockSize
not present in the header but implied by other bitfields
- nFramesPerBlock
not present in the header (and not necessary?)
- nCodecDelay
not present in the header (and not necessary?)
My file is I3CodecP.acm (I for India) and that is how I
downloaded it. I don't know if it _is_ Frauenhofer's
although that is how it is labelled with an ACM call.

If it's not a lower-case L (l), then I really doubt it's the
original FhG codec or, at least, they changed the name of
the file.
 
Alessandro said:
OK, but the Delphi structure shows 10, and interrogating
the driver with ACM gives 14 <g>

The Delphi definition is wrong [...]

On second thought, the Delphi definition you posted is
correct and reserves 12 bytes, not 10.
 
Alessandro said:
OK, but the Delphi structure shows 10, and interrogating
the driver with ACM gives 14 <g>

The Delphi definition is wrong [...]

On second thought, the Delphi definition you posted is
correct and reserves 12 bytes, not 10.
 
mp3format->nBlockSize = MP3_BLOCK_SIZE; // 417
- 417 as nBlockSize is only valid for 44KHz/128Kbps/stereo:
it is the actual MP3 frame size and it depends on the
combination of samplerate/bitrate/channels and
nFramesPerBlock

Do you know the relationship betwee nBlockSize and nSamplesPerSec /
bitrate / nChannels / nFramesPerBlock ?

Alan Lloyd
 
Back
Top