2016-04-29 3 views
1

Здесь у меня есть код для покрытия аудиофайла в формате wav для лучшего качества и уменьшения размера файла. Здесь я использую исходный код сжатия файла naudio, и я получил исключение, когда пытаюсь преобразовать этот файл.«Должен быть уже с плавающей запятой» при преобразовании аудиофайла в wav-файл

Должно быть, уже с плавающей точкой

public string ConvertToWAV(string tempFilePath, string tempFileName, string audioType) 
{ 
    //Try to transform the file, if it fails use the original file    
    FileInfo fileInfo = new FileInfo(tempFilePath + tempFileName); 
    byte[] fileData = new byte[fileInfo.Length]; 
    fileData = File.ReadAllBytes(tempFilePath + tempFileName); 
    ISampleProvider sampleProvider; 
    try 
    { 
     if (audioType.ToLower().Contains("wav")) 
     { 
      try 
      { 
       using (MemoryStream wav = new MemoryStream(fileData)) 
       { 
        WaveStream stream = new WaveFileReader(wav); 

        WaveFormat target = new WaveFormat(); 

        var s = new RawSourceWaveStream(new MemoryStream(), new WaveFormat(8000, 16, 1)); 
        var c = new WaveFormatConversionStream(WaveFormat.CreateALawFormat(8000, 1), s); 

        sampleProvider = new WaveToSampleProvider(c); 

        WaveFileWriter.CreateWaveFile16(tempFilePath + tempFileName, sampleProvider); 

        wav.Close(); 
       } 
      } 
      catch (Exception ex) 
      { 
       //We couldn't convert the file, continue with the original file.       
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     throw ex; 
    } 
    return Convert.ToBase64String(fileData); 
} 
+0

Пожалуйста, переформатируйте свой вопрос, чтобы его можно было легко прочитать. – Hendry

+2

@Hendry надеюсь, что вы можете его прочитать –

ответ

1

наконец я получил решение этой проблемы, т.е., необходимо добавить вид дополнительной функции под названием Media Foundation в лучшую сторону работы в Windows Server 2012 ,

Используйте мастер добавления ролей и возможностей в диспетчере сервера. Перейдите к функциям и выберите Media Foundation

2

Есть пара проблем с кодом и концепции в целом.

Во-первых, вы игнорируете входной файл WaveFormat. Я предполагаю, что вы предполагаете, что это 8K, 16-бит, 1 канал на основе линии, где вы создаете var s, но это не гарантия.

Во-вторых, вам не нужен MemoryStream или RawSourceWaveStream. WaveFileReader - это WaveStream, и он подходит для любого волнового процессора NA следующей ступени.

Третий (и это, скорее всего, ваше исключение): Процессоры и конвертеры NAudio Wave не любят закон A-закона (или u-Law) в WaveFormat. A-Law (и u-Law) технически не является данными PCM. Таким образом, они не являются «волновыми» данными, с которыми NAudio любит играть.

Хорошо, со всем этим сказанным, вот несколько советов. В пространстве имен NAudio.Codecs есть очень специальные кодеры A-Law и u-Law. Как ни странно, их называют ALawEncoder и MuLawEncoder. Эти вещи не потоко-совместимые, поэтому мы хотим сделать их совместимыми.

Я добавил класс в конце здесь, который делает именно это: Создает IWaveProvider, который фактически выплескивает закон A-закона или U-закона. Вот тестовый код, который использует новый класс. Тестовый код выполняет следующие действия:

  1. читает входной файл с помощью MediaFoundationReader (я как этого)
  2. Преобразует независимо от формата входного сигнала в 16-разрядный PCM (при сохранении числа каналов) с помощью MediaFoundationResampler. Обратите внимание, что это означает, что ваш входной файл не должен иметь тот же формат, что и выход A-law, поэтому он будет конвертировать практически все.
  3. Подает этот новый 16-разрядный поток PCM в пользовательский класс преобразования «ALaw-to-IWaveProvider».
  4. Записывает вывод IWaveProvider-A-Law в файл волны.

Здесь я использую классы MediaFoundation, потому что они, похоже, не так характерны для волновых форматов, как для ACM-based.

static void ConversionTest(string _outfilename, string _infilename) 
    { 
     try 
     { 
      using(var reader = new MediaFoundationReader(_infilename)) 
      { 
       // Create a wave format for 16-bit pcm at 8000 samples per second. 
       int channels = reader.WaveFormat.Channels; 
       int rate = 8000; 
       int rawsize = 2; 
       int blockalign = rawsize * channels; // this is the size of one sample. 
       int bytespersecond = rate * blockalign; 
       var midformat = 
        WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, 
                rate, 
                channels, 
                bytespersecond, 
                blockalign, 
                rawsize * 8); 

       // And a conversion stream to turn input into 16-bit PCM. 
       var midstream = new MediaFoundationResampler(reader, midformat); 
       //var midstream = new WaveFormatConversionStream(midformat, reader); 

       // The output stream is our custom stream. 
       var outstream = new PcmToALawConversionStream(midstream); 


       WaveFileWriter.CreateWaveFile(_outfilename, outstream); 
      } 
     } 
     catch(Exception _ex) 
     { 
     } 
    } 

А вот класс, который преобразует 16-битный PCM в A-Law или у-закона. В конце являются специализациями для A-Law или у-права:

/// <summary> 
    /// Encodes 16-bit PCM input into A- or u-Law, presenting the output 
    /// as an IWaveProvider. 
    /// </summary> 
    public class PcmToG711ConversionStream : IWaveProvider 
    { 
     /// <summary>Gets the local a-law or u-law format.</summary> 
     public WaveFormat WaveFormat { get { return waveFormat; } } 

     /// <summary>Returns <paramref name="count"/> encoded bytes.</summary> 
     /// <remarks> 
     /// Note that <paramref name="count"/> is raw bytes. It doesn't consider 
     /// channel counts, etc. 
     /// </remarks> 
     /// <param name="buffer">The output buffer.</param> 
     /// <param name="offset">The starting position in the output buffer.</param> 
     /// <param name="count">The number of bytes to read.</param> 
     /// <returns>The total number of bytes encoded into <paramref name="buffer"/>.</returns> 
     public int Read(byte[] buffer, int offset, int count) 
     { 
      // We'll need a source buffer, twice the size of 'count'. 
      int shortcount = count*2; 
      byte [] rawsource = new byte [shortcount]; 
      int sourcecount = Provider.Read(rawsource, 0, shortcount); 
      int bytecount = sourcecount/2; 
      for(int index = 0; index < bytecount; ++index) 
      { 
       short source = BitConverter.ToInt16(rawsource, index*2); 
       buffer[offset+index] = Encode(source); 
      } 
      return bytecount; 
     } 


     /// <summary> 
     /// Initializes and A-Law or u-Law "WaveStream". The source stream 
     /// must be 16-bit PCM! 
     /// </summary> 
     /// <param name="_encoding">ALaw or MuLaw only.</param> 
     /// <param name="_sourcestream">The input PCM stream.</param> 
     public PcmToG711ConversionStream(WaveFormatEncoding _encoding, 
              IWaveProvider _provider) 
     { 
      Provider = _provider; 
      WaveFormat sourceformat = Provider.WaveFormat; 
      if((sourceformat.Encoding != WaveFormatEncoding.Pcm) && 
       (sourceformat.BitsPerSample != 16)) 
      { 
       throw new NotSupportedException("Input must be 16-bit PCM. Try using a conversion stream."); 
      } 

      if(_encoding == WaveFormatEncoding.ALaw) 
      { 
       Encode = this.EncodeALaw; 
       waveFormat = WaveFormat.CreateALawFormat(_provider.WaveFormat.SampleRate, 
                  _provider.WaveFormat.Channels) ; 

      } 
      else if(_encoding == WaveFormatEncoding.MuLaw) 
      { 
       Encode = this.EncodeMuLaw; 
       waveFormat = WaveFormat.CreateMuLawFormat(_provider.WaveFormat.SampleRate, 
                  _provider.WaveFormat.Channels) ; 
      } 
      else 
      { 
       throw new NotSupportedException("Encoding must be A-Law or u-Law"); 
      } 
     } 


     /// <summary>The a-law or u-law encoder delegate.</summary> 
     EncodeHandler Encode; 
     /// <summary>a-law or u-law wave format.</summary> 
     WaveFormat waveFormat; 
     /// <summary>The input stream.</summary> 
     IWaveProvider Provider; 

     /// <summary>A-Law or u-Law encoder delegate.</summary> 
     /// <param name="_sample">The 16-bit PCM sample to encode.</param> 
     /// <returns>The encoded value.</returns> 
     delegate byte EncodeHandler(short _sample); 

     byte EncodeALaw(short _sample) 
     { 
      return ALawEncoder.LinearToALawSample(_sample); 
     } 
     byte EncodeMuLaw(short _sample) 
     { 
      return MuLawEncoder.LinearToMuLawSample(_sample); 
     } 
    } 


    public class PcmToALawConversionStream : PcmToG711ConversionStream 
    { 
     public PcmToALawConversionStream(IWaveProvider _provider) 
      : base(WaveFormatEncoding.ALaw, _provider) 
     { 
     } 
    } 

    public class PcmToMuLawConversionStream : PcmToG711ConversionStream 
    { 
     public PcmToMuLawConversionStream(IWaveProvider _provider) 
      : base(WaveFormatEncoding.MuLaw, _provider) 
     { 
     } 
    } 
} 
+0

использовал ваш код ... он работает локально, но запускается на сервере iis. Я получил ошибку, например: «Не удалось загрузить DLL« mfplat.dll »: указанный модуль не найден. (Исключение из HRESULT: 0x8007007E) ». –

+0

@Bob C \t использовал ваш код ... он работает локально, но запускается на сервере iis. Я получил ошибку, например:« Не удалось загрузить DLL «mfplat.dll»: указанный модуль мог не существует. (Исключение из HRESULT: 0x8007007E) « –

+0

@JerryJohn - Это может быть или не быть ноу-хау. Нет сборки NAudio с именем «mfplat.dll», но она * может * быть связана с классами MediaFoundation. Попробуйте заменить их «нормальными» классами NAudio (например, «WaveFileReader» и т. Д.) И посмотреть, загружается ли она тогда. В качестве альтернативы просто напишите заглушки для этого кода в другой сборке (т. Е. Не используйте NAudio) и посмотрите, имеет ли это исключение. –