【脑洞大开:C# CSCore转NAudio播放所有无损音频格式】
事情是这样的,NAudio支持的格式有限,而且都是硬转,然后CSCore默认支持的也不多,甚至更少;西喀西,CSCore自带一个FFmpeg拓展,这样不用我多说了吧,支持格式一下子超了NAudio!但是博主又是NAudio用得比较熟,于是参考NAudio的WaveStream接口设计把CSCore转化到NAudio里播放,当然既然正着能转,反着肯定可以转!Just show me the CODE
当然也可以播放普通有损音频der~
独家原创,这篇文章你找遍世界都找不到第二篇!
事情是这样的,NAudio支持的格式有限,而且都是硬转,然后CSCore默认支持的也不多,甚至更少;西喀西,CSCore自带一个FFmpeg拓展,这样不用我多说了吧,支持格式一下子超了NAudio!但是博主又是NAudio用得比较熟,于是参考NAudio的WaveStream接口设计把CSCore转化到NAudio里播放,当然既然正着能转,反着肯定可以转!
目前能补充NAudio无法解码的常见无损格式有:tta,tak,dsf/dff/dsd/diff等 有损常见格式有mpc等,立体声dts,具体可以翻FFmpeg的支持格式;另外所有的视频里的音频也可以全部支持!比如可以播放mp4,avi,mkv,webm里的音频(只要带音频),是不是非常酷炫?
看到这里其实稍微有点代码能力的可以动手实践一下了,你可以做出比Foobar2K更好的播放器的!
Just show me the CODE!:
头文件:
using CSCore;
using CSCore.Ffmpeg;
using NAudio.Wave;
using Imouto.Audio;
解码端:
namespace Imouto.Audio
{
/// <summary>
/// <see cref="WaveStream"/> for reading Audio files
/// </summary>
public class FFmpegAudioReader : WaveStream
{
private IWaveSource ffmpegDecoder;
private readonly NAudio.Wave.WaveFormat waveFormat;
public override NAudio.Wave.WaveFormat WaveFormat
{
get { return waveFormat; }
}
public override long Length
{
get
{
if (ffmpegDecoder != null)
return ffmpegDecoder.Length;
return 0;
}
}
public override long Position
{
get
{
if (null != ffmpegDecoder)
return ffmpegDecoder.Position;
return 0;
}
set
{
if (null != ffmpegDecoder)
ffmpegDecoder.Position = value;
}
}
public FFmpegAudioReader(string filename)
{
ffmpegDecoder = new FfmpegDecoder(filename);
if(null!= ffmpegDecoder)
{
int sampleRate = ffmpegDecoder.WaveFormat.SampleRate;
int bitsPerSample = ffmpegDecoder.WaveFormat.BitsPerSample;
int channels = ffmpegDecoder.WaveFormat.Channels;
this.waveFormat = new NAudio.Wave.WaveFormat(sampleRate, bitsPerSample, channels);
}
}
//fill pcm data to buffer
public override int Read(byte[] buffer, int offset, int count)
{
if (null != ffmpegDecoder)
{
byte[] tempBuf = new byte[count];
count = ffmpegDecoder.Read(tempBuf, 0, tempBuf.Length);
Buffer.BlockCopy(tempBuf, 0, buffer, 0, count);
return count;
}
else
{
return 0;
}
}
protected override void Dispose(bool disposing)
{
if (null != ffmpegDecoder)
ffmpegDecoder.Dispose();
}
}
}
播放Demo:
FFmpegAudioReader audioReader = new FFmpegAudioReader(url);
var waveOut = new NAudio.Wave.WaveOut();
waveOut.Init(audioReader);
waveOut.Play();
Console.ReadKey();//控制台播放必须加这条阻塞代码,不然直接跳出了!
使用到了这些解码库,原则上可以官方下载最新版,可能支持格式更多!
但是WavPack并不是所有的版本或类型都支持,但是这个可以参考博主上一篇博文用NAudio的BufferedWaveProvider缓冲播放解压的PCM数据
指路:https://blog.csdn.net/weixin_44029053/article/details/122711501
原则上你可以把音频看成是带压缩的PCM数据!我们要做的就是解压后把PCM按规律塞到系统的音频播放接口
关于DSD:
一般DSD格式主要有*.dsf(Sony定制)和*.dff(Philips定制)
可以看这篇播放详细了解:https://www.techbang.com/posts/22079-unlocking-the-mystery-of-dsd-the-dsd-digital-audio-coding-vs-pcm
PS:播放DSD格式音频不要用上面接口,因为上面那个是基于PCM(線性脈衝編碼調變編碼)的,而DSD是基于PDM(脈衝密度調變編碼)的,用CSCore原生播放接口(这里的IWaveSource 是CScore原版的):
string url = System.IO.File.ReadAllText("aaa.txt");
Stream stream = null;//File.OpenRead(url);
//we could also easily pass the filename as url
//but since we want to test the decoding of System.IO.Stream, we
//pass a FileStream as argument.
IWaveSource ffmpegDecoder = (stream == null) ? new FfmpegDecoder(url) : new FfmpegDecoder(stream);
using (stream)
using (ffmpegDecoder)
using (var wasapiOut = new CSCore.SoundOut.WasapiOut())
{
wasapiOut.Initialize(ffmpegDecoder);
wasapiOut.Play();
Console.WriteLine("..end..2");
Console.ReadKey();//控制台播放需要加上这句阻塞
}
也不推荐DSD格式转化为PCM的,这是一个有损过程,因为一般DSD码率会更高
下一步:博主将用这个工具无损格式互相转换,比如把Wavpack转化为Flac
(PS:博主其实已经实现了NAudio端PCM转Flac,就差整理代码啦!)

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)