2017-03-27 128 views
0

我有一個字節數組(從數據庫)以16000Hz,32位,1通道格式在IEEE浮點數的IEEE數據流中的WAV數據。我想將其轉換爲mp3並通過WCF服務中的響應對象進行流式傳輸。NAudio:在WCF中將IEEE Float輸入流轉換爲MP3輸出流

使用NAudio包,到目前爲止我所做的工作是使用MediaFoundationEncoder.EncodetoMp3()寫入文件。但是,一旦將該文件寫出到響應中,它就沒用了。我想跳過文件寫入步驟並輸出到流或字節數組並將其寫入響應對象。

有沒有辦法讓MediaFoundationEncoder在某種內存對象(沒有文件)中輸出mp3?

或者,試圖使用LameMP3FileWriter,這並寫入流, 我可以在IEEE浮點WAV輸入直接傳送給LameMP3FileWriter但似乎無論我使用的輸出格式的所產生的mp3流聽起來像一個響亮的嘶嘶聲(44100 ,16,1),(22050,16,1),(11025,16,1),...

當我嘗試將IEEE浮點源轉換爲PCM或使用WaveFormatConversion對其進行上採樣時,它出錯與

AcmNotPossible調用acmStreamOpen

如果我在IEEE浮點源上使用Wave32to16Stream,它沒有錯誤,但沒有音頻。此鏈不是爲我工作:

byte[] bytes = (Byte[])dt.Rows[0]["AudioContent"];//this is the dataTable from the database query containing the WAV audio 

    var ms = new MemoryStream(bytes); 
    var OLDfmt = WaveFormat.CreateIeeeFloatWaveFormat(16000,1); 
    var NEWfmt = new WaveFormat(16000, 16, 1);//tried many 
    var readr = new RawSourceWaveStream(ms,OLDfmt); 

    //the following line errors on 'AcmNotPossible calling acmStreamOpen' 
    //var wav16 = new WaveFormatConversionStream(NEWfmt, readr); 

    //the following does not error but no mp3 streams out at the end 
    var wav16 = new Wave32To16Stream(readr); 

    var outptMP3 = new MemoryStream(); 
    var writr = new LameMP3FileWriter(outptMP3, NEWfmt, LAMEPreset.STANDARD); 
    wav16.CopyTo(writr); 
    HttpContext.Current.Response.BufferOutput = true; 
    HttpContext.Current.Response.AddHeader("Content-Type", "audio/mpeg"); 
    HttpContext.Current.Response.BinaryWrite(outptMP3.ToArray()); 

原始音頻播放在Chrome罰款(爲WAV流),如果我只是做了毫秒的MemoryStream的的BinaryWrite,所以我覺得IEEE浮點源數據是有效的。

糾正我是否錯誤,但該錯誤(AcmNotPossible)似乎意味着我的機器上沒有ACM編解碼器用於IEEE浮點格式?我查詢了我的機器,似乎沒有32位ACM編解碼器,這就是我試圖進行Wave32To16Stream轉換的原因。

是否有一個臨時步驟的Lame MP3管道從IEEE浮點數32位到MP3?

回答

0

對不起,我的主要問題有很多關於將IEEE浮點32位波轉碼爲mp3流的問題,但我至少可以告訴你我是如何使用ACM編解碼器工作的(我認爲)我簡單的WCF服務:

  1. 變化對服務的返回類型爲流
  2. 設置MemoryStream的位置爲0返回

之前,否則上述鏈實際上做的工作對我來說。爲了完整起見,我將給出完整的代碼和所有無關的SQL內容,因爲我在無關SO問題中找到了答案:

public Stream playWAVEFileFromDB() { 
     //if using the file output method, I change the return type to string and return text instead of streams 
     try 
     { 
      SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["myconnectionstring"].ConnectionString); 
      SqlCommand cmd = new SqlCommand(); 
      cmd.Connection = conn; 
      cmd.CommandText = "SELECT theWAVEColumn FROM myTable WHERE allThoseAudiosAreStored"; 
      SqlDataAdapter sda = new SqlDataAdapter(); 
      DataTable dt = new DataTable(); 

      conn.Open(); 
      sda.SelectCommand = cmd; 
      sda.Fill(dt); 

      //read the raw audio from database into a byte array 
      byte[] bytes = (Byte[])dt.Rows[0]["colName"]; 
      var ms = new MemoryStream(bytes); 
      var NEWfmt = new WaveFormat(16000, 16, 1); 
      var OLDfmt = WaveFormat.CreateIeeeFloatWaveFormat(16000,1);//how its stored 
      var readr = new RawSourceWaveStream(ms,OLDfmt); 
      var wav16 = new Wave32To16Stream(readr); 
      var outptMP3 = new MemoryStream();  
      var writr = new LameMP3FileWriter(outptMP3, NEWfmt, LAMEPreset.STANDARD); 
      wav16.CopyTo(writr); 
      outptMP3.Position = 0; 

      HttpContext.Current.Response.BufferOutput = true; 
      HttpContext.Current.Response.AddHeader("Content-Type", "audio/mpeg"); 

      conn.Close(); 
      conn.Dispose(); 
      sda.Dispose(); 

      return outptMP3; 
     } 
      catch (Exception e) 
     { 
      //do the error logging stuff 
      return Stream.Null; 
     } 
    }