Alaw <-> Pcm Conversion & MixingStream32 or MixingStream16

Mar 28, 2011 at 12:52 PM

Hello,

I like to use a WaveFormatConversionStream in two directions, 8bit aLaw <-> 16bit Pcm.

After converting the aLaw data to Pcm data, the resulting stream has to be added to a WaveMixerStream to mix the pcm bytes.

The mixed pcm bytes than have to be reconverted again back to 8 bit alaw.

At the moment only WaveMixerStream32 in NAudio exists in the default VS solution, but I had no luck yet to get alaw converted into 32bit IeeeFloat.

I also recognized the Wave32To16Stream, but anyway the puzzle is not solved. The stream conversion from 16bit Pcm to IeeeFloat Pcm always throws an AcmNotPossible exception.

I always stuck in the conversion streaming.

Is it possible to convert 16bit Pcm into IeeeFloat for mixing it with standard WaveMixerStream32, or do I have to implement my own WaveMixerStream16?

And how would such a WaveMixerStream16 implementation mix the bytes without floating points? Do you know an algorithm function for this, something like ( Sum16BitAudio() )?

Or how could such a WaveMixerStream16 be used to convert the 16 bit stream into a 32bit Ieeefloat stream and vice versa?

Could you please help me to get this solved?

Any help would be gratefully appreciated.

Thank you in advance.

Micha.

 

 

Coordinator
Mar 30, 2011 at 9:20 AM

look at WaveChannel32 which convers 16 bit PCM into IEEEFloat.

Mixing directly in 16 bit is more awkward because you have no headroom, and risk arithmetic overflows.

Mark

May 3, 2011 at 10:07 AM

Thank your for the advice.

And sorry, my answer is a bit late. I had no time to test this yet.

The waveChannel32 seems to work. But the back conversion doesn't.

For the input conversion I build a WaveAlawTo32Stream. It doesn't throw a AcmNotPossible exception.

Here is the code:

        public WaveAlawTo32Stream()
        {
            m_OutputWaveFormat =  WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, 8000, 1, 16000, 2, 16);
            m_InputWaveFormat = WaveFormat.CreateALawFormat(8000, 1);
            m_waveFormat = m_InputWaveFormat;

            m_ConversionStream = new WaveFormatConversionStream(m_OutputWaveFormat, m_AlawWaveStream);
            m_WaveChannel32 = new WaveChannel32(m_ConversionStream);
        }

So I thought I could build something like a Wave32ToAlawStream. But this doesn't work yet. Here is the not yet working code which throws an "AcmNotPossible calling acmStreamOpen" exception:

        public Wave32ToAlawStream(int sampleRate)
        {
            m_OutputWaveFormat = WaveFormat.CreateALawFormat(8000, 1);
            m_InputWaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, 2);
            m_waveFormat = m_InputWaveFormat;

            m_InputStream = new WaveStreamMemory(m_InputWaveFormat);
            m_Wave32To16Stream = new Wave32To16Stream(m_InputStream);

            m_OutputStream = new WaveFormatConversionStream(m_OutputWaveFormat, m_Wave32To16Stream);
          
        }
The sample Rate is 8000 too.
So my question is, why does the WaveFormatConversionStream throw a AcmnotPossible exception and how can I fix this.
When debugging the delivered waveFormats are:
 
Debugging Line: "conversionStream = new AcmStream(sourceStream.WaveFormat, targetFormat);"
 
sourceStream.WaveFormat:
averageBytesPerSecond = 32000
BitsPerSample         = 16
BlockAlign            = 4
Channels              = 2
Encoding              = Pcm
SampleRate            = 8000
 
targetFormat:
averageBytesPerSecond = 8000
BitsPerSample         = 8
BlockAlign            = 1
Channels              = 1
Encoding              = ALaw
SampleRate            = 8000
 
  
Thank you very much for helping me.
 
Best regards,
 
Micha
 
       

 



 

Coordinator
May 3, 2011 at 10:23 AM

AcmNotPossible exception either means you have no encoder for Alaw (unlikely since I think most Windows installs have one) or that it doesn't like your source format. I suspect it is that you are trying to go from stereo to mono in one step. Try encoding to stereo alaw, or having two encoder streams one for left and one for right

Mark

May 3, 2011 at 11:44 AM

I found out, that it is a mono/stereo problem.

Maybe Acm doesn't support stereo -> mono conversion?

Can you provide an example how "IeeeFloat stereo" -> "ALaw mono" conversion could be done?

I only need one of the two channels and not the mono mix. This should be not so complicated i think.

Thank you very much for your help,

Micha.

 

May 3, 2011 at 11:47 AM
Edited May 3, 2011 at 12:03 PM

Oh,

I send the reply before reading yours. :-)

So it is a  stereo -> mono  problem.

How to get only left or right enocder stream out of a stereo stream?

To be more precisely. How can I extract one of the two mono channels of a IeeeFloat 32 stereo stream?

 By the way: stereo Alaw seems not to be supported. Isn't Alaw mono in any case?

Coordinator
May 3, 2011 at 12:01 PM

To make a stereo float stream mono, read four bytes (i.e. one sample), then throw away four bytes, etc. Have a look at the StereoToMonoWaveProvider included with NAudio for a more complete example.

May 3, 2011 at 12:13 PM

Thank you, this helps a lot.

Best regards.

Feb 14, 2014 at 9:12 AM
Hi

I have the same problem and wrote these lines of code acoording to this discussion,
    WaveFileReader r1 = new WaveFileReader(...);
    WaveFileReader r2 = new WaveFileReader(...);

    WaveFormat OutputWaveFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, 8000, 1, 16000, 2, 16);
    WaveFormat InputWaveFormat = WaveFormat.CreateALawFormat(8000, 1);

    WaveFormatConversionStream ConversionStream1 = new WaveFormatConversionStream(OutputWaveFormat, r1);
    WaveFormatConversionStream ConversionStream2 = new WaveFormatConversionStream(OutputWaveFormat, r2);

    WaveChannel32 WaveChannel32_1 = new WaveChannel32(ConversionStream1);
    WaveChannel32 WaveChannel32_2 = new WaveChannel32(ConversionStream2);

    WaveMixerStream32 mixer32 = new WaveMixerStream32();
    mixer32.AddInputStream(WaveChannel32_1);
(*) mixer32.AddInputStream(WaveChannel32_2);
    Wave32To16Stream stereo16 = new Wave32To16Stream(mixer32);        
after line (*) I have data in this sequence : 0 0 32 60 0 0 32 60 0 0 59 126 0 0 59 126 ...
but after applying Wave32To16Stream, I have a sequence of just zeros in stereo16!!
what should I do in this step?
after that, how can I converte stereo16 to mono16 and mono16 to monoA-Law?
Coordinator
Feb 17, 2014 at 2:57 PM
the best way to troubleshoot issues like this is to write to Wave file at different points in your stream. So for example, write ConversionStream1 to WAV and see if that sounds OK.

Also, you don't need to use CreateCustomFormat to create a PCM waveformat. Just use new WaveFormat(8000,1);