gpt4 book ai didi

c# - "Must be already floating point"将音频文件转换为 wav 文件时

转载 作者:行者123 更新时间:2023-11-30 21:49:25 25 4
gpt4 key购买 nike

这里我有一个代码可以将音频文件转换为 wav 格式以获得更好的质量并减小文件大小。这里我使用的是 naudio 文件压缩源代码,当我尝试转换该文件时出现异常。

Must be already floating point

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);
}

最佳答案

一般而言,代码和概念存在一些问题。

首先,您忽略了输入文件的 WaveFormat。我猜你假设它是 8K、16 位、1 个 channel ,基于你创建 var s 的行,但这不是保证。

其次,您不需要 MemoryStreamRawSourceWaveStreamWaveFileReader 是一个 WaveStream,适用于任何“下一阶段”NAudio 波形处理器。

第三(这很可能是您的异常(exception)):NAudio Wave 处理器和转换器不喜欢 WaveFormat 中的 A-Law(或 u-Law)。 A-Law(和 u-Law)在技术上不是 PCM 数据。因此,它们不是 NAudio 喜欢使用的“波形”数据。

好了,综上所述,这里有一些建议。 NAudio.Codecs 命名空间中有非常特殊的 A-Law 和 u-Law 编码器。奇怪的是,它们被命名为 ALawEncoderMuLawEncoder。这些东西流兼容,所以我们想让它们兼容。

我在此处的末尾添加了一个类来执行此操作:创建一个 IWaveProvider,它实际上吐出流 A-Law 或 u-Law。下面是使用新类的测试代码。测试代码执行以下操作:

  1. 使用 MediaFoundationReader 读取输入文件(我喜欢这个)
  2. 使用 MediaFoundationResampler 将任何输入格式转换为 16 位 PCM(同时保持 channel 数)。请注意,这意味着您的输入文件不必与 A-law 输出具有相同的格式,因此它几乎可以转换任何内容。
  3. 将新的 16 位 PCM 流提供给自定义的“ALaw-to-IWaveProvider”转换器类。
  4. IWaveProvider 兼容的 A-Law 输出写入波形文件。

我在这里使用 MediaFoundation 类,因为它们似乎不像基于 ACM 的那些那样特别注重波形格式。

    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 或 u-Law 的类。最后是 A-Law 或 u-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)
{
}
}
}

关于c# - "Must be already floating point"将音频文件转换为 wav 文件时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36934672/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com