Ima Adpcm Error during Compression

Mar 10, 2012 at 1:54 PM

Can you please reply as early as possible for my Ima Adpcm Error which i already posted .......

Coordinator
Mar 10, 2012 at 1:56 PM

where did you post the error?

Mar 12, 2012 at 5:12 AM

Hi,

i am using following Wave Format for recoding a audio file.

waveIn =

New WaveIn ()

waveIn.WaveFormat =New WaveFormat (8000, 1)

inputformat = waveIn.WaveFormat

Now,i need to Encode/Compress these recorded audio file into Ima Adpcm Format.And,I also seen the discussion about this issue in your forum.There you said,

"Simply add a short in there. Extra size means how many extra bytes there are on top of the original WaveFormat structure. You need a variable to hold that data (a short because you have two extra bytes). And you should also set the contents of that extra data according to the specification of the specific WaveFormatTag you are using"

private class MyWaveFormat:WaveFormat
{
short extraData;

public MyWaveFormat(WaveFormatEncoding WaveFormatTag, short BitsPerSample, short Channels, int AverageBytesPerSecond, short BlockAlign, int SampleRate, short ExtraSize)
{
base.extraSize = ExtraSize;
base.averageBytesPerSecond = AverageBytesPerSecond;
base.bitsPerSample = BitsPerSample;
base.blockAlign = BlockAlign;
base.channels = Channels;
base.sampleRate = SampleRate;
base.waveFormatTag = WaveFormatTag;
}
}

But i am not getting how to set  contents "ExtraData" corresponding to Extra Size.

I also tried  to set Extrqa Data using following Methods,but still i am getting the Same Error ""AcmNotPossible Calling the AcmStreamOpen""

ptr=Waveformat.MarshalToPtr (inputformat)

TargetFormat=waveformat.MarshalFromPtr(ptr)

Can you Please guide me About this problem  as early as possible.

Regards,

Chandan k.s

 

 

 

Mar 12, 2012 at 11:30 AM

Hi,

Whether it is possible to play a Encoded file using ... following method directly?

 PlayOutputFile.Play()

Mar 12, 2012 at 3:35 PM

Hi,

Even though i installed LameAcm on my system,its not listing in the Format Combo box 

Coordinator
Mar 12, 2012 at 11:23 PM

No, NAudio does not allow you to play compressed audio directly. I don't know why your LAME Acm is not showing up. Are you sure it installed correctly?

Mar 13, 2012 at 5:29 AM

 

Hi,

i am using following Wave Format for recoding a audio file.

 

waveIn =New WaveIn () 

waveIn.WaveFormat =New WaveFormat (8000, 1)

inputformat = waveIn.WaveFormat

 

Now,i need to Encode/Compress these recorded audio file into Ima Adpcm Format.And,I also seen the discussion about this issue in your forum.There you said,

"Simply add a short in there. Extra size means how many extra bytes there are on top of the original WaveFormat structure. You need a variable to hold that data (a short because you have two extra bytes). And you should also set the contents of that extra data according to the specification of the specific WaveFormatTag you are using"

private class MyWaveFormat:WaveFormat
{
short extraData;

public MyWaveFormat(WaveFormatEncoding WaveFormatTag, short BitsPerSample, short Channels, int AverageBytesPerSecond, short BlockAlign, int SampleRate, short ExtraSize)
{
base.extraSize = ExtraSize;
base.averageBytesPerSecond = AverageBytesPerSecond;
base.bitsPerSample = BitsPerSample;
base.blockAlign = BlockAlign;
base.channels = Channels;
base.sampleRate = SampleRate;
base.waveFormatTag = WaveFormatTag;
}
}

But i am not getting how to set  contents "ExtraData" corresponding to Extra Size.

I also tried  to set ""ExtraData"" using following Methods,but still i am getting the Same Error ""AcmNotPossible Calling the AcmStreamOpen""

ptr=Waveformat.MarshalToPtr (inputformat)

TargetFormat=waveformat.MarshalFromPtr(ptr)

Can you Please guide me About this problem  as early as possible.

Regards,

Chandan k.s

 

Coordinator
Mar 13, 2012 at 8:43 AM

Look here at the WAVE_FORMAT_DVI_ADPCM structure definition. You'll need to find appropriate values for the wSamplesPerBlock value, but you can do that by examining the extra bytes reported by the NAudioDemo ACM screen for the IMA ADPCM codec

Mar 13, 2012 at 10:04 AM

How i need to make use of those extra bytes...? . Also,CreateCustomWaveFormat() wont woks for this Ima Adpcm WaveFormat,So which method i need to use for Ima Adpcm  Encoding...?

Mar 13, 2012 at 1:33 PM

 I tried in this way by creating  My_ImaAdpcmWaveFormat method Ima Adpcm class,and i am passing that Extra Byte value,since Extra Byte in Hexadecimal,i converted that to Decimal,then passed to these Function.

public My_ImaAdpcmWaveFormat(int sampleRate, int channels, int bitsPerSample,int sampleperblock)     

  {       

       this.waveFormatTag = WaveFormatEncoding.DviAdpcm; // can also be ImaAdpcm - they are the same         

       this.sampleRate = sampleRate;       

       this.channels = (short)channels;

       this.bitsPerSample = (short)bitsPerSample; // TODO: can be 3 or 4   

       this.extraSize = 2;//    

       this.blockAlign = 0; //TODO    //Also i tried for blockalign and avgbytespersecond also i assigned values 

        this.averageBytesPerSecond = 0; //TODO       

        this.samplesPerBlock = short(sampleperblock);                

}

Then,when i excecute following line,

convertedStream=NewWaveFormatConversionStream(NewImaAdpcmWaveFormat(InputFormat.SampleRate,InputFormat.Channels,InputFormat.bitspersample,63745), Reader)                  

Getting the same error ""AcmNotPossible Calling the AcmStreamOpen"".So " How i need to make use of those extra bytes...?"

Coordinator
Mar 13, 2012 at 1:43 PM

you need to look very carefully at the values returned in the NAudioDemo application. This shows what the ACM codec is expecting from a WaveFormat. The WaveFormat you pass in must be exactly the same.

Mar 14, 2012 at 5:47 AM

Ya,i tried the way you said.but still i am getting the same error .

public  ImaAdpcmWaveFormat(int sampleRate, int channels, int bitsPerSample,int sperblock) 

      {     

         this.waveFormatTag = WaveFormatEncoding.DviAdpcm; // can also be ImaAdpcm - they are the same 

          this.sampleRate = sampleRate; 

          this.channels = (short)channels; 

          this.bitsPerSample = (short)bitsPerSample; // TODO: can be 3 or 4   

          this.extraSize = 2;//    

          this.blockAlign = 256; //TODO       

          this.averageBytesPerSecond = 4055; //TODO     

          this.samplesPerBlock = (short)sperblock; // TODO                   

}

Above values which i am assigning are same as  NaudioDemo Application values.

   Format 0: 8.000 kHz, 4 Bit, Mono      FormatTag: DviAdpcm, Support Flags: Codec      WaveFormat: DviAdpcm 8000Hz Channels: 1 Bits: 4 Block Align: 256,     AverageBytesPerSecond: 4055 (32.4 kbps), Extra Size: 2      Extra Bytes:      F9 01 

In my code i wrote like this,

 convertedStream = New WaveFormatConversionStream(New ImaAdpcmWaveFormat(8000, 1, 4, 2048), Reader)                     WaveFileWriter.CreateWaveFile(CurrentFile, convertedStream)

Since Extra Bytes in Hexa Decimal,i converted it into Decimal.

Mar 14, 2012 at 7:18 AM

Like this way also i tried..... 63745 is the Decimal value of Extra Byte:F901 


 TargetFormat = ImaAdpcmWaveFormat.MyImaAdpcmWaveFormat(8000, 1, 4, 63745)

convertedStream = New WaveFormatConversionStream(TargetFormat, Reader)

public static ImaAdpcmWaveFormat MyImaAdpcmWaveFormat(int sampleRate, int channels, int bitsPerSample, float sperblock)   

    {

          ImaAdpcmWaveFormat ImaAdpcmWformat = new ImaAdpcmWaveFormat();

          ImaAdpcmWformat.waveFormatTag = WaveFormatEncoding.DviAdpcm; // can also be ImaAdpcm - they are the same   

        ImaAdpcmWformat.sampleRate = sampleRate;   

        ImaAdpcmWformat.channels = (short)channels;   

        ImaAdpcmWformat.bitsPerSample = (short)bitsPerSample; // TODO: can be 3 or 4       

       ImaAdpcmWformat.extraSize = 2;//          

       ImaAdpcmWformat.blockAlign = 256; //TODO       

      ImaAdpcmWformat.averageBytesPerSecond = 4055; //TODO       

      ImaAdpcmWformat.samplesPerBlock = (short)sperblock; // TODO           

   return ImaAdpcmWformat;       

}

Same error i am getting.

Coordinator
Mar 14, 2012 at 8:13 AM

I think you must be getting close now. Try 505 as the samplesPerBlock value (intel byte order is the other way round so this is 0x01F9)

Also, make sure that the thing you are converting is 8kHz, mono, 16 bit PCM, since ACM codecs do not usually support changing sample rates or number of channels.

Mark

Mar 14, 2012 at 8:15 AM

Also i converted "F9" and "01" separately to Decimal ,Then i got the value "249" & "01".

now i assigned "249" & "01"  to SamplesPerBlock.

but same error.

Coordinator
Mar 14, 2012 at 8:19 AM

Your class should have a single private variable of type short. Set it to 505.

Mar 14, 2012 at 10:07 AM

Ya ,now its Encoding,but when i try to play the Encoded Audio File using " System.Diagnostics.Process.Start(outputFileName)",i am getting the error stating that

"Windows Media Player encountered a problem while playing the file"

and i tried using following steps to play the Encoded Audio,but getting the error  "Invalid WAV file - No data chunk found" .

           wavePlayer = New WaveOut()   

            FileRdr = New AudioFileReader(CurrentFile)       

           wavePlayer.Init(FileRdr)         

          wavePlayer.Play()

And above Stpes are working fine for all other Encoded Wave Format Audio Files.

Please reply as early as possible.

Regards ,

chandan.ks

Coordinator
Mar 14, 2012 at 10:28 AM

what is the code you are using to create the WAV file?

Mar 14, 2012 at 10:39 AM
Edited Mar 14, 2012 at 10:48 AM

 waveIn = New WaveIn()

waveIn.WaveFormat = New WaveFormat(8000, 16, 1)

 writer = New WaveFileWriter(CurrentFile, waveIn.WaveFormat)

where currentfile contains newly cretaed file path.

Also Event Handler i added followed by above lines.

 AddHandler waveIn.DataAvailable, AddressOf waveIn_DataAvailable   

 AddHandler waveIn.RecordingStopped, AddressOf waveIn_RecordingStopped

Coordinator
Mar 14, 2012 at 10:40 AM

yes, but where are you writing data to the writer? And where are you closing it?

Mar 14, 2012 at 10:46 AM

In  this method i am writing to the writer,

 Private Sub waveIn_DataAvailable(ByVal sender As Object, ByVal e As WaveInEventArgs)

        Try
            If (Me.InvokeRequired) Then     

           Me.BeginInvoke(New waveIn_DataAvailable(AddressOf waveIn_DataAvailable), sender, e)           

                 Else
                If writer IsNot Nothing Then   

                writer.Write(e.Buffer, 0, e.BytesRecorded)   

                secondsRecorded = (writer.Length / writer.WaveFormat.AverageBytesPerSecond)
                    If (secondsRecorded >= 60) Then                       

                     StopRecording(sender)                   

                 End If
                End If

            End If
        Catch ex As Exception   

        MsgBox(ex.Message)     

  End Try
    End Sub

 

here, i am closing

Private Sub waveIn_RecordingStopped(ByVal sender As Object, ByVal e As EventArgs)
        Try
            If (Me.InvokeRequired) Then   

            Me.BeginInvoke(New waveIn_RecordingStopped(AddressOf waveIn_RecordingStopped), sender, e)     

      Else             

  waveIn.Dispose()       

        waveIn = Nothing     

          writer.Close()   

            writer = Nothing


            End If
        Catch ex As Exception     

      MsgBox(ex.Message)   

    End Try   

End Sub

Mar 14, 2012 at 10:49 AM

 

 waveIn = New WaveIn()

waveIn.WaveFormat = New WaveFormat(8000, 16, 1)

 writer = New WaveFileWriter(CurrentFile, waveIn.WaveFormat)

where currentfile contains newly cretaed file path.

Also Event Handler i added followed by above lines.

 AddHandler waveIn.DataAvailable, AddressOf waveIn_DataAvailable   

 AddHandler waveIn.RecordingStopped, AddressOf waveIn_RecordingStopped

Coordinator
Mar 14, 2012 at 10:56 AM

and you are absolutely sure you are calling writer.Close / dispose?

Mar 14, 2012 at 11:02 AM

ya ya writer.close() and writer.dispose() both statements are excuting once after Stop Recording Button pressed.

Mar 14, 2012 at 11:14 AM

Recorded Audio File is working fine,, once after encoding to Ima Adpcm Format ,audio file is not working.But if i encode the recorded audio file to other formats,and then if i try to play that encoded file,its working fine.

Coordinator
Mar 14, 2012 at 11:16 AM

OK, so show me the code that converts your recorded Audio file into IMA ADPCM

Also, try converting the file using the NAudio demo application

Mar 14, 2012 at 11:22 AM

 

                TargetFormat = ImaAdpcmWaveFormat.MyImaAdpcmWaveFormat(8000, 1, 4, 505)   

                 convertedStream = New WaveFormatConversionStream(TargetFormat, Reader)

                  WaveFileWriter.CreateWaveFile(CurrentFile, convertedStream)

 

MyImaAdpcmWaveFormat class:

 public static ImaAdpcmWaveFormat MyImaAdpcmWaveFormat(int sampleRate, int channels, int bitsPerSample, float samplesperblock)   

    {   

        ImaAdpcmWaveFormat ImaAdpcmWformat = new ImaAdpcmWaveFormat();
        ImaAdpcmWformat.waveFormatTag = WaveFormatEncoding.ImaAdpcm; //

        ImaAdpcmWformat.sampleRate = sampleRate;   

        ImaAdpcmWformat.channels = (short)channels; 

         ImaAdpcmWformat.bitsPerSample = (short)bitsPerSample; // TODO: can be 3 or 4     

         ImaAdpcmWformat.extraSize = 2;//      

         ImaAdpcmWformat.blockAlign = 256; //TODO       

        ImaAdpcmWformat.averageBytesPerSecond = 4055; //TODO       

        ImaAdpcmWformat.samplesPerBlock = (short)samplesperblock; // TODO         

  return ImaAdpcmWformat;   

    }

Mar 14, 2012 at 11:29 AM

Nudio Demo Application is working fine.but i dont want to launch the dialog box crates by AcmFormatChoose Function.

Coordinator
Mar 14, 2012 at 12:23 PM

well I can't see anything wrong with your code. If your WaveFormat is the same as the one that NAudioDemo uses, then it should work. Possibly there is an issue with CreateWaveFile. Try this code and step through it in the debugger and see what you are managing to read. It might be that the buffer size might need to be set to an exact multiple of blockAlign. (e.g. 1024 bytes)

        public static void CreateWaveFile(string filename, IWaveProvider sourceProvider)
        {
            using (WaveFileWriter writer = new WaveFileWriter(filename, sourceProvider.WaveFormat))
            {

                byte[] buffer = new byte[sourceProvider.WaveFormat.AverageBytesPerSecond * 4];
                while (true)
                {
                    int bytesRead = sourceProvider.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0)
                        break;
                    writer.Write(buffer, 0, bytesRead);
                }
            }
        }

 

Mar 14, 2012 at 1:37 PM

For Above Wave Format only,Simply i replaced the 

  byte[] buffer = new byte[sourceProvider.WaveFormat.AverageBytesPerSecond * 4]  by 

 byte[] buffer = new byte[sourceProvider.WaveFormat.BlockAlign* 4]

 i traced NaudioDemo code,in same way my code is going. i guess everything is going in write way.But not getting why Encoded File is not able to play.

 

Mar 14, 2012 at 2:16 PM
Edited Mar 15, 2012 at 5:18 AM

CreateWaveFile() method you posted is same as which i am already using.

Can you please try once by your self considering above WaveFormat Structure .

Please reply as early as possible

Regards,

chandan ks

Mar 15, 2012 at 8:33 AM

 

Can you please try once by your self considering above WaveFormat Structure .

Mar 16, 2012 at 10:14 AM
Edited Mar 16, 2012 at 12:47 PM

Hi Mark,

LameAcm is getting listed in the Format combobox Windows xp and other OS,But mine is Windows -7,may that is the issue....?

If that is the case,what i need to do...?

Mar 27, 2012 at 6:40 AM

Hi Mark,

CreateWaveFile() method you posted is same as which i am already using.

Can you please try once by your self considering above WaveFormat Structure .

Please reply as early as possible

Regards, 

Chandan