change format from wav to mp3 in memory stream in NAudio
Asked Answered
S

7

15

Hi there iam trying to convert text to speech (wav) in the memorystream convert it to mp3 and then play it on the users page.so need i help what to do next?

here is my asmx code :

[WebMethod]
public byte[] StartSpeak(string Word)
{
    MemoryStream ms = new MemoryStream();
    using (System.Speech.Synthesis.SpeechSynthesizer synhesizer = new System.Speech.Synthesis.SpeechSynthesizer())
    {
        synhesizer.SelectVoiceByHints(System.Speech.Synthesis.VoiceGender.NotSet, System.Speech.Synthesis.VoiceAge.NotSet, 0, new System.Globalization.CultureInfo("en-US"));
        synhesizer.SetOutputToWaveStream(ms);
        synhesizer.Speak(Word);
    }
    return ms.ToArray();

    }

Thanks.

Sturm answered 27/9, 2013 at 19:21 Comment(3)
How far have you gotten? Are you getting an error? Also, I'm assuming that this is just the speech to text piece, and not the conversion?Garnetgarnett
thanks for replying .well iam a beginner so i have trouble what to do next if there is an example it would help.Sturm
Possible duplicate of Audio Conversion C#Ultramundane
D
13

You need an MP3 compressor library. I use Lame via the Yeti Lame wrapper. You can find code and a sample project here.

Steps to get this working:

  1. Copy the following files from MP3Compressor to your project:

    • AudioWriters.cs
    • Lame.cs
    • Lame_enc.dll
    • Mp3Writer.cs
    • Mp3WriterConfig.cs
    • WaveNative.cs
    • WriterConfig.cs

  2. In the project properties for Lame_enc.dll set the Copy to Output property to Copy if newer or Copy always.

  3. Edit Lame.cs and replace all instances of:

    [DllImport("Lame_enc.dll")]
    

    with:

    [DllImport("Lame_enc.dll", CallingConvention = CallingConvention.Cdecl)]
    
  4. Add the following code to your project:

    public static Byte[] WavToMP3(byte[] wavFile)
    {
         using (MemoryStream source = new MemoryStream(wavFile))
         using (NAudio.Wave.WaveFileReader rdr = new NAudio.Wave.WaveFileReader(source))
         {
             WaveLib.WaveFormat fmt = new WaveLib.WaveFormat(rdr.WaveFormat.SampleRate, rdr.WaveFormat.BitsPerSample, rdr.WaveFormat.Channels);
    
             // convert to MP3 at 96kbit/sec...
             Yeti.Lame.BE_CONFIG conf = new Yeti.Lame.BE_CONFIG(fmt, 96);
    
             // Allocate a 1-second buffer
             int blen = rdr.WaveFormat.AverageBytesPerSecond;
             byte[] buffer = new byte[blen];
    
             // Do conversion
             using (MemoryStream output = new MemoryStream())
             { 
                 Yeti.MMedia.Mp3.Mp3Writer mp3 = new Yeti.MMedia.Mp3.Mp3Writer(output, fmt, conf);
    
                 int readCount;
                 while ((readCount = rdr.Read(buffer, 0, blen)) > 0)
                     mp3.Write(buffer, 0, readCount);
                 mp3.Close();
    
                 return output.ToArray();
             }
         }
     }
    
  5. Either add a reference to System.Windows.Forms to your project (if it's not there already), or edit AudioWriter.cs and WriterConfig.cs to remove the references. Both of these have a using System.Windows.Forms; that you can remove, and WriterConfig.cs has a ConfigControl declaration that needs to be removed/commented out.

Once all of that is done you should have a functional in-memory wave-file to MP3 converter that you can use to convert the WAV file that you are getting from the SpeechSynthesizer into an MP3.

Devitalize answered 1/10, 2013 at 7:19 Comment(0)
W
62

Just wanted to post my example too using NAudio.Lame:

NuGet:

Install-Package NAudio.Lame

Code Snip: Mine obviously returns a byte[] - I have a separate save to disk method b/c I think it makes unit testing easier.

public static byte[] ConvertWavToMp3(byte[] wavFile)
        {

            using(var retMs = new MemoryStream())
            using (var ms = new MemoryStream(wavFile))
            using(var rdr = new WaveFileReader(ms))
            using (var wtr = new LameMP3FileWriter(retMs, rdr.WaveFormat, 128))
            {
                rdr.CopyTo(wtr);
                return retMs.ToArray();
            }


        }
Windom answered 6/4, 2014 at 1:53 Comment(5)
Wow I don't know why this wasn't upvoted more. it worked perfectly. The simplest solution. Thanks Wjdavis5!Lippold
It didn't worked for me, whatever I did the returned byte array was empty.Dogwood
@AdrianC. Add wtr.Flush(); after rdr.CopyTo(wtr);. Cheers.Xanthochroism
I find this solution truncates the audio by a couple of seconds.Rouse
I think you'll want to Flush() the stream as some others have suggestedWindom
D
13

You need an MP3 compressor library. I use Lame via the Yeti Lame wrapper. You can find code and a sample project here.

Steps to get this working:

  1. Copy the following files from MP3Compressor to your project:

    • AudioWriters.cs
    • Lame.cs
    • Lame_enc.dll
    • Mp3Writer.cs
    • Mp3WriterConfig.cs
    • WaveNative.cs
    • WriterConfig.cs

  2. In the project properties for Lame_enc.dll set the Copy to Output property to Copy if newer or Copy always.

  3. Edit Lame.cs and replace all instances of:

    [DllImport("Lame_enc.dll")]
    

    with:

    [DllImport("Lame_enc.dll", CallingConvention = CallingConvention.Cdecl)]
    
  4. Add the following code to your project:

    public static Byte[] WavToMP3(byte[] wavFile)
    {
         using (MemoryStream source = new MemoryStream(wavFile))
         using (NAudio.Wave.WaveFileReader rdr = new NAudio.Wave.WaveFileReader(source))
         {
             WaveLib.WaveFormat fmt = new WaveLib.WaveFormat(rdr.WaveFormat.SampleRate, rdr.WaveFormat.BitsPerSample, rdr.WaveFormat.Channels);
    
             // convert to MP3 at 96kbit/sec...
             Yeti.Lame.BE_CONFIG conf = new Yeti.Lame.BE_CONFIG(fmt, 96);
    
             // Allocate a 1-second buffer
             int blen = rdr.WaveFormat.AverageBytesPerSecond;
             byte[] buffer = new byte[blen];
    
             // Do conversion
             using (MemoryStream output = new MemoryStream())
             { 
                 Yeti.MMedia.Mp3.Mp3Writer mp3 = new Yeti.MMedia.Mp3.Mp3Writer(output, fmt, conf);
    
                 int readCount;
                 while ((readCount = rdr.Read(buffer, 0, blen)) > 0)
                     mp3.Write(buffer, 0, readCount);
                 mp3.Close();
    
                 return output.ToArray();
             }
         }
     }
    
  5. Either add a reference to System.Windows.Forms to your project (if it's not there already), or edit AudioWriter.cs and WriterConfig.cs to remove the references. Both of these have a using System.Windows.Forms; that you can remove, and WriterConfig.cs has a ConfigControl declaration that needs to be removed/commented out.

Once all of that is done you should have a functional in-memory wave-file to MP3 converter that you can use to convert the WAV file that you are getting from the SpeechSynthesizer into an MP3.

Devitalize answered 1/10, 2013 at 7:19 Comment(0)
D
11

This is a bit old now, but since you haven't accepted the answer I previously provided...

I have recently built an extension for NAudio that encapsulates the LAME library to provide simplified MP3 encoding.

Use the NuGet package manager to find NAudio.Lame. Basic example for using it available here.

Devitalize answered 4/11, 2013 at 6:16 Comment(6)
I couldn't add the reference to my phone project. How should i be doing? Please cover a tutorial to do this.Damning
Sorry @max, but the LAME encoder is a native Windows DLL that - as far as I can tell - will not work for Windows Phone. That being the case, it's not possible for a LAME wrapper to work on Windows Phone either. You'll have to find a different mechanism for your MP3 encoding.Devitalize
How can i build a web service for this code to let it work? Understand that I am not too much involved into server side coding or such mechanisms. @DevitalizeDamning
@max If you're running an ASP.NET or MVC4 website or similar (ie: IIS on Win32/Win64) then you can use NAudio.Lame on the server side. Need to add some stuff though - refer to this question.Devitalize
That's a good suggestion. I will try to build a web service for it. Many thanks :)Damning
Wow. Excellent stuff.Adjective
G
1

Assuming you're trying to convert the output into MP3, you need something that can handle transcoding the audio. There are a number of tools available, but my personal preference is FFmpeg. It's a command line tool so you will need to take that into account, but otherwise it's very easy to use.

There's lots of information online, but you can start by checking out their documentation here.

Garnetgarnett answered 27/9, 2013 at 19:49 Comment(0)
M
1

I had a similar requirement in .net4.0 to convert 8bit 8Khz mono wav and used the following code

public void WavToMp3(string wavPath, string fileId)
    {
        var tempMp3Path = TempPath + "tempFiles\\" + fileId + ".mp3";
        var mp3strm = new FileStream(tempMp3Path, FileMode.Create);
        try
        {
            using (var reader = new WaveFileReader(wavPath))
            {
                var blen = 65536;
                var buffer = new byte[blen];
                int rc;
                var bit16WaveFormat = new WaveFormat(16000, 16, 1);
                using (var conversionStream = new WaveFormatConversionStream(bit16WaveFormat, reader))
                {
                    var targetMp3Format = new WaveLib.WaveFormat(16000, 16, 1);
                    using (var mp3Wri = new Mp3Writer(mp3strm, new Mp3WriterConfig(targetMp3Format, new BE_CONFIG(targetMp3Format,64))))
                    {
                        while ((rc = conversionStream.Read(buffer, 0, blen)) > 0) mp3Wri.Write(buffer, 0, rc);
                        mp3strm.Flush();
                        conversionStream.Close();
                    }
                }
                reader.Close();
            }
            File.Move(tempMp3Path, TempPath + fileId + ".mp3");
        }
        finally
        {
            mp3strm.Close();
        }
    }

Prerequists:

  1. .net 4 compiled yeti library (to obtain it download this older one (http://www.codeproject.com/KB/audio-video/MP3Compressor/MP3Compressor.zip) and convert it to .net4.0 then build the solution to obtain the new version dlls)
  2. download the NAudio libraries (as Lame support 16bit wav sample only i had to first convert it from 8bit to 16bit wav)

I have used a buffer size of 64kpbs (my custom requirement)

Marilla answered 7/1, 2014 at 10:31 Comment(0)
D
0

have a try:

using (WaveStream waveStream = WaveFormatConversionStream.CreatePcmStream(new     
Mp3FileReader(inputStream))) 
using (WaveFileWriter waveFileWriter = new WaveFileWriter(outputStream, waveStream.WaveFormat)) 
{ 
    byte[] bytes = new byte[waveStream.Length]; 
    waveStream.Position = 0;
    waveStream.Read(bytes, 0, waveStream.Length); 
    waveFileWriter.WriteData(bytes, 0, bytes.Length); 
    waveFileWriter.Flush(); 
} 
Defrayal answered 1/6, 2021 at 6:59 Comment(0)
R
0

Assuming you have installed NAudio and NAudio.Lame from NuGet:

using (var reader = new AudioFileReader(@"C:\Temp\Test0001.wav"))
using (var writer = new LameMP3FileWriter(@"C:\Temp\Test0001.mp3", reader.WaveFormat, LAMEPreset.STANDARD))
Rouse answered 27/2, 2023 at 11:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.