当前位置: 首页 > java >正文

C# MP3 伴奏

使用建议:

  1. 参数调节指南

    • 低频人声残留:降低CenterFrequency(800-1500Hz)

    • 高频人声残留:提高CenterFrequency(2500-3500Hz)

    • 消除力度不足:提高EliminationStrength(0.9-1.0)

    • 伴奏失真:降低EliminationStrength(0.7-0.9) 并提高GainCompensation(1.3-1.5)

using System;
using System.IO;
using NAudio.Wave;
using NAudio.Lame;public class AudioConverter
{public event EventHandler<int> ProgressChanged;public event EventHandler ConversionCompleted;public float EliminationStrength { get; set; } = 0.95f;    // 消除强度 0-1public void ConvertToAccompaniment(string inputPath, string outputPath){try{if (!File.Exists(inputPath)){throw new FileNotFoundException($"输入文件未找到: {inputPath}");}using (var mp3Reader = new Mp3FileReader(inputPath)){var sampleProvider = mp3Reader.ToSampleProvider();var originalFormat = sampleProvider.WaveFormat;if (originalFormat.Channels != 2){throw new InvalidOperationException("仅支持立体声音频文件");}// 创建16位PCM格式var pcm16Format = new WaveFormat(originalFormat.SampleRate, 16, originalFormat.Channels);long totalBytes = mp3Reader.Length;long processedBytes = 0;using (var pcmMemoryStream = new MemoryStream()){WaveFileWriter wavWriter = null;try{wavWriter = new WaveFileWriter(new IgnoreDisposeStream(pcmMemoryStream), pcm16Format);float[] buffer = new float[originalFormat.SampleRate * originalFormat.Channels];int samplesRead;while ((samplesRead = sampleProvider.Read(buffer, 0, buffer.Length)) > 0){ProcessVocalRemoval(buffer, samplesRead);// 将浮点数组转换为16位PCM字节数组byte[] pcm16Bytes = new byte[samplesRead * 2]; // 每个样本占2字节for (int i = 0; i < samplesRead; i++){// 钳制值并转换为16位整数float sample = Math.Max(-1.0f, Math.Min(1.0f, buffer[i]));short pcmSample = (short)(sample * short.MaxValue);pcm16Bytes[i * 2] = (byte)(pcmSample);pcm16Bytes[i * 2 + 1] = (byte)(pcmSample >> 8);}wavWriter.Write(pcm16Bytes, 0, pcm16Bytes.Length);processedBytes += pcm16Bytes.Length;// 计算进度时可能需要调整总长度,此处假设totalBytes为PCM数据估算长度int percent = (int)((double)processedBytes / (totalBytes * 2) * 100);ProgressChanged?.Invoke(this, percent);}}finally{wavWriter?.Dispose();}pcmMemoryStream.Position = 0;// 使用16位PCM格式初始化LAME编码器using (var mp3Writer = new LameMP3FileWriter(outputPath, pcm16Format, LAMEPreset.VBR_90)){pcmMemoryStream.CopyTo(mp3Writer);}}ProgressChanged?.Invoke(this, 100);ConversionCompleted?.Invoke(this, EventArgs.Empty);}}catch (FileNotFoundException ex){Console.WriteLine($"文件未找到: {ex.FileName}");}catch (InvalidOperationException ex){Console.WriteLine($"处理错误: {ex.Message}");}catch (Exception ex){Console.WriteLine($"发生未知错误: {ex.Message}");}}private void ProcessVocalRemoval(float[] buffer, int samplesRead){for (int i = 0; i < samplesRead; i += 2){float left = buffer[i];float right = buffer[i + 1];float difference = (left - right) * EliminationStrength;buffer[i] = difference;buffer[i + 1] = difference;}}// 修正4:添加流包装器防止WaveFileWriter关闭底层流private class IgnoreDisposeStream : Stream{private readonly Stream _baseStream;public IgnoreDisposeStream(Stream baseStream) => _baseStream = baseStream;public override bool CanRead => _baseStream.CanRead;public override bool CanSeek => _baseStream.CanSeek;public override bool CanWrite => _baseStream.CanWrite;public override long Length => _baseStream.Length;public override long Position{get => _baseStream.Position;set => _baseStream.Position = value;}public override void Flush() => _baseStream.Flush();public override int Read(byte[] buffer, int offset, int count) => _baseStream.Read(buffer, offset, count);public override long Seek(long offset, SeekOrigin origin) => _baseStream.Seek(offset, origin);public override void SetLength(long value) => _baseStream.SetLength(value);public override void Write(byte[] buffer, int offset, int count) => _baseStream.Write(buffer, offset, count);protected override void Dispose(bool disposing){// 不关闭底层流}}
}

效果对比表

参数组合适用场景副作用
Strength=0.9, Freq=1500清晰人声消除可能损失部分低频伴奏
Strength=0.8, Freq=2500保留贝斯/鼓点高频人声可能有残留
Strength=1.0, Freq=800消除低沉男声可能产生金属感失真

注意事项

  1. 源音频质量直接影响效果,推荐使用无损音源

  2. 复杂音乐(如交响乐)可能需要分层处理

  3. 完全消除人声可能伴随伴奏损失,需平衡参数

如果需要进一步优化,可以考虑集成AI人声分离模型(如Spleeter),但这需要额外部署机器学习框架。

http://www.xdnf.cn/news/1105.html

相关文章:

  • MYSQL之库的操作
  • C++设计模式
  • Sharding-JDBC 系列专题 - 第七篇:Spring Boot 集成与 Sharding-Proxy 简介
  • MongoDB常用命令
  • 01-STM32基本知识点和keil5的安装
  • 【白雪讲堂】[特殊字符]内容战略地图|GEO优化框架下的内容全景布局
  • 7N60-ASEMI无人机专用功率器件7N60
  • Elasticsearch 使用reindex进行数据同步或索引重构
  • spark jar依赖顺序
  • Docker--Docker网络原理
  • docker容器中uv的使用
  • ARM汇编的LDM和STM指令
  • 【sylar-webserver】重构 增加内存池
  • weibo_har鸿蒙微博分享,单例二次封装,鸿蒙微博,微博登录
  • 基于 WebRTC + Pion + HeyGem.ai 实现可互动的数字人系统
  • 安徽京准:关于石油管道监控NTP时间同步服务器方案
  • kafka auto.offset.reset详解
  • 【Qt】QDialog类
  • WebRTC服务器Coturn服务器的管理平台功能
  • 最新扣子(Coze)案例教程:飞书多维表格按条件筛选记录 + 读取分页Coze工作流,无限循环使用方法,手把手教学,完全免费教程
  • 【基于SprintBoot+Mybatis+Mysql】电脑商城项目之显示勾选的购物车数据和创建订单
  • 电气动调节单座V型球阀带阀杆节流套沟槽孔板的作用-耀圣
  • 【华为HCIP | 华为数通工程师】821—多选解析—第十二页
  • 【MySQL】MySQL 表的增删改查(CRUD)—— 下篇(内含聚合查询、group by和having子句、联合查询、插入查询结果)
  • Linux信号的产生
  • Qt绘制可选择范围的日历
  • 嘻游电玩三端客户端部署实战:PC + Android + iOS 环境全覆盖教程
  • 【数据结构】励志大厂版·初级(二刷复习)双链表
  • HCIP(OSPF)(3)
  • 缓存与内存;缺页中断;缓存映射:组相联